@coinbase/agentkit 0.2.3-nightly.20250325.54 → 0.2.3-nightly.20250326.56
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.
- package/README.md +13 -0
- package/dist/action-providers/across/acrossActionProvider.d.ts +50 -0
- package/dist/action-providers/across/acrossActionProvider.js +333 -0
- package/dist/action-providers/across/acrossActionProvider.test.d.ts +1 -0
- package/dist/action-providers/across/acrossActionProvider.test.js +391 -0
- package/dist/action-providers/across/constants.d.ts +1 -0
- package/dist/action-providers/across/constants.js +2 -0
- package/dist/action-providers/across/index.d.ts +1 -0
- package/dist/action-providers/across/index.js +17 -0
- package/dist/action-providers/across/schemas.d.ts +36 -0
- package/dist/action-providers/across/schemas.js +46 -0
- package/dist/action-providers/across/utils.d.ts +7 -0
- package/dist/action-providers/across/utils.js +25 -0
- package/dist/action-providers/index.d.ts +1 -0
- package/dist/action-providers/index.js +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -137,6 +137,19 @@ const agent = createReactAgent({
|
|
|
137
137
|
|
|
138
138
|
## Action Providers
|
|
139
139
|
<details>
|
|
140
|
+
<summary><strong>Across</strong></summary>
|
|
141
|
+
<table width="100%">
|
|
142
|
+
<tr>
|
|
143
|
+
<td width="200"><code>bridge_token</code></td>
|
|
144
|
+
<td width="768">Bridges tokens between supported chains using Across Protocol.</td>
|
|
145
|
+
</tr>
|
|
146
|
+
<tr>
|
|
147
|
+
<td width="200"><code>check_deposit_status</code></td>
|
|
148
|
+
<td width="768">Checks the status of a cross-chain bridge deposit on the Across Protocol (mainnet networks only).</td>
|
|
149
|
+
</tr>
|
|
150
|
+
</table>
|
|
151
|
+
</details>
|
|
152
|
+
<details>
|
|
140
153
|
<summary><strong>Basename</strong></summary>
|
|
141
154
|
<table width="100%">
|
|
142
155
|
<tr>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ActionProvider } from "../actionProvider";
|
|
3
|
+
import { Network } from "../../network";
|
|
4
|
+
import { BridgeTokenSchema, CheckDepositStatusSchema } from "./schemas";
|
|
5
|
+
import { EvmWalletProvider } from "../../wallet-providers";
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for the SafeWalletProvider.
|
|
8
|
+
*/
|
|
9
|
+
export interface AcrossActionProviderConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Private key of the wallet provider
|
|
12
|
+
*/
|
|
13
|
+
privateKey: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* AcrossActionProvider provides actions for cross-chain bridging via Across Protocol.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AcrossActionProvider extends ActionProvider<EvmWalletProvider> {
|
|
19
|
+
#private;
|
|
20
|
+
/**
|
|
21
|
+
* Constructor for the AcrossActionProvider.
|
|
22
|
+
*
|
|
23
|
+
* @param config - The configuration options for the AcrossActionProvider.
|
|
24
|
+
*/
|
|
25
|
+
constructor(config: AcrossActionProviderConfig);
|
|
26
|
+
/**
|
|
27
|
+
* Bridges a token from one chain to another using Across Protocol.
|
|
28
|
+
*
|
|
29
|
+
* @param walletProvider - The wallet provider to use for the transaction.
|
|
30
|
+
* @param args - The input arguments for the action.
|
|
31
|
+
* @returns A message containing the bridge details.
|
|
32
|
+
*/
|
|
33
|
+
bridgeToken(walletProvider: EvmWalletProvider, args: z.infer<typeof BridgeTokenSchema>): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Checks the status of a bridge deposit via Across Protocol.
|
|
36
|
+
*
|
|
37
|
+
* @param walletProvider - The wallet provider to use for the transaction.
|
|
38
|
+
* @param args - The input arguments for the action.
|
|
39
|
+
* @returns A message containing the deposit status details.
|
|
40
|
+
*/
|
|
41
|
+
checkDepositStatus(walletProvider: EvmWalletProvider, args: z.infer<typeof CheckDepositStatusSchema>): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Checks if the Across action provider supports the given network.
|
|
44
|
+
*
|
|
45
|
+
* @param network - The network to check.
|
|
46
|
+
* @returns True if the Across action provider supports the network, false otherwise.
|
|
47
|
+
*/
|
|
48
|
+
supportsNetwork: (network: Network) => boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare const acrossActionProvider: (config: AcrossActionProviderConfig) => AcrossActionProvider;
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
15
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
|
+
};
|
|
17
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
18
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
19
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
20
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
|
+
};
|
|
22
|
+
var _AcrossActionProvider_privateKey;
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.acrossActionProvider = exports.AcrossActionProvider = void 0;
|
|
25
|
+
const zod_1 = require("zod");
|
|
26
|
+
const viem_1 = require("viem");
|
|
27
|
+
const actionProvider_1 = require("../actionProvider");
|
|
28
|
+
const network_1 = require("../../network");
|
|
29
|
+
const actionDecorator_1 = require("../actionDecorator");
|
|
30
|
+
const schemas_1 = require("./schemas");
|
|
31
|
+
const wallet_providers_1 = require("../../wallet-providers");
|
|
32
|
+
const utils_1 = require("./utils");
|
|
33
|
+
const accounts_1 = require("viem/accounts");
|
|
34
|
+
const constants_1 = require("../erc20/constants");
|
|
35
|
+
/**
|
|
36
|
+
* AcrossActionProvider provides actions for cross-chain bridging via Across Protocol.
|
|
37
|
+
*/
|
|
38
|
+
class AcrossActionProvider extends actionProvider_1.ActionProvider {
|
|
39
|
+
/**
|
|
40
|
+
* Constructor for the AcrossActionProvider.
|
|
41
|
+
*
|
|
42
|
+
* @param config - The configuration options for the AcrossActionProvider.
|
|
43
|
+
*/
|
|
44
|
+
constructor(config) {
|
|
45
|
+
super("across", []);
|
|
46
|
+
_AcrossActionProvider_privateKey.set(this, void 0);
|
|
47
|
+
/**
|
|
48
|
+
* Checks if the Across action provider supports the given network.
|
|
49
|
+
*
|
|
50
|
+
* @param network - The network to check.
|
|
51
|
+
* @returns True if the Across action provider supports the network, false otherwise.
|
|
52
|
+
*/
|
|
53
|
+
this.supportsNetwork = (network) => {
|
|
54
|
+
// Across only supports EVM-compatible chains
|
|
55
|
+
return network.protocolFamily === "evm";
|
|
56
|
+
};
|
|
57
|
+
__classPrivateFieldSet(this, _AcrossActionProvider_privateKey, config.privateKey, "f");
|
|
58
|
+
const account = (0, accounts_1.privateKeyToAccount)(__classPrivateFieldGet(this, _AcrossActionProvider_privateKey, "f"));
|
|
59
|
+
if (!account)
|
|
60
|
+
throw new Error("Invalid private key");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Bridges a token from one chain to another using Across Protocol.
|
|
64
|
+
*
|
|
65
|
+
* @param walletProvider - The wallet provider to use for the transaction.
|
|
66
|
+
* @param args - The input arguments for the action.
|
|
67
|
+
* @returns A message containing the bridge details.
|
|
68
|
+
*/
|
|
69
|
+
async bridgeToken(walletProvider, args) {
|
|
70
|
+
try {
|
|
71
|
+
// Use dynamic import to get the Across SDK
|
|
72
|
+
const acrossModule = await import("@across-protocol/app-sdk");
|
|
73
|
+
const createAcrossClient = acrossModule.createAcrossClient;
|
|
74
|
+
// Get recipient address if provided, otherwise use sender
|
|
75
|
+
const address = walletProvider.getAddress();
|
|
76
|
+
const recipient = (args.recipient || address);
|
|
77
|
+
// Get origin chain
|
|
78
|
+
const originChain = (0, network_1.getChain)(walletProvider.getNetwork().chainId);
|
|
79
|
+
if (!originChain) {
|
|
80
|
+
throw new Error(`Unsupported origin chain: ${walletProvider.getNetwork()}`);
|
|
81
|
+
}
|
|
82
|
+
// Get destination chain
|
|
83
|
+
const destinationNetworkId = network_1.CHAIN_ID_TO_NETWORK_ID[Number(args.destinationChainId)];
|
|
84
|
+
const destinationChain = network_1.NETWORK_ID_TO_VIEM_CHAIN[destinationNetworkId];
|
|
85
|
+
if (!destinationChain) {
|
|
86
|
+
throw new Error(`Unsupported destination chain: ${args.destinationChainId}`);
|
|
87
|
+
}
|
|
88
|
+
// Sanity checks
|
|
89
|
+
if (originChain.id === destinationChain.id) {
|
|
90
|
+
throw new Error("Origin and destination chains cannot be the same");
|
|
91
|
+
}
|
|
92
|
+
const useTestnet = (0, utils_1.isAcrossSupportedTestnet)(originChain.id);
|
|
93
|
+
if (useTestnet !== (0, utils_1.isAcrossSupportedTestnet)(destinationChain.id)) {
|
|
94
|
+
throw new Error(`Cross-chain transfers between ${originChain.name} and ${destinationChain.name} are not supported.
|
|
95
|
+
Origin and destination chains must either be both testnets or both mainnets.`);
|
|
96
|
+
}
|
|
97
|
+
// Create wallet client
|
|
98
|
+
const account = (0, accounts_1.privateKeyToAccount)(__classPrivateFieldGet(this, _AcrossActionProvider_privateKey, "f"));
|
|
99
|
+
if (account.address !== walletProvider.getAddress()) {
|
|
100
|
+
throw new Error("Private key does not match wallet provider address");
|
|
101
|
+
}
|
|
102
|
+
const walletClient = (0, viem_1.createWalletClient)({
|
|
103
|
+
account,
|
|
104
|
+
chain: originChain,
|
|
105
|
+
transport: (0, viem_1.http)(),
|
|
106
|
+
});
|
|
107
|
+
// Create Across client
|
|
108
|
+
const acrossClient = createAcrossClient({
|
|
109
|
+
chains: [originChain, destinationChain],
|
|
110
|
+
useTestnet,
|
|
111
|
+
});
|
|
112
|
+
// Get chain details to find token information
|
|
113
|
+
const chainDetails = await acrossClient.getSupportedChains({});
|
|
114
|
+
const originChainDetails = chainDetails.find(chain => chain.chainId === originChain.id);
|
|
115
|
+
if (!originChainDetails) {
|
|
116
|
+
throw new Error(`Origin chain ${originChain.id} not supported by Across Protocol`);
|
|
117
|
+
}
|
|
118
|
+
// Find token by symbol on the origin chain
|
|
119
|
+
const inputTokens = originChainDetails.inputTokens;
|
|
120
|
+
if (!inputTokens || inputTokens.length === 0) {
|
|
121
|
+
throw new Error(`No input tokens available on chain ${originChain.id}`);
|
|
122
|
+
}
|
|
123
|
+
const tokenInfo = inputTokens.find(token => token.symbol.toUpperCase() === args.inputTokenSymbol.toUpperCase());
|
|
124
|
+
if (!tokenInfo) {
|
|
125
|
+
throw new Error(`Token ${args.inputTokenSymbol} not found on chain ${originChain.id}. Available tokens: ${inputTokens.map(t => t.symbol).join(", ")}`);
|
|
126
|
+
}
|
|
127
|
+
// Get token address and decimals to parse the amount
|
|
128
|
+
const inputToken = tokenInfo.address;
|
|
129
|
+
const decimals = tokenInfo.decimals;
|
|
130
|
+
const inputAmount = (0, viem_1.parseUnits)(args.amount, decimals);
|
|
131
|
+
// Check balance
|
|
132
|
+
const isNative = args.inputTokenSymbol.toUpperCase() === "ETH";
|
|
133
|
+
if (isNative) {
|
|
134
|
+
// Check native ETH balance
|
|
135
|
+
const ethBalance = await walletProvider.getBalance();
|
|
136
|
+
if (ethBalance < inputAmount) {
|
|
137
|
+
throw new Error(`Insufficient balance. Requested to bridge ${(0, viem_1.formatUnits)(inputAmount, decimals)} ${args.inputTokenSymbol} but balance is only ${(0, viem_1.formatUnits)(ethBalance, decimals)} ${args.inputTokenSymbol}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Check ERC20 token balance
|
|
142
|
+
const tokenBalance = (await walletProvider.readContract({
|
|
143
|
+
address: inputToken,
|
|
144
|
+
abi: constants_1.abi,
|
|
145
|
+
functionName: "balanceOf",
|
|
146
|
+
args: [address],
|
|
147
|
+
}));
|
|
148
|
+
if (tokenBalance < inputAmount) {
|
|
149
|
+
throw new Error(`Insufficient balance. Requested to bridge ${(0, viem_1.formatUnits)(inputAmount, decimals)} ${args.inputTokenSymbol} but balance is only ${(0, viem_1.formatUnits)(tokenBalance, decimals)} ${args.inputTokenSymbol}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Get available routes
|
|
153
|
+
const routeInfo = await acrossClient.getAvailableRoutes({
|
|
154
|
+
originChainId: originChain.id,
|
|
155
|
+
destinationChainId: destinationChain.id,
|
|
156
|
+
originToken: inputToken,
|
|
157
|
+
});
|
|
158
|
+
// Select the appropriate route for native ETH or ERC20 token
|
|
159
|
+
const route = routeInfo.find(route => route.isNative === isNative);
|
|
160
|
+
if (!route) {
|
|
161
|
+
throw new Error(`No routes available from chain ${originChain.name} to chain ${destinationChain.name} for token ${args.inputTokenSymbol}`);
|
|
162
|
+
}
|
|
163
|
+
// Get quote
|
|
164
|
+
const quote = await acrossClient.getQuote({
|
|
165
|
+
route,
|
|
166
|
+
inputAmount,
|
|
167
|
+
recipient,
|
|
168
|
+
});
|
|
169
|
+
// Convert units to readable format
|
|
170
|
+
const formattedInfo = {
|
|
171
|
+
minDeposit: (0, viem_1.formatUnits)(quote.limits.minDeposit, decimals),
|
|
172
|
+
maxDeposit: (0, viem_1.formatUnits)(quote.limits.maxDeposit, decimals),
|
|
173
|
+
inputAmount: (0, viem_1.formatUnits)(quote.deposit.inputAmount, decimals),
|
|
174
|
+
outputAmount: (0, viem_1.formatUnits)(quote.deposit.outputAmount, decimals),
|
|
175
|
+
};
|
|
176
|
+
// Check if input amount is within valid deposit range
|
|
177
|
+
if (quote.deposit.inputAmount < quote.limits.minDeposit) {
|
|
178
|
+
throw new Error(`Input amount ${formattedInfo.inputAmount} ${args.inputTokenSymbol} is below the minimum deposit of ${formattedInfo.minDeposit} ${args.inputTokenSymbol}`);
|
|
179
|
+
}
|
|
180
|
+
if (quote.deposit.inputAmount > quote.limits.maxDeposit) {
|
|
181
|
+
throw new Error(`Input amount ${formattedInfo.inputAmount} ${args.inputTokenSymbol} exceeds the maximum deposit of ${formattedInfo.maxDeposit} ${args.inputTokenSymbol}`);
|
|
182
|
+
}
|
|
183
|
+
// Check if output amount is within acceptable slippage limits
|
|
184
|
+
const actualSlippagePercentage = ((Number(formattedInfo.inputAmount) - Number(formattedInfo.outputAmount)) /
|
|
185
|
+
Number(formattedInfo.inputAmount)) *
|
|
186
|
+
100;
|
|
187
|
+
if (actualSlippagePercentage > args.maxSplippage) {
|
|
188
|
+
throw new Error(`Output amount has high slippage of ${actualSlippagePercentage.toFixed(2)}%, which exceeds the maximum allowed slippage of ${args.maxSplippage}%. ` +
|
|
189
|
+
`Input: ${formattedInfo.inputAmount} ${args.inputTokenSymbol}, Output: ${formattedInfo.outputAmount} ${args.inputTokenSymbol}`);
|
|
190
|
+
}
|
|
191
|
+
//Approve ERC20 token if needed
|
|
192
|
+
let approvalTxHash;
|
|
193
|
+
if (!isNative) {
|
|
194
|
+
approvalTxHash = await walletProvider.sendTransaction({
|
|
195
|
+
to: inputToken,
|
|
196
|
+
data: (0, viem_1.encodeFunctionData)({
|
|
197
|
+
abi: constants_1.abi,
|
|
198
|
+
functionName: "approve",
|
|
199
|
+
args: [quote.deposit.spokePoolAddress, quote.deposit.inputAmount],
|
|
200
|
+
}),
|
|
201
|
+
});
|
|
202
|
+
await walletProvider.waitForTransactionReceipt(approvalTxHash);
|
|
203
|
+
}
|
|
204
|
+
// Simulate the deposit transaction
|
|
205
|
+
const { request } = await acrossClient.simulateDepositTx({
|
|
206
|
+
walletClient: walletClient,
|
|
207
|
+
deposit: quote.deposit,
|
|
208
|
+
});
|
|
209
|
+
// Execute the deposit transaction
|
|
210
|
+
const transactionHash = await walletClient.writeContract(request);
|
|
211
|
+
// Wait for tx to be mined
|
|
212
|
+
const { depositId } = await acrossClient.waitForDepositTx({
|
|
213
|
+
transactionHash,
|
|
214
|
+
originChainId: originChain.id,
|
|
215
|
+
});
|
|
216
|
+
return `
|
|
217
|
+
Successfully deposited tokens:
|
|
218
|
+
- From: Chain ${originChain.id} (${originChain.name})
|
|
219
|
+
- To: Chain ${destinationChain.id} (${destinationChain.name})
|
|
220
|
+
- Token: ${args.inputTokenSymbol} (${inputToken})
|
|
221
|
+
- Input Amount: ${formattedInfo.inputAmount} ${args.inputTokenSymbol}
|
|
222
|
+
- Output Amount: ${formattedInfo.outputAmount} ${args.inputTokenSymbol}
|
|
223
|
+
- Recipient: ${recipient}
|
|
224
|
+
${!isNative ? `- Transaction Hash for approval: ${approvalTxHash}\n` : ""}
|
|
225
|
+
- Transaction Hash for deposit: ${transactionHash}
|
|
226
|
+
- Deposit ID: ${depositId}
|
|
227
|
+
`;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return `Error with Across SDK: ${error}`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Checks the status of a bridge deposit via Across Protocol.
|
|
235
|
+
*
|
|
236
|
+
* @param walletProvider - The wallet provider to use for the transaction.
|
|
237
|
+
* @param args - The input arguments for the action.
|
|
238
|
+
* @returns A message containing the deposit status details.
|
|
239
|
+
*/
|
|
240
|
+
async checkDepositStatus(walletProvider, args) {
|
|
241
|
+
const originChainId = Number(args.originChainId) || Number(walletProvider.getNetwork().chainId);
|
|
242
|
+
if ((0, utils_1.isAcrossSupportedTestnet)(originChainId)) {
|
|
243
|
+
throw new Error("Checking deposit status on testnets is currently not supported by the Across API");
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const response = await fetch(`https://app.across.to/api/deposit/status?originChainId=${originChainId}&depositId=${args.depositId}`, {
|
|
247
|
+
method: "GET",
|
|
248
|
+
});
|
|
249
|
+
if (!response.ok) {
|
|
250
|
+
throw new Error(`Across API request failed with status ${response.status}`);
|
|
251
|
+
}
|
|
252
|
+
const apiData = await response.json();
|
|
253
|
+
// Get chain names
|
|
254
|
+
const originChainName = (0, network_1.getChain)(String(apiData.originChainId))?.name || "Unknown Chain";
|
|
255
|
+
const destinationChainName = (0, network_1.getChain)(String(apiData.destinationChainId))?.name || "Unknown Chain";
|
|
256
|
+
// Create structured response
|
|
257
|
+
const structuredResponse = {
|
|
258
|
+
status: apiData.status || "unknown",
|
|
259
|
+
depositTxInfo: apiData.depositTxHash
|
|
260
|
+
? {
|
|
261
|
+
txHash: apiData.depositTxHash,
|
|
262
|
+
chainId: apiData.originChainId,
|
|
263
|
+
chainName: originChainName,
|
|
264
|
+
}
|
|
265
|
+
: null,
|
|
266
|
+
fillTxInfo: apiData.fillTx
|
|
267
|
+
? {
|
|
268
|
+
txHash: apiData.fillTx,
|
|
269
|
+
chainId: apiData.destinationChainId,
|
|
270
|
+
chainName: destinationChainName,
|
|
271
|
+
}
|
|
272
|
+
: null,
|
|
273
|
+
depositRefundTxInfo: apiData.depositRefundTxHash
|
|
274
|
+
? {
|
|
275
|
+
txHash: apiData.depositRefundTxHash,
|
|
276
|
+
chainId: apiData.originChainId,
|
|
277
|
+
chainName: originChainName,
|
|
278
|
+
}
|
|
279
|
+
: null,
|
|
280
|
+
};
|
|
281
|
+
return JSON.stringify(structuredResponse, null, 2);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
return `Error checking deposit status: ${error}`;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
exports.AcrossActionProvider = AcrossActionProvider;
|
|
289
|
+
_AcrossActionProvider_privateKey = new WeakMap();
|
|
290
|
+
__decorate([
|
|
291
|
+
(0, actionDecorator_1.CreateAction)({
|
|
292
|
+
name: "bridge_token",
|
|
293
|
+
description: `
|
|
294
|
+
This tool will bridge tokens from the current chain to another chain using the Across Protocol.
|
|
295
|
+
|
|
296
|
+
It takes the following inputs:
|
|
297
|
+
- destinationChainId: The chain ID of the destination chain (e.g. 8453 for base-mainnet)
|
|
298
|
+
- inputTokenSymbol: The symbol of the token to bridge (e.g. 'ETH', 'USDC')
|
|
299
|
+
- amount: The amount of tokens to bridge in whole units (e.g. 1.5 WETH, 10 USDC)
|
|
300
|
+
- recipient: (Optional) The recipient address on the destination chain (defaults to sender)
|
|
301
|
+
- maxSplippage: (Optional) The maximum slippage percentage (defaults to 1.5%)
|
|
302
|
+
|
|
303
|
+
Important notes:
|
|
304
|
+
- Origin chain is the currently connected chain of the wallet provider
|
|
305
|
+
- Supports cross-chain transfers between EVM-compatible chains for both mainnets and test networks
|
|
306
|
+
- Testnet deposits are not refunded if not filled on destination chain
|
|
307
|
+
- Ensure sufficient balance of the input token before bridging
|
|
308
|
+
- Returns deposit ID that can be used to check the status of the deposit
|
|
309
|
+
`,
|
|
310
|
+
schema: schemas_1.BridgeTokenSchema,
|
|
311
|
+
}),
|
|
312
|
+
__metadata("design:type", Function),
|
|
313
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
314
|
+
__metadata("design:returntype", Promise)
|
|
315
|
+
], AcrossActionProvider.prototype, "bridgeToken", null);
|
|
316
|
+
__decorate([
|
|
317
|
+
(0, actionDecorator_1.CreateAction)({
|
|
318
|
+
name: "check_deposit_status",
|
|
319
|
+
description: `
|
|
320
|
+
This tool will check the status of a cross-chain bridge deposit on the Across Protocol.
|
|
321
|
+
|
|
322
|
+
It takes the following inputs:
|
|
323
|
+
- originChainId: The chain ID of the origin chain (defaults to the current chain)
|
|
324
|
+
- depositId: The ID of the deposit to check (returned by the bridge deposit transaction)
|
|
325
|
+
`,
|
|
326
|
+
schema: schemas_1.CheckDepositStatusSchema,
|
|
327
|
+
}),
|
|
328
|
+
__metadata("design:type", Function),
|
|
329
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
330
|
+
__metadata("design:returntype", Promise)
|
|
331
|
+
], AcrossActionProvider.prototype, "checkDepositStatus", null);
|
|
332
|
+
const acrossActionProvider = (config) => new AcrossActionProvider(config);
|
|
333
|
+
exports.acrossActionProvider = acrossActionProvider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const acrossActionProvider_1 = require("./acrossActionProvider");
|
|
4
|
+
const viem_1 = require("viem");
|
|
5
|
+
// Mock the necessary imports and modules
|
|
6
|
+
jest.mock("viem", () => {
|
|
7
|
+
return {
|
|
8
|
+
...jest.requireActual("viem"),
|
|
9
|
+
createPublicClient: jest.fn(),
|
|
10
|
+
createWalletClient: jest.fn(() => ({
|
|
11
|
+
writeContract: jest.fn().mockResolvedValue("0xdepositTxHash"),
|
|
12
|
+
})),
|
|
13
|
+
http: jest.fn(),
|
|
14
|
+
formatUnits: jest.fn().mockImplementation((value, decimals) => {
|
|
15
|
+
// Simple mock implementation just for testing
|
|
16
|
+
if (typeof value === "bigint") {
|
|
17
|
+
if (decimals === 18) {
|
|
18
|
+
return (Number(value) / 10 ** 18).toString();
|
|
19
|
+
}
|
|
20
|
+
return value.toString();
|
|
21
|
+
}
|
|
22
|
+
return value.toString();
|
|
23
|
+
}),
|
|
24
|
+
parseUnits: jest.fn().mockImplementation((value, decimals) => {
|
|
25
|
+
if (decimals === 18) {
|
|
26
|
+
return BigInt(Number(value) * 10 ** 18);
|
|
27
|
+
}
|
|
28
|
+
return BigInt(value);
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
jest.mock("viem/accounts", () => ({
|
|
33
|
+
privateKeyToAccount: jest.fn().mockReturnValue({
|
|
34
|
+
address: "0x9876543210987654321098765432109876543210",
|
|
35
|
+
}),
|
|
36
|
+
}));
|
|
37
|
+
// Mock the network module
|
|
38
|
+
jest.mock("../../network", () => {
|
|
39
|
+
return {
|
|
40
|
+
...jest.requireActual("../../network"),
|
|
41
|
+
NETWORK_ID_TO_VIEM_CHAIN: {
|
|
42
|
+
"ethereum-mainnet": {
|
|
43
|
+
id: 1,
|
|
44
|
+
name: "Ethereum",
|
|
45
|
+
network: "mainnet",
|
|
46
|
+
},
|
|
47
|
+
optimism: {
|
|
48
|
+
id: 10,
|
|
49
|
+
name: "Optimism",
|
|
50
|
+
network: "optimism",
|
|
51
|
+
},
|
|
52
|
+
"base-sepolia": {
|
|
53
|
+
id: 84532,
|
|
54
|
+
name: "Base Sepolia",
|
|
55
|
+
network: "base-sepolia",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
CHAIN_ID_TO_NETWORK_ID: {
|
|
59
|
+
"1": "ethereum-mainnet",
|
|
60
|
+
"10": "optimism",
|
|
61
|
+
"84532": "base-sepolia",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
// Mock the Across SDK
|
|
66
|
+
const mockCreateAcrossClient = jest.fn();
|
|
67
|
+
jest.mock("@across-protocol/app-sdk", () => ({
|
|
68
|
+
createAcrossClient: mockCreateAcrossClient,
|
|
69
|
+
}));
|
|
70
|
+
// Default implementation for the createAcrossClient mock
|
|
71
|
+
const defaultClientImplementation = () => ({
|
|
72
|
+
getSupportedChains: jest.fn().mockResolvedValue([
|
|
73
|
+
{
|
|
74
|
+
chainId: 1, // Ethereum
|
|
75
|
+
name: "Ethereum",
|
|
76
|
+
network: "mainnet",
|
|
77
|
+
inputTokens: [
|
|
78
|
+
{
|
|
79
|
+
symbol: "ETH",
|
|
80
|
+
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
81
|
+
decimals: 18,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
symbol: "USDC",
|
|
85
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
86
|
+
decimals: 6,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
chainId: 10, // Optimism
|
|
92
|
+
name: "Optimism",
|
|
93
|
+
network: "optimism",
|
|
94
|
+
inputTokens: [
|
|
95
|
+
{
|
|
96
|
+
symbol: "ETH",
|
|
97
|
+
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
98
|
+
decimals: 18,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
]),
|
|
103
|
+
getAvailableRoutes: jest.fn().mockResolvedValue([
|
|
104
|
+
{
|
|
105
|
+
isNative: true,
|
|
106
|
+
originToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
isNative: false,
|
|
110
|
+
originToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
111
|
+
},
|
|
112
|
+
]),
|
|
113
|
+
getQuote: jest.fn().mockResolvedValue({
|
|
114
|
+
deposit: {
|
|
115
|
+
inputAmount: BigInt("1000000000000000000"), // 1 ETH
|
|
116
|
+
outputAmount: BigInt("990000000000000000"), // 0.99 ETH (1% difference)
|
|
117
|
+
spokePoolAddress: "0x1234567890123456789012345678901234567890",
|
|
118
|
+
},
|
|
119
|
+
limits: {
|
|
120
|
+
minDeposit: BigInt("100000000000000000"), // 0.1 ETH
|
|
121
|
+
maxDeposit: BigInt("10000000000000000000"), // 10 ETH
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
simulateDepositTx: jest.fn().mockResolvedValue({
|
|
125
|
+
request: {
|
|
126
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
127
|
+
abi: [],
|
|
128
|
+
functionName: "deposit",
|
|
129
|
+
args: [],
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
waitForDepositTx: jest.fn().mockResolvedValue({
|
|
133
|
+
depositId: "123456",
|
|
134
|
+
}),
|
|
135
|
+
});
|
|
136
|
+
// Set the default implementation
|
|
137
|
+
mockCreateAcrossClient.mockImplementation(() => {
|
|
138
|
+
const client = defaultClientImplementation();
|
|
139
|
+
// Add the chains property to match what the code expects
|
|
140
|
+
return {
|
|
141
|
+
...client,
|
|
142
|
+
chains: [
|
|
143
|
+
{
|
|
144
|
+
id: 1,
|
|
145
|
+
name: "Ethereum",
|
|
146
|
+
network: "mainnet",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 10,
|
|
150
|
+
name: "Optimism",
|
|
151
|
+
network: "optimism",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
// Mock the isTestnet function
|
|
157
|
+
jest.mock("./utils", () => ({
|
|
158
|
+
isAcrossSupportedTestnet: jest.fn().mockReturnValue(false),
|
|
159
|
+
}));
|
|
160
|
+
describe("Across Action Provider", () => {
|
|
161
|
+
const MOCK_PRIVATE_KEY = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
162
|
+
const MOCK_INPUT_TOKEN_SYMBOL = "ETH";
|
|
163
|
+
const MOCK_AMOUNT = "1.0";
|
|
164
|
+
const MOCK_DESTINATION_CHAIN_ID = "10"; // Optimism
|
|
165
|
+
const MOCK_RECIPIENT = "0x9876543210987654321098765432109876543210";
|
|
166
|
+
const MOCK_MAX_SLIPPAGE = 2.0;
|
|
167
|
+
let mockWallet;
|
|
168
|
+
let actionProvider;
|
|
169
|
+
let mockPublicClient;
|
|
170
|
+
beforeEach(() => {
|
|
171
|
+
jest.clearAllMocks();
|
|
172
|
+
// Reset to default implementation
|
|
173
|
+
mockCreateAcrossClient.mockImplementation(() => {
|
|
174
|
+
const client = defaultClientImplementation();
|
|
175
|
+
// Add the chains property to match what the code expects
|
|
176
|
+
return {
|
|
177
|
+
...client,
|
|
178
|
+
chains: [
|
|
179
|
+
{
|
|
180
|
+
id: 1,
|
|
181
|
+
name: "Ethereum",
|
|
182
|
+
network: "mainnet",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 10,
|
|
186
|
+
name: "Optimism",
|
|
187
|
+
network: "optimism",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
mockPublicClient = {
|
|
193
|
+
getBalance: jest.fn().mockResolvedValue(BigInt("2000000000000000000")), // 2 ETH
|
|
194
|
+
readContract: jest.fn().mockResolvedValue(BigInt("2000000000000000000")), // 2 ETH or 2 USDC
|
|
195
|
+
waitForTransactionReceipt: jest.fn().mockResolvedValue({}),
|
|
196
|
+
};
|
|
197
|
+
viem_1.createPublicClient.mockReturnValue(mockPublicClient);
|
|
198
|
+
mockWallet = {
|
|
199
|
+
getAddress: jest.fn().mockReturnValue(MOCK_RECIPIENT),
|
|
200
|
+
sendTransaction: jest.fn().mockResolvedValue("0xmocktxhash"),
|
|
201
|
+
waitForTransactionReceipt: jest.fn(),
|
|
202
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
203
|
+
chainId: "1", // Ethereum mainnet
|
|
204
|
+
networkId: "ethereum-mainnet",
|
|
205
|
+
protocolFamily: "evm",
|
|
206
|
+
}),
|
|
207
|
+
getBalance: jest.fn().mockResolvedValue(BigInt("2000000000000000000")), // 2 ETH
|
|
208
|
+
readContract: jest.fn().mockResolvedValue(BigInt("2000000000000000000")), // 2 ETH/USDC
|
|
209
|
+
};
|
|
210
|
+
actionProvider = (0, acrossActionProvider_1.acrossActionProvider)({
|
|
211
|
+
privateKey: MOCK_PRIVATE_KEY,
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
describe("bridgeToken", () => {
|
|
215
|
+
it("should successfully bridge native ETH", async () => {
|
|
216
|
+
const args = {
|
|
217
|
+
inputTokenSymbol: MOCK_INPUT_TOKEN_SYMBOL,
|
|
218
|
+
amount: MOCK_AMOUNT,
|
|
219
|
+
destinationChainId: MOCK_DESTINATION_CHAIN_ID,
|
|
220
|
+
recipient: MOCK_RECIPIENT,
|
|
221
|
+
maxSplippage: MOCK_MAX_SLIPPAGE,
|
|
222
|
+
};
|
|
223
|
+
const response = await actionProvider.bridgeToken(mockWallet, args);
|
|
224
|
+
// Verify the SDK interactions and response
|
|
225
|
+
expect(response).toContain("Successfully deposited tokens");
|
|
226
|
+
expect(response).toContain(`Token: ${MOCK_INPUT_TOKEN_SYMBOL}`);
|
|
227
|
+
expect(response).toContain("Transaction Hash for deposit: 0xdepositTxHash");
|
|
228
|
+
});
|
|
229
|
+
it("should successfully bridge ERC20 tokens", async () => {
|
|
230
|
+
const args = {
|
|
231
|
+
inputTokenSymbol: "USDC",
|
|
232
|
+
amount: "100",
|
|
233
|
+
destinationChainId: MOCK_DESTINATION_CHAIN_ID,
|
|
234
|
+
recipient: MOCK_RECIPIENT,
|
|
235
|
+
maxSplippage: MOCK_MAX_SLIPPAGE,
|
|
236
|
+
};
|
|
237
|
+
// Set up mock for approval and deposit transactions
|
|
238
|
+
mockWallet.sendTransaction
|
|
239
|
+
.mockResolvedValueOnce("0xapprovalTxHash")
|
|
240
|
+
.mockResolvedValueOnce("0xdepositTxHash");
|
|
241
|
+
const response = await actionProvider.bridgeToken(mockWallet, args);
|
|
242
|
+
// Verify the SDK interactions and response
|
|
243
|
+
expect(response).toContain("Successfully deposited tokens");
|
|
244
|
+
expect(response).toContain(`Token: ${args.inputTokenSymbol}`);
|
|
245
|
+
expect(response).toContain("Transaction Hash for approval: 0xapprovalTxHash");
|
|
246
|
+
expect(response).toContain("Transaction Hash for deposit: 0xdepositTxHash");
|
|
247
|
+
});
|
|
248
|
+
it("should fail when slippage is too high", async () => {
|
|
249
|
+
// Override the default mock with high slippage for this test only
|
|
250
|
+
mockCreateAcrossClient.mockImplementationOnce(() => ({
|
|
251
|
+
getSupportedChains: jest.fn().mockResolvedValue([
|
|
252
|
+
{
|
|
253
|
+
chainId: 1,
|
|
254
|
+
inputTokens: [
|
|
255
|
+
{
|
|
256
|
+
symbol: "ETH",
|
|
257
|
+
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
258
|
+
decimals: 18,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
]),
|
|
263
|
+
getAvailableRoutes: jest.fn().mockResolvedValue([
|
|
264
|
+
{
|
|
265
|
+
isNative: true,
|
|
266
|
+
originToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
|
267
|
+
},
|
|
268
|
+
]),
|
|
269
|
+
getQuote: jest.fn().mockResolvedValue({
|
|
270
|
+
deposit: {
|
|
271
|
+
inputAmount: BigInt("1000000000000000000"), // 1 ETH
|
|
272
|
+
outputAmount: BigInt("800000000000000000"), // 0.8 ETH (20% difference)
|
|
273
|
+
spokePoolAddress: "0x1234567890123456789012345678901234567890",
|
|
274
|
+
},
|
|
275
|
+
limits: {
|
|
276
|
+
minDeposit: BigInt("100000000000000000"),
|
|
277
|
+
maxDeposit: BigInt("10000000000000000000"),
|
|
278
|
+
},
|
|
279
|
+
}),
|
|
280
|
+
simulateDepositTx: jest.fn().mockResolvedValue({
|
|
281
|
+
request: {
|
|
282
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
283
|
+
abi: [],
|
|
284
|
+
functionName: "deposit",
|
|
285
|
+
args: [],
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
288
|
+
waitForDepositTx: jest.fn().mockResolvedValue({
|
|
289
|
+
depositId: "123456",
|
|
290
|
+
}),
|
|
291
|
+
}));
|
|
292
|
+
// Set a low max slippage
|
|
293
|
+
const args = {
|
|
294
|
+
inputTokenSymbol: MOCK_INPUT_TOKEN_SYMBOL,
|
|
295
|
+
amount: MOCK_AMOUNT,
|
|
296
|
+
destinationChainId: MOCK_DESTINATION_CHAIN_ID,
|
|
297
|
+
recipient: MOCK_RECIPIENT,
|
|
298
|
+
maxSplippage: 0.5, // Only allow 0.5% slippage
|
|
299
|
+
};
|
|
300
|
+
const response = await actionProvider.bridgeToken(mockWallet, args);
|
|
301
|
+
// Verify the error response
|
|
302
|
+
expect(response).toContain("Error with Across SDK");
|
|
303
|
+
expect(response).toContain("exceeds the maximum allowed slippage of 0.5%");
|
|
304
|
+
});
|
|
305
|
+
it("should handle errors in bridging", async () => {
|
|
306
|
+
const error = new Error("Insufficient balance");
|
|
307
|
+
mockWallet.getBalance.mockRejectedValueOnce(error);
|
|
308
|
+
mockWallet.sendTransaction.mockRejectedValueOnce(error);
|
|
309
|
+
const args = {
|
|
310
|
+
inputTokenSymbol: MOCK_INPUT_TOKEN_SYMBOL,
|
|
311
|
+
amount: MOCK_AMOUNT,
|
|
312
|
+
destinationChainId: MOCK_DESTINATION_CHAIN_ID,
|
|
313
|
+
recipient: MOCK_RECIPIENT,
|
|
314
|
+
maxSplippage: MOCK_MAX_SLIPPAGE,
|
|
315
|
+
};
|
|
316
|
+
const response = await actionProvider.bridgeToken(mockWallet, args);
|
|
317
|
+
expect(response).toContain("Error with Across SDK");
|
|
318
|
+
expect(response).toContain(error.message);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
describe("checkDepositStatus", () => {
|
|
322
|
+
beforeEach(() => {
|
|
323
|
+
global.fetch = jest.fn();
|
|
324
|
+
});
|
|
325
|
+
it("should successfully check deposit status", async () => {
|
|
326
|
+
// Mock successful API response
|
|
327
|
+
const mockApiResponse = {
|
|
328
|
+
status: "filled",
|
|
329
|
+
originChainId: 1,
|
|
330
|
+
destinationChainId: 10,
|
|
331
|
+
depositTxHash: "0xdepositTxHash",
|
|
332
|
+
fillTx: "0xfillTxHash",
|
|
333
|
+
};
|
|
334
|
+
global.fetch.mockResolvedValueOnce({
|
|
335
|
+
ok: true,
|
|
336
|
+
json: async () => mockApiResponse,
|
|
337
|
+
});
|
|
338
|
+
const args = {
|
|
339
|
+
originChainId: "1",
|
|
340
|
+
depositId: "123456",
|
|
341
|
+
};
|
|
342
|
+
const response = await actionProvider.checkDepositStatus(mockWallet, args);
|
|
343
|
+
const parsedResponse = JSON.parse(response);
|
|
344
|
+
expect(parsedResponse.status).toEqual("filled");
|
|
345
|
+
expect(parsedResponse.depositTxInfo.txHash).toEqual("0xdepositTxHash");
|
|
346
|
+
expect(parsedResponse.fillTxInfo.txHash).toEqual("0xfillTxHash");
|
|
347
|
+
});
|
|
348
|
+
it("should handle API errors", async () => {
|
|
349
|
+
// Mock API error
|
|
350
|
+
global.fetch.mockResolvedValueOnce({
|
|
351
|
+
ok: false,
|
|
352
|
+
status: 404,
|
|
353
|
+
});
|
|
354
|
+
const args = {
|
|
355
|
+
originChainId: "1",
|
|
356
|
+
depositId: "123456",
|
|
357
|
+
};
|
|
358
|
+
const response = await actionProvider.checkDepositStatus(mockWallet, args);
|
|
359
|
+
expect(response).toContain("Error checking deposit status");
|
|
360
|
+
expect(response).toContain("404");
|
|
361
|
+
});
|
|
362
|
+
it("should handle network errors", async () => {
|
|
363
|
+
// Mock network error
|
|
364
|
+
global.fetch.mockRejectedValueOnce(new Error("Network error"));
|
|
365
|
+
const args = {
|
|
366
|
+
originChainId: "1",
|
|
367
|
+
depositId: "123456",
|
|
368
|
+
};
|
|
369
|
+
const response = await actionProvider.checkDepositStatus(mockWallet, args);
|
|
370
|
+
expect(response).toContain("Error checking deposit status");
|
|
371
|
+
expect(response).toContain("Network error");
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
describe("supportsNetwork", () => {
|
|
375
|
+
it("should return true for supported networks", () => {
|
|
376
|
+
const evmNetwork = {
|
|
377
|
+
protocolFamily: "evm",
|
|
378
|
+
networkId: "ethereum",
|
|
379
|
+
chainId: "1",
|
|
380
|
+
};
|
|
381
|
+
expect(actionProvider.supportsNetwork(evmNetwork)).toBe(true);
|
|
382
|
+
});
|
|
383
|
+
it("should return false for unsupported networks", () => {
|
|
384
|
+
const nonEvmNetwork = {
|
|
385
|
+
protocolFamily: "solana",
|
|
386
|
+
networkId: "mainnet",
|
|
387
|
+
};
|
|
388
|
+
expect(actionProvider.supportsNetwork(nonEvmNetwork)).toBe(false);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./acrossActionProvider";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./acrossActionProvider"), exports);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Input schema for bridge token action.
|
|
4
|
+
*/
|
|
5
|
+
export declare const BridgeTokenSchema: z.ZodObject<{
|
|
6
|
+
destinationChainId: z.ZodString;
|
|
7
|
+
inputTokenSymbol: z.ZodDefault<z.ZodString>;
|
|
8
|
+
amount: z.ZodString;
|
|
9
|
+
recipient: z.ZodOptional<z.ZodString>;
|
|
10
|
+
maxSplippage: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
amount: string;
|
|
13
|
+
destinationChainId: string;
|
|
14
|
+
inputTokenSymbol: string;
|
|
15
|
+
maxSplippage: number;
|
|
16
|
+
recipient?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
amount: string;
|
|
19
|
+
destinationChainId: string;
|
|
20
|
+
inputTokenSymbol?: string | undefined;
|
|
21
|
+
recipient?: string | undefined;
|
|
22
|
+
maxSplippage?: number | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Input schema for check deposit status action.
|
|
26
|
+
*/
|
|
27
|
+
export declare const CheckDepositStatusSchema: z.ZodObject<{
|
|
28
|
+
originChainId: z.ZodOptional<z.ZodString>;
|
|
29
|
+
depositId: z.ZodString;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
depositId: string;
|
|
32
|
+
originChainId?: string | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
depositId: string;
|
|
35
|
+
originChainId?: string | undefined;
|
|
36
|
+
}>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CheckDepositStatusSchema = exports.BridgeTokenSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/**
|
|
6
|
+
* Input schema for bridge token action.
|
|
7
|
+
*/
|
|
8
|
+
exports.BridgeTokenSchema = zod_1.z
|
|
9
|
+
.object({
|
|
10
|
+
destinationChainId: zod_1.z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("The chain ID of the destination chain (e.g. 11155111 for ethereum-sepolia)"),
|
|
13
|
+
inputTokenSymbol: zod_1.z
|
|
14
|
+
.string()
|
|
15
|
+
.describe("The symbol of the token to bridge (e.g., 'ETH', 'WETH', 'USDC')")
|
|
16
|
+
.default("ETH"),
|
|
17
|
+
amount: zod_1.z
|
|
18
|
+
.string()
|
|
19
|
+
.describe("The amount of tokens to bridge in whole units (e.g. 1.5 WETH, 10 USDC)"),
|
|
20
|
+
recipient: zod_1.z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("The recipient address on the destination chain (defaults to sender)"),
|
|
24
|
+
maxSplippage: zod_1.z
|
|
25
|
+
.number()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("The maximum slippage percentage (e.g. 10 for 10%)")
|
|
28
|
+
.default(1.5),
|
|
29
|
+
})
|
|
30
|
+
.strip()
|
|
31
|
+
.describe("Instructions for bridging tokens across chains using Across Protocol");
|
|
32
|
+
/**
|
|
33
|
+
* Input schema for check deposit status action.
|
|
34
|
+
*/
|
|
35
|
+
exports.CheckDepositStatusSchema = zod_1.z
|
|
36
|
+
.object({
|
|
37
|
+
originChainId: zod_1.z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("The chain ID of the origin chain (defaults to the current chain)"),
|
|
41
|
+
depositId: zod_1.z
|
|
42
|
+
.string()
|
|
43
|
+
.describe("The ID of the deposit to check (returned by the bridge deposit transaction)"),
|
|
44
|
+
})
|
|
45
|
+
.strip()
|
|
46
|
+
.describe("Instructions for checking the status of a deposit on Across Protocol");
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a chain ID corresponds to a testnet network supported by Across
|
|
3
|
+
*
|
|
4
|
+
* @param chainId - The blockchain network chain ID
|
|
5
|
+
* @returns true if the chain ID corresponds to a testnet network supported by Across, false otherwise
|
|
6
|
+
*/
|
|
7
|
+
export declare function isAcrossSupportedTestnet(chainId: number): boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAcrossSupportedTestnet = isAcrossSupportedTestnet;
|
|
4
|
+
/**
|
|
5
|
+
* Checks if a chain ID corresponds to a testnet network supported by Across
|
|
6
|
+
*
|
|
7
|
+
* @param chainId - The blockchain network chain ID
|
|
8
|
+
* @returns true if the chain ID corresponds to a testnet network supported by Across, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
function isAcrossSupportedTestnet(chainId) {
|
|
11
|
+
// List of testnet chain IDs
|
|
12
|
+
const testnetChainIds = [
|
|
13
|
+
11155111, // Sepolia
|
|
14
|
+
84532, // Base Sepolia
|
|
15
|
+
421614, // Arbitrum Sepolia
|
|
16
|
+
11155420, // Optimism Sepolia
|
|
17
|
+
919, // Mode Sepolia
|
|
18
|
+
80002, // Polygon Amoy
|
|
19
|
+
168587773, // Blast Sepolia
|
|
20
|
+
4202, // Lisk Sepolia
|
|
21
|
+
37111, // Lens Sepolia
|
|
22
|
+
1301, // Unichain Sepolia
|
|
23
|
+
];
|
|
24
|
+
return testnetChainIds.includes(chainId);
|
|
25
|
+
}
|
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./actionDecorator"), exports);
|
|
18
18
|
__exportStar(require("./actionProvider"), exports);
|
|
19
19
|
__exportStar(require("./customActionProvider"), exports);
|
|
20
|
+
__exportStar(require("./across"), exports);
|
|
20
21
|
__exportStar(require("./alchemy"), exports);
|
|
21
22
|
__exportStar(require("./basename"), exports);
|
|
22
23
|
__exportStar(require("./cdp"), exports);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@coinbase/agentkit",
|
|
3
3
|
"description": "Coinbase AgentKit core primitives",
|
|
4
4
|
"repository": "https://github.com/coinbase/agentkit",
|
|
5
|
-
"version": "0.2.3-nightly.
|
|
5
|
+
"version": "0.2.3-nightly.20250326.56",
|
|
6
6
|
"author": "Coinbase Inc.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"main": "dist/index.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"typescript"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@across-protocol/app-sdk": "^0.2.0",
|
|
43
44
|
"@alloralabs/allora-sdk": "^0.1.0",
|
|
44
45
|
"@coinbase/coinbase-sdk": "^0.20.0",
|
|
45
46
|
"@jup-ag/api": "^6.0.39",
|