@coinbase/agentkit 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +195 -23
  2. package/dist/action-providers/across/acrossActionProvider.js +3 -3
  3. package/dist/action-providers/across/schemas.d.ts +1 -1
  4. package/dist/action-providers/baseAccount/baseAccountActionProvider.d.ts +46 -0
  5. package/dist/action-providers/baseAccount/baseAccountActionProvider.js +404 -0
  6. package/dist/action-providers/baseAccount/baseAccountActionProvider.test.d.ts +1 -0
  7. package/dist/action-providers/baseAccount/baseAccountActionProvider.test.js +325 -0
  8. package/dist/action-providers/baseAccount/index.d.ts +2 -0
  9. package/dist/action-providers/baseAccount/index.js +18 -0
  10. package/dist/action-providers/baseAccount/schemas.d.ts +43 -0
  11. package/dist/action-providers/baseAccount/schemas.js +62 -0
  12. package/dist/action-providers/baseAccount/types.d.ts +17 -0
  13. package/dist/action-providers/baseAccount/types.js +2 -0
  14. package/dist/action-providers/baseAccount/utils.d.ts +14 -0
  15. package/dist/action-providers/baseAccount/utils.js +57 -0
  16. package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +3 -12
  17. package/dist/action-providers/cdp/cdpApiActionProvider.js +2 -81
  18. package/dist/action-providers/cdp/cdpApiActionProvider.test.js +0 -125
  19. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.d.ts +18 -3
  20. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +224 -23
  21. package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.js +280 -0
  22. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.d.ts +17 -2
  23. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +224 -18
  24. package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.js +267 -1
  25. package/dist/action-providers/cdp/schemas.d.ts +12 -12
  26. package/dist/action-providers/cdp/schemas.js +17 -5
  27. package/dist/action-providers/cdp/swapUtils.d.ts +23 -0
  28. package/dist/action-providers/cdp/swapUtils.js +106 -0
  29. package/dist/action-providers/clanker/clankerActionProvider.d.ts +43 -0
  30. package/dist/action-providers/clanker/clankerActionProvider.js +130 -0
  31. package/dist/action-providers/clanker/clankerActionProvider.test.d.ts +4 -0
  32. package/dist/action-providers/clanker/clankerActionProvider.test.js +119 -0
  33. package/dist/action-providers/clanker/index.d.ts +2 -0
  34. package/dist/action-providers/clanker/index.js +18 -0
  35. package/dist/action-providers/clanker/schemas.d.ts +56 -0
  36. package/dist/action-providers/clanker/schemas.js +47 -0
  37. package/dist/action-providers/clanker/utils.d.ts +9 -0
  38. package/dist/action-providers/clanker/utils.js +23 -0
  39. package/dist/action-providers/compound/constants.d.ts +1 -1
  40. package/dist/action-providers/compound/constants.js +2 -2
  41. package/dist/action-providers/erc20/constants.d.ts +35 -135
  42. package/dist/action-providers/erc20/constants.js +37 -189
  43. package/dist/action-providers/erc20/erc20ActionProvider.d.ts +9 -1
  44. package/dist/action-providers/erc20/erc20ActionProvider.js +87 -35
  45. package/dist/action-providers/erc20/erc20ActionProvider.test.js +115 -52
  46. package/dist/action-providers/erc20/schemas.d.ts +25 -12
  47. package/dist/action-providers/erc20/schemas.js +34 -6
  48. package/dist/action-providers/erc20/utils.d.ts +19 -0
  49. package/dist/action-providers/erc20/utils.js +54 -0
  50. package/dist/action-providers/flaunch/client_utils.d.ts +25 -0
  51. package/dist/action-providers/flaunch/client_utils.js +62 -0
  52. package/dist/action-providers/flaunch/constants.d.ts +42 -21
  53. package/dist/action-providers/flaunch/constants.js +113 -38
  54. package/dist/action-providers/flaunch/flaunchActionProvider.d.ts +4 -43
  55. package/dist/action-providers/flaunch/flaunchActionProvider.js +133 -209
  56. package/dist/action-providers/flaunch/flaunchActionProvider.test.js +113 -13
  57. package/dist/action-providers/flaunch/metadata_utils.d.ts +12 -0
  58. package/dist/action-providers/flaunch/metadata_utils.js +216 -0
  59. package/dist/action-providers/flaunch/schemas.d.ts +39 -3
  60. package/dist/action-providers/flaunch/schemas.js +62 -10
  61. package/dist/action-providers/flaunch/{utils.d.ts → swap_utils.d.ts} +17 -19
  62. package/dist/action-providers/flaunch/{utils.js → swap_utils.js} +137 -172
  63. package/dist/action-providers/index.d.ts +4 -0
  64. package/dist/action-providers/index.js +4 -0
  65. package/dist/action-providers/jupiter/schemas.d.ts +1 -1
  66. package/dist/action-providers/moonwell/schemas.d.ts +2 -2
  67. package/dist/action-providers/morpho/morphoActionProvider.js +5 -5
  68. package/dist/action-providers/morpho/schemas.d.ts +2 -2
  69. package/dist/action-providers/pyth/pythActionProvider.d.ts +2 -2
  70. package/dist/action-providers/pyth/pythActionProvider.js +83 -26
  71. package/dist/action-providers/pyth/pythActionProvider.test.js +179 -23
  72. package/dist/action-providers/pyth/schemas.d.ts +6 -0
  73. package/dist/action-providers/pyth/schemas.js +9 -1
  74. package/dist/action-providers/superfluid/constants.d.ts +814 -0
  75. package/dist/action-providers/superfluid/constants.js +2826 -0
  76. package/dist/action-providers/superfluid/graphQueries/endpoints.d.ts +2 -0
  77. package/dist/action-providers/superfluid/graphQueries/endpoints.js +5 -0
  78. package/dist/action-providers/superfluid/graphQueries/queries.d.ts +1 -0
  79. package/dist/action-providers/superfluid/graphQueries/queries.js +35 -0
  80. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.d.ts +8 -0
  81. package/dist/action-providers/superfluid/graphQueries/superfluidGraphQueries.js +24 -0
  82. package/dist/action-providers/superfluid/graphQueries/types.d.ts +27 -0
  83. package/dist/action-providers/superfluid/graphQueries/types.js +2 -0
  84. package/dist/action-providers/superfluid/index.d.ts +7 -0
  85. package/dist/action-providers/superfluid/index.js +23 -0
  86. package/dist/action-providers/superfluid/schemas.d.ts +86 -0
  87. package/dist/action-providers/superfluid/schemas.js +103 -0
  88. package/dist/action-providers/superfluid/superfluidActionProvider.d.ts +20 -0
  89. package/dist/action-providers/superfluid/superfluidActionProvider.js +36 -0
  90. package/dist/action-providers/superfluid/superfluidPoolActionProvider.d.ts +46 -0
  91. package/dist/action-providers/superfluid/superfluidPoolActionProvider.js +143 -0
  92. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.d.ts +1 -0
  93. package/dist/action-providers/superfluid/superfluidPoolActionProvider.test.js +92 -0
  94. package/dist/action-providers/superfluid/superfluidQueryActionProvider.d.ts +27 -0
  95. package/dist/action-providers/superfluid/superfluidQueryActionProvider.js +71 -0
  96. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.d.ts +1 -0
  97. package/dist/action-providers/superfluid/superfluidQueryActionProvider.test.js +57 -0
  98. package/dist/action-providers/superfluid/superfluidStreamActionProvider.d.ts +56 -0
  99. package/dist/action-providers/superfluid/superfluidStreamActionProvider.js +191 -0
  100. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.d.ts +1 -0
  101. package/dist/action-providers/superfluid/superfluidStreamActionProvider.test.js +80 -0
  102. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.d.ts +30 -0
  103. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.js +109 -0
  104. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.d.ts +1 -0
  105. package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.test.js +75 -0
  106. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.d.ts +32 -0
  107. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.js +101 -0
  108. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.d.ts +1 -0
  109. package/dist/action-providers/superfluid/superfluidWrapperActionProvider.test.js +85 -0
  110. package/dist/action-providers/superfluid/utils/parseLogs.d.ts +19 -0
  111. package/dist/action-providers/superfluid/utils/parseLogs.js +81 -0
  112. package/dist/action-providers/truemarkets/truemarketsActionProvider.d.ts +4 -16
  113. package/dist/action-providers/truemarkets/truemarketsActionProvider.js +20 -41
  114. package/dist/action-providers/truemarkets/truemarketsActionProvider.test.js +11 -33
  115. package/dist/action-providers/wallet/walletActionProvider.js +24 -10
  116. package/dist/action-providers/wallet/walletActionProvider.test.js +6 -2
  117. package/dist/action-providers/x402/schemas.d.ts +7 -0
  118. package/dist/action-providers/x402/schemas.js +11 -1
  119. package/dist/action-providers/x402/utils.d.ts +55 -0
  120. package/dist/action-providers/x402/utils.js +160 -0
  121. package/dist/action-providers/x402/x402ActionProvider.d.ts +9 -9
  122. package/dist/action-providers/x402/x402ActionProvider.js +158 -39
  123. package/dist/action-providers/x402/x402ActionProvider.test.js +116 -10
  124. package/dist/action-providers/zeroX/index.d.ts +1 -0
  125. package/dist/action-providers/zeroX/index.js +17 -0
  126. package/dist/action-providers/zeroX/schemas.d.ts +51 -0
  127. package/dist/action-providers/zeroX/schemas.js +82 -0
  128. package/dist/action-providers/zeroX/utils.d.ts +23 -0
  129. package/dist/action-providers/zeroX/utils.js +106 -0
  130. package/dist/action-providers/zeroX/zeroXActionProvider.d.ts +57 -0
  131. package/dist/action-providers/zeroX/zeroXActionProvider.js +407 -0
  132. package/dist/action-providers/zeroX/zeroXActionProvider.test.d.ts +1 -0
  133. package/dist/action-providers/zeroX/zeroXActionProvider.test.js +445 -0
  134. package/dist/utils.d.ts +10 -0
  135. package/dist/utils.js +43 -13
  136. package/dist/wallet-providers/cdpEvmWalletProvider.d.ts +27 -2
  137. package/dist/wallet-providers/cdpEvmWalletProvider.js +54 -36
  138. package/dist/wallet-providers/cdpEvmWalletProvider.test.js +7 -0
  139. package/dist/wallet-providers/cdpShared.d.ts +5 -0
  140. package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +29 -3
  141. package/dist/wallet-providers/cdpSmartWalletProvider.js +66 -25
  142. package/dist/wallet-providers/cdpSmartWalletProvider.test.js +6 -10
  143. package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +1 -1
  144. package/dist/wallet-providers/cdpSolanaWalletProvider.js +7 -7
  145. package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +15 -12
  146. package/dist/wallet-providers/evmWalletProvider.d.ts +13 -2
  147. package/dist/wallet-providers/evmWalletProvider.js +4 -0
  148. package/dist/wallet-providers/legacyCdpSmartWalletProvider.d.ts +18 -2
  149. package/dist/wallet-providers/legacyCdpSmartWalletProvider.js +23 -2
  150. package/dist/wallet-providers/legacyCdpWalletProvider.d.ts +19 -2
  151. package/dist/wallet-providers/legacyCdpWalletProvider.js +27 -2
  152. package/dist/wallet-providers/legacyCdpWalletProvider.test.js +6 -0
  153. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.d.ts +17 -2
  154. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.js +39 -3
  155. package/dist/wallet-providers/privyEvmDelegatedEmbeddedWalletProvider.test.js +1 -1
  156. package/dist/wallet-providers/privyEvmWalletProvider.d.ts +2 -0
  157. package/dist/wallet-providers/privyEvmWalletProvider.js +2 -1
  158. package/dist/wallet-providers/privyEvmWalletProvider.test.js +12 -1
  159. package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +1 -1
  160. package/dist/wallet-providers/solanaKeypairWalletProvider.js +3 -4
  161. package/dist/wallet-providers/solanaKeypairWalletProvider.test.js +4 -2
  162. package/dist/wallet-providers/viemWalletProvider.d.ts +20 -3
  163. package/dist/wallet-providers/viemWalletProvider.js +33 -4
  164. package/dist/wallet-providers/viemWalletProvider.test.js +27 -6
  165. package/dist/wallet-providers/walletProvider.d.ts +1 -1
  166. package/dist/wallet-providers/zeroDevWalletProvider.d.ts +17 -2
  167. package/dist/wallet-providers/zeroDevWalletProvider.js +26 -5
  168. package/dist/wallet-providers/zeroDevWalletProvider.test.js +12 -2
  169. package/package.json +8 -4
@@ -1,195 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseSepoliaTokenToAssetId = exports.BaseTokenToAssetId = exports.abi = void 0;
3
+ exports.TOKEN_ADDRESSES_BY_SYMBOLS = exports.BaseSepoliaTokenToAssetId = exports.BaseTokenToAssetId = void 0;
4
4
  const coinbase_sdk_1 = require("@coinbase/coinbase-sdk");
5
- exports.abi = [
6
- {
7
- type: "event",
8
- name: "Approval",
9
- inputs: [
10
- {
11
- indexed: true,
12
- name: "owner",
13
- type: "address",
14
- },
15
- {
16
- indexed: true,
17
- name: "spender",
18
- type: "address",
19
- },
20
- {
21
- indexed: false,
22
- name: "value",
23
- type: "uint256",
24
- },
25
- ],
26
- },
27
- {
28
- type: "event",
29
- name: "Transfer",
30
- inputs: [
31
- {
32
- indexed: true,
33
- name: "from",
34
- type: "address",
35
- },
36
- {
37
- indexed: true,
38
- name: "to",
39
- type: "address",
40
- },
41
- {
42
- indexed: false,
43
- name: "value",
44
- type: "uint256",
45
- },
46
- ],
47
- },
48
- {
49
- type: "function",
50
- name: "allowance",
51
- stateMutability: "view",
52
- inputs: [
53
- {
54
- name: "owner",
55
- type: "address",
56
- },
57
- {
58
- name: "spender",
59
- type: "address",
60
- },
61
- ],
62
- outputs: [
63
- {
64
- type: "uint256",
65
- },
66
- ],
67
- },
68
- {
69
- type: "function",
70
- name: "approve",
71
- stateMutability: "nonpayable",
72
- inputs: [
73
- {
74
- name: "spender",
75
- type: "address",
76
- },
77
- {
78
- name: "amount",
79
- type: "uint256",
80
- },
81
- ],
82
- outputs: [
83
- {
84
- type: "bool",
85
- },
86
- ],
87
- },
88
- {
89
- type: "function",
90
- name: "balanceOf",
91
- stateMutability: "view",
92
- inputs: [
93
- {
94
- name: "account",
95
- type: "address",
96
- },
97
- ],
98
- outputs: [
99
- {
100
- type: "uint256",
101
- },
102
- ],
103
- },
104
- {
105
- type: "function",
106
- name: "decimals",
107
- stateMutability: "view",
108
- inputs: [],
109
- outputs: [
110
- {
111
- type: "uint8",
112
- },
113
- ],
114
- },
115
- {
116
- type: "function",
117
- name: "name",
118
- stateMutability: "view",
119
- inputs: [],
120
- outputs: [
121
- {
122
- type: "string",
123
- },
124
- ],
125
- },
126
- {
127
- type: "function",
128
- name: "symbol",
129
- stateMutability: "view",
130
- inputs: [],
131
- outputs: [
132
- {
133
- type: "string",
134
- },
135
- ],
136
- },
137
- {
138
- type: "function",
139
- name: "totalSupply",
140
- stateMutability: "view",
141
- inputs: [],
142
- outputs: [
143
- {
144
- type: "uint256",
145
- },
146
- ],
147
- },
148
- {
149
- type: "function",
150
- name: "transfer",
151
- stateMutability: "nonpayable",
152
- inputs: [
153
- {
154
- name: "recipient",
155
- type: "address",
156
- },
157
- {
158
- name: "amount",
159
- type: "uint256",
160
- },
161
- ],
162
- outputs: [
163
- {
164
- type: "bool",
165
- },
166
- ],
167
- },
168
- {
169
- type: "function",
170
- name: "transferFrom",
171
- stateMutability: "nonpayable",
172
- inputs: [
173
- {
174
- name: "sender",
175
- type: "address",
176
- },
177
- {
178
- name: "recipient",
179
- type: "address",
180
- },
181
- {
182
- name: "amount",
183
- type: "uint256",
184
- },
185
- ],
186
- outputs: [
187
- {
188
- type: "bool",
189
- },
190
- ],
191
- },
192
- ];
193
5
  exports.BaseTokenToAssetId = new Map([
194
6
  ["0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", coinbase_sdk_1.Coinbase.assets.Cbbtc],
195
7
  ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", coinbase_sdk_1.Coinbase.assets.Usdc],
@@ -200,3 +12,39 @@ exports.BaseSepoliaTokenToAssetId = new Map([
200
12
  ["0x036CbD53842c5426634e7929541eC2318f3dCF7e", coinbase_sdk_1.Coinbase.assets.Usdc],
201
13
  ["0x808456652fdb597867f38412077A9182bf77359F", coinbase_sdk_1.Coinbase.assets.Eurc],
202
14
  ]);
15
+ // Token symbol to address mappings for frequently used tokens
16
+ exports.TOKEN_ADDRESSES_BY_SYMBOLS = {
17
+ "base-mainnet": {
18
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
19
+ EURC: "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42",
20
+ CBBTC: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
21
+ CBETH: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22",
22
+ WETH: "0x4200000000000000000000000000000000000006",
23
+ ZORA: "0x1111111111166b7FE7bd91427724B487980aFc69",
24
+ AERO: "0x940181a94a35a4569e4529a3cdfb74e38fd98631",
25
+ BNKR: "0x22af33fe49fd1fa80c7149773dde5890d3c76f3b",
26
+ CLANKER: "0x1bc0c42215582d5a085795f4badbac3ff36d1bcb",
27
+ },
28
+ "base-sepolia": {
29
+ USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
30
+ EURC: "0x808456652fdb597867f38412077A9182bf77359F",
31
+ CBBTC: "0xcbB7C0006F23900c38EB856149F799620fcb8A4a",
32
+ WETH: "0x4200000000000000000000000000000000000006",
33
+ },
34
+ "ethereum-mainnet": {
35
+ USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
36
+ EURC: "0x1abaea1f7c830bd89acc67ec4af516284b1bc33c",
37
+ CBBTC: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
38
+ WETH: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
39
+ CBETH: "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704",
40
+ },
41
+ "polygon-mainnet": {
42
+ USDC: "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
43
+ },
44
+ "arbitrum-mainnet": {
45
+ USDC: "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
46
+ },
47
+ "optimism-mainnet": {
48
+ USDC: "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
49
+ },
50
+ };
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { ActionProvider } from "../actionProvider";
3
3
  import { Network } from "../../network";
4
- import { GetBalanceSchema, TransferSchema } from "./schemas";
4
+ import { GetBalanceSchema, TransferSchema, GetTokenAddressSchema } from "./schemas";
5
5
  import { EvmWalletProvider } from "../../wallet-providers";
6
6
  /**
7
7
  * ERC20ActionProvider is an action provider for ERC20 tokens.
@@ -27,6 +27,14 @@ export declare class ERC20ActionProvider extends ActionProvider<EvmWalletProvide
27
27
  * @returns A message containing the transfer details.
28
28
  */
29
29
  transfer(walletProvider: EvmWalletProvider, args: z.infer<typeof TransferSchema>): Promise<string>;
30
+ /**
31
+ * Gets the contract address for a token symbol on the current network.
32
+ *
33
+ * @param walletProvider - The wallet provider to get the network from.
34
+ * @param args - The input arguments for the action.
35
+ * @returns A message containing the token address or an error if not found.
36
+ */
37
+ getTokenAddress(walletProvider: EvmWalletProvider, args: z.infer<typeof GetTokenAddressSchema>): Promise<string>;
30
38
  /**
31
39
  * Checks if the ERC20 action provider supports the given network.
32
40
  *
@@ -15,6 +15,7 @@ const actionProvider_1 = require("../actionProvider");
15
15
  const actionDecorator_1 = require("../actionDecorator");
16
16
  const schemas_1 = require("./schemas");
17
17
  const constants_1 = require("./constants");
18
+ const utils_1 = require("./utils");
18
19
  const viem_1 = require("viem");
19
20
  const wallet_providers_1 = require("../../wallet-providers");
20
21
  /**
@@ -42,24 +43,12 @@ class ERC20ActionProvider extends actionProvider_1.ActionProvider {
42
43
  * @returns A message containing the balance.
43
44
  */
44
45
  async getBalance(walletProvider, args) {
45
- try {
46
- const balance = await walletProvider.readContract({
47
- address: args.contractAddress,
48
- abi: constants_1.abi,
49
- functionName: "balanceOf",
50
- args: [walletProvider.getAddress()],
51
- });
52
- const decimals = await walletProvider.readContract({
53
- address: args.contractAddress,
54
- abi: constants_1.abi,
55
- functionName: "decimals",
56
- args: [],
57
- });
58
- return `Balance of ${args.contractAddress} is ${(0, viem_1.formatUnits)(balance, decimals)}`;
59
- }
60
- catch (error) {
61
- return `Error getting balance: ${error}`;
46
+ const address = args.address || walletProvider.getAddress();
47
+ const tokenDetails = await (0, utils_1.getTokenDetails)(walletProvider, args.tokenAddress, args.address);
48
+ if (!tokenDetails) {
49
+ return `Error: Could not fetch token details for ${args.tokenAddress}`;
62
50
  }
51
+ return `Balance of ${tokenDetails.name} (${args.tokenAddress}) at address ${address} is ${tokenDetails.formattedBalance}`;
63
52
  }
64
53
  /**
65
54
  * Transfers a specified amount of an ERC20 token to a destination onchain.
@@ -70,11 +59,36 @@ class ERC20ActionProvider extends actionProvider_1.ActionProvider {
70
59
  */
71
60
  async transfer(walletProvider, args) {
72
61
  try {
62
+ // Check token details
63
+ const tokenAddress = (0, viem_1.getAddress)(args.tokenAddress);
64
+ const tokenDetails = await (0, utils_1.getTokenDetails)(walletProvider, args.tokenAddress);
65
+ if (!tokenDetails) {
66
+ return `Error: Could not fetch token details for ${args.tokenAddress}. Please verify the token address is correct.`;
67
+ }
68
+ // Check token balance
69
+ const amountInWei = (0, viem_1.parseUnits)(String(args.amount), tokenDetails.decimals);
70
+ if (tokenDetails.balance < amountInWei) {
71
+ return `Error: Insufficient ${tokenDetails.name} (${args.tokenAddress}) token balance. Requested to send ${args.amount} of ${tokenDetails.name} (${args.tokenAddress}), but only ${tokenDetails.formattedBalance} is available.`;
72
+ }
73
+ // Guardrails to prevent loss of funds
74
+ if (args.tokenAddress === args.destinationAddress) {
75
+ return "Error: Transfer destination is the token contract address. Refusing transfer to prevent loss of funds.";
76
+ }
77
+ if ((await walletProvider
78
+ .getPublicClient()
79
+ .getCode({ address: args.destinationAddress })) !== "0x") {
80
+ // If destination address is a contract, check if its an ERC20 token
81
+ // This assumes if the contract implements name, balance and decimals functions, it is an ERC20 token
82
+ const destinationTokenDetails = await (0, utils_1.getTokenDetails)(walletProvider, args.destinationAddress);
83
+ if (destinationTokenDetails) {
84
+ return "Error: Transfer destination is an ERC20 token contract. Refusing to transfer to prevent loss of funds.";
85
+ }
86
+ // If contract but not an ERC20 token (e.g a smart wallet), allow the transfer
87
+ }
73
88
  // Check if we can do gasless transfer
74
- const isCdpWallet = walletProvider.getName() === "cdp_wallet_provider";
89
+ const isLegacyCdpWallet = walletProvider.getName() === "legacy_cdp_wallet_provider";
75
90
  const network = walletProvider.getNetwork();
76
- const tokenAddress = (0, viem_1.getAddress)(args.contractAddress);
77
- const canDoGasless = isCdpWallet &&
91
+ const canDoGasless = isLegacyCdpWallet &&
78
92
  ((network.networkId === "base-mainnet" && constants_1.BaseTokenToAssetId.has(tokenAddress)) ||
79
93
  (network.networkId === "base-sepolia" && constants_1.BaseSepoliaTokenToAssetId.has(tokenAddress)));
80
94
  if (canDoGasless) {
@@ -83,33 +97,59 @@ class ERC20ActionProvider extends actionProvider_1.ActionProvider {
83
97
  const assetId = network.networkId === "base-mainnet"
84
98
  ? constants_1.BaseTokenToAssetId.get(tokenAddress)
85
99
  : constants_1.BaseSepoliaTokenToAssetId.get(tokenAddress);
86
- const hash = await cdpWallet.gaslessERC20Transfer(assetId, args.destination, args.amount);
100
+ const hash = await cdpWallet.gaslessERC20Transfer(assetId, args.destinationAddress, BigInt(args.amount));
87
101
  await walletProvider.waitForTransactionReceipt(hash);
88
- return `Transferred ${args.amount} of ${args.contractAddress} to ${args.destination} using gasless transfer.\nTransaction hash: ${hash}`;
102
+ return `Transferred ${args.amount} of ${args.tokenAddress} to ${args.destinationAddress} using gasless transfer.\nTransaction hash: ${hash}`;
89
103
  }
90
104
  // Fallback to regular transfer
91
105
  const hash = await walletProvider.sendTransaction({
92
- to: args.contractAddress,
106
+ to: args.tokenAddress,
93
107
  data: (0, viem_1.encodeFunctionData)({
94
- abi: constants_1.abi,
108
+ abi: viem_1.erc20Abi,
95
109
  functionName: "transfer",
96
- args: [args.destination, BigInt(args.amount)],
110
+ args: [args.destinationAddress, amountInWei],
97
111
  }),
98
112
  });
99
113
  await walletProvider.waitForTransactionReceipt(hash);
100
- return `Transferred ${args.amount} of ${args.contractAddress} to ${args.destination}.\nTransaction hash for the transfer: ${hash}`;
114
+ return `Transferred ${args.amount} of ${tokenDetails?.name} (${args.tokenAddress}) to ${args.destinationAddress}.\nTransaction hash for the transfer: ${hash}`;
101
115
  }
102
116
  catch (error) {
103
117
  return `Error transferring the asset: ${error}`;
104
118
  }
105
119
  }
120
+ /**
121
+ * Gets the contract address for a token symbol on the current network.
122
+ *
123
+ * @param walletProvider - The wallet provider to get the network from.
124
+ * @param args - The input arguments for the action.
125
+ * @returns A message containing the token address or an error if not found.
126
+ */
127
+ async getTokenAddress(walletProvider, args) {
128
+ const network = walletProvider.getNetwork();
129
+ const networkTokens = constants_1.TOKEN_ADDRESSES_BY_SYMBOLS[network.networkId ?? ""];
130
+ const tokenAddress = networkTokens?.[args.symbol];
131
+ if (tokenAddress) {
132
+ return `Token address for ${args.symbol} on ${network.networkId}: ${tokenAddress}`;
133
+ }
134
+ // Get available token symbols for the current network
135
+ const availableSymbols = networkTokens ? Object.keys(networkTokens) : [];
136
+ const availableSymbolsText = availableSymbols.length > 0
137
+ ? ` Available token symbols on ${network.networkId}: ${availableSymbols.join(", ")}`
138
+ : ` No token symbols are configured for ${network.networkId}`;
139
+ return `Error: Token symbol "${args.symbol}" not found on ${network.networkId}.${availableSymbolsText}`;
140
+ }
106
141
  }
107
142
  exports.ERC20ActionProvider = ERC20ActionProvider;
108
143
  __decorate([
109
144
  (0, actionDecorator_1.CreateAction)({
110
145
  name: "get_balance",
111
146
  description: `
112
- This tool will get the balance of an ERC20 asset in the wallet. It takes the contract address as input.
147
+ This tool will get the balance of an ERC20 token for a given address.
148
+ It takes the following inputs:
149
+ - tokenAddress: The contract address of the token to get the balance for
150
+ - address: (Optional) The address to check the balance for. If not provided, uses the wallet's address
151
+ Important notes:
152
+ - Never assume token or address, they have to be provided as inputs. If only token symbol is provided, use the get_token_address tool to get the token address first
113
153
  `,
114
154
  schema: schemas_1.GetBalanceSchema,
115
155
  }),
@@ -121,22 +161,34 @@ __decorate([
121
161
  (0, actionDecorator_1.CreateAction)({
122
162
  name: "transfer",
123
163
  description: `
124
- This tool will transfer an ERC20 token from the wallet to another onchain address.
164
+ This tool will transfer (send) an ERC20 token from the wallet to another onchain address.
125
165
 
126
166
  It takes the following inputs:
127
- - amount: The amount to transfer
128
- - contractAddress: The contract address of the token to transfer
129
- - destination: Where to send the funds (can be an onchain address, ENS 'example.eth', or Basename 'example.base.eth')
130
-
167
+ - amount: The amount to transfer in whole units (e.g. 10.5 USDC)
168
+ - tokenAddress: The contract address of the token to transfer
169
+ - destinationAddress: Where to send the funds (can be an onchain address, ENS 'example.eth', or Basename 'example.base.eth')
131
170
  Important notes:
132
- - Ensure sufficient balance of the input asset before transferring
133
- - When sending native assets (e.g. 'eth' on base-mainnet), ensure there is sufficient balance for the transfer itself AND the gas cost of this transfer
134
- `,
171
+ - Never assume token or destination addresses, they have to be provided as inputs. If only token symbol is provided, use the get_token_address tool to get the token address first
172
+ `,
135
173
  schema: schemas_1.TransferSchema,
136
174
  }),
137
175
  __metadata("design:type", Function),
138
176
  __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
139
177
  __metadata("design:returntype", Promise)
140
178
  ], ERC20ActionProvider.prototype, "transfer", null);
179
+ __decorate([
180
+ (0, actionDecorator_1.CreateAction)({
181
+ name: "get_erc20_token_address",
182
+ description: `
183
+ This tool will get the contract address for frequently used ERC20 tokens on different networks.
184
+ It takes the following input:
185
+ - symbol: The token symbol (e.g. USDC, EURC, CBBTC)
186
+ `,
187
+ schema: schemas_1.GetTokenAddressSchema,
188
+ }),
189
+ __metadata("design:type", Function),
190
+ __metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
191
+ __metadata("design:returntype", Promise)
192
+ ], ERC20ActionProvider.prototype, "getTokenAddress", null);
141
193
  const erc20ActionProvider = () => new ERC20ActionProvider();
142
194
  exports.erc20ActionProvider = erc20ActionProvider;
@@ -2,8 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const erc20ActionProvider_1 = require("./erc20ActionProvider");
4
4
  const schemas_1 = require("./schemas");
5
- const viem_1 = require("viem");
6
- const constants_1 = require("./constants");
7
5
  const MOCK_AMOUNT = 15;
8
6
  const MOCK_DECIMALS = 6;
9
7
  const MOCK_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890";
@@ -12,9 +10,9 @@ const MOCK_ADDRESS = "0x1234567890123456789012345678901234567890";
12
10
  describe("Transfer Schema", () => {
13
11
  it("should successfully parse valid input", () => {
14
12
  const validInput = {
15
- amount: MOCK_AMOUNT,
16
- contractAddress: MOCK_CONTRACT_ADDRESS,
17
- destination: MOCK_DESTINATION,
13
+ amount: MOCK_AMOUNT.toString(),
14
+ tokenAddress: MOCK_CONTRACT_ADDRESS,
15
+ destinationAddress: MOCK_DESTINATION,
18
16
  };
19
17
  const result = schemas_1.TransferSchema.safeParse(validInput);
20
18
  expect(result.success).toBe(true);
@@ -28,49 +26,53 @@ describe("Transfer Schema", () => {
28
26
  });
29
27
  describe("Get Balance Action", () => {
30
28
  let mockWallet;
29
+ let mockMulticall;
31
30
  const actionProvider = (0, erc20ActionProvider_1.erc20ActionProvider)();
32
31
  beforeEach(async () => {
32
+ mockMulticall = jest.fn();
33
+ const mockPublicClient = {
34
+ multicall: mockMulticall,
35
+ getCode: jest.fn().mockResolvedValue("0x"),
36
+ };
33
37
  mockWallet = {
34
38
  getAddress: jest.fn().mockReturnValue(MOCK_ADDRESS),
35
- readContract: jest.fn(),
39
+ getPublicClient: jest.fn().mockReturnValue(mockPublicClient),
36
40
  };
37
41
  });
38
42
  it("should successfully respond", async () => {
39
- mockWallet.readContract.mockResolvedValueOnce(MOCK_AMOUNT);
40
- mockWallet.readContract.mockResolvedValueOnce(MOCK_DECIMALS);
43
+ mockMulticall.mockResolvedValueOnce([
44
+ { result: "MockToken" }, // name
45
+ { result: MOCK_DECIMALS }, // decimals
46
+ { result: BigInt(MOCK_AMOUNT * 10 ** MOCK_DECIMALS) }, // balance
47
+ ]);
41
48
  const args = {
42
- contractAddress: MOCK_CONTRACT_ADDRESS,
49
+ tokenAddress: MOCK_CONTRACT_ADDRESS,
43
50
  };
44
51
  const response = await actionProvider.getBalance(mockWallet, args);
45
- expect(mockWallet.readContract).toHaveBeenCalledWith({
46
- address: args.contractAddress,
47
- abi: constants_1.abi,
48
- functionName: "balanceOf",
49
- args: [mockWallet.getAddress()],
50
- });
51
- expect(response).toContain(`Balance of ${MOCK_CONTRACT_ADDRESS} is ${MOCK_AMOUNT / 10 ** MOCK_DECIMALS}`);
52
+ expect(mockMulticall).toHaveBeenCalled();
53
+ expect(response).toContain(`Balance of MockToken (${MOCK_CONTRACT_ADDRESS}) at address ${MOCK_ADDRESS} is ${MOCK_AMOUNT}`);
52
54
  });
53
55
  it("should fail with an error", async () => {
54
56
  const args = {
55
- contractAddress: MOCK_CONTRACT_ADDRESS,
57
+ tokenAddress: MOCK_CONTRACT_ADDRESS,
56
58
  };
57
- const error = new Error("Failed to get balance");
58
- mockWallet.readContract.mockRejectedValue(error);
59
+ mockMulticall.mockRejectedValue(new Error("Failed to get balance"));
59
60
  const response = await actionProvider.getBalance(mockWallet, args);
60
- expect(mockWallet.readContract).toHaveBeenCalledWith({
61
- address: args.contractAddress,
62
- abi: constants_1.abi,
63
- functionName: "balanceOf",
64
- args: [mockWallet.getAddress()],
65
- });
66
- expect(response).toContain(`Error getting balance: ${error}`);
61
+ expect(mockMulticall).toHaveBeenCalled();
62
+ expect(response).toContain("Error: Could not fetch token details");
67
63
  });
68
64
  });
69
65
  describe("Transfer Action", () => {
70
66
  const TRANSACTION_HASH = "0xghijkl987654321";
71
67
  let mockWallet;
68
+ let mockMulticall;
72
69
  const actionProvider = (0, erc20ActionProvider_1.erc20ActionProvider)();
73
70
  beforeEach(async () => {
71
+ mockMulticall = jest.fn();
72
+ const mockPublicClient = {
73
+ multicall: mockMulticall,
74
+ getCode: jest.fn().mockResolvedValue("0x"),
75
+ };
74
76
  mockWallet = {
75
77
  sendTransaction: jest.fn(),
76
78
  waitForTransactionReceipt: jest.fn(),
@@ -78,47 +80,40 @@ describe("Transfer Action", () => {
78
80
  getNetwork: jest.fn().mockReturnValue({
79
81
  networkId: "base-mainnet",
80
82
  }),
83
+ getPublicClient: jest.fn().mockReturnValue(mockPublicClient),
84
+ getAddress: jest.fn().mockReturnValue(MOCK_ADDRESS),
81
85
  };
82
86
  mockWallet.sendTransaction.mockResolvedValue(TRANSACTION_HASH);
83
87
  mockWallet.waitForTransactionReceipt.mockResolvedValue({});
84
88
  });
85
89
  it("should successfully respond", async () => {
90
+ mockMulticall.mockResolvedValueOnce([
91
+ { result: "MockToken" }, // name
92
+ { result: MOCK_DECIMALS }, // decimals
93
+ { result: BigInt(100000 * 10 ** MOCK_DECIMALS) }, // balance
94
+ ]);
86
95
  const args = {
87
- amount: BigInt(MOCK_AMOUNT),
88
- contractAddress: MOCK_CONTRACT_ADDRESS,
89
- destination: MOCK_DESTINATION,
96
+ amount: MOCK_AMOUNT.toString(),
97
+ tokenAddress: MOCK_CONTRACT_ADDRESS,
98
+ destinationAddress: MOCK_DESTINATION,
90
99
  };
91
100
  const response = await actionProvider.transfer(mockWallet, args);
92
- expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
93
- to: args.contractAddress,
94
- data: (0, viem_1.encodeFunctionData)({
95
- abi: constants_1.abi,
96
- functionName: "transfer",
97
- args: [args.destination, BigInt(args.amount)],
98
- }),
99
- });
101
+ expect(mockMulticall).toHaveBeenCalled();
102
+ expect(mockWallet.sendTransaction).toHaveBeenCalled();
100
103
  expect(mockWallet.waitForTransactionReceipt).toHaveBeenCalledWith(TRANSACTION_HASH);
101
- expect(response).toContain(`Transferred ${MOCK_AMOUNT} of ${MOCK_CONTRACT_ADDRESS} to ${MOCK_DESTINATION}`);
104
+ expect(response).toContain(`Transferred ${MOCK_AMOUNT} of MockToken (${MOCK_CONTRACT_ADDRESS}) to ${MOCK_DESTINATION}`);
102
105
  expect(response).toContain(`Transaction hash for the transfer: ${TRANSACTION_HASH}`);
103
106
  });
104
107
  it("should fail with an error", async () => {
108
+ mockMulticall.mockRejectedValue(new Error("Failed to get token details"));
105
109
  const args = {
106
- amount: BigInt(MOCK_AMOUNT),
107
- contractAddress: MOCK_CONTRACT_ADDRESS,
108
- destination: MOCK_DESTINATION,
110
+ amount: MOCK_AMOUNT.toString(),
111
+ tokenAddress: MOCK_CONTRACT_ADDRESS,
112
+ destinationAddress: MOCK_DESTINATION,
109
113
  };
110
- const error = new Error("Failed to execute transfer");
111
- mockWallet.sendTransaction.mockRejectedValue(error);
112
114
  const response = await actionProvider.transfer(mockWallet, args);
113
- expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
114
- to: args.contractAddress,
115
- data: (0, viem_1.encodeFunctionData)({
116
- abi: constants_1.abi,
117
- functionName: "transfer",
118
- args: [args.destination, BigInt(args.amount)],
119
- }),
120
- });
121
- expect(response).toContain(`Error transferring the asset: ${error}`);
115
+ expect(mockMulticall).toHaveBeenCalled();
116
+ expect(response).toContain("Error: Could not fetch token details");
122
117
  });
123
118
  describe("supportsNetwork", () => {
124
119
  it("should return true when protocolFamily is evm", () => {
@@ -129,3 +124,71 @@ describe("Transfer Action", () => {
129
124
  });
130
125
  });
131
126
  });
127
+ describe("GetTokenAddress Schema", () => {
128
+ it("should successfully parse valid token symbol", () => {
129
+ const validInput = { symbol: "usdc" };
130
+ const result = schemas_1.GetTokenAddressSchema.safeParse(validInput);
131
+ expect(result.success).toBe(true);
132
+ expect(result.data?.symbol).toBe("USDC"); // Should be uppercase
133
+ });
134
+ it("should fail parsing empty symbol", () => {
135
+ const emptyInput = { symbol: "" };
136
+ const result = schemas_1.GetTokenAddressSchema.safeParse(emptyInput);
137
+ expect(result.success).toBe(false);
138
+ });
139
+ it("should fail parsing symbol too long", () => {
140
+ const longInput = { symbol: "VERYLONGTOKENSYMBOL" };
141
+ const result = schemas_1.GetTokenAddressSchema.safeParse(longInput);
142
+ expect(result.success).toBe(false);
143
+ });
144
+ });
145
+ describe("Get Token Address Action", () => {
146
+ let mockWallet;
147
+ const actionProvider = (0, erc20ActionProvider_1.erc20ActionProvider)();
148
+ beforeEach(() => {
149
+ mockWallet = {
150
+ getNetwork: jest.fn(),
151
+ };
152
+ });
153
+ it("should return token address for valid symbol on base-mainnet", async () => {
154
+ mockWallet.getNetwork.mockReturnValue({
155
+ protocolFamily: "evm",
156
+ networkId: "base-mainnet",
157
+ });
158
+ const response = await actionProvider.getTokenAddress(mockWallet, { symbol: "USDC" });
159
+ expect(response).toContain("Token address for USDC on base-mainnet: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913");
160
+ });
161
+ it("should return token address for valid symbol on base-sepolia", async () => {
162
+ mockWallet.getNetwork.mockReturnValue({
163
+ protocolFamily: "evm",
164
+ networkId: "base-sepolia",
165
+ });
166
+ const response = await actionProvider.getTokenAddress(mockWallet, { symbol: "EURC" });
167
+ expect(response).toContain("Token address for EURC on base-sepolia: 0x808456652fdb597867f38412077A9182bf77359F");
168
+ });
169
+ it("should return error for unsupported network", async () => {
170
+ mockWallet.getNetwork.mockReturnValue({
171
+ protocolFamily: "evm",
172
+ networkId: "unsupported-network",
173
+ });
174
+ const response = await actionProvider.getTokenAddress(mockWallet, { symbol: "USDC" });
175
+ expect(response).toContain('Error: Token symbol "USDC" not found on unsupported-network');
176
+ });
177
+ it("should return error for unknown token symbol", async () => {
178
+ mockWallet.getNetwork.mockReturnValue({
179
+ protocolFamily: "evm",
180
+ networkId: "base-mainnet",
181
+ });
182
+ const response = await actionProvider.getTokenAddress(mockWallet, { symbol: "UNKNOWN" });
183
+ expect(response).toContain('Error: Token symbol "UNKNOWN" not found on base-mainnet');
184
+ expect(response).toContain('Error: Token symbol "UNKNOWN" not found on base-mainnet');
185
+ });
186
+ it("should return error when network ID is not available", async () => {
187
+ mockWallet.getNetwork.mockReturnValue({
188
+ protocolFamily: "evm",
189
+ // networkId is undefined
190
+ });
191
+ const response = await actionProvider.getTokenAddress(mockWallet, { symbol: "USDC" });
192
+ expect(response).toContain('Error: Token symbol "USDC" not found on undefined');
193
+ });
194
+ });