@coinbase/agentkit 0.6.2 → 0.7.1
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 +234 -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 +2 -0
- package/dist/action-providers/index.js +2 -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/action-providers/zerodev/index.d.ts +1 -0
- package/dist/action-providers/zerodev/index.js +17 -0
- package/dist/action-providers/zerodev/schemas.d.ts +29 -0
- package/dist/action-providers/zerodev/schemas.js +21 -0
- package/dist/action-providers/zerodev/zeroDevWalletActionProvider.d.ts +32 -0
- package/dist/action-providers/zerodev/zeroDevWalletActionProvider.js +66 -0
- package/dist/action-providers/zerodev/zeroDevWalletActionProvider.test.d.ts +1 -0
- package/dist/action-providers/zerodev/zeroDevWalletActionProvider.test.js +112 -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/cdpWalletProvider.js +1 -1
- package/dist/wallet-providers/cdpWalletProvider.test.js +1 -0
- package/dist/wallet-providers/evmWalletProvider.d.ts +7 -1
- package/dist/wallet-providers/evmWalletProvider.js +20 -0
- package/dist/wallet-providers/index.d.ts +5 -0
- package/dist/wallet-providers/index.js +5 -0
- package/dist/wallet-providers/walletProvider.test.js +22 -0
- package/dist/wallet-providers/zeroDevWalletProvider.d.ts +147 -0
- package/dist/wallet-providers/zeroDevWalletProvider.js +301 -0
- package/dist/wallet-providers/zeroDevWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/zeroDevWalletProvider.test.js +435 -0
- package/package.json +5 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { CdpClient } from "@coinbase/cdp-sdk";
|
|
2
|
+
import { Connection, PublicKey, RpcResponseAndContext, SignatureResult, SignatureStatus, SignatureStatusConfig, VersionedTransaction } from "@solana/web3.js";
|
|
3
|
+
import { Network } from "../network";
|
|
4
|
+
import { WalletProviderWithClient, CdpV2WalletProviderConfig } from "./cdpV2Shared";
|
|
5
|
+
import { SvmWalletProvider } from "./svmWalletProvider";
|
|
6
|
+
/**
|
|
7
|
+
* A wallet provider that uses the Coinbase SDK.
|
|
8
|
+
*/
|
|
9
|
+
export declare class CdpV2SolanaWalletProvider extends SvmWalletProvider 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<CdpV2SolanaWalletProvider>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the connection instance
|
|
27
|
+
*
|
|
28
|
+
* @returns The Solana connection instance
|
|
29
|
+
*/
|
|
30
|
+
getConnection(): Connection;
|
|
31
|
+
/**
|
|
32
|
+
* Get the public key of the wallet
|
|
33
|
+
*
|
|
34
|
+
* @returns The wallet's public key
|
|
35
|
+
*/
|
|
36
|
+
getPublicKey(): PublicKey;
|
|
37
|
+
/**
|
|
38
|
+
* Get the address of the wallet
|
|
39
|
+
*
|
|
40
|
+
* @returns The base58 encoded address of the wallet
|
|
41
|
+
*/
|
|
42
|
+
getAddress(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Get the network
|
|
45
|
+
*
|
|
46
|
+
* @returns The network
|
|
47
|
+
*/
|
|
48
|
+
getNetwork(): Network;
|
|
49
|
+
/**
|
|
50
|
+
* Gets the name of the wallet provider.
|
|
51
|
+
*
|
|
52
|
+
* @returns The name of the wallet provider.
|
|
53
|
+
*/
|
|
54
|
+
getName(): string;
|
|
55
|
+
/**
|
|
56
|
+
* Sign a transaction
|
|
57
|
+
*
|
|
58
|
+
* @param transaction - The transaction to sign
|
|
59
|
+
* @returns The signed transaction
|
|
60
|
+
*/
|
|
61
|
+
signTransaction(transaction: VersionedTransaction): Promise<VersionedTransaction>;
|
|
62
|
+
/**
|
|
63
|
+
* Send a transaction
|
|
64
|
+
*
|
|
65
|
+
* @param transaction - The transaction to send
|
|
66
|
+
* @returns The signature
|
|
67
|
+
*/
|
|
68
|
+
sendTransaction(transaction: VersionedTransaction): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Sign and send a transaction
|
|
71
|
+
*
|
|
72
|
+
* @param transaction - The transaction to sign and send
|
|
73
|
+
* @returns The signature
|
|
74
|
+
*/
|
|
75
|
+
signAndSendTransaction(transaction: VersionedTransaction): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the status of a transaction
|
|
78
|
+
*
|
|
79
|
+
* @param signature - The signature
|
|
80
|
+
* @param options - The options for the status
|
|
81
|
+
* @returns The status
|
|
82
|
+
*/
|
|
83
|
+
getSignatureStatus(signature: string, options?: SignatureStatusConfig): Promise<RpcResponseAndContext<SignatureStatus | null>>;
|
|
84
|
+
/**
|
|
85
|
+
* Wait for signature receipt
|
|
86
|
+
*
|
|
87
|
+
* @param signature - The signature
|
|
88
|
+
* @returns The confirmation response
|
|
89
|
+
*/
|
|
90
|
+
waitForSignatureResult(signature: string): Promise<RpcResponseAndContext<SignatureResult>>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the balance of the wallet
|
|
93
|
+
*
|
|
94
|
+
* @returns The balance of the wallet
|
|
95
|
+
*/
|
|
96
|
+
getBalance(): Promise<bigint>;
|
|
97
|
+
/**
|
|
98
|
+
* Gets the CDP client.
|
|
99
|
+
*
|
|
100
|
+
* @returns The CDP client.
|
|
101
|
+
*/
|
|
102
|
+
getClient(): CdpClient;
|
|
103
|
+
/**
|
|
104
|
+
* Transfer SOL from the wallet to another address
|
|
105
|
+
*
|
|
106
|
+
* @param to - The base58 encoded address to transfer the SOL to
|
|
107
|
+
* @param value - The amount of SOL to transfer (as a decimal string, e.g. "0.0001")
|
|
108
|
+
* @returns The signature
|
|
109
|
+
*/
|
|
110
|
+
nativeTransfer(to: string, value: string): Promise<string>;
|
|
111
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
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 _CdpV2SolanaWalletProvider_connection, _CdpV2SolanaWalletProvider_serverAccount, _CdpV2SolanaWalletProvider_cdp, _CdpV2SolanaWalletProvider_network;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CdpV2SolanaWalletProvider = void 0;
|
|
16
|
+
const cdp_sdk_1 = require("@coinbase/cdp-sdk");
|
|
17
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
18
|
+
const svm_1 = require("../network/svm");
|
|
19
|
+
const svmWalletProvider_1 = require("./svmWalletProvider");
|
|
20
|
+
/**
|
|
21
|
+
* A wallet provider that uses the Coinbase SDK.
|
|
22
|
+
*/
|
|
23
|
+
class CdpV2SolanaWalletProvider extends svmWalletProvider_1.SvmWalletProvider {
|
|
24
|
+
/**
|
|
25
|
+
* Constructs a new CdpWalletProvider.
|
|
26
|
+
*
|
|
27
|
+
* @param config - The configuration options for the CdpWalletProvider.
|
|
28
|
+
*/
|
|
29
|
+
constructor(config) {
|
|
30
|
+
super();
|
|
31
|
+
_CdpV2SolanaWalletProvider_connection.set(this, void 0);
|
|
32
|
+
_CdpV2SolanaWalletProvider_serverAccount.set(this, void 0);
|
|
33
|
+
_CdpV2SolanaWalletProvider_cdp.set(this, void 0);
|
|
34
|
+
_CdpV2SolanaWalletProvider_network.set(this, void 0);
|
|
35
|
+
__classPrivateFieldSet(this, _CdpV2SolanaWalletProvider_serverAccount, config.serverAccount, "f");
|
|
36
|
+
__classPrivateFieldSet(this, _CdpV2SolanaWalletProvider_cdp, config.cdp, "f");
|
|
37
|
+
__classPrivateFieldSet(this, _CdpV2SolanaWalletProvider_connection, config.connection, "f");
|
|
38
|
+
__classPrivateFieldSet(this, _CdpV2SolanaWalletProvider_network, config.network, "f");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Configures a new CdpWalletProvider with a wallet.
|
|
42
|
+
*
|
|
43
|
+
* @param config - Optional configuration parameters
|
|
44
|
+
* @returns A Promise that resolves to a new CdpWalletProvider instance
|
|
45
|
+
* @throws Error if required environment variables are missing or wallet initialization fails
|
|
46
|
+
*/
|
|
47
|
+
static async configureWithWallet(config = {}) {
|
|
48
|
+
const apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
|
|
49
|
+
const apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
|
|
50
|
+
const walletSecret = config.walletSecret || process.env.CDP_WALLET_SECRET;
|
|
51
|
+
const idempotencyKey = config.idempotencyKey || process.env.IDEMPOTENCY_KEY;
|
|
52
|
+
if (!apiKeyId || !apiKeySecret || !walletSecret) {
|
|
53
|
+
throw new Error("Missing required environment variables. CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET are required.");
|
|
54
|
+
}
|
|
55
|
+
const networkId = config.networkId || process.env.NETWORK_ID || "solana-devnet";
|
|
56
|
+
let network;
|
|
57
|
+
let rpcUrl;
|
|
58
|
+
switch (networkId) {
|
|
59
|
+
case svm_1.SOLANA_MAINNET_NETWORK_ID:
|
|
60
|
+
network = svm_1.SOLANA_MAINNET_NETWORK;
|
|
61
|
+
rpcUrl = (0, web3_js_1.clusterApiUrl)("mainnet-beta");
|
|
62
|
+
break;
|
|
63
|
+
case svm_1.SOLANA_DEVNET_NETWORK_ID:
|
|
64
|
+
network = svm_1.SOLANA_DEVNET_NETWORK;
|
|
65
|
+
rpcUrl = (0, web3_js_1.clusterApiUrl)("devnet");
|
|
66
|
+
break;
|
|
67
|
+
case svm_1.SOLANA_TESTNET_NETWORK_ID:
|
|
68
|
+
network = svm_1.SOLANA_TESTNET_NETWORK;
|
|
69
|
+
rpcUrl = (0, web3_js_1.clusterApiUrl)("testnet");
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`${networkId} is not a valid SVM networkId`);
|
|
73
|
+
}
|
|
74
|
+
const cdpClient = new cdp_sdk_1.CdpClient({
|
|
75
|
+
apiKeyId,
|
|
76
|
+
apiKeySecret,
|
|
77
|
+
walletSecret,
|
|
78
|
+
});
|
|
79
|
+
const connection = new web3_js_1.Connection(rpcUrl);
|
|
80
|
+
const serverAccount = await (config.address
|
|
81
|
+
? cdpClient.solana.getAccount({ address: config.address })
|
|
82
|
+
: cdpClient.solana.createAccount({ idempotencyKey }));
|
|
83
|
+
return new CdpV2SolanaWalletProvider({
|
|
84
|
+
connection,
|
|
85
|
+
cdp: cdpClient,
|
|
86
|
+
serverAccount,
|
|
87
|
+
network,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the connection instance
|
|
92
|
+
*
|
|
93
|
+
* @returns The Solana connection instance
|
|
94
|
+
*/
|
|
95
|
+
getConnection() {
|
|
96
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f");
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get the public key of the wallet
|
|
100
|
+
*
|
|
101
|
+
* @returns The wallet's public key
|
|
102
|
+
*/
|
|
103
|
+
getPublicKey() {
|
|
104
|
+
return new web3_js_1.PublicKey(__classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_serverAccount, "f").address);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the address of the wallet
|
|
108
|
+
*
|
|
109
|
+
* @returns The base58 encoded address of the wallet
|
|
110
|
+
*/
|
|
111
|
+
getAddress() {
|
|
112
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_serverAccount, "f").address;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get the network
|
|
116
|
+
*
|
|
117
|
+
* @returns The network
|
|
118
|
+
*/
|
|
119
|
+
getNetwork() {
|
|
120
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_network, "f");
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Gets the name of the wallet provider.
|
|
124
|
+
*
|
|
125
|
+
* @returns The name of the wallet provider.
|
|
126
|
+
*/
|
|
127
|
+
getName() {
|
|
128
|
+
return "cdp_v2_solana_wallet_provider";
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Sign a transaction
|
|
132
|
+
*
|
|
133
|
+
* @param transaction - The transaction to sign
|
|
134
|
+
* @returns The signed transaction
|
|
135
|
+
*/
|
|
136
|
+
async signTransaction(transaction) {
|
|
137
|
+
const serializedTransaction = transaction.serialize();
|
|
138
|
+
const encodedSerializedTransaction = Buffer.from(serializedTransaction).toString("base64");
|
|
139
|
+
const signedTransaction = await __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_cdp, "f").solana.signTransaction({
|
|
140
|
+
transaction: encodedSerializedTransaction,
|
|
141
|
+
address: __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_serverAccount, "f").address,
|
|
142
|
+
});
|
|
143
|
+
transaction.addSignature(this.getPublicKey(), Buffer.from(signedTransaction.signature, "base64"));
|
|
144
|
+
return transaction;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Send a transaction
|
|
148
|
+
*
|
|
149
|
+
* @param transaction - The transaction to send
|
|
150
|
+
* @returns The signature
|
|
151
|
+
*/
|
|
152
|
+
async sendTransaction(transaction) {
|
|
153
|
+
const signature = await __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").sendTransaction(transaction);
|
|
154
|
+
await this.waitForSignatureResult(signature);
|
|
155
|
+
return signature;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Sign and send a transaction
|
|
159
|
+
*
|
|
160
|
+
* @param transaction - The transaction to sign and send
|
|
161
|
+
* @returns The signature
|
|
162
|
+
*/
|
|
163
|
+
async signAndSendTransaction(transaction) {
|
|
164
|
+
const signedTransaction = await this.signTransaction(transaction);
|
|
165
|
+
return this.sendTransaction(signedTransaction);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get the status of a transaction
|
|
169
|
+
*
|
|
170
|
+
* @param signature - The signature
|
|
171
|
+
* @param options - The options for the status
|
|
172
|
+
* @returns The status
|
|
173
|
+
*/
|
|
174
|
+
async getSignatureStatus(signature, options) {
|
|
175
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").getSignatureStatus(signature, options);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Wait for signature receipt
|
|
179
|
+
*
|
|
180
|
+
* @param signature - The signature
|
|
181
|
+
* @returns The confirmation response
|
|
182
|
+
*/
|
|
183
|
+
async waitForSignatureResult(signature) {
|
|
184
|
+
const { blockhash, lastValidBlockHeight } = await __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").getLatestBlockhash();
|
|
185
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").confirmTransaction({
|
|
186
|
+
signature: signature,
|
|
187
|
+
lastValidBlockHeight,
|
|
188
|
+
blockhash,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get the balance of the wallet
|
|
193
|
+
*
|
|
194
|
+
* @returns The balance of the wallet
|
|
195
|
+
*/
|
|
196
|
+
getBalance() {
|
|
197
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").getBalance(this.getPublicKey()).then(balance => BigInt(balance));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Gets the CDP client.
|
|
201
|
+
*
|
|
202
|
+
* @returns The CDP client.
|
|
203
|
+
*/
|
|
204
|
+
getClient() {
|
|
205
|
+
return __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_cdp, "f");
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Transfer SOL from the wallet to another address
|
|
209
|
+
*
|
|
210
|
+
* @param to - The base58 encoded address to transfer the SOL to
|
|
211
|
+
* @param value - The amount of SOL to transfer (as a decimal string, e.g. "0.0001")
|
|
212
|
+
* @returns The signature
|
|
213
|
+
*/
|
|
214
|
+
async nativeTransfer(to, value) {
|
|
215
|
+
const initialBalance = await this.getBalance();
|
|
216
|
+
const solAmount = parseFloat(value);
|
|
217
|
+
const lamports = BigInt(Math.floor(solAmount * web3_js_1.LAMPORTS_PER_SOL));
|
|
218
|
+
// Check if we have enough balance (including estimated fees)
|
|
219
|
+
if (initialBalance < lamports + BigInt(5000)) {
|
|
220
|
+
throw new Error(`Insufficient balance. Have ${Number(initialBalance) / web3_js_1.LAMPORTS_PER_SOL} SOL, need ${solAmount + 0.000005} SOL (including fees)`);
|
|
221
|
+
}
|
|
222
|
+
const toPubkey = new web3_js_1.PublicKey(to);
|
|
223
|
+
const instructions = [
|
|
224
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
225
|
+
microLamports: 10000,
|
|
226
|
+
}),
|
|
227
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
228
|
+
units: 2000,
|
|
229
|
+
}),
|
|
230
|
+
web3_js_1.SystemProgram.transfer({
|
|
231
|
+
fromPubkey: this.getPublicKey(),
|
|
232
|
+
toPubkey: toPubkey,
|
|
233
|
+
lamports: lamports,
|
|
234
|
+
}),
|
|
235
|
+
];
|
|
236
|
+
const tx = new web3_js_1.VersionedTransaction(web3_js_1.MessageV0.compile({
|
|
237
|
+
payerKey: this.getPublicKey(),
|
|
238
|
+
instructions: instructions,
|
|
239
|
+
recentBlockhash: (await __classPrivateFieldGet(this, _CdpV2SolanaWalletProvider_connection, "f").getLatestBlockhash()).blockhash,
|
|
240
|
+
}));
|
|
241
|
+
const signature = await this.signAndSendTransaction(tx);
|
|
242
|
+
await this.waitForSignatureResult(signature);
|
|
243
|
+
return signature;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
exports.CdpV2SolanaWalletProvider = CdpV2SolanaWalletProvider;
|
|
247
|
+
_CdpV2SolanaWalletProvider_connection = new WeakMap(), _CdpV2SolanaWalletProvider_serverAccount = new WeakMap(), _CdpV2SolanaWalletProvider_cdp = new WeakMap(), _CdpV2SolanaWalletProvider_network = new WeakMap();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const cdp_sdk_1 = require("@coinbase/cdp-sdk");
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const cdpV2SolanaWalletProvider_1 = require("./cdpV2SolanaWalletProvider");
|
|
6
|
+
// =========================================================
|
|
7
|
+
// consts
|
|
8
|
+
// =========================================================
|
|
9
|
+
const mockConnection = {
|
|
10
|
+
sendTransaction: jest.fn(),
|
|
11
|
+
getBalance: jest.fn(),
|
|
12
|
+
getLatestBlockhash: jest.fn(),
|
|
13
|
+
getSignatureStatus: jest.fn(),
|
|
14
|
+
confirmTransaction: jest.fn(),
|
|
15
|
+
};
|
|
16
|
+
// =========================================================
|
|
17
|
+
// mocks
|
|
18
|
+
// =========================================================
|
|
19
|
+
jest.mock("../analytics", () => ({
|
|
20
|
+
sendAnalyticsEvent: jest.fn().mockImplementation(() => Promise.resolve()),
|
|
21
|
+
}));
|
|
22
|
+
jest.mock("../../package.json", () => ({
|
|
23
|
+
version: "1.0.0",
|
|
24
|
+
}));
|
|
25
|
+
jest.mock("@solana/web3.js", () => {
|
|
26
|
+
const mockPublicKey = {
|
|
27
|
+
toBase58: () => MOCK_ADDRESS,
|
|
28
|
+
equals: () => true,
|
|
29
|
+
};
|
|
30
|
+
const MockPublicKey = jest.fn(() => mockPublicKey);
|
|
31
|
+
MockPublicKey.prototype = mockPublicKey;
|
|
32
|
+
return {
|
|
33
|
+
Connection: jest.fn(() => mockConnection),
|
|
34
|
+
PublicKey: MockPublicKey,
|
|
35
|
+
VersionedTransaction: jest.fn().mockImplementation(() => ({
|
|
36
|
+
serialize: jest.fn(() => Buffer.from("mock-serialized-tx")),
|
|
37
|
+
addSignature: jest.fn(),
|
|
38
|
+
})),
|
|
39
|
+
MessageV0: {
|
|
40
|
+
compile: jest.fn(),
|
|
41
|
+
},
|
|
42
|
+
SystemProgram: {
|
|
43
|
+
transfer: jest.fn(),
|
|
44
|
+
},
|
|
45
|
+
ComputeBudgetProgram: {
|
|
46
|
+
setComputeUnitPrice: jest.fn(),
|
|
47
|
+
setComputeUnitLimit: jest.fn(),
|
|
48
|
+
},
|
|
49
|
+
clusterApiUrl: jest.fn((cluster) => {
|
|
50
|
+
switch (cluster) {
|
|
51
|
+
case "mainnet-beta":
|
|
52
|
+
return "https://api.mainnet-beta.solana.com";
|
|
53
|
+
case "devnet":
|
|
54
|
+
return "https://api.devnet.solana.com";
|
|
55
|
+
case "testnet":
|
|
56
|
+
return "https://api.testnet.solana.com";
|
|
57
|
+
default:
|
|
58
|
+
return "https://api.devnet.solana.com";
|
|
59
|
+
}
|
|
60
|
+
}),
|
|
61
|
+
LAMPORTS_PER_SOL: 1000000000,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
// Mock CdpClient
|
|
65
|
+
jest.mock("@coinbase/cdp-sdk", () => {
|
|
66
|
+
const MOCK_ADDRESS = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin";
|
|
67
|
+
const MOCK_SIGNATURE = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjrrVHx6";
|
|
68
|
+
const mockCreateAccount = jest.fn().mockImplementation(() => Promise.resolve({
|
|
69
|
+
address: MOCK_ADDRESS,
|
|
70
|
+
signTransaction: jest.fn().mockResolvedValue({ signature: MOCK_SIGNATURE }),
|
|
71
|
+
}));
|
|
72
|
+
const mockSignTransaction = jest
|
|
73
|
+
.fn()
|
|
74
|
+
.mockImplementation(async () => ({ signature: MOCK_SIGNATURE }));
|
|
75
|
+
const mockSolanaClient = {
|
|
76
|
+
createAccount: mockCreateAccount,
|
|
77
|
+
getAccount: jest.fn(),
|
|
78
|
+
signTransaction: mockSignTransaction,
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
CdpClient: jest.fn().mockImplementation(() => ({
|
|
82
|
+
solana: mockSolanaClient,
|
|
83
|
+
})),
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
// =========================================================
|
|
87
|
+
// test constants
|
|
88
|
+
// =========================================================
|
|
89
|
+
const MOCK_ADDRESS = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin";
|
|
90
|
+
const MOCK_NETWORK_ID = "solana-mainnet";
|
|
91
|
+
const MOCK_SIGNATURE = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjrrVHx6";
|
|
92
|
+
const MOCK_BALANCE = 1000000000n; // 1 SOL in lamports
|
|
93
|
+
const MOCK_NETWORK = {
|
|
94
|
+
protocolFamily: "svm",
|
|
95
|
+
networkId: MOCK_NETWORK_ID,
|
|
96
|
+
chainId: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d", // Solana mainnet chain ID
|
|
97
|
+
};
|
|
98
|
+
const MOCK_SIGNATURE_RESULT = {
|
|
99
|
+
value: {
|
|
100
|
+
err: null,
|
|
101
|
+
slot: 123456,
|
|
102
|
+
confirmations: 32,
|
|
103
|
+
},
|
|
104
|
+
context: {
|
|
105
|
+
slot: 123456,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
describe("CdpV2SolanaWalletProvider", () => {
|
|
109
|
+
let provider;
|
|
110
|
+
let mockCdpClient;
|
|
111
|
+
let mockServerAccount;
|
|
112
|
+
beforeEach(async () => {
|
|
113
|
+
jest.clearAllMocks();
|
|
114
|
+
mockCdpClient = new cdp_sdk_1.CdpClient({
|
|
115
|
+
apiKeyId: "test-key-id",
|
|
116
|
+
apiKeySecret: "test-key-secret",
|
|
117
|
+
walletSecret: "test-wallet-secret",
|
|
118
|
+
});
|
|
119
|
+
mockServerAccount = {
|
|
120
|
+
address: MOCK_ADDRESS,
|
|
121
|
+
signTransaction: jest.fn().mockResolvedValue({ signature: MOCK_SIGNATURE }),
|
|
122
|
+
};
|
|
123
|
+
// Set up the mock server account for the provider
|
|
124
|
+
mockCdpClient.solana.createAccount.mockResolvedValue(mockServerAccount);
|
|
125
|
+
mockCdpClient.solana.signTransaction = jest
|
|
126
|
+
.fn()
|
|
127
|
+
.mockResolvedValue({ signature: MOCK_SIGNATURE });
|
|
128
|
+
mockConnection.getBalance.mockResolvedValue(Number(MOCK_BALANCE));
|
|
129
|
+
mockConnection.getLatestBlockhash.mockResolvedValue({
|
|
130
|
+
blockhash: "test-blockhash",
|
|
131
|
+
lastValidBlockHeight: 123456,
|
|
132
|
+
});
|
|
133
|
+
mockConnection.confirmTransaction.mockResolvedValue(MOCK_SIGNATURE_RESULT);
|
|
134
|
+
mockConnection.sendTransaction.mockResolvedValue(MOCK_SIGNATURE);
|
|
135
|
+
provider = await cdpV2SolanaWalletProvider_1.CdpV2SolanaWalletProvider.configureWithWallet({
|
|
136
|
+
apiKeyId: "test-key-id",
|
|
137
|
+
apiKeySecret: "test-key-secret",
|
|
138
|
+
walletSecret: "test-wallet-secret",
|
|
139
|
+
networkId: MOCK_NETWORK_ID,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
// =========================================================
|
|
143
|
+
// initialization tests
|
|
144
|
+
// =========================================================
|
|
145
|
+
describe("initialization", () => {
|
|
146
|
+
it("should initialize with API keys", async () => {
|
|
147
|
+
const provider = await cdpV2SolanaWalletProvider_1.CdpV2SolanaWalletProvider.configureWithWallet({
|
|
148
|
+
apiKeyId: "test-key-id",
|
|
149
|
+
apiKeySecret: "test-key-secret",
|
|
150
|
+
walletSecret: "test-wallet-secret",
|
|
151
|
+
networkId: MOCK_NETWORK_ID,
|
|
152
|
+
});
|
|
153
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
154
|
+
expect(provider.getNetwork()).toEqual(MOCK_NETWORK);
|
|
155
|
+
});
|
|
156
|
+
it("should default to solana-devnet if network not provided", async () => {
|
|
157
|
+
const provider = await cdpV2SolanaWalletProvider_1.CdpV2SolanaWalletProvider.configureWithWallet({
|
|
158
|
+
apiKeyId: "test-key-id",
|
|
159
|
+
apiKeySecret: "test-key-secret",
|
|
160
|
+
walletSecret: "test-wallet-secret",
|
|
161
|
+
});
|
|
162
|
+
expect(provider.getNetwork().networkId).toBe("solana-devnet");
|
|
163
|
+
});
|
|
164
|
+
it("should handle initialization failures gracefully", async () => {
|
|
165
|
+
const mockCreateAccount = jest.fn().mockRejectedValue(new Error("Failed to create account"));
|
|
166
|
+
const mockSolanaClient = {
|
|
167
|
+
createAccount: mockCreateAccount,
|
|
168
|
+
getAccount: jest.fn(),
|
|
169
|
+
signTransaction: jest.fn(),
|
|
170
|
+
};
|
|
171
|
+
const mockCdpClient = new cdp_sdk_1.CdpClient({
|
|
172
|
+
apiKeyId: "test-key-id",
|
|
173
|
+
apiKeySecret: "test-key-secret",
|
|
174
|
+
walletSecret: "test-wallet-secret",
|
|
175
|
+
});
|
|
176
|
+
mockCdpClient.solana = mockSolanaClient;
|
|
177
|
+
cdp_sdk_1.CdpClient.mockImplementation(() => mockCdpClient);
|
|
178
|
+
await expect(cdpV2SolanaWalletProvider_1.CdpV2SolanaWalletProvider.configureWithWallet({
|
|
179
|
+
apiKeyId: "test-key-id",
|
|
180
|
+
apiKeySecret: "test-key-secret",
|
|
181
|
+
walletSecret: "test-wallet-secret",
|
|
182
|
+
networkId: MOCK_NETWORK_ID,
|
|
183
|
+
})).rejects.toThrow("Failed to create account");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
// =========================================================
|
|
187
|
+
// basic wallet method tests
|
|
188
|
+
// =========================================================
|
|
189
|
+
describe("basic wallet methods", () => {
|
|
190
|
+
it("should get the address", () => {
|
|
191
|
+
expect(provider.getAddress()).toBe(MOCK_ADDRESS);
|
|
192
|
+
});
|
|
193
|
+
it("should get the network", () => {
|
|
194
|
+
expect(provider.getNetwork()).toEqual(MOCK_NETWORK);
|
|
195
|
+
});
|
|
196
|
+
it("should get the name", () => {
|
|
197
|
+
expect(provider.getName()).toBe("cdp_v2_solana_wallet_provider");
|
|
198
|
+
});
|
|
199
|
+
it("should get the balance", async () => {
|
|
200
|
+
const balance = await provider.getBalance();
|
|
201
|
+
expect(balance).toBe(MOCK_BALANCE);
|
|
202
|
+
expect(mockConnection.getBalance).toHaveBeenCalledWith(expect.any(Object));
|
|
203
|
+
});
|
|
204
|
+
it("should handle connection errors during balance check", async () => {
|
|
205
|
+
mockConnection.getBalance.mockRejectedValueOnce(new Error("Network connection error"));
|
|
206
|
+
await expect(provider.getBalance()).rejects.toThrow("Network connection error");
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
// =========================================================
|
|
210
|
+
// transaction operation tests
|
|
211
|
+
// =========================================================
|
|
212
|
+
describe("transaction operations", () => {
|
|
213
|
+
it("should sign transactions", async () => {
|
|
214
|
+
const mockTransaction = new web3_js_1.VersionedTransaction(web3_js_1.MessageV0.compile({
|
|
215
|
+
payerKey: new web3_js_1.PublicKey(MOCK_ADDRESS),
|
|
216
|
+
instructions: [],
|
|
217
|
+
recentBlockhash: "test-blockhash",
|
|
218
|
+
}));
|
|
219
|
+
const signedTx = await provider.signTransaction(mockTransaction);
|
|
220
|
+
expect(mockCdpClient.solana.signTransaction).toHaveBeenCalledWith({
|
|
221
|
+
transaction: expect.any(String),
|
|
222
|
+
address: MOCK_ADDRESS,
|
|
223
|
+
});
|
|
224
|
+
expect(signedTx).toBe(mockTransaction);
|
|
225
|
+
});
|
|
226
|
+
it("should send transactions", async () => {
|
|
227
|
+
const mockTransaction = new web3_js_1.VersionedTransaction(web3_js_1.MessageV0.compile({
|
|
228
|
+
payerKey: new web3_js_1.PublicKey(MOCK_ADDRESS),
|
|
229
|
+
instructions: [],
|
|
230
|
+
recentBlockhash: "test-blockhash",
|
|
231
|
+
}));
|
|
232
|
+
const signature = await provider.sendTransaction(mockTransaction);
|
|
233
|
+
expect(mockConnection.sendTransaction).toHaveBeenCalledWith(mockTransaction);
|
|
234
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
235
|
+
});
|
|
236
|
+
it("should sign and send transactions", async () => {
|
|
237
|
+
const mockTransaction = new web3_js_1.VersionedTransaction(web3_js_1.MessageV0.compile({
|
|
238
|
+
payerKey: new web3_js_1.PublicKey(MOCK_ADDRESS),
|
|
239
|
+
instructions: [],
|
|
240
|
+
recentBlockhash: "test-blockhash",
|
|
241
|
+
}));
|
|
242
|
+
const signature = await provider.signAndSendTransaction(mockTransaction);
|
|
243
|
+
expect(mockCdpClient.solana.signTransaction).toHaveBeenCalled();
|
|
244
|
+
expect(mockConnection.sendTransaction).toHaveBeenCalled();
|
|
245
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
246
|
+
});
|
|
247
|
+
it("should handle transaction failures during send", async () => {
|
|
248
|
+
mockConnection.sendTransaction.mockRejectedValueOnce(new Error("Transaction failed"));
|
|
249
|
+
const mockTransaction = new web3_js_1.VersionedTransaction(web3_js_1.MessageV0.compile({
|
|
250
|
+
payerKey: new web3_js_1.PublicKey(MOCK_ADDRESS),
|
|
251
|
+
instructions: [],
|
|
252
|
+
recentBlockhash: "test-blockhash",
|
|
253
|
+
}));
|
|
254
|
+
await expect(provider.sendTransaction(mockTransaction)).rejects.toThrow("Transaction failed");
|
|
255
|
+
});
|
|
256
|
+
it("should get signature status", async () => {
|
|
257
|
+
const mockStatus = {
|
|
258
|
+
value: {
|
|
259
|
+
slot: 123456,
|
|
260
|
+
confirmations: 32,
|
|
261
|
+
err: null,
|
|
262
|
+
},
|
|
263
|
+
context: {
|
|
264
|
+
slot: 123456,
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
mockConnection.getSignatureStatus.mockResolvedValue(mockStatus);
|
|
268
|
+
const status = await provider.getSignatureStatus(MOCK_SIGNATURE);
|
|
269
|
+
expect(status).toBe(mockStatus);
|
|
270
|
+
expect(mockConnection.getSignatureStatus).toHaveBeenCalledWith(MOCK_SIGNATURE, undefined);
|
|
271
|
+
});
|
|
272
|
+
it("should wait for signature result", async () => {
|
|
273
|
+
const result = await provider.waitForSignatureResult(MOCK_SIGNATURE);
|
|
274
|
+
expect(result).toBe(MOCK_SIGNATURE_RESULT);
|
|
275
|
+
expect(mockConnection.confirmTransaction).toHaveBeenCalledWith({
|
|
276
|
+
signature: MOCK_SIGNATURE,
|
|
277
|
+
lastValidBlockHeight: 123456,
|
|
278
|
+
blockhash: "test-blockhash",
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
// =========================================================
|
|
283
|
+
// native transfer tests
|
|
284
|
+
// =========================================================
|
|
285
|
+
describe("native transfer", () => {
|
|
286
|
+
it("should transfer SOL", async () => {
|
|
287
|
+
const toAddress = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin";
|
|
288
|
+
const amount = "1.0";
|
|
289
|
+
// Set a balance that's high enough to cover the transfer + fees
|
|
290
|
+
mockConnection.getBalance.mockResolvedValueOnce(Number(2000000000n)); // 2 SOL
|
|
291
|
+
const signature = await provider.nativeTransfer(toAddress, amount);
|
|
292
|
+
expect(signature).toBe(MOCK_SIGNATURE);
|
|
293
|
+
expect(mockConnection.sendTransaction).toHaveBeenCalled();
|
|
294
|
+
});
|
|
295
|
+
it("should handle insufficient balance", async () => {
|
|
296
|
+
mockConnection.getBalance.mockResolvedValueOnce(Number(1000000n)); // 0.001 SOL
|
|
297
|
+
const toAddress = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin";
|
|
298
|
+
const amount = "1.0";
|
|
299
|
+
await expect(provider.nativeTransfer(toAddress, amount)).rejects.toThrow("Insufficient balance");
|
|
300
|
+
});
|
|
301
|
+
it("should handle invalid address", async () => {
|
|
302
|
+
const invalidAddress = "invalid-address";
|
|
303
|
+
const amount = "1.0";
|
|
304
|
+
await expect(provider.nativeTransfer(invalidAddress, amount)).rejects.toThrow();
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
});
|