Uh oh!
There was an error while loading. Please reload this page.
feat: added Clanker typescript action support - #825
Conversation
✅ Heimdall Review Status
|
be629f1 to
97da2b1Compare94e3d49 to
cc79e82Compare28d2442 to
c059efcCompare| /** | ||
| * Clanker Action Provider | ||
| * | ||
| * This file contains the implementation of the ClankerActionProvider, | ||
| * which provides actions for clanker operations. | ||
| * | ||
| * @module clanker | ||
| */ | ||
There was a problem hiding this comment.
Please remove in accordance with code style elsewhere
| * @returns True if the network is supported | ||
| */ | ||
| supportsNetwork(network: Network): boolean { | ||
| // all protocol networks |
| /** | ||
| * Exports for clanker action provider | ||
| * | ||
| * @module clanker | ||
| */ | ||
| // depending on usage, you might export the factory like this: | ||
| // export { clankerActionProviderFactory } from "./clankerActionProvider"; |
| tokenName: z.string().min(1).max(100), | ||
| /** | ||
| * Symbol of token (lets keep it short <= 10) | ||
| */ | ||
| tokenSymbol: z.string().min(1).max(10), |
There was a problem hiding this comment.
out of curiosity, are the max character limits enforced by the protocol/sdk or a choice by you?
There was a problem hiding this comment.
Enforced by me, happy to remove it!
| * @param networkId - The network to Clank on (this will most likely be Base, unless the action implementation is extended to include other networks) | ||
| * @returns The Clanker implementation | ||
| */ | ||
| export async function makeClanker(walletProvider: EvmWalletProvider, networkId: string) { |
There was a problem hiding this comment.
please rename makeClanker -> createClankerClient
The "clankerBridge" notation is also misleading, please move the file utils/clankerBridge.ts -> utils.ts
| const wallet = createWalletClient({ | ||
| account, | ||
| chain: NETWORK_ID_TO_VIEM_CHAIN[networkId], | ||
| transport: http(), |
There was a problem hiding this comment.
This should use transport as configured in walletProvider:
| transport: http(), | |
| transport: http(publicClient.transport.url) |
| expect(makeClankerMock).toHaveBeenCalledWith(expect.any(Object), expect.any(String)); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing dedicated supportsNetwork test block like other providers
describe("supportsNetwork", () => {
it("should return true for base-mainnet with evm protocol", () => {
expect(provider.supportsNetwork({ protocolFamily: "evm", networkId: "base-mainnet" })).toBe(true);
});
it("should return false for non-base networks", () => {
expect(provider.supportsNetwork({ protocolFamily: "evm", networkId: "ethereum-mainnet" })).toBe(false);
});
});
| description: ` | ||
| This tool will launch a token (called a Clanker, named after the token launch protocol). | ||
| Clanker tokens can only be launched when your network ID is 'base-mainnet'. | ||
| `, |
There was a problem hiding this comment.
Description is too brief and misses important details. Suggestion:
| description: ` | |
| Thistoolwilllaunchatoken(calledaClanker,namedafterthetokenlaunchprotocol). | |
| ClankertokenscanonlybelaunchedwhenyournetworkIDis'base-mainnet'. | |
| `, | |
| description: ` | |
| ThistoolwilllaunchaClankertoken using theClankerSDK. | |
| Ittakesthefollowinginputs: | |
| -tokenName: Thenameofthedeployedtoken | |
| -tokenSymbol: The symbol ofthedeployedtoken | |
| -image: AnormaloripfsURLpointingtotheimageofthetoken | |
| -vaultPercentage: Thepercentageofthetokensupplytoallocatetoavaultaccessibletothedeployedafterthelockupperiodwithoptionalvesting | |
| -lockDuration_Days: Thelockdurationofthetokensinthevault(indays)(minimum7days) | |
| -vestingDuration_Days: Theduration(indays)thatthetokenshouldvestafterlockupperiod,vestingislinear. | |
| `, |
| const res = await clanker.deploy(tokenConfig); | ||
| if ("error" in res) { | ||
| return `There was an error deploying the clanker token: ${res}`; | ||
| } | ||
| const { txHash } = res; | ||
| const confirmed = await res.waitForTransaction(); | ||
| if ("error" in confirmed) { | ||
| return `There was an error confirming the clanker token deployment: ${confirmed}`; | ||
| } |
There was a problem hiding this comment.
Please wrap main logic in try-catch
| const { address } = confirmed; | ||
| return `Clanker token deployed at ${address}! View the transaction at ${txHash}`; |
There was a problem hiding this comment.
Could add link to deployed coin here, https://clanker.world/clanker/
| export const ClankTokenSchema = z.object({ | ||
| /** | ||
| * Name of token | ||
| */ | ||
| tokenName: z.string().min(1).max(100), | ||
| /** | ||
| * Symbol of token (lets keep it short <= 10) | ||
| */ | ||
| tokenSymbol: z.string().min(1).max(10), | ||
| /** | ||
| * String URL pointing to image | ||
| */ | ||
| image: z.string().url(), | ||
| /** | ||
| * Percentage of token for deployer initially locked |
There was a problem hiding this comment.
Please remove all the TSDoc comments and use describe() on the Zod fields instead. Suggestion:
| exportconstClankTokenSchema=z.object({ | |
| /** | |
| *Nameoftoken | |
| */ | |
| tokenName: z.string().min(1).max(100), | |
| /** | |
| *Symboloftoken(letskeepitshort<=10) | |
| */ | |
| tokenSymbol: z.string().min(1).max(10), | |
| /** | |
| *StringURLpointingtoimage | |
| */ | |
| image: z.string().url(), | |
| /** | |
| *Percentageoftokenfordeployerinitiallylocked | |
| exportconstClankTokenSchema=z | |
| .object({ | |
| tokenName: z.string().min(1).max(100).describe("The name of the token (max 100 characters)"), | |
| tokenSymbol: z.string().min(1).max(10).describe("The symbol of the token (max 10 characters)"), | |
| image: z.string().url().describe("Normal or ipfs URL pointing to the token image"), | |
| vaultPercentage: z.number().min(0).max(99).describe("Percentage of token supply allocated to a vault that can be claimed by deployer after lockup period with optional vesting"), | |
| lockDuration_Days: z.number().min(7).describe("Lockup duration of token (in days), minimum 7 days"), | |
| vestingDuration_Days: z.number().min(0).describe("Vesting duration of token after lockup has passed (in days). Vesting is linear over the duration"), | |
| }) | |
| .strip() | |
| .describe("Instructions for deploying a Clanker token"); |
| /** | ||
| * Percentage of token for deployer initially locked | ||
| */ | ||
| vestingPercentage: z.number().min(0).max(99), |
There was a problem hiding this comment.
Seems max percentage for vault is 90%, not 99%. See: https://github.com/clanker-devco/clanker-sdk/blob/e82ee2af17301012a1d32c21e215068a84fba590/src/config/clankerTokenV4.ts#L125C1-L126C1.
Notation "vestingPercentage" also misleading, should be vaultPercentage
| * Creates the client Clanker expects from the EvmWalletProvider | ||
| * | ||
| * @param walletProvider - The wallet provider instance for blockchain interactions | ||
| * @param networkId - The network to Clank on (this will most likely be Base, unless the action implementation is extended to include other networks) |
There was a problem hiding this comment.
remove "(this will most likely be Base, unless the action implementation is extended to include other networks)"
| const tokenConfig = { | ||
| name: args.tokenName, | ||
| symbol: args.tokenSymbol, | ||
| image: args.image, |
There was a problem hiding this comment.
Please add optional metadata field with description and socialMediaUrls, see https://www.npmjs.com/package/clanker-sdk and https://github.com/clanker-devco/clanker-sdk/blob/e82ee2af17301012a1d32c21e215068a84fba590/src/utils/zod-onchain.ts#L7.
| symbol: args.tokenSymbol, | ||
| image: args.image, | ||
| context: { | ||
| interface: "Clanker SDK", |
There was a problem hiding this comment.
add optional arg to shemas to set interface, should default to "CDP AgentKit"
| platform: "Clanker", | ||
| messageId: "Deploy Example", | ||
| id: "TKN-1", |
There was a problem hiding this comment.
should also be optional args, not hardcoded. Can default to "".
Hi @gtspencer, thanks for your contribution. That's a great addition! Please have a look at my comments above, hope we can get this in soon Note: Please avoid force-pushing all your code changes into the same commit. Instead, push new commits so I can review what changed more easily. |
| ├── schemas.ts # Action schemas and types | ||
| ├── index.ts # Package exports | ||
| ├── utils/ | ||
| │ ├── clankerBridge.ts # Helprs to wrap the EVMWalletProvider in the type the Clanker SDK expects |
gtspencer
commented
Sep 2, 2025
hey @phdargen , just made those requested changes! let me know if there's anything else! |
| ├── utils/ | ||
| │ ├── clankerBridge.ts # Helpers to wrap the EVMWalletProvider in the type the Clanker SDK expects |
| tokenName: "Test Token", | ||
| tokenSymbol: "TT", | ||
| image: "https://test.com/image.png", | ||
| vestingPercentage: 10, |
| supportsNetwork(network: Network): boolean { | ||
| return network.protocolFamily === "evm" && network.networkId == "base-mainnet"; | ||
| } |
There was a problem hiding this comment.
Lets include all supported networks:
| supportsNetwork(network: Network): boolean { | |
| returnnetwork.protocolFamily==="evm"&&network.networkId=="base-mainnet"; | |
| } | |
| supportsNetwork=(network: Network)=> | |
| network.networkId==="base-mainnet"||network.networkId==="base-sepolia"||network.networkId==="arbitrum-mainnet"; |
| description: args.description, | ||
| socialMediaUrls: args.socialMediaUrls, |
There was a problem hiding this comment.
needs to be wrapped in metadata field:
| description: args.description, | |
| socialMediaUrls: args.socialMediaUrls, | |
| metadata: { | |
| description: args.description, | |
| socialMediaUrls: args.socialMediaUrls, | |
| }, |
| percentage: args.vaultPercentage, | ||
| lockupDuration: lockDuration, | ||
| vestingDuration: vestingDuration, | ||
| }, |
There was a problem hiding this comment.
add:chainId: Number(network.chainId) as 8453 | 84532 | 42161 | undefined,
| if (!networkId || networkId !== "base-mainnet") { | ||
| return `Can't Clank token; network must be Base Mainnet`; | ||
| } |
There was a problem hiding this comment.
please change to:
| if(!networkId||networkId!=="base-mainnet"){ | |
| return`Can't Clank token; network must be Base Mainnet`; | |
| } | |
| if(!this.supportsNetwork(network)){ | |
| return`Can't Clank token; network ${networkId} is not supported`; | |
| } |
| #### Example | ||
| ``` | ||
| Prompt: Can you clank a token with name [CDP Clanker], and symbol [CDPC] and image hosted at [https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQF6hcTTU1A8Ymi2VldXqCsPkBu_ltAhIKiRg&s]? vest 10%, locked for 30 days, and then vested for 30 days. do this on base-mainnet | ||
| ``` | ||
| ``` | ||
| ------------------- | ||
| Internal address: 0xE8D165388b13c460F02f4dC922309450a9bF6f22 | ||
| Clanker token deployed at 0x15E91EAF0848c8FEfE8c287923B5A78E254A76eb! View the transaction at 0xf67befc5da942288a7bb4baee2cbbc1a09853e62552e736aa272b91e09f918fa | ||
| ------------------- | ||
| The Clanker token has been successfully deployed with the name "CDP Clanker" and symbol "CDPC." You can view the transaction [here](https://etherscan.io/tx/0xf67befc5da942288a7bb4baee2cbbc1a09853e62552e736aa272b91e09f918fa). The token address is 0x15E91EAF0848c8FEfE8c287923B5A78E254A76eb. | ||
| ------------------- | ||
| ``` |
There was a problem hiding this comment.
not needed here, please remove
phdargen
commented
Sep 3, 2025
Hi @gtspencer, thanks for the update! The action failed in my test as the |
gtspencer
commented
Sep 4, 2025
@phdargen apologies, should have caught those sooner! Just updated and think its good to go! |
phdargen
commented
Sep 5, 2025
No worries @gtspencer, thanks for the quick fixes! This is reviewed and tested @CarsonRoscoe
|
CarsonRoscoe
left a comment
There was a problem hiding this comment.
Thank you @gtspencer for the contribution! And thanks @phdargen for the review.
This looks good to me!
Clanker Action Provider
Description
This action adds Clanker token deployment support to the typescript implementation of AgentKit.
Although Clanker already has an agent that deploys tokens, their open library and protocol allows anyone to launch a "Clank" token and be recognized by their ecosystem.
Tests
Checklist
A couple of things to include in your PR for completeness: