@coinbase/agentkit 0.0.0-nightly-20250424210504 → 0.0.0-nightly-20250429210433
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 +142 -0
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.d.ts +37 -0
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.js +91 -0
- package/dist/action-providers/cdp-v2/index.d.ts +2 -0
- package/dist/action-providers/cdp-v2/index.js +18 -0
- package/dist/action-providers/cdp-v2/schemas.d.ts +11 -0
- package/dist/action-providers/cdp-v2/schemas.js +13 -0
- package/dist/action-providers/compound/schemas.d.ts +8 -8
- package/dist/action-providers/flaunch/utils.js +1 -1
- package/dist/action-providers/index.d.ts +1 -0
- package/dist/action-providers/index.js +1 -0
- package/dist/action-providers/twitter/twitterActionProvider.d.ts +8 -1
- package/dist/action-providers/twitter/twitterActionProvider.js +36 -18
- package/dist/action-providers/twitter/twitterActionProvider.test.js +45 -0
- package/dist/network/svm.d.ts +1 -0
- package/dist/network/svm.js +6 -1
- package/dist/wallet-providers/cdpV2EvmWalletProvider.d.ts +105 -0
- package/dist/wallet-providers/cdpV2EvmWalletProvider.js +212 -0
- package/dist/wallet-providers/cdpV2EvmWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/cdpV2EvmWalletProvider.test.js +343 -0
- package/dist/wallet-providers/cdpV2Shared.d.ts +41 -0
- package/dist/wallet-providers/cdpV2Shared.js +2 -0
- package/dist/wallet-providers/cdpV2SolanaWalletProvider.d.ts +111 -0
- package/dist/wallet-providers/cdpV2SolanaWalletProvider.js +247 -0
- package/dist/wallet-providers/cdpV2SolanaWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/cdpV2SolanaWalletProvider.test.js +307 -0
- package/dist/wallet-providers/cdpV2WalletProvider.d.ts +35 -0
- package/dist/wallet-providers/cdpV2WalletProvider.js +42 -0
- package/dist/wallet-providers/index.d.ts +4 -0
- package/dist/wallet-providers/index.js +4 -0
- package/package.json +2 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { CdpClient } from "@coinbase/cdp-sdk";
|
|
2
|
+
import { Abi, Address, ContractFunctionArgs, ContractFunctionName, Hex, ReadContractParameters, ReadContractReturnType, TransactionRequest } from "viem";
|
|
3
|
+
import { Network } from "../network";
|
|
4
|
+
import { EvmWalletProvider } from "./evmWalletProvider";
|
|
5
|
+
import { WalletProviderWithClient, CdpV2WalletProviderConfig } from "./cdpV2Shared";
|
|
6
|
+
/**
|
|
7
|
+
* A wallet provider that uses the Coinbase SDK.
|
|
8
|
+
*/
|
|
9
|
+
export declare class CdpV2EvmWalletProvider extends EvmWalletProvider implements WalletProviderWithClient {
|
|
10
|
+
#private;
|
|
11
|
+
/**
|
|
12
|
+
* Constructs a new CdpWalletProvider.
|
|
13
|
+
*
|
|
14
|
+
* @param config - The configuration options for the CdpWalletProvider.
|
|
15
|
+
*/
|
|
16
|
+
private constructor();
|
|
17
|
+
/**
|
|
18
|
+
* Configures a new CdpWalletProvider with a wallet.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Optional configuration parameters
|
|
21
|
+
* @returns A Promise that resolves to a new CdpWalletProvider instance
|
|
22
|
+
* @throws Error if required environment variables are missing or wallet initialization fails
|
|
23
|
+
*/
|
|
24
|
+
static configureWithWallet(config?: CdpV2WalletProviderConfig): Promise<CdpV2EvmWalletProvider>;
|
|
25
|
+
/**
|
|
26
|
+
* Signs a message.
|
|
27
|
+
*
|
|
28
|
+
* @param message - The message to sign.
|
|
29
|
+
* @returns The signed message.
|
|
30
|
+
*/
|
|
31
|
+
signMessage(message: string): Promise<Hex>;
|
|
32
|
+
/**
|
|
33
|
+
* Signs a typed data object.
|
|
34
|
+
*
|
|
35
|
+
* @param typedData - The typed data object to sign.
|
|
36
|
+
* @returns The signed typed data object.
|
|
37
|
+
*/
|
|
38
|
+
signTypedData(typedData: any): Promise<Hex>;
|
|
39
|
+
/**
|
|
40
|
+
* Signs a transaction.
|
|
41
|
+
*
|
|
42
|
+
* @param transaction - The transaction to sign.
|
|
43
|
+
* @returns The signed transaction.
|
|
44
|
+
*/
|
|
45
|
+
signTransaction(transaction: TransactionRequest): Promise<Hex>;
|
|
46
|
+
/**
|
|
47
|
+
* Sends a transaction.
|
|
48
|
+
*
|
|
49
|
+
* @param transaction - The transaction to send.
|
|
50
|
+
* @returns The hash of the transaction.
|
|
51
|
+
*/
|
|
52
|
+
sendTransaction(transaction: TransactionRequest): Promise<Hex>;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the address of the wallet.
|
|
55
|
+
*
|
|
56
|
+
* @returns The address of the wallet.
|
|
57
|
+
*/
|
|
58
|
+
getAddress(): string;
|
|
59
|
+
/**
|
|
60
|
+
* Gets the network of the wallet.
|
|
61
|
+
*
|
|
62
|
+
* @returns The network of the wallet.
|
|
63
|
+
*/
|
|
64
|
+
getNetwork(): Network;
|
|
65
|
+
/**
|
|
66
|
+
* Gets the name of the wallet provider.
|
|
67
|
+
*
|
|
68
|
+
* @returns The name of the wallet provider.
|
|
69
|
+
*/
|
|
70
|
+
getName(): string;
|
|
71
|
+
/**
|
|
72
|
+
* Gets the CDP client.
|
|
73
|
+
*
|
|
74
|
+
* @returns The CDP client.
|
|
75
|
+
*/
|
|
76
|
+
getClient(): CdpClient;
|
|
77
|
+
/**
|
|
78
|
+
* Gets the balance of the wallet.
|
|
79
|
+
*
|
|
80
|
+
* @returns The balance of the wallet in wei
|
|
81
|
+
*/
|
|
82
|
+
getBalance(): Promise<bigint>;
|
|
83
|
+
/**
|
|
84
|
+
* Waits for a transaction receipt.
|
|
85
|
+
*
|
|
86
|
+
* @param txHash - The hash of the transaction to wait for.
|
|
87
|
+
* @returns The transaction receipt.
|
|
88
|
+
*/
|
|
89
|
+
waitForTransactionReceipt(txHash: Hex): Promise<any>;
|
|
90
|
+
/**
|
|
91
|
+
* Reads a contract.
|
|
92
|
+
*
|
|
93
|
+
* @param params - The parameters to read the contract.
|
|
94
|
+
* @returns The response from the contract.
|
|
95
|
+
*/
|
|
96
|
+
readContract<const abi extends Abi | readonly unknown[], functionName extends ContractFunctionName<abi, "pure" | "view">, const args extends ContractFunctionArgs<abi, "pure" | "view", functionName>>(params: ReadContractParameters<abi, functionName, args>): Promise<ReadContractReturnType<abi, functionName, args>>;
|
|
97
|
+
/**
|
|
98
|
+
* Transfer the native asset of the network.
|
|
99
|
+
*
|
|
100
|
+
* @param to - The destination address.
|
|
101
|
+
* @param value - The amount to transfer in Wei.
|
|
102
|
+
* @returns The transaction hash.
|
|
103
|
+
*/
|
|
104
|
+
nativeTransfer(to: Address, value: string): Promise<Hex>;
|
|
105
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
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");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
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");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _CdpV2EvmWalletProvider_instances, _CdpV2EvmWalletProvider_publicClient, _CdpV2EvmWalletProvider_serverAccount, _CdpV2EvmWalletProvider_cdp, _CdpV2EvmWalletProvider_network, _CdpV2EvmWalletProvider_getCdpSdkNetwork;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CdpV2EvmWalletProvider = void 0;
|
|
16
|
+
const cdp_sdk_1 = require("@coinbase/cdp-sdk");
|
|
17
|
+
const viem_1 = require("viem");
|
|
18
|
+
const network_1 = require("../network");
|
|
19
|
+
const evmWalletProvider_1 = require("./evmWalletProvider");
|
|
20
|
+
/**
|
|
21
|
+
* A wallet provider that uses the Coinbase SDK.
|
|
22
|
+
*/
|
|
23
|
+
class CdpV2EvmWalletProvider extends evmWalletProvider_1.EvmWalletProvider {
|
|
24
|
+
/**
|
|
25
|
+
* Constructs a new CdpWalletProvider.
|
|
26
|
+
*
|
|
27
|
+
* @param config - The configuration options for the CdpWalletProvider.
|
|
28
|
+
*/
|
|
29
|
+
constructor(config) {
|
|
30
|
+
super();
|
|
31
|
+
_CdpV2EvmWalletProvider_instances.add(this);
|
|
32
|
+
_CdpV2EvmWalletProvider_publicClient.set(this, void 0);
|
|
33
|
+
_CdpV2EvmWalletProvider_serverAccount.set(this, void 0);
|
|
34
|
+
_CdpV2EvmWalletProvider_cdp.set(this, void 0);
|
|
35
|
+
_CdpV2EvmWalletProvider_network.set(this, void 0);
|
|
36
|
+
__classPrivateFieldSet(this, _CdpV2EvmWalletProvider_serverAccount, config.serverAccount, "f");
|
|
37
|
+
__classPrivateFieldSet(this, _CdpV2EvmWalletProvider_cdp, config.cdp, "f");
|
|
38
|
+
__classPrivateFieldSet(this, _CdpV2EvmWalletProvider_publicClient, config.publicClient, "f");
|
|
39
|
+
__classPrivateFieldSet(this, _CdpV2EvmWalletProvider_network, config.network, "f");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Configures a new CdpWalletProvider with a wallet.
|
|
43
|
+
*
|
|
44
|
+
* @param config - Optional configuration parameters
|
|
45
|
+
* @returns A Promise that resolves to a new CdpWalletProvider instance
|
|
46
|
+
* @throws Error if required environment variables are missing or wallet initialization fails
|
|
47
|
+
*/
|
|
48
|
+
static async configureWithWallet(config = {}) {
|
|
49
|
+
const apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
|
|
50
|
+
const apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
|
|
51
|
+
const walletSecret = config.walletSecret || process.env.CDP_WALLET_SECRET;
|
|
52
|
+
const idempotencyKey = config.idempotencyKey || process.env.IDEMPOTENCY_KEY;
|
|
53
|
+
if (!apiKeyId || !apiKeySecret || !walletSecret) {
|
|
54
|
+
throw new Error("Missing required environment variables. CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET are required.");
|
|
55
|
+
}
|
|
56
|
+
const networkId = config.networkId || process.env.NETWORK_ID || "base-sepolia";
|
|
57
|
+
const network = {
|
|
58
|
+
protocolFamily: "evm",
|
|
59
|
+
chainId: network_1.NETWORK_ID_TO_CHAIN_ID[networkId],
|
|
60
|
+
networkId: networkId,
|
|
61
|
+
};
|
|
62
|
+
const cdpClient = new cdp_sdk_1.CdpClient({
|
|
63
|
+
apiKeyId,
|
|
64
|
+
apiKeySecret,
|
|
65
|
+
walletSecret,
|
|
66
|
+
});
|
|
67
|
+
const serverAccount = await (config.address
|
|
68
|
+
? cdpClient.evm.getAccount({ address: config.address })
|
|
69
|
+
: cdpClient.evm.createAccount({ idempotencyKey }));
|
|
70
|
+
const publicClient = (0, viem_1.createPublicClient)({
|
|
71
|
+
chain: network_1.NETWORK_ID_TO_VIEM_CHAIN[networkId],
|
|
72
|
+
transport: (0, viem_1.http)(),
|
|
73
|
+
});
|
|
74
|
+
return new CdpV2EvmWalletProvider({
|
|
75
|
+
publicClient,
|
|
76
|
+
cdp: cdpClient,
|
|
77
|
+
serverAccount,
|
|
78
|
+
network,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Signs a message.
|
|
83
|
+
*
|
|
84
|
+
* @param message - The message to sign.
|
|
85
|
+
* @returns The signed message.
|
|
86
|
+
*/
|
|
87
|
+
async signMessage(message) {
|
|
88
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").signMessage({ message });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Signs a typed data object.
|
|
92
|
+
*
|
|
93
|
+
* @param typedData - The typed data object to sign.
|
|
94
|
+
* @returns The signed typed data object.
|
|
95
|
+
*/
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
97
|
+
async signTypedData(typedData) {
|
|
98
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").signTypedData(typedData);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Signs a transaction.
|
|
102
|
+
*
|
|
103
|
+
* @param transaction - The transaction to sign.
|
|
104
|
+
* @returns The signed transaction.
|
|
105
|
+
*/
|
|
106
|
+
async signTransaction(transaction) {
|
|
107
|
+
const serializedTx = (0, viem_1.serializeTransaction)(transaction);
|
|
108
|
+
const signedTx = await __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_cdp, "f").evm.signTransaction({
|
|
109
|
+
address: __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").address,
|
|
110
|
+
transaction: serializedTx,
|
|
111
|
+
});
|
|
112
|
+
return signedTx.signature;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sends a transaction.
|
|
116
|
+
*
|
|
117
|
+
* @param transaction - The transaction to send.
|
|
118
|
+
* @returns The hash of the transaction.
|
|
119
|
+
*/
|
|
120
|
+
async sendTransaction(transaction) {
|
|
121
|
+
const result = await __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_cdp, "f").evm.sendTransaction({
|
|
122
|
+
address: __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").address,
|
|
123
|
+
transaction: (0, viem_1.serializeTransaction)(transaction),
|
|
124
|
+
network: __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_instances, "m", _CdpV2EvmWalletProvider_getCdpSdkNetwork).call(this),
|
|
125
|
+
});
|
|
126
|
+
return result.transactionHash;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Gets the address of the wallet.
|
|
130
|
+
*
|
|
131
|
+
* @returns The address of the wallet.
|
|
132
|
+
*/
|
|
133
|
+
getAddress() {
|
|
134
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").address;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Gets the network of the wallet.
|
|
138
|
+
*
|
|
139
|
+
* @returns The network of the wallet.
|
|
140
|
+
*/
|
|
141
|
+
getNetwork() {
|
|
142
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_network, "f");
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Gets the name of the wallet provider.
|
|
146
|
+
*
|
|
147
|
+
* @returns The name of the wallet provider.
|
|
148
|
+
*/
|
|
149
|
+
getName() {
|
|
150
|
+
return "cdp_v2_wallet_provider";
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets the CDP client.
|
|
154
|
+
*
|
|
155
|
+
* @returns The CDP client.
|
|
156
|
+
*/
|
|
157
|
+
getClient() {
|
|
158
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_cdp, "f");
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Gets the balance of the wallet.
|
|
162
|
+
*
|
|
163
|
+
* @returns The balance of the wallet in wei
|
|
164
|
+
*/
|
|
165
|
+
async getBalance() {
|
|
166
|
+
return await __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_publicClient, "f").getBalance({ address: __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_serverAccount, "f").address });
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Waits for a transaction receipt.
|
|
170
|
+
*
|
|
171
|
+
* @param txHash - The hash of the transaction to wait for.
|
|
172
|
+
* @returns The transaction receipt.
|
|
173
|
+
*/
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
async waitForTransactionReceipt(txHash) {
|
|
176
|
+
return await __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_publicClient, "f").waitForTransactionReceipt({ hash: txHash });
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Reads a contract.
|
|
180
|
+
*
|
|
181
|
+
* @param params - The parameters to read the contract.
|
|
182
|
+
* @returns The response from the contract.
|
|
183
|
+
*/
|
|
184
|
+
async readContract(params) {
|
|
185
|
+
return __classPrivateFieldGet(this, _CdpV2EvmWalletProvider_publicClient, "f").readContract(params);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Transfer the native asset of the network.
|
|
189
|
+
*
|
|
190
|
+
* @param to - The destination address.
|
|
191
|
+
* @param value - The amount to transfer in Wei.
|
|
192
|
+
* @returns The transaction hash.
|
|
193
|
+
*/
|
|
194
|
+
async nativeTransfer(to, value) {
|
|
195
|
+
return this.sendTransaction({
|
|
196
|
+
to: to,
|
|
197
|
+
value: BigInt(value),
|
|
198
|
+
data: "0x",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.CdpV2EvmWalletProvider = CdpV2EvmWalletProvider;
|
|
203
|
+
_CdpV2EvmWalletProvider_publicClient = new WeakMap(), _CdpV2EvmWalletProvider_serverAccount = new WeakMap(), _CdpV2EvmWalletProvider_cdp = new WeakMap(), _CdpV2EvmWalletProvider_network = new WeakMap(), _CdpV2EvmWalletProvider_instances = new WeakSet(), _CdpV2EvmWalletProvider_getCdpSdkNetwork = function _CdpV2EvmWalletProvider_getCdpSdkNetwork() {
|
|
204
|
+
switch (__classPrivateFieldGet(this, _CdpV2EvmWalletProvider_network, "f").networkId) {
|
|
205
|
+
case "base-sepolia":
|
|
206
|
+
return "base-sepolia";
|
|
207
|
+
case "base-mainnet":
|
|
208
|
+
return "base";
|
|
209
|
+
default:
|
|
210
|
+
throw new Error(`Unsupported network: ${__classPrivateFieldGet(this, _CdpV2EvmWalletProvider_network, "f").networkId}`);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cdp_sdk_1 = require("@coinbase/cdp-sdk");
|
|
4
|
+
const cdpV2EvmWalletProvider_1 = require("./cdpV2EvmWalletProvider");
|
|
5
|
+
// =========================================================
|
|
6
|
+
// consts
|
|
7
|
+
// =========================================================
|
|
8
|
+
const mockPublicClient = {
|
|
9
|
+
waitForTransactionReceipt: jest.fn(),
|
|
10
|
+
readContract: jest.fn(),
|
|
11
|
+
getTransactionCount: jest.fn(),
|
|
12
|
+
estimateFeesPerGas: jest.fn(),
|
|
13
|
+
estimateGas: jest.fn(),
|
|
14
|
+
getBalance: jest.fn(),
|
|
15
|
+
};
|
|
16
|
+
const mockWalletClient = {
|
|
17
|
+
sendTransaction: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
// =========================================================
|
|
20
|
+
// mocks
|
|
21
|
+
// =========================================================
|
|
22
|
+
jest.mock("../analytics", () => ({
|
|
23
|
+
sendAnalyticsEvent: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
24
|
+
}));
|
|
25
|
+
jest.mock("../../package.json", () => ({
|
|
26
|
+
version: "1.0.0",
|
|
27
|
+
}));
|
|
28
|
+
jest.mock("viem", () => {
|
|
29
|
+
return {
|
|
30
|
+
createPublicClient: jest.fn(() => mockPublicClient),
|
|
31
|
+
createWalletClient: jest.fn(() => mockWalletClient),
|
|
32
|
+
http: jest.fn(),
|
|
33
|
+
serializeTransaction: jest.fn((_tx) => "0xserialized"),
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
jest.mock("../network", () => {
|
|
37
|
+
return {
|
|
38
|
+
NETWORK_ID_TO_CHAIN_ID: {
|
|
39
|
+
"base-mainnet": "8453",
|
|
40
|
+
"base-sepolia": "84532",
|
|
41
|
+
},
|
|
42
|
+
NETWORK_ID_TO_VIEM_CHAIN: {
|
|
43
|
+
"base-mainnet": { id: 8453 },
|
|
44
|
+
"base-sepolia": { id: 84532 },
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
// Mock CdpClient
|
|
49
|
+
jest.mock("@coinbase/cdp-sdk", () => {
|
|
50
|
+
const MOCK_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
|
|
51
|
+
const MOCK_SIGNATURE = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1b01";
|
|
52
|
+
const mockCreateAccount = jest.fn().mockImplementation(() => Promise.resolve({
|
|
53
|
+
address: MOCK_ADDRESS,
|
|
54
|
+
signMessage: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
55
|
+
signTypedData: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
56
|
+
signTransaction: jest.fn().mockResolvedValue({ signature: MOCK_SIGNATURE }),
|
|
57
|
+
}));
|
|
58
|
+
const mockSignTransaction = jest
|
|
59
|
+
.fn()
|
|
60
|
+
.mockImplementation(async () => ({ signature: MOCK_SIGNATURE }));
|
|
61
|
+
const mockSendTransaction = jest
|
|
62
|
+
.fn()
|
|
63
|
+
.mockImplementation(async () => ({ transactionHash: MOCK_TRANSACTION_HASH }));
|
|
64
|
+
const mockEvmClient = {
|
|
65
|
+
createAccount: mockCreateAccount,
|
|
66
|
+
getAccount: jest.fn(),
|
|
67
|
+
signTransaction: mockSignTransaction,
|
|
68
|
+
sendTransaction: mockSendTransaction,
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
CdpClient: jest.fn().mockImplementation(() => ({
|
|
72
|
+
evm: mockEvmClient,
|
|
73
|
+
})),
|
|
74
|
+
EvmServerAccount: jest.fn().mockImplementation(() => ({
|
|
75
|
+
address: MOCK_ADDRESS,
|
|
76
|
+
signMessage: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
77
|
+
signTypedData: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
78
|
+
signTransaction: jest.fn().mockResolvedValue({ signature: MOCK_SIGNATURE }),
|
|
79
|
+
})),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
// =========================================================
|
|
83
|
+
// test constants
|
|
84
|
+
// =========================================================
|
|
85
|
+
const MOCK_ADDRESS = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
|
|
86
|
+
const MOCK_NETWORK_ID = "base-mainnet";
|
|
87
|
+
const MOCK_TRANSACTION_HASH = "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba";
|
|
88
|
+
const MOCK_SIGNATURE = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1b01";
|
|
89
|
+
const MOCK_BALANCE = 1000000000000000000n;
|
|
90
|
+
const MOCK_NETWORK = {
|
|
91
|
+
protocolFamily: "evm",
|
|
92
|
+
networkId: MOCK_NETWORK_ID,
|
|
93
|
+
chainId: "8453",
|
|
94
|
+
};
|
|
95
|
+
const MOCK_TRANSACTION_RECEIPT = {
|
|
96
|
+
transactionHash: MOCK_TRANSACTION_HASH,
|
|
97
|
+
};
|
|
98
|
+
describe("CdpV2EvmWalletProvider", () => {
|
|
99
|
+
let provider;
|
|
100
|
+
let mockCdpClient;
|
|
101
|
+
let mockServerAccount;
|
|
102
|
+
let mockSignTransaction;
|
|
103
|
+
let mockSendTransaction;
|
|
104
|
+
beforeEach(async () => {
|
|
105
|
+
jest.clearAllMocks();
|
|
106
|
+
mockSignTransaction = jest.fn().mockImplementation(async () => ({ signature: MOCK_SIGNATURE }));
|
|
107
|
+
mockSendTransaction = jest
|
|
108
|
+
.fn()
|
|
109
|
+
.mockImplementation(async () => ({ transactionHash: MOCK_TRANSACTION_HASH }));
|
|
110
|
+
mockCdpClient = new cdp_sdk_1.CdpClient({
|
|
111
|
+
apiKeyId: "test-key-id",
|
|
112
|
+
apiKeySecret: "test-key-secret",
|
|
113
|
+
walletSecret: "test-wallet-secret",
|
|
114
|
+
});
|
|
115
|
+
mockServerAccount = {
|
|
116
|
+
address: MOCK_ADDRESS,
|
|
117
|
+
signMessage: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
118
|
+
signTypedData: jest.fn().mockResolvedValue(MOCK_SIGNATURE),
|
|
119
|
+
};
|
|
120
|
+
// Set up the mock server account for the provider
|
|
121
|
+
mockCdpClient.evm.createAccount.mockResolvedValue(mockServerAccount);
|
|
122
|
+
mockCdpClient.evm.signTransaction = mockSignTransaction;
|
|
123
|
+
mockCdpClient.evm.sendTransaction = mockSendTransaction;
|
|
124
|
+
mockPublicClient.waitForTransactionReceipt.mockResolvedValue(MOCK_TRANSACTION_RECEIPT);
|
|
125
|
+
mockPublicClient.readContract.mockResolvedValue("mock_result");
|
|
126
|
+
mockPublicClient.getTransactionCount.mockResolvedValue(1);
|
|
127
|
+
mockPublicClient.estimateFeesPerGas.mockResolvedValue({
|
|
128
|
+
maxFeePerGas: BigInt(100000000),
|
|
129
|
+
maxPriorityFeePerGas: BigInt(10000000),
|
|
130
|
+
});
|
|
131
|
+
mockPublicClient.estimateGas.mockResolvedValue(BigInt(21000));
|
|
132
|
+
mockPublicClient.getBalance.mockResolvedValue(MOCK_BALANCE);
|
|
133
|
+
mockWalletClient.sendTransaction.mockResolvedValue(MOCK_TRANSACTION_HASH);
|
|
134
|
+
provider = await cdpV2EvmWalletProvider_1.CdpV2EvmWalletProvider.configureWithWallet({
|
|
135
|
+
apiKeyId: "test-key-id",
|
|
136
|
+
apiKeySecret: "test-key-secret",
|
|
137
|
+
walletSecret: "test-wallet-secret",
|
|
138
|
+
networkId: MOCK_NETWORK_ID,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// =========================================================
|
|
142
|
+
// initialization tests
|
|
143
|
+
// =========================================================
|
|
144
|
+
describe("initialization", () => {
|
|
145
|
+
it("should initialize with API keys", async () => {
|
|
146
|
+
const provider = await cdpV2EvmWalletProvider_1.CdpV2EvmWalletProvider.configureWithWallet({
|
|
147
|
+
apiKeyId: "test-key-id",
|
|
148
|
+
apiKeySecret: "test-key-secret",
|
|
149
|
+
walletSecret: "test-wallet-secret",
|
|
150
|
+
networkId: MOCK_NETWORK_ID,
|
|
151
|
+
});
|
|
152
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
153
|
+
expect(provider.getNetwork()).toEqual(MOCK_NETWORK);
|
|
154
|
+
});
|
|
155
|
+
it("should default to base-sepolia if network not provided", async () => {
|
|
156
|
+
const provider = await cdpV2EvmWalletProvider_1.CdpV2EvmWalletProvider.configureWithWallet({
|
|
157
|
+
apiKeyId: "test-key-id",
|
|
158
|
+
apiKeySecret: "test-key-secret",
|
|
159
|
+
walletSecret: "test-wallet-secret",
|
|
160
|
+
});
|
|
161
|
+
expect(provider.getNetwork().networkId).toBe("base-sepolia");
|
|
162
|
+
});
|
|
163
|
+
it("should handle initialization failures gracefully", async () => {
|
|
164
|
+
// Create a new mock client for this test
|
|
165
|
+
const mockCreateAccount = jest.fn().mockRejectedValue(new Error("Failed to create account"));
|
|
166
|
+
const mockEvmClient = {
|
|
167
|
+
createAccount: mockCreateAccount,
|
|
168
|
+
getAccount: jest.fn(),
|
|
169
|
+
signTransaction: jest.fn(),
|
|
170
|
+
};
|
|
171
|
+
// Override the mock for this test
|
|
172
|
+
const mockCdpClient = new cdp_sdk_1.CdpClient({
|
|
173
|
+
apiKeyId: "test-key-id",
|
|
174
|
+
apiKeySecret: "test-key-secret",
|
|
175
|
+
walletSecret: "test-wallet-secret",
|
|
176
|
+
});
|
|
177
|
+
mockCdpClient.evm = mockEvmClient;
|
|
178
|
+
// Override the CdpClient constructor mock
|
|
179
|
+
cdp_sdk_1.CdpClient.mockImplementation(() => mockCdpClient);
|
|
180
|
+
await expect(cdpV2EvmWalletProvider_1.CdpV2EvmWalletProvider.configureWithWallet({
|
|
181
|
+
apiKeyId: "test-key-id",
|
|
182
|
+
apiKeySecret: "test-key-secret",
|
|
183
|
+
walletSecret: "test-wallet-secret",
|
|
184
|
+
networkId: MOCK_NETWORK_ID,
|
|
185
|
+
})).rejects.toThrow("Failed to create account");
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
// =========================================================
|
|
189
|
+
// basic wallet method tests
|
|
190
|
+
// =========================================================
|
|
191
|
+
describe("basic wallet methods", () => {
|
|
192
|
+
it("should get the address", () => {
|
|
193
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
194
|
+
});
|
|
195
|
+
it("should get the network", () => {
|
|
196
|
+
expect(provider.getNetwork()).toEqual(MOCK_NETWORK);
|
|
197
|
+
});
|
|
198
|
+
it("should get the name", () => {
|
|
199
|
+
expect(provider.getName()).toBe("cdp_v2_wallet_provider");
|
|
200
|
+
});
|
|
201
|
+
it("should get the balance", async () => {
|
|
202
|
+
const balance = await provider.getBalance();
|
|
203
|
+
expect(balance).toBe(MOCK_BALANCE);
|
|
204
|
+
expect(mockPublicClient.getBalance).toHaveBeenCalledWith({
|
|
205
|
+
address: MOCK_ADDRESS,
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
it("should handle connection errors during balance check", async () => {
|
|
209
|
+
mockPublicClient.getBalance.mockRejectedValueOnce(new Error("Network connection error"));
|
|
210
|
+
await expect(provider.getBalance()).rejects.toThrow("Network connection error");
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
// =========================================================
|
|
214
|
+
// signing operation tests
|
|
215
|
+
// =========================================================
|
|
216
|
+
describe("signing operations", () => {
|
|
217
|
+
it("should sign messages", async () => {
|
|
218
|
+
const signature = await provider.signMessage("Hello, world!");
|
|
219
|
+
expect(mockServerAccount.signMessage).toHaveBeenCalledWith({ message: "Hello, world!" });
|
|
220
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
221
|
+
});
|
|
222
|
+
it("should sign typed data", async () => {
|
|
223
|
+
const typedData = {
|
|
224
|
+
domain: { name: "Example" },
|
|
225
|
+
types: { Test: [{ name: "test", type: "string" }] },
|
|
226
|
+
message: { test: "example" },
|
|
227
|
+
primaryType: "Test",
|
|
228
|
+
};
|
|
229
|
+
const signature = await provider.signTypedData(typedData);
|
|
230
|
+
expect(mockServerAccount.signTypedData).toHaveBeenCalledWith(typedData);
|
|
231
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
232
|
+
});
|
|
233
|
+
it("should sign transactions", async () => {
|
|
234
|
+
const tx = {
|
|
235
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
236
|
+
value: BigInt(1000000000000000000),
|
|
237
|
+
};
|
|
238
|
+
const signature = await provider.signTransaction(tx);
|
|
239
|
+
expect(mockCdpClient.evm.signTransaction).toHaveBeenCalledWith({
|
|
240
|
+
address: MOCK_ADDRESS,
|
|
241
|
+
transaction: expect.any(String),
|
|
242
|
+
});
|
|
243
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
244
|
+
});
|
|
245
|
+
it("should handle signing failures", async () => {
|
|
246
|
+
// Create a failing mock for this test
|
|
247
|
+
const mockFailingSignTransaction = jest.fn().mockRejectedValue(new Error("Signing failed"));
|
|
248
|
+
mockCdpClient.evm.signTransaction = mockFailingSignTransaction;
|
|
249
|
+
const tx = {
|
|
250
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
251
|
+
value: BigInt(1000000000000000000),
|
|
252
|
+
};
|
|
253
|
+
await expect(provider.signTransaction(tx)).rejects.toThrow("Signing failed");
|
|
254
|
+
// Restore the original mock
|
|
255
|
+
mockCdpClient.evm.signTransaction = mockSignTransaction;
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
// =========================================================
|
|
259
|
+
// transaction operation tests
|
|
260
|
+
// =========================================================
|
|
261
|
+
describe("transaction operations", () => {
|
|
262
|
+
it("should send transactions", async () => {
|
|
263
|
+
const transaction = {
|
|
264
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
265
|
+
value: BigInt(1000000000000000000),
|
|
266
|
+
};
|
|
267
|
+
const txHash = await provider.sendTransaction(transaction);
|
|
268
|
+
expect(mockSendTransaction).toHaveBeenCalled();
|
|
269
|
+
expect(txHash).toBe(MOCK_TRANSACTION_HASH);
|
|
270
|
+
});
|
|
271
|
+
it("should handle transaction failures during send", async () => {
|
|
272
|
+
mockSendTransaction.mockRejectedValueOnce(new Error("Transaction signing failed"));
|
|
273
|
+
const transaction = {
|
|
274
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
275
|
+
value: BigInt(1000000000000000000),
|
|
276
|
+
};
|
|
277
|
+
await expect(provider.sendTransaction(transaction)).rejects.toThrow("Transaction signing failed");
|
|
278
|
+
});
|
|
279
|
+
it("should handle receipt timeout errors", async () => {
|
|
280
|
+
mockPublicClient.waitForTransactionReceipt.mockRejectedValueOnce(new Error("Timed out"));
|
|
281
|
+
const hash = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
282
|
+
await expect(provider.waitForTransactionReceipt(hash)).rejects.toThrow("Timed out");
|
|
283
|
+
});
|
|
284
|
+
it("should handle transaction with invalid address", async () => {
|
|
285
|
+
mockSendTransaction.mockRejectedValueOnce(new Error("Invalid address format"));
|
|
286
|
+
const invalidAddress = "not_a_valid_address";
|
|
287
|
+
const value = "1000000000000000000"; // 1 ETH in wei
|
|
288
|
+
await expect(provider.nativeTransfer(invalidAddress, value)).rejects.toThrow("Invalid address format");
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
// =========================================================
|
|
292
|
+
// contract interaction tests
|
|
293
|
+
// =========================================================
|
|
294
|
+
describe("contract interactions", () => {
|
|
295
|
+
it("should read contract data", async () => {
|
|
296
|
+
const abi = [
|
|
297
|
+
{
|
|
298
|
+
name: "balanceOf",
|
|
299
|
+
type: "function",
|
|
300
|
+
inputs: [{ name: "account", type: "address" }],
|
|
301
|
+
outputs: [{ name: "balance", type: "uint256" }],
|
|
302
|
+
stateMutability: "view",
|
|
303
|
+
},
|
|
304
|
+
];
|
|
305
|
+
const result = await provider.readContract({
|
|
306
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
307
|
+
abi,
|
|
308
|
+
functionName: "balanceOf",
|
|
309
|
+
args: [MOCK_ADDRESS],
|
|
310
|
+
});
|
|
311
|
+
expect(result).toBe("mock_result");
|
|
312
|
+
expect(mockPublicClient.readContract).toHaveBeenCalled();
|
|
313
|
+
});
|
|
314
|
+
it("should handle network errors during contract reads", async () => {
|
|
315
|
+
mockPublicClient.readContract.mockRejectedValueOnce(new Error("Contract read error"));
|
|
316
|
+
const abi = [
|
|
317
|
+
{
|
|
318
|
+
name: "balanceOf",
|
|
319
|
+
type: "function",
|
|
320
|
+
inputs: [{ name: "account", type: "address" }],
|
|
321
|
+
outputs: [{ name: "balance", type: "uint256" }],
|
|
322
|
+
stateMutability: "view",
|
|
323
|
+
},
|
|
324
|
+
];
|
|
325
|
+
await expect(provider.readContract({
|
|
326
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
327
|
+
abi,
|
|
328
|
+
functionName: "balanceOf",
|
|
329
|
+
args: [MOCK_ADDRESS],
|
|
330
|
+
})).rejects.toThrow("Contract read error");
|
|
331
|
+
});
|
|
332
|
+
it("should handle invalid ABI format in contract reads", async () => {
|
|
333
|
+
mockPublicClient.readContract.mockRejectedValueOnce(new TypeError("Invalid ABI format"));
|
|
334
|
+
const invalidAbi = "not_a_valid_abi";
|
|
335
|
+
await expect(provider.readContract({
|
|
336
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
337
|
+
abi: invalidAbi,
|
|
338
|
+
functionName: "balanceOf",
|
|
339
|
+
args: [MOCK_ADDRESS],
|
|
340
|
+
})).rejects.toThrow("Invalid ABI format");
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
});
|