@coinbase/agentkit 0.0.0-nightly-20250919210434 → 0.0.0-nightly-20251002210424
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 +170 -39
- package/dist/action-providers/across/schemas.d.ts +1 -1
- package/dist/action-providers/baseAccount/baseAccountActionProvider.d.ts +46 -0
- package/dist/action-providers/baseAccount/baseAccountActionProvider.js +404 -0
- package/dist/action-providers/baseAccount/baseAccountActionProvider.test.d.ts +1 -0
- package/dist/action-providers/baseAccount/baseAccountActionProvider.test.js +325 -0
- package/dist/action-providers/baseAccount/index.d.ts +2 -0
- package/dist/action-providers/baseAccount/index.js +18 -0
- package/dist/action-providers/baseAccount/schemas.d.ts +43 -0
- package/dist/action-providers/baseAccount/schemas.js +62 -0
- package/dist/action-providers/baseAccount/types.d.ts +17 -0
- package/dist/action-providers/baseAccount/types.js +2 -0
- package/dist/action-providers/baseAccount/utils.d.ts +14 -0
- package/dist/action-providers/baseAccount/utils.js +57 -0
- package/dist/action-providers/cdp/cdpApiActionProvider.js +7 -30
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +2 -8
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +2 -1
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.test.js +3 -1
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +2 -1
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.test.js +3 -1
- package/dist/action-providers/cdp/faucetUtils.d.ts +38 -0
- package/dist/action-providers/cdp/faucetUtils.js +81 -0
- package/dist/action-providers/cdp/swapUtils.d.ts +0 -9
- package/dist/action-providers/cdp/swapUtils.js +0 -36
- package/dist/action-providers/clanker/schemas.d.ts +6 -6
- package/dist/action-providers/enso/constants.d.ts +4 -0
- package/dist/action-providers/enso/constants.js +10 -0
- package/dist/action-providers/enso/ensoActionProvider.d.ts +34 -0
- package/dist/action-providers/enso/ensoActionProvider.js +125 -0
- package/dist/action-providers/enso/ensoActionProvider.test.d.ts +1 -0
- package/dist/action-providers/enso/ensoActionProvider.test.js +141 -0
- package/dist/action-providers/enso/index.d.ts +1 -0
- package/dist/action-providers/enso/index.js +17 -0
- package/dist/action-providers/enso/schemas.d.ts +23 -0
- package/dist/action-providers/enso/schemas.js +22 -0
- package/dist/action-providers/erc20/constants.d.ts +2 -0
- package/dist/action-providers/erc20/constants.js +2 -0
- package/dist/action-providers/erc20/erc20ActionProvider.d.ts +17 -1
- package/dist/action-providers/erc20/erc20ActionProvider.js +102 -0
- package/dist/action-providers/erc20/erc20ActionProvider.test.js +201 -0
- package/dist/action-providers/erc20/schemas.d.ts +29 -0
- package/dist/action-providers/erc20/schemas.js +34 -1
- package/dist/action-providers/flaunch/client_utils.d.ts +25 -0
- package/dist/action-providers/flaunch/client_utils.js +62 -0
- package/dist/action-providers/flaunch/constants.d.ts +41 -20
- package/dist/action-providers/flaunch/constants.js +111 -36
- package/dist/action-providers/flaunch/flaunchActionProvider.d.ts +4 -43
- package/dist/action-providers/flaunch/flaunchActionProvider.js +132 -200
- package/dist/action-providers/flaunch/flaunchActionProvider.test.js +108 -13
- package/dist/action-providers/flaunch/metadata_utils.d.ts +12 -0
- package/dist/action-providers/flaunch/metadata_utils.js +216 -0
- package/dist/action-providers/flaunch/schemas.d.ts +39 -3
- package/dist/action-providers/flaunch/schemas.js +62 -10
- package/dist/action-providers/flaunch/{utils.d.ts → swap_utils.d.ts} +17 -19
- package/dist/action-providers/flaunch/{utils.js → swap_utils.js} +137 -172
- package/dist/action-providers/index.d.ts +4 -1
- package/dist/action-providers/index.js +4 -1
- package/dist/action-providers/superfluid/superfluidSuperTokenCreatorActionProvider.js +5 -4
- package/dist/action-providers/superfluid/utils/parseLogs.d.ts +2 -1
- package/dist/action-providers/superfluid/utils/parseLogs.js +6 -3
- package/dist/action-providers/wallet/walletActionProvider.js +3 -0
- package/dist/action-providers/weth/constants.d.ts +0 -1
- package/dist/action-providers/weth/constants.js +1 -2
- package/dist/action-providers/weth/schemas.js +6 -2
- package/dist/action-providers/weth/wethActionProvider.d.ts +7 -0
- package/dist/action-providers/weth/wethActionProvider.js +57 -32
- package/dist/action-providers/weth/wethActionProvider.test.js +60 -11
- package/dist/action-providers/x402/utils.d.ts +4 -4
- package/dist/action-providers/x402/utils.js +42 -5
- package/dist/action-providers/x402/x402ActionProvider.d.ts +6 -6
- package/dist/action-providers/x402/x402ActionProvider.js +23 -8
- package/dist/action-providers/x402/x402ActionProvider.test.js +50 -6
- package/dist/action-providers/yelay/constants.d.ts +64 -0
- package/dist/action-providers/yelay/constants.js +137 -0
- package/dist/action-providers/yelay/index.d.ts +2 -0
- package/dist/action-providers/yelay/index.js +18 -0
- package/dist/action-providers/yelay/schemas.d.ts +47 -0
- package/dist/action-providers/yelay/schemas.js +59 -0
- package/dist/action-providers/yelay/types.d.ts +24 -0
- package/dist/action-providers/yelay/types.js +2 -0
- package/dist/action-providers/yelay/yelayActionProvider.d.ts +70 -0
- package/dist/action-providers/yelay/yelayActionProvider.js +329 -0
- package/dist/action-providers/yelay/yelayActionProvider.test.d.ts +1 -0
- package/dist/action-providers/yelay/yelayActionProvider.test.js +302 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +43 -13
- package/dist/wallet-providers/cdpEvmWalletProvider.js +5 -21
- package/dist/wallet-providers/cdpSmartWalletProvider.js +10 -7
- package/dist/wallet-providers/cdpSmartWalletProvider.test.js +0 -8
- package/dist/wallet-providers/cdpSolanaWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/cdpSolanaWalletProvider.js +39 -3
- package/dist/wallet-providers/cdpSolanaWalletProvider.test.js +16 -0
- package/dist/wallet-providers/privySvmWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/privySvmWalletProvider.js +17 -0
- package/dist/wallet-providers/privySvmWalletProvider.test.js +10 -0
- package/dist/wallet-providers/solanaKeypairWalletProvider.d.ts +14 -0
- package/dist/wallet-providers/solanaKeypairWalletProvider.js +17 -0
- package/dist/wallet-providers/svmWalletProvider.d.ts +34 -0
- package/dist/wallet-providers/svmWalletProvider.js +43 -0
- package/dist/wallet-providers/svmWalletProvider.test.js +10 -0
- package/dist/wallet-providers/viemWalletProvider.d.ts +1 -1
- package/dist/wallet-providers/viemWalletProvider.js +5 -1
- package/dist/wallet-providers/viemWalletProvider.test.js +12 -1
- package/package.json +4 -1
|
@@ -42,6 +42,11 @@ describe("Wrap Eth Action", () => {
|
|
|
42
42
|
beforeEach(async () => {
|
|
43
43
|
mockWallet = {
|
|
44
44
|
getAddress: jest.fn().mockReturnValue(MOCK_ADDRESS),
|
|
45
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
46
|
+
protocolFamily: "evm",
|
|
47
|
+
networkId: "base-mainnet",
|
|
48
|
+
}),
|
|
49
|
+
getBalance: jest.fn().mockResolvedValue((0, viem_1.parseUnits)("20", 18)), // 20 ETH balance
|
|
45
50
|
sendTransaction: jest.fn(),
|
|
46
51
|
waitForTransactionReceipt: jest.fn(),
|
|
47
52
|
};
|
|
@@ -54,14 +59,14 @@ describe("Wrap Eth Action", () => {
|
|
|
54
59
|
mockWallet.sendTransaction.mockResolvedValue(hash);
|
|
55
60
|
const response = await actionProvider.wrapEth(mockWallet, args);
|
|
56
61
|
expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
|
|
57
|
-
to:
|
|
62
|
+
to: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
58
63
|
data: (0, viem_1.encodeFunctionData)({
|
|
59
64
|
abi: constants_1.WETH_ABI,
|
|
60
65
|
functionName: "deposit",
|
|
61
66
|
}),
|
|
62
|
-
value:
|
|
67
|
+
value: (0, viem_1.parseUnits)(MOCK_AMOUNT, 18),
|
|
63
68
|
});
|
|
64
|
-
expect(response).toContain(`Wrapped ETH
|
|
69
|
+
expect(response).toContain(`Wrapped ${MOCK_AMOUNT} ETH to WETH. Transaction hash: ${hash}`);
|
|
65
70
|
});
|
|
66
71
|
it("should fail with an error", async () => {
|
|
67
72
|
const args = {
|
|
@@ -71,15 +76,25 @@ describe("Wrap Eth Action", () => {
|
|
|
71
76
|
mockWallet.sendTransaction.mockRejectedValue(error);
|
|
72
77
|
const response = await actionProvider.wrapEth(mockWallet, args);
|
|
73
78
|
expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
|
|
74
|
-
to:
|
|
79
|
+
to: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
75
80
|
data: (0, viem_1.encodeFunctionData)({
|
|
76
81
|
abi: constants_1.WETH_ABI,
|
|
77
82
|
functionName: "deposit",
|
|
78
83
|
}),
|
|
79
|
-
value:
|
|
84
|
+
value: (0, viem_1.parseUnits)(MOCK_AMOUNT, 18),
|
|
80
85
|
});
|
|
81
86
|
expect(response).toContain(`Error wrapping ETH: ${error}`);
|
|
82
87
|
});
|
|
88
|
+
it("should fail with insufficient ETH balance", async () => {
|
|
89
|
+
const args = {
|
|
90
|
+
amountToWrap: MOCK_AMOUNT,
|
|
91
|
+
};
|
|
92
|
+
// Mock insufficient balance (less than 15 ETH)
|
|
93
|
+
mockWallet.getBalance.mockResolvedValue((0, viem_1.parseUnits)("10", 18));
|
|
94
|
+
const response = await actionProvider.wrapEth(mockWallet, args);
|
|
95
|
+
expect(mockWallet.sendTransaction).not.toHaveBeenCalled();
|
|
96
|
+
expect(response).toContain("Error: Insufficient ETH balance");
|
|
97
|
+
});
|
|
83
98
|
});
|
|
84
99
|
describe("Unwrap Eth Action", () => {
|
|
85
100
|
let mockWallet;
|
|
@@ -87,6 +102,11 @@ describe("Unwrap Eth Action", () => {
|
|
|
87
102
|
beforeEach(async () => {
|
|
88
103
|
mockWallet = {
|
|
89
104
|
getAddress: jest.fn().mockReturnValue(MOCK_ADDRESS),
|
|
105
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
106
|
+
protocolFamily: "evm",
|
|
107
|
+
networkId: "base-mainnet",
|
|
108
|
+
}),
|
|
109
|
+
readContract: jest.fn().mockResolvedValue((0, viem_1.parseUnits)("20", 18)), // 20 WETH balance
|
|
90
110
|
sendTransaction: jest.fn(),
|
|
91
111
|
waitForTransactionReceipt: jest.fn(),
|
|
92
112
|
};
|
|
@@ -98,15 +118,21 @@ describe("Unwrap Eth Action", () => {
|
|
|
98
118
|
const hash = "0x1234567890123456789012345678901234567890";
|
|
99
119
|
mockWallet.sendTransaction.mockResolvedValue(hash);
|
|
100
120
|
const response = await actionProvider.unwrapEth(mockWallet, args);
|
|
121
|
+
expect(mockWallet.readContract).toHaveBeenCalledWith({
|
|
122
|
+
address: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
123
|
+
abi: viem_1.erc20Abi,
|
|
124
|
+
functionName: "balanceOf",
|
|
125
|
+
args: [MOCK_ADDRESS],
|
|
126
|
+
});
|
|
101
127
|
expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
|
|
102
|
-
to:
|
|
128
|
+
to: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
103
129
|
data: (0, viem_1.encodeFunctionData)({
|
|
104
130
|
abi: constants_1.WETH_ABI,
|
|
105
131
|
functionName: "withdraw",
|
|
106
|
-
args: [
|
|
132
|
+
args: [(0, viem_1.parseUnits)(MOCK_AMOUNT, 18)],
|
|
107
133
|
}),
|
|
108
134
|
});
|
|
109
|
-
expect(response).toContain(`Unwrapped WETH
|
|
135
|
+
expect(response).toContain(`Unwrapped ${MOCK_AMOUNT} WETH to ETH. Transaction hash: ${hash}`);
|
|
110
136
|
});
|
|
111
137
|
it("should fail with an error", async () => {
|
|
112
138
|
const args = {
|
|
@@ -115,16 +141,32 @@ describe("Unwrap Eth Action", () => {
|
|
|
115
141
|
const error = new Error("Failed to unwrap WETH");
|
|
116
142
|
mockWallet.sendTransaction.mockRejectedValue(error);
|
|
117
143
|
const response = await actionProvider.unwrapEth(mockWallet, args);
|
|
144
|
+
expect(mockWallet.readContract).toHaveBeenCalledWith({
|
|
145
|
+
address: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
146
|
+
abi: viem_1.erc20Abi,
|
|
147
|
+
functionName: "balanceOf",
|
|
148
|
+
args: [MOCK_ADDRESS],
|
|
149
|
+
});
|
|
118
150
|
expect(mockWallet.sendTransaction).toHaveBeenCalledWith({
|
|
119
|
-
to:
|
|
151
|
+
to: (0, wethActionProvider_1.getWethAddress)({ protocolFamily: "evm", networkId: "base-mainnet" }),
|
|
120
152
|
data: (0, viem_1.encodeFunctionData)({
|
|
121
153
|
abi: constants_1.WETH_ABI,
|
|
122
154
|
functionName: "withdraw",
|
|
123
|
-
args: [
|
|
155
|
+
args: [(0, viem_1.parseUnits)(MOCK_AMOUNT, 18)],
|
|
124
156
|
}),
|
|
125
157
|
});
|
|
126
158
|
expect(response).toContain(`Error unwrapping WETH: ${error}`);
|
|
127
159
|
});
|
|
160
|
+
it("should fail with insufficient WETH balance", async () => {
|
|
161
|
+
const args = {
|
|
162
|
+
amountToUnwrap: MOCK_AMOUNT,
|
|
163
|
+
};
|
|
164
|
+
// Mock insufficient WETH balance (less than 15 WETH)
|
|
165
|
+
mockWallet.readContract.mockResolvedValue((0, viem_1.parseUnits)("10", 18));
|
|
166
|
+
const response = await actionProvider.unwrapEth(mockWallet, args);
|
|
167
|
+
expect(mockWallet.sendTransaction).not.toHaveBeenCalled();
|
|
168
|
+
expect(response).toContain("Error: Insufficient WETH balance");
|
|
169
|
+
});
|
|
128
170
|
});
|
|
129
171
|
describe("supportsNetwork", () => {
|
|
130
172
|
const actionProvider = (0, wethActionProvider_1.wethActionProvider)();
|
|
@@ -142,11 +184,18 @@ describe("supportsNetwork", () => {
|
|
|
142
184
|
});
|
|
143
185
|
expect(result).toBe(true);
|
|
144
186
|
});
|
|
145
|
-
it("should return
|
|
187
|
+
it("should return true for ethereum-mainnet", () => {
|
|
146
188
|
const result = actionProvider.supportsNetwork({
|
|
147
189
|
protocolFamily: "evm",
|
|
148
190
|
networkId: "ethereum-mainnet",
|
|
149
191
|
});
|
|
192
|
+
expect(result).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
it("should return false for networks without WETH", () => {
|
|
195
|
+
const result = actionProvider.supportsNetwork({
|
|
196
|
+
protocolFamily: "evm",
|
|
197
|
+
networkId: "polygon-mainnet",
|
|
198
|
+
});
|
|
150
199
|
expect(result).toBe(false);
|
|
151
200
|
});
|
|
152
201
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Network } from "../../network";
|
|
2
2
|
import { AxiosError } from "axios";
|
|
3
|
-
import {
|
|
3
|
+
import { WalletProvider } from "../../wallet-providers";
|
|
4
4
|
/**
|
|
5
5
|
* Supported network types for x402 protocol
|
|
6
6
|
*/
|
|
@@ -35,7 +35,7 @@ export declare function formatPaymentOption(option: {
|
|
|
35
35
|
asset: string;
|
|
36
36
|
maxAmountRequired: string;
|
|
37
37
|
network: string;
|
|
38
|
-
}, walletProvider:
|
|
38
|
+
}, walletProvider: WalletProvider): Promise<string>;
|
|
39
39
|
/**
|
|
40
40
|
* Checks if an asset is USDC on any supported network.
|
|
41
41
|
*
|
|
@@ -43,7 +43,7 @@ export declare function formatPaymentOption(option: {
|
|
|
43
43
|
* @param walletProvider - The wallet provider for network context
|
|
44
44
|
* @returns True if the asset is USDC, false otherwise
|
|
45
45
|
*/
|
|
46
|
-
export declare function isUsdcAsset(asset: string, walletProvider:
|
|
46
|
+
export declare function isUsdcAsset(asset: string, walletProvider: WalletProvider): boolean;
|
|
47
47
|
/**
|
|
48
48
|
* Converts whole units to atomic units for a given asset.
|
|
49
49
|
*
|
|
@@ -52,4 +52,4 @@ export declare function isUsdcAsset(asset: string, walletProvider: EvmWalletProv
|
|
|
52
52
|
* @param walletProvider - The wallet provider for token details lookup
|
|
53
53
|
* @returns The amount in atomic units as a string, or null if conversion fails
|
|
54
54
|
*/
|
|
55
|
-
export declare function convertWholeUnitsToAtomic(wholeUnits: number, asset: string, walletProvider:
|
|
55
|
+
export declare function convertWholeUnitsToAtomic(wholeUnits: number, asset: string, walletProvider: WalletProvider): Promise<string | null>;
|
|
@@ -8,6 +8,14 @@ exports.convertWholeUnitsToAtomic = convertWholeUnitsToAtomic;
|
|
|
8
8
|
const utils_1 = require("../erc20/utils");
|
|
9
9
|
const constants_1 = require("../erc20/constants");
|
|
10
10
|
const viem_1 = require("viem");
|
|
11
|
+
const wallet_providers_1 = require("../../wallet-providers");
|
|
12
|
+
/**
|
|
13
|
+
* USDC token addresses for Solana networks
|
|
14
|
+
*/
|
|
15
|
+
const SOLANA_USDC_ADDRESSES = {
|
|
16
|
+
"solana-devnet": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
|
|
17
|
+
"solana-mainnet": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
18
|
+
};
|
|
11
19
|
/**
|
|
12
20
|
* Converts the internal network ID to the format expected by the x402 protocol.
|
|
13
21
|
*
|
|
@@ -75,7 +83,8 @@ async function formatPaymentOption(option, walletProvider) {
|
|
|
75
83
|
// Check if this is an EVM network and we can use ERC20 helpers
|
|
76
84
|
const walletNetwork = walletProvider.getNetwork();
|
|
77
85
|
const isEvmNetwork = walletNetwork.protocolFamily === "evm";
|
|
78
|
-
|
|
86
|
+
const isSvmNetwork = walletNetwork.protocolFamily === "svm";
|
|
87
|
+
if (isEvmNetwork && walletProvider instanceof wallet_providers_1.EvmWalletProvider) {
|
|
79
88
|
const networkId = walletNetwork.networkId;
|
|
80
89
|
const tokenSymbols = constants_1.TOKEN_ADDRESSES_BY_SYMBOLS[networkId];
|
|
81
90
|
if (tokenSymbols) {
|
|
@@ -99,7 +108,17 @@ async function formatPaymentOption(option, walletProvider) {
|
|
|
99
108
|
// If we can't get token details, fall back to raw format
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
|
-
|
|
111
|
+
if (isSvmNetwork && walletProvider instanceof wallet_providers_1.SvmWalletProvider) {
|
|
112
|
+
// Check if the asset is USDC on Solana networks
|
|
113
|
+
const networkId = walletNetwork.networkId;
|
|
114
|
+
const usdcAddress = SOLANA_USDC_ADDRESSES[networkId];
|
|
115
|
+
if (usdcAddress && asset === usdcAddress) {
|
|
116
|
+
// USDC has 6 decimals on Solana
|
|
117
|
+
const formattedAmount = (0, viem_1.formatUnits)(BigInt(maxAmountRequired), 6);
|
|
118
|
+
return `${formattedAmount} USDC on ${network} network`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Fallback to original format for non-EVM/SVM networks or when token details can't be fetched
|
|
103
122
|
return `${asset} ${maxAmountRequired} on ${network} network`;
|
|
104
123
|
}
|
|
105
124
|
/**
|
|
@@ -112,13 +131,21 @@ async function formatPaymentOption(option, walletProvider) {
|
|
|
112
131
|
function isUsdcAsset(asset, walletProvider) {
|
|
113
132
|
const walletNetwork = walletProvider.getNetwork();
|
|
114
133
|
const isEvmNetwork = walletNetwork.protocolFamily === "evm";
|
|
115
|
-
|
|
134
|
+
const isSvmNetwork = walletNetwork.protocolFamily === "svm";
|
|
135
|
+
if (isEvmNetwork && walletProvider instanceof wallet_providers_1.EvmWalletProvider) {
|
|
116
136
|
const networkId = walletNetwork.networkId;
|
|
117
137
|
const tokenSymbols = constants_1.TOKEN_ADDRESSES_BY_SYMBOLS[networkId];
|
|
118
138
|
if (tokenSymbols && tokenSymbols.USDC) {
|
|
119
139
|
return asset.toLowerCase() === tokenSymbols.USDC.toLowerCase();
|
|
120
140
|
}
|
|
121
141
|
}
|
|
142
|
+
if (isSvmNetwork && walletProvider instanceof wallet_providers_1.SvmWalletProvider) {
|
|
143
|
+
const networkId = walletNetwork.networkId;
|
|
144
|
+
const usdcAddress = SOLANA_USDC_ADDRESSES[networkId];
|
|
145
|
+
if (usdcAddress) {
|
|
146
|
+
return asset === usdcAddress;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
122
149
|
return false;
|
|
123
150
|
}
|
|
124
151
|
/**
|
|
@@ -133,7 +160,8 @@ async function convertWholeUnitsToAtomic(wholeUnits, asset, walletProvider) {
|
|
|
133
160
|
// Check if this is an EVM network and we can use ERC20 helpers
|
|
134
161
|
const walletNetwork = walletProvider.getNetwork();
|
|
135
162
|
const isEvmNetwork = walletNetwork.protocolFamily === "evm";
|
|
136
|
-
|
|
163
|
+
const isSvmNetwork = walletNetwork.protocolFamily === "svm";
|
|
164
|
+
if (isEvmNetwork && walletProvider instanceof wallet_providers_1.EvmWalletProvider) {
|
|
137
165
|
const networkId = walletNetwork.networkId;
|
|
138
166
|
const tokenSymbols = constants_1.TOKEN_ADDRESSES_BY_SYMBOLS[networkId];
|
|
139
167
|
if (tokenSymbols) {
|
|
@@ -155,6 +183,15 @@ async function convertWholeUnitsToAtomic(wholeUnits, asset, walletProvider) {
|
|
|
155
183
|
// If we can't get token details, fall back to assuming 18 decimals
|
|
156
184
|
}
|
|
157
185
|
}
|
|
158
|
-
|
|
186
|
+
if (isSvmNetwork && walletProvider instanceof wallet_providers_1.SvmWalletProvider) {
|
|
187
|
+
// Check if the asset is USDC on Solana networks
|
|
188
|
+
const networkId = walletNetwork.networkId;
|
|
189
|
+
const usdcAddress = SOLANA_USDC_ADDRESSES[networkId];
|
|
190
|
+
if (usdcAddress && asset === usdcAddress) {
|
|
191
|
+
// USDC has 6 decimals on Solana
|
|
192
|
+
return (0, viem_1.parseUnits)(wholeUnits.toString(), 6).toString();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Fallback to 18 decimals for unknown tokens or non-EVM/SVM networks
|
|
159
196
|
return (0, viem_1.parseUnits)(wholeUnits.toString(), 18).toString();
|
|
160
197
|
}
|
|
@@ -2,11 +2,11 @@ import { z } from "zod";
|
|
|
2
2
|
import { ActionProvider } from "../actionProvider";
|
|
3
3
|
import { Network } from "../../network";
|
|
4
4
|
import { HttpRequestSchema, RetryWithX402Schema, DirectX402RequestSchema, ListX402ServicesSchema } from "./schemas";
|
|
5
|
-
import {
|
|
5
|
+
import { WalletProvider } from "../../wallet-providers";
|
|
6
6
|
/**
|
|
7
7
|
* X402ActionProvider provides actions for making HTTP requests, with optional x402 payment handling.
|
|
8
8
|
*/
|
|
9
|
-
export declare class X402ActionProvider extends ActionProvider<
|
|
9
|
+
export declare class X402ActionProvider extends ActionProvider<WalletProvider> {
|
|
10
10
|
/**
|
|
11
11
|
* Creates a new instance of X402ActionProvider.
|
|
12
12
|
* Initializes the provider with x402 capabilities.
|
|
@@ -19,7 +19,7 @@ export declare class X402ActionProvider extends ActionProvider<EvmWalletProvider
|
|
|
19
19
|
* @param args - Optional filters: maxUsdcPrice
|
|
20
20
|
* @returns JSON string with the list of services (filtered by network and description)
|
|
21
21
|
*/
|
|
22
|
-
discoverX402Services(walletProvider:
|
|
22
|
+
discoverX402Services(walletProvider: WalletProvider, args: z.infer<typeof ListX402ServicesSchema>): Promise<string>;
|
|
23
23
|
/**
|
|
24
24
|
* Makes a basic HTTP request to an API endpoint.
|
|
25
25
|
*
|
|
@@ -27,7 +27,7 @@ export declare class X402ActionProvider extends ActionProvider<EvmWalletProvider
|
|
|
27
27
|
* @param args - The request parameters including URL, method, headers, and body
|
|
28
28
|
* @returns A JSON string containing the response or error details
|
|
29
29
|
*/
|
|
30
|
-
makeHttpRequest(walletProvider:
|
|
30
|
+
makeHttpRequest(walletProvider: WalletProvider, args: z.infer<typeof HttpRequestSchema>): Promise<string>;
|
|
31
31
|
/**
|
|
32
32
|
* Retries a request with x402 payment after receiving a 402 response.
|
|
33
33
|
*
|
|
@@ -35,7 +35,7 @@ export declare class X402ActionProvider extends ActionProvider<EvmWalletProvider
|
|
|
35
35
|
* @param args - The request parameters including URL, method, headers, body, and payment option
|
|
36
36
|
* @returns A JSON string containing the response with payment details or error information
|
|
37
37
|
*/
|
|
38
|
-
retryWithX402(walletProvider:
|
|
38
|
+
retryWithX402(walletProvider: WalletProvider, args: z.infer<typeof RetryWithX402Schema>): Promise<string>;
|
|
39
39
|
/**
|
|
40
40
|
* Makes an HTTP request with automatic x402 payment handling.
|
|
41
41
|
*
|
|
@@ -43,7 +43,7 @@ export declare class X402ActionProvider extends ActionProvider<EvmWalletProvider
|
|
|
43
43
|
* @param args - The request parameters including URL, method, headers, and body
|
|
44
44
|
* @returns A JSON string containing the response with optional payment details or error information
|
|
45
45
|
*/
|
|
46
|
-
makeHttpRequestWithX402(walletProvider:
|
|
46
|
+
makeHttpRequestWithX402(walletProvider: WalletProvider, args: z.infer<typeof DirectX402RequestSchema>): Promise<string>;
|
|
47
47
|
/**
|
|
48
48
|
* Checks if the action provider supports the given network.
|
|
49
49
|
*
|
|
@@ -40,7 +40,7 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
40
40
|
* @param network - The network to check support for
|
|
41
41
|
* @returns True if the network is supported, false otherwise
|
|
42
42
|
*/
|
|
43
|
-
this.supportsNetwork = (network) =>
|
|
43
|
+
this.supportsNetwork = (network) => SUPPORTED_NETWORKS.includes(network.networkId);
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
46
|
* Discovers available x402 services with optional filtering.
|
|
@@ -224,8 +224,16 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
224
224
|
details: `Wallet is on ${walletNetwork} but payment requires ${selectedNetwork}`,
|
|
225
225
|
}, null, 2);
|
|
226
226
|
}
|
|
227
|
+
// Check if wallet provider is supported
|
|
228
|
+
if (!(walletProvider instanceof wallet_providers_1.SvmWalletProvider || walletProvider instanceof wallet_providers_1.EvmWalletProvider)) {
|
|
229
|
+
return JSON.stringify({
|
|
230
|
+
error: true,
|
|
231
|
+
message: "Unsupported wallet provider",
|
|
232
|
+
details: "Only SvmWalletProvider and EvmWalletProvider are supported",
|
|
233
|
+
}, null, 2);
|
|
234
|
+
}
|
|
227
235
|
// Make the request with payment handling
|
|
228
|
-
const account = walletProvider.toSigner();
|
|
236
|
+
const account = await walletProvider.toSigner();
|
|
229
237
|
const paymentSelector = (accepts) => {
|
|
230
238
|
const { scheme, network, maxAmountRequired, asset } = args.selectedPaymentOption;
|
|
231
239
|
let paymentRequirements = accepts.find(accept => accept.scheme === scheme &&
|
|
@@ -292,7 +300,14 @@ class X402ActionProvider extends actionProvider_1.ActionProvider {
|
|
|
292
300
|
*/
|
|
293
301
|
async makeHttpRequestWithX402(walletProvider, args) {
|
|
294
302
|
try {
|
|
295
|
-
|
|
303
|
+
if (!(walletProvider instanceof wallet_providers_1.SvmWalletProvider || walletProvider instanceof wallet_providers_1.EvmWalletProvider)) {
|
|
304
|
+
return JSON.stringify({
|
|
305
|
+
error: true,
|
|
306
|
+
message: "Unsupported wallet provider",
|
|
307
|
+
details: "Only SvmWalletProvider and EvmWalletProvider are supported",
|
|
308
|
+
}, null, 2);
|
|
309
|
+
}
|
|
310
|
+
const account = await walletProvider.toSigner();
|
|
296
311
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
297
312
|
const api = (0, x402_axios_1.withPaymentInterceptor)(axios_1.default.create({}), account);
|
|
298
313
|
const response = await api.request({
|
|
@@ -330,11 +345,11 @@ exports.X402ActionProvider = X402ActionProvider;
|
|
|
330
345
|
__decorate([
|
|
331
346
|
(0, actionDecorator_1.CreateAction)({
|
|
332
347
|
name: "discover_x402_services",
|
|
333
|
-
description: "Discover available x402 services. Optionally filter by a maximum price in whole units of USDC (only USDC payment options will be considered when filter is applied).",
|
|
348
|
+
description: "Discover available x402 services. Only services available on the current network will be returned. Optionally filter by a maximum price in whole units of USDC (only USDC payment options will be considered when filter is applied).",
|
|
334
349
|
schema: schemas_1.ListX402ServicesSchema,
|
|
335
350
|
}),
|
|
336
351
|
__metadata("design:type", Function),
|
|
337
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
352
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
338
353
|
__metadata("design:returntype", Promise)
|
|
339
354
|
], X402ActionProvider.prototype, "discoverX402Services", null);
|
|
340
355
|
__decorate([
|
|
@@ -353,7 +368,7 @@ If you receive a 402 Payment Required response, use retry_http_request_with_x402
|
|
|
353
368
|
schema: schemas_1.HttpRequestSchema,
|
|
354
369
|
}),
|
|
355
370
|
__metadata("design:type", Function),
|
|
356
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
371
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
357
372
|
__metadata("design:returntype", Promise)
|
|
358
373
|
], X402ActionProvider.prototype, "makeHttpRequest", null);
|
|
359
374
|
__decorate([
|
|
@@ -372,7 +387,7 @@ DO NOT use this action directly without first trying make_http_request!`,
|
|
|
372
387
|
schema: schemas_1.RetryWithX402Schema,
|
|
373
388
|
}),
|
|
374
389
|
__metadata("design:type", Function),
|
|
375
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
390
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
376
391
|
__metadata("design:returntype", Promise)
|
|
377
392
|
], X402ActionProvider.prototype, "retryWithX402", null);
|
|
378
393
|
__decorate([
|
|
@@ -400,7 +415,7 @@ Unless specifically instructed otherwise, prefer the two-step approach with make
|
|
|
400
415
|
schema: schemas_1.DirectX402RequestSchema,
|
|
401
416
|
}),
|
|
402
417
|
__metadata("design:type", Function),
|
|
403
|
-
__metadata("design:paramtypes", [wallet_providers_1.
|
|
418
|
+
__metadata("design:paramtypes", [wallet_providers_1.WalletProvider, void 0]),
|
|
404
419
|
__metadata("design:returntype", Promise)
|
|
405
420
|
], X402ActionProvider.prototype, "makeHttpRequestWithX402", null);
|
|
406
421
|
const x402ActionProvider = () => new X402ActionProvider();
|
|
@@ -37,9 +37,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const x402ActionProvider_1 = require("./x402ActionProvider");
|
|
40
|
+
const wallet_providers_1 = require("../../wallet-providers");
|
|
40
41
|
const axios_1 = __importDefault(require("axios"));
|
|
41
42
|
const x402axios = __importStar(require("x402-axios"));
|
|
42
43
|
const x402Verify = __importStar(require("x402/verify"));
|
|
44
|
+
const utils = __importStar(require("./utils"));
|
|
43
45
|
// Mock external facilitator dependency
|
|
44
46
|
jest.mock("@coinbase/x402", () => ({
|
|
45
47
|
facilitator: {},
|
|
@@ -48,6 +50,7 @@ jest.mock("@coinbase/x402", () => ({
|
|
|
48
50
|
jest.mock("axios");
|
|
49
51
|
jest.mock("x402-axios");
|
|
50
52
|
jest.mock("x402/verify");
|
|
53
|
+
jest.mock("./utils");
|
|
51
54
|
// Create mock functions
|
|
52
55
|
const mockRequest = jest.fn();
|
|
53
56
|
// Create a complete mock axios instance
|
|
@@ -90,6 +93,10 @@ const mockAxios = {
|
|
|
90
93
|
const mockWithPaymentInterceptor = jest.fn().mockReturnValue(mockAxiosInstance);
|
|
91
94
|
const mockDecodeXPaymentResponse = jest.fn();
|
|
92
95
|
const mockUseFacilitator = jest.fn();
|
|
96
|
+
const mockIsUsdcAsset = jest.fn();
|
|
97
|
+
const mockConvertWholeUnitsToAtomic = jest.fn();
|
|
98
|
+
const mockFormatPaymentOption = jest.fn();
|
|
99
|
+
const mockGetX402Network = jest.fn();
|
|
93
100
|
// Override the mocked modules
|
|
94
101
|
axios_1.default.create = mockAxios.create;
|
|
95
102
|
axios_1.default.request = mockRequest;
|
|
@@ -98,11 +105,25 @@ axios_1.default.isAxiosError = mockAxios.isAxiosError;
|
|
|
98
105
|
jest.mocked(x402axios.withPaymentInterceptor).mockImplementation(mockWithPaymentInterceptor);
|
|
99
106
|
jest.mocked(x402axios.decodeXPaymentResponse).mockImplementation(mockDecodeXPaymentResponse);
|
|
100
107
|
jest.mocked(x402Verify.useFacilitator).mockImplementation(mockUseFacilitator);
|
|
101
|
-
// Mock
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
// Mock utils functions
|
|
109
|
+
jest.mocked(utils.isUsdcAsset).mockImplementation(mockIsUsdcAsset);
|
|
110
|
+
jest.mocked(utils.convertWholeUnitsToAtomic).mockImplementation(mockConvertWholeUnitsToAtomic);
|
|
111
|
+
jest.mocked(utils.formatPaymentOption).mockImplementation(mockFormatPaymentOption);
|
|
112
|
+
jest.mocked(utils.getX402Network).mockImplementation(mockGetX402Network);
|
|
113
|
+
jest.mocked(utils.handleHttpError).mockImplementation((error, url) => {
|
|
114
|
+
return JSON.stringify({
|
|
115
|
+
error: true,
|
|
116
|
+
message: error instanceof Error ? error.message : "Network error",
|
|
117
|
+
url: url,
|
|
118
|
+
});
|
|
105
119
|
});
|
|
120
|
+
// Mock wallet provider
|
|
121
|
+
const makeMockWalletProvider = (networkId) => {
|
|
122
|
+
const mockProvider = Object.create(wallet_providers_1.EvmWalletProvider.prototype);
|
|
123
|
+
mockProvider.toSigner = jest.fn().mockReturnValue("mock-signer");
|
|
124
|
+
mockProvider.getNetwork = jest.fn().mockReturnValue({ protocolFamily: "evm", networkId });
|
|
125
|
+
return mockProvider;
|
|
126
|
+
};
|
|
106
127
|
// Sample responses based on real examples
|
|
107
128
|
const MOCK_PAYMENT_INFO_RESPONSE = {
|
|
108
129
|
paymentRequired: true,
|
|
@@ -150,6 +171,11 @@ describe("X402ActionProvider", () => {
|
|
|
150
171
|
.mockImplementation((error) => Boolean(error &&
|
|
151
172
|
typeof error === "object" &&
|
|
152
173
|
("isAxiosError" in error || "response" in error || "request" in error)));
|
|
174
|
+
// Reset all utility mocks to default behavior
|
|
175
|
+
mockGetX402Network.mockImplementation(network => network.networkId);
|
|
176
|
+
mockIsUsdcAsset.mockReturnValue(false);
|
|
177
|
+
mockConvertWholeUnitsToAtomic.mockResolvedValue("100000");
|
|
178
|
+
mockFormatPaymentOption.mockResolvedValue("mocked payment option");
|
|
153
179
|
});
|
|
154
180
|
afterEach(() => {
|
|
155
181
|
jest.clearAllMocks();
|
|
@@ -167,8 +193,12 @@ describe("X402ActionProvider", () => {
|
|
|
167
193
|
const network = { protocolFamily: "evm", networkId: "ethereum" };
|
|
168
194
|
expect(provider.supportsNetwork(network)).toBe(false);
|
|
169
195
|
});
|
|
170
|
-
it("should
|
|
171
|
-
const network = { protocolFamily: "
|
|
196
|
+
it("should support SVM networks", () => {
|
|
197
|
+
const network = { protocolFamily: "svm", networkId: "solana-mainnet" };
|
|
198
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
it("should not support non-EVM/SVM networks", () => {
|
|
201
|
+
const network = { protocolFamily: "bitcoin", networkId: "mainnet" };
|
|
172
202
|
expect(provider.supportsNetwork(network)).toBe(false);
|
|
173
203
|
});
|
|
174
204
|
});
|
|
@@ -190,6 +220,8 @@ describe("X402ActionProvider", () => {
|
|
|
190
220
|
expect(parsedResult.data).toEqual({ message: "Success" });
|
|
191
221
|
});
|
|
192
222
|
it("should handle 402 responses with payment options", async () => {
|
|
223
|
+
mockGetX402Network.mockReturnValue("base-sepolia");
|
|
224
|
+
mockFormatPaymentOption.mockResolvedValue("10000 USDC on base-sepolia network");
|
|
193
225
|
mockRequest.mockResolvedValue({
|
|
194
226
|
status: 402,
|
|
195
227
|
data: MOCK_PAYMENT_INFO_RESPONSE.data,
|
|
@@ -241,6 +273,7 @@ describe("X402ActionProvider", () => {
|
|
|
241
273
|
],
|
|
242
274
|
});
|
|
243
275
|
mockUseFacilitator.mockReturnValue({ list: mockList });
|
|
276
|
+
mockGetX402Network.mockReturnValue("base-sepolia");
|
|
244
277
|
const result = await provider.discoverX402Services(makeMockWalletProvider("base-sepolia"), {});
|
|
245
278
|
const parsed = JSON.parse(result);
|
|
246
279
|
expect(parsed.success).toBe(true);
|
|
@@ -299,6 +332,14 @@ describe("X402ActionProvider", () => {
|
|
|
299
332
|
],
|
|
300
333
|
});
|
|
301
334
|
mockUseFacilitator.mockReturnValue({ list: mockList });
|
|
335
|
+
// Mock the utility functions for this test
|
|
336
|
+
mockGetX402Network.mockReturnValue("base-sepolia");
|
|
337
|
+
mockIsUsdcAsset.mockReturnValue(true); // All assets are USDC
|
|
338
|
+
mockConvertWholeUnitsToAtomic
|
|
339
|
+
.mockResolvedValueOnce("100000") // 0.1 USDC in atomic units
|
|
340
|
+
.mockResolvedValueOnce("100000")
|
|
341
|
+
.mockResolvedValueOnce("100000");
|
|
342
|
+
mockFormatPaymentOption.mockResolvedValue("formatted payment option");
|
|
302
343
|
const result = await provider.discoverX402Services(makeMockWalletProvider("base-sepolia"), {
|
|
303
344
|
maxUsdcPrice: 0.1,
|
|
304
345
|
});
|
|
@@ -319,6 +360,7 @@ describe("X402ActionProvider", () => {
|
|
|
319
360
|
describe("retryHttpRequestWithX402", () => {
|
|
320
361
|
it("should successfully retry with payment", async () => {
|
|
321
362
|
mockDecodeXPaymentResponse.mockReturnValue(MOCK_PAYMENT_RESPONSE);
|
|
363
|
+
mockGetX402Network.mockReturnValue("base-sepolia");
|
|
322
364
|
mockRequest.mockResolvedValue({
|
|
323
365
|
status: 200,
|
|
324
366
|
statusText: "OK",
|
|
@@ -353,6 +395,7 @@ describe("X402ActionProvider", () => {
|
|
|
353
395
|
error.isAxiosError = true;
|
|
354
396
|
error.request = {};
|
|
355
397
|
mockRequest.mockRejectedValue(error);
|
|
398
|
+
mockGetX402Network.mockReturnValue("base-sepolia");
|
|
356
399
|
const result = await provider.retryWithX402(makeMockWalletProvider("base-sepolia"), {
|
|
357
400
|
url: "https://www.x402.org/protected",
|
|
358
401
|
method: "GET",
|
|
@@ -395,6 +438,7 @@ describe("X402ActionProvider", () => {
|
|
|
395
438
|
});
|
|
396
439
|
});
|
|
397
440
|
it("should handle successful non-payment requests", async () => {
|
|
441
|
+
mockDecodeXPaymentResponse.mockReturnValue(null); // No payment made
|
|
398
442
|
mockRequest.mockResolvedValue({
|
|
399
443
|
status: 200,
|
|
400
444
|
statusText: "OK",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export declare const YELAY_BACKEND_URL = "https://lite.api.yelay.io/v2";
|
|
2
|
+
export declare const RETAIL_POOL_ID = 10;
|
|
3
|
+
export declare const YELAY_VAULT_ABI: {
|
|
4
|
+
type: string;
|
|
5
|
+
name: string;
|
|
6
|
+
inputs: {
|
|
7
|
+
name: string;
|
|
8
|
+
type: string;
|
|
9
|
+
internalType: string;
|
|
10
|
+
}[];
|
|
11
|
+
outputs: {
|
|
12
|
+
name: string;
|
|
13
|
+
type: string;
|
|
14
|
+
internalType: string;
|
|
15
|
+
}[];
|
|
16
|
+
stateMutability: string;
|
|
17
|
+
}[];
|
|
18
|
+
export declare const YIELD_EXTRACTOR_ABI: ({
|
|
19
|
+
inputs: {
|
|
20
|
+
components: {
|
|
21
|
+
internalType: string;
|
|
22
|
+
name: string;
|
|
23
|
+
type: string;
|
|
24
|
+
}[];
|
|
25
|
+
internalType: string;
|
|
26
|
+
name: string;
|
|
27
|
+
type: string;
|
|
28
|
+
}[];
|
|
29
|
+
name: string;
|
|
30
|
+
outputs: never[];
|
|
31
|
+
stateMutability: string;
|
|
32
|
+
type: string;
|
|
33
|
+
} | {
|
|
34
|
+
inputs: {
|
|
35
|
+
internalType: string;
|
|
36
|
+
name: string;
|
|
37
|
+
type: string;
|
|
38
|
+
}[];
|
|
39
|
+
name: string;
|
|
40
|
+
outputs: {
|
|
41
|
+
internalType: string;
|
|
42
|
+
name: string;
|
|
43
|
+
type: string;
|
|
44
|
+
}[];
|
|
45
|
+
stateMutability: string;
|
|
46
|
+
type: string;
|
|
47
|
+
})[];
|
|
48
|
+
export declare const CONTRACTS_BY_CHAIN: {
|
|
49
|
+
readonly 1: {
|
|
50
|
+
readonly YieldExtractor: "0x226239384EB7d78Cdf279BA6Fb458E2A4945E275";
|
|
51
|
+
};
|
|
52
|
+
readonly 146: {
|
|
53
|
+
readonly YieldExtractor: "0xB84B621D3da3E5e47A1927883C685455Ad731D7C";
|
|
54
|
+
};
|
|
55
|
+
readonly 8453: {
|
|
56
|
+
readonly YieldExtractor: "0x4d6a89dc55d8bacc0cbc3824bd7e44fa051c3958";
|
|
57
|
+
};
|
|
58
|
+
readonly 42161: {
|
|
59
|
+
readonly YieldExtractor: "0x79b7e90F1BAe837362DBD2c83Bd0715c2De5E47f";
|
|
60
|
+
};
|
|
61
|
+
readonly 43114: {
|
|
62
|
+
readonly YieldExtractor: "0x98732e2FEb854bAd400D4b5336f4439E7E53fe88";
|
|
63
|
+
};
|
|
64
|
+
};
|