@coinbase/cdp-sdk 1.38.3 → 1.38.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +24 -0
  3. package/_cjs/accounts/evm/toEvmServerAccount.js +0 -36
  4. package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
  5. package/_cjs/accounts/evm/toEvmSmartAccount.js +0 -36
  6. package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
  7. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js +0 -42
  8. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  9. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js +0 -42
  10. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  11. package/_cjs/accounts/solana/toSolanaAccount.js +0 -30
  12. package/_cjs/accounts/solana/toSolanaAccount.js.map +1 -1
  13. package/_cjs/actions/evm/sendUserOperation.js +2 -0
  14. package/_cjs/actions/evm/sendUserOperation.js.map +1 -1
  15. package/_cjs/actions/solana/rpc.js +16 -0
  16. package/_cjs/actions/solana/rpc.js.map +1 -0
  17. package/_cjs/actions/solana/transfer.js +74 -48
  18. package/_cjs/actions/solana/transfer.js.map +1 -1
  19. package/_cjs/actions/solana/utils.js +4 -6
  20. package/_cjs/actions/solana/utils.js.map +1 -1
  21. package/_cjs/auth/utils/http.js +5 -2
  22. package/_cjs/auth/utils/http.js.map +1 -1
  23. package/_cjs/auth/utils/jwt.js +1 -1
  24. package/_cjs/auth/utils/jwt.js.map +1 -1
  25. package/_cjs/client/evm/evm.js +49 -0
  26. package/_cjs/client/evm/evm.js.map +1 -1
  27. package/_cjs/openapi-client/cdpApiClient.js +4 -0
  28. package/_cjs/openapi-client/cdpApiClient.js.map +1 -1
  29. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +6 -41
  30. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  31. package/_cjs/openapi-client/generated/end-user-accounts/end-user-accounts.js +10 -1
  32. package/_cjs/openapi-client/generated/end-user-accounts/end-user-accounts.js.map +1 -1
  33. package/_cjs/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js +14 -1
  34. package/_cjs/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js.map +1 -1
  35. package/_cjs/openapi-client/generated/sql-api-alpha/sql-api-alpha.js +14 -1
  36. package/_cjs/openapi-client/generated/sql-api-alpha/sql-api-alpha.js.map +1 -1
  37. package/_cjs/openapi-client/index.js +0 -3
  38. package/_cjs/openapi-client/index.js.map +1 -1
  39. package/_cjs/version.js +1 -1
  40. package/_esm/accounts/evm/toEvmServerAccount.js +0 -36
  41. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  42. package/_esm/accounts/evm/toEvmSmartAccount.js +0 -36
  43. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  44. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +0 -42
  45. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  46. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js +0 -42
  47. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  48. package/_esm/accounts/solana/toSolanaAccount.js +0 -30
  49. package/_esm/accounts/solana/toSolanaAccount.js.map +1 -1
  50. package/_esm/actions/evm/sendUserOperation.js +2 -0
  51. package/_esm/actions/evm/sendUserOperation.js.map +1 -1
  52. package/_esm/actions/solana/rpc.js +13 -0
  53. package/_esm/actions/solana/rpc.js.map +1 -0
  54. package/_esm/actions/solana/transfer.js +72 -48
  55. package/_esm/actions/solana/transfer.js.map +1 -1
  56. package/_esm/actions/solana/utils.js +4 -6
  57. package/_esm/actions/solana/utils.js.map +1 -1
  58. package/_esm/auth/utils/http.js +5 -2
  59. package/_esm/auth/utils/http.js.map +1 -1
  60. package/_esm/auth/utils/jwt.js +1 -1
  61. package/_esm/auth/utils/jwt.js.map +1 -1
  62. package/_esm/client/evm/evm.js +49 -0
  63. package/_esm/client/evm/evm.js.map +1 -1
  64. package/_esm/openapi-client/cdpApiClient.js +4 -0
  65. package/_esm/openapi-client/cdpApiClient.js.map +1 -1
  66. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +5 -39
  67. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  68. package/_esm/openapi-client/generated/end-user-accounts/end-user-accounts.js +8 -0
  69. package/_esm/openapi-client/generated/end-user-accounts/end-user-accounts.js.map +1 -1
  70. package/_esm/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js +12 -0
  71. package/_esm/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js.map +1 -1
  72. package/_esm/openapi-client/generated/sql-api-alpha/sql-api-alpha.js +12 -0
  73. package/_esm/openapi-client/generated/sql-api-alpha/sql-api-alpha.js.map +1 -1
  74. package/_esm/openapi-client/index.js +0 -3
  75. package/_esm/openapi-client/index.js.map +1 -1
  76. package/_esm/version.js +1 -1
  77. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  78. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  79. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
  80. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts.map +1 -1
  81. package/_types/accounts/evm/types.d.ts +3 -18
  82. package/_types/accounts/evm/types.d.ts.map +1 -1
  83. package/_types/accounts/solana/toSolanaAccount.d.ts.map +1 -1
  84. package/_types/actions/evm/sendUserOperation.d.ts +11 -0
  85. package/_types/actions/evm/sendUserOperation.d.ts.map +1 -1
  86. package/_types/actions/evm/types.d.ts +1 -66
  87. package/_types/actions/evm/types.d.ts.map +1 -1
  88. package/_types/actions/solana/rpc.d.ts +10 -0
  89. package/_types/actions/solana/rpc.d.ts.map +1 -0
  90. package/_types/actions/solana/transfer.d.ts +37 -1
  91. package/_types/actions/solana/transfer.d.ts.map +1 -1
  92. package/_types/actions/solana/types.d.ts +1 -62
  93. package/_types/actions/solana/types.d.ts.map +1 -1
  94. package/_types/actions/solana/utils.d.ts +4 -6
  95. package/_types/actions/solana/utils.d.ts.map +1 -1
  96. package/_types/auth/utils/http.d.ts.map +1 -1
  97. package/_types/client/evm/evm.d.ts +29 -2
  98. package/_types/client/evm/evm.d.ts.map +1 -1
  99. package/_types/client/evm/evm.types.d.ts +20 -2
  100. package/_types/client/evm/evm.types.d.ts.map +1 -1
  101. package/_types/openapi-client/cdpApiClient.d.ts.map +1 -1
  102. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +44 -246
  103. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
  104. package/_types/openapi-client/generated/end-user-accounts/end-user-accounts.d.ts +8 -1
  105. package/_types/openapi-client/generated/end-user-accounts/end-user-accounts.d.ts.map +1 -1
  106. package/_types/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.d.ts +7 -1
  107. package/_types/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.d.ts.map +1 -1
  108. package/_types/openapi-client/generated/sql-api-alpha/sql-api-alpha.d.ts +11 -0
  109. package/_types/openapi-client/generated/sql-api-alpha/sql-api-alpha.d.ts.map +1 -1
  110. package/_types/openapi-client/index.d.ts +3 -6
  111. package/_types/openapi-client/index.d.ts.map +1 -1
  112. package/_types/types/calls.d.ts +1 -0
  113. package/_types/types/calls.d.ts.map +1 -1
  114. package/_types/version.d.ts +1 -1
  115. package/accounts/evm/toEvmServerAccount.ts +0 -47
  116. package/accounts/evm/toEvmSmartAccount.ts +0 -47
  117. package/accounts/evm/toNetworkScopedEvmServerAccount.ts +0 -50
  118. package/accounts/evm/toNetworkScopedEvmSmartAccount.ts +0 -49
  119. package/accounts/evm/types.ts +5 -49
  120. package/accounts/solana/toSolanaAccount.ts +0 -41
  121. package/actions/evm/sendUserOperation.ts +14 -0
  122. package/actions/evm/types.ts +1 -74
  123. package/actions/solana/rpc.ts +17 -0
  124. package/actions/solana/transfer.ts +115 -84
  125. package/actions/solana/types.ts +1 -70
  126. package/actions/solana/utils.ts +4 -6
  127. package/auth/utils/http.ts +5 -2
  128. package/auth/utils/jwt.ts +1 -1
  129. package/client/evm/evm.ts +61 -0
  130. package/client/evm/evm.types.ts +23 -0
  131. package/openapi-client/cdpApiClient.ts +5 -0
  132. package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +53 -289
  133. package/openapi-client/generated/end-user-accounts/end-user-accounts.ts +14 -0
  134. package/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.ts +23 -0
  135. package/openapi-client/generated/sql-api-alpha/sql-api-alpha.ts +13 -0
  136. package/openapi-client/index.ts +0 -3
  137. package/package.json +5 -6
  138. package/types/calls.ts +1 -0
  139. package/version.ts +1 -1
  140. package/_cjs/actions/Quote.js +0 -106
  141. package/_cjs/actions/Quote.js.map +0 -1
  142. package/_cjs/actions/evm/fund/fund.js +0 -50
  143. package/_cjs/actions/evm/fund/fund.js.map +0 -1
  144. package/_cjs/actions/evm/fund/quoteFund.js +0 -47
  145. package/_cjs/actions/evm/fund/quoteFund.js.map +0 -1
  146. package/_cjs/actions/solana/fund/fund.js +0 -50
  147. package/_cjs/actions/solana/fund/fund.js.map +0 -1
  148. package/_cjs/actions/solana/fund/quoteFund.js +0 -47
  149. package/_cjs/actions/solana/fund/quoteFund.js.map +0 -1
  150. package/_cjs/actions/types.js +0 -3
  151. package/_cjs/actions/types.js.map +0 -1
  152. package/_cjs/actions/waitForFundOperationReceipt.js +0 -64
  153. package/_cjs/actions/waitForFundOperationReceipt.js.map +0 -1
  154. package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.js +0 -50
  155. package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.js.map +0 -1
  156. package/_esm/actions/Quote.js +0 -101
  157. package/_esm/actions/Quote.js.map +0 -1
  158. package/_esm/actions/evm/fund/fund.js +0 -47
  159. package/_esm/actions/evm/fund/fund.js.map +0 -1
  160. package/_esm/actions/evm/fund/quoteFund.js +0 -44
  161. package/_esm/actions/evm/fund/quoteFund.js.map +0 -1
  162. package/_esm/actions/solana/fund/fund.js +0 -47
  163. package/_esm/actions/solana/fund/fund.js.map +0 -1
  164. package/_esm/actions/solana/fund/quoteFund.js +0 -44
  165. package/_esm/actions/solana/fund/quoteFund.js.map +0 -1
  166. package/_esm/actions/types.js +0 -2
  167. package/_esm/actions/types.js.map +0 -1
  168. package/_esm/actions/waitForFundOperationReceipt.js +0 -61
  169. package/_esm/actions/waitForFundOperationReceipt.js.map +0 -1
  170. package/_esm/openapi-client/generated/payments-alpha/payments-alpha.js +0 -42
  171. package/_esm/openapi-client/generated/payments-alpha/payments-alpha.js.map +0 -1
  172. package/_types/actions/Quote.d.ts +0 -97
  173. package/_types/actions/Quote.d.ts.map +0 -1
  174. package/_types/actions/evm/fund/fund.d.ts +0 -21
  175. package/_types/actions/evm/fund/fund.d.ts.map +0 -1
  176. package/_types/actions/evm/fund/quoteFund.d.ts +0 -22
  177. package/_types/actions/evm/fund/quoteFund.d.ts.map +0 -1
  178. package/_types/actions/solana/fund/fund.d.ts +0 -19
  179. package/_types/actions/solana/fund/fund.d.ts.map +0 -1
  180. package/_types/actions/solana/fund/quoteFund.d.ts +0 -20
  181. package/_types/actions/solana/fund/quoteFund.d.ts.map +0 -1
  182. package/_types/actions/types.d.ts +0 -37
  183. package/_types/actions/types.d.ts.map +0 -1
  184. package/_types/actions/waitForFundOperationReceipt.d.ts +0 -68
  185. package/_types/actions/waitForFundOperationReceipt.d.ts.map +0 -1
  186. package/_types/openapi-client/generated/payments-alpha/payments-alpha.d.ts +0 -42
  187. package/_types/openapi-client/generated/payments-alpha/payments-alpha.d.ts.map +0 -1
  188. package/actions/Quote.ts +0 -154
  189. package/actions/evm/fund/fund.ts +0 -73
  190. package/actions/evm/fund/quoteFund.ts +0 -79
  191. package/actions/solana/fund/fund.ts +0 -71
  192. package/actions/solana/fund/quoteFund.ts +0 -77
  193. package/actions/types.ts +0 -39
  194. package/actions/waitForFundOperationReceipt.ts +0 -118
  195. package/openapi-client/generated/payments-alpha/payments-alpha.ts +0 -96
@@ -1,18 +1,28 @@
1
1
  import {
2
- getMint,
3
- getAssociatedTokenAddress,
4
- getAccount,
5
- createAssociatedTokenAccountInstruction,
6
- createTransferCheckedInstruction,
7
- } from "@solana/spl-token";
2
+ pipe,
3
+ createTransactionMessage,
4
+ setTransactionMessageLifetimeUsingBlockhash,
5
+ appendTransactionMessageInstructions,
6
+ Instruction,
7
+ createSolanaRpc,
8
+ address,
9
+ compileTransaction,
10
+ setTransactionMessageFeePayer,
11
+ createNoopSigner,
12
+ getBase64EncodedWireTransaction,
13
+ } from "@solana/kit";
14
+ import { Connection } from "@solana/web3.js";
15
+ import { getTransferSolInstruction } from "@solana-program/system";
8
16
  import {
9
- Connection,
10
- PublicKey,
11
- SystemProgram,
12
- SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
13
- Transaction,
14
- } from "@solana/web3.js";
15
-
17
+ findAssociatedTokenPda,
18
+ getCreateAssociatedTokenInstructionAsync,
19
+ getTransferCheckedInstruction,
20
+ fetchToken,
21
+ fetchMint,
22
+ TOKEN_PROGRAM_ADDRESS,
23
+ } from "@solana-program/token";
24
+
25
+ import { createRpcClient } from "./rpc.js";
16
26
  import { sendTransaction } from "./sendTransaction.js";
17
27
  import {
18
28
  getConnectedNetwork,
@@ -42,7 +52,7 @@ export interface TransferOptions {
42
52
  */
43
53
  token: "sol" | "usdc" | string;
44
54
  /**
45
- * The network to use which will be used to create a Connection, otherwise a Connection can be provided.
55
+ * The network to use which will be used to create an RPC client, otherwise an RPC client can be provided.
46
56
  */
47
57
  network: Network | Connection;
48
58
  }
@@ -61,16 +71,18 @@ export async function transfer(
61
71
  ): Promise<SignatureResult> {
62
72
  const connection = getOrCreateConnection({ networkOrConnection: options.network });
63
73
  const connectedNetwork = await getConnectedNetwork(connection);
74
+ const rpc = createRpcClient(connectedNetwork);
64
75
 
65
- const tx =
76
+ const base64Transaction =
66
77
  options.token === "sol"
67
- ? await getNativeTransfer({
78
+ ? await getNativeTransferBase64Transaction({
79
+ rpc,
68
80
  from: options.from,
69
81
  to: options.to,
70
82
  amount: options.amount,
71
83
  })
72
- : await getSplTransfer({
73
- connection,
84
+ : await getSplTransferBase64Transaction({
85
+ rpc,
74
86
  from: options.from,
75
87
  to: options.to,
76
88
  mintAddress:
@@ -78,59 +90,63 @@ export async function transfer(
78
90
  amount: options.amount,
79
91
  });
80
92
 
81
- const serializedTx = Buffer.from(tx.serialize({ requireAllSignatures: false })).toString(
82
- "base64",
83
- );
84
-
85
93
  const signature = await sendTransaction(apiClient, {
86
94
  network: connectedNetwork === "mainnet" ? "solana" : "solana-devnet",
87
- transaction: serializedTx,
95
+ transaction: base64Transaction,
88
96
  });
89
97
 
90
98
  return signature;
91
99
  }
92
100
 
93
- type GetNativeTransferOptions = Omit<TransferOptions, "token" | "network">;
101
+ type GetNativeTransferOptions = Omit<TransferOptions, "token" | "network"> & {
102
+ rpc: ReturnType<typeof createSolanaRpc>;
103
+ };
94
104
 
95
105
  /**
96
- * Gets the transaction for a native SOL transfer
106
+ * Gets the transaction for a SOL transfer
97
107
  *
98
- * @param options - The options for the native SOL transfer
108
+ * @param options - The options for the SOL transfer
99
109
  *
110
+ * @param options.rpc - The Solana RPC client
100
111
  * @param options.from - The source address
101
112
  * @param options.to - The destination address
102
- * @param options.amount - The amount to transfer
113
+ * @param options.amount - The amount in lamports to transfer
103
114
  *
104
- * @returns The native SOL transfer transaction
115
+ * @returns The SOL transfer transaction
105
116
  */
106
- async function getNativeTransfer({
117
+ export async function getNativeTransferBase64Transaction({
118
+ rpc,
107
119
  from,
108
120
  to,
109
121
  amount,
110
- }: GetNativeTransferOptions): Promise<Transaction> {
111
- const transaction = new Transaction();
112
- transaction.add(
113
- SystemProgram.transfer({
114
- fromPubkey: new PublicKey(from),
115
- toPubkey: new PublicKey(to),
116
- lamports: amount,
122
+ }: GetNativeTransferOptions): Promise<string> {
123
+ const fromAddr = address(from);
124
+ const toAddr = address(to);
125
+
126
+ const instructions: Instruction[] = [
127
+ getTransferSolInstruction({
128
+ source: createNoopSigner(fromAddr),
129
+ destination: toAddr,
130
+ amount,
117
131
  }),
132
+ ];
133
+
134
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
135
+
136
+ const txMsg = pipe(
137
+ createTransactionMessage({ version: 0 }),
138
+ tx => setTransactionMessageFeePayer(fromAddr, tx),
139
+ tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
140
+ tx => appendTransactionMessageInstructions(instructions, tx),
118
141
  );
119
- transaction.recentBlockhash = SYSVAR_RECENT_BLOCKHASHES_PUBKEY.toBase58();
120
- transaction.feePayer = new PublicKey(from);
121
142
 
122
- return transaction;
143
+ const compiledTransaction = compileTransaction(txMsg);
144
+ return getBase64EncodedWireTransaction(compiledTransaction);
123
145
  }
124
146
 
125
- type GetSplTransferOptions = Omit<TransferOptions, "token" | "network"> & {
126
- /**
127
- * The mint address of the token
128
- */
147
+ type GetSplTokenTransferOptions = Omit<TransferOptions, "network" | "token"> & {
129
148
  mintAddress: string;
130
- /**
131
- * The connection to the Solana network.
132
- */
133
- connection: Connection;
149
+ rpc: ReturnType<typeof createSolanaRpc>;
134
150
  };
135
151
 
136
152
  /**
@@ -138,63 +154,78 @@ type GetSplTransferOptions = Omit<TransferOptions, "token" | "network"> & {
138
154
  *
139
155
  * @param options - The options for the SPL token transfer
140
156
  *
141
- * @param options.connection - The Solana connection
157
+ * @param options.rpc - The Solana RPC client
142
158
  * @param options.from - The source address
143
159
  * @param options.to - The destination address
144
160
  * @param options.mintAddress - The mint address of the token
145
- * @param options.amount - The amount to transfer
161
+ * @param options.amount - The amount in units of the token to transfer
146
162
  *
147
163
  * @returns The SPL token transfer transaction
148
164
  */
149
- async function getSplTransfer({
150
- connection,
165
+ export async function getSplTransferBase64Transaction({
166
+ rpc,
151
167
  from,
152
168
  to,
153
169
  mintAddress,
154
170
  amount,
155
- }: GetSplTransferOptions): Promise<Transaction> {
156
- const fromPubkey = new PublicKey(from);
157
- const toPubkey = new PublicKey(to);
158
- const mintPubkey = new PublicKey(mintAddress);
171
+ }: GetSplTokenTransferOptions): Promise<string> {
172
+ const fromAddr = address(from);
173
+ const toAddr = address(to);
174
+ const mintAddr = address(mintAddress);
159
175
 
160
- let mintInfo: Awaited<ReturnType<typeof getMint>>;
161
- try {
162
- mintInfo = await getMint(connection, mintPubkey);
163
- } catch (error) {
164
- throw new Error(`Failed to fetch mint info for mint address ${mintAddress}. Error: ${error}`);
165
- }
166
-
167
- const sourceAta = await getAssociatedTokenAddress(mintPubkey, fromPubkey);
168
- const destinationAta = await getAssociatedTokenAddress(mintPubkey, toPubkey);
176
+ const mintInfo = await fetchMint(rpc, mintAddr);
169
177
 
170
- const transaction = new Transaction();
178
+ const [sourceAta] = await findAssociatedTokenPda({
179
+ mint: mintAddr,
180
+ owner: fromAddr,
181
+ tokenProgram: TOKEN_PROGRAM_ADDRESS,
182
+ });
183
+ const [destAta] = await findAssociatedTokenPda({
184
+ mint: mintAddr,
185
+ owner: toAddr,
186
+ tokenProgram: TOKEN_PROGRAM_ADDRESS,
187
+ });
171
188
 
172
- const sourceAccount = await getAccount(connection, sourceAta);
173
- if (sourceAccount.amount < amount) {
174
- throw new Error(`Insufficient token balance. Have ${sourceAccount.amount}, need ${amount}`);
189
+ const sourceAcct = await fetchToken(rpc, sourceAta);
190
+ if (sourceAcct.data.amount < amount) {
191
+ throw new Error(`Insufficient token balance: have ${sourceAcct.data.amount}, need ${amount}`);
175
192
  }
176
193
 
177
- // Check if destination account exists, if not create it
194
+ const instructions: Instruction[] = [];
195
+
196
+ // If destination ATA does not exist, add create instruction
178
197
  try {
179
- await getAccount(connection, destinationAta);
198
+ await fetchToken(rpc, destAta);
180
199
  } catch {
181
- transaction.add(
182
- createAssociatedTokenAccountInstruction(fromPubkey, destinationAta, toPubkey, mintPubkey),
183
- );
200
+ const createDestIx = await getCreateAssociatedTokenInstructionAsync({
201
+ payer: createNoopSigner(fromAddr),
202
+ owner: toAddr,
203
+ ata: destAta,
204
+ mint: mintAddr,
205
+ });
206
+ instructions.push(createDestIx);
184
207
  }
185
208
 
186
- transaction.add(
187
- createTransferCheckedInstruction(
188
- sourceAta,
189
- mintPubkey,
190
- destinationAta,
191
- fromPubkey,
209
+ instructions.push(
210
+ getTransferCheckedInstruction({
211
+ source: sourceAta,
212
+ mint: mintAddr,
213
+ destination: destAta,
214
+ authority: fromAddr,
192
215
  amount,
193
- mintInfo.decimals,
194
- ),
216
+ decimals: mintInfo.data.decimals,
217
+ }),
218
+ );
219
+
220
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
221
+
222
+ const txMsg = pipe(
223
+ createTransactionMessage({ version: 0 }),
224
+ tx => setTransactionMessageFeePayer(fromAddr, tx),
225
+ tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
226
+ tx => appendTransactionMessageInstructions(instructions, tx),
195
227
  );
196
- transaction.recentBlockhash = SYSVAR_RECENT_BLOCKHASHES_PUBKEY.toBase58();
197
- transaction.feePayer = new PublicKey(from);
198
228
 
199
- return transaction;
229
+ const compiledTransaction = compileTransaction(txMsg);
230
+ return getBase64EncodedWireTransaction(compiledTransaction);
200
231
  }
@@ -2,6 +2,7 @@
2
2
  * @module Actions
3
3
  */
4
4
 
5
+ import { SendTransactionResult } from "./sendTransaction.js";
5
6
  import { TransferOptions } from "./transfer.js";
6
7
  import {
7
8
  RequestFaucetOptions,
@@ -10,15 +11,6 @@ import {
10
11
  SignMessageOptions,
11
12
  SignTransactionOptions,
12
13
  } from "../../client/solana/solana.types.js";
13
- import { SolanaQuote } from "../Quote.js";
14
- import { FundOperationResult } from "../types.js";
15
- import {
16
- WaitForFundOperationOptions,
17
- WaitForFundOperationResult,
18
- } from "../waitForFundOperationReceipt.js";
19
- import { SolanaFundOptions } from "./fund/fund.js";
20
- import { SolanaQuoteFundOptions } from "./fund/quoteFund.js";
21
- import { SendTransactionResult } from "./sendTransaction.js";
22
14
 
23
15
  import type { SignTransactionResult } from "./signTransaction.js";
24
16
 
@@ -166,65 +158,4 @@ export type AccountActions = {
166
158
  * ```
167
159
  */
168
160
  transfer: (options: Omit<TransferOptions, "from">) => Promise<SignatureResult>;
169
-
170
- /**
171
- * Gets a quote to fund a Solana account.
172
- *
173
- * @param options - The options for the quote fund.
174
- * @param options.token - The token to fund the account with.
175
- * @param options.amount - The amount of the token to fund represented as an atomic unit.
176
- * It's common to use `parseUnits` utils from viem to convert to atomic units.
177
- * Otherwise, you can pass atomic units directly.
178
- *
179
- * @returns A promise that resolves to a Quote object containing details about the funding operation.
180
- *
181
- * @example
182
- * ```ts
183
- * const quote = await account.quoteFund({
184
- * token: "usdc",
185
- * amount: 1000000n,
186
- * });
187
- * ```
188
- */
189
- quoteFund: (options: Omit<SolanaQuoteFundOptions, "address">) => Promise<SolanaQuote>;
190
-
191
- /**
192
- * Funds a Solana account with the specified token amount.
193
- *
194
- * @param options - The options for the fund operation.
195
- * @param options.token - The token to fund the account with (e.g., 'usdc').
196
- * @param options.amount - The amount of the token to fund represented as an atomic unit.
197
- * It's common to use `parseUnits` utils from viem to convert to atomic units.
198
- * Otherwise, you can pass atomic units directly.
199
- *
200
- * @returns A promise that resolves to the fund operation result containing the transfer details.
201
- *
202
- * @example
203
- * ```ts
204
- * const fundOperation = await account.fund({
205
- * token: "usdc",
206
- * amount: 1000000n,
207
- * });
208
- * ```
209
- */
210
- fund: (options: Omit<SolanaFundOptions, "address">) => Promise<FundOperationResult>;
211
-
212
- /**
213
- * Waits for a fund operation to complete and returns the transfer receipt.
214
- *
215
- * @param options - The options for the wait for fund operation.
216
- * @param options.transferId - The ID of the transfer to wait for.
217
- *
218
- * @returns A promise that resolves to the completed transfer receipt containing details about the funding operation.
219
- *
220
- * @example
221
- * ```ts
222
- * const completedTransfer = await account.waitForFundOperationReceipt({
223
- * transferId: "transfer_123",
224
- * });
225
- * ```
226
- */
227
- waitForFundOperationReceipt(
228
- options: WaitForFundOperationOptions,
229
- ): Promise<WaitForFundOperationResult>;
230
161
  };
@@ -14,7 +14,7 @@ type GetOrCreateConnectionOptions = {
14
14
  };
15
15
 
16
16
  /**
17
- * Get a connection to the Solana network
17
+ * Get a connection for the Solana network
18
18
  *
19
19
  * @param options - The options for the connection
20
20
  *
@@ -37,12 +37,10 @@ export function getOrCreateConnection({
37
37
  }
38
38
 
39
39
  /**
40
- * Get the network of the connected Solana node
40
+ * Legacy function for compatibility during migration
41
41
  *
42
- * @param connection - The connection to the Solana network
43
- * @throws {Error} If the network is not mainnet or devnet
44
- *
45
- * @returns The network of the connected Solana node
42
+ * @param connection - The Solana Connection instance
43
+ * @returns The network type (mainnet or devnet)
46
44
  */
47
45
  export async function getConnectedNetwork(connection: Connection): Promise<Network> {
48
46
  const genesisHash = await connection.getGenesisHash();
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { generateWalletJwt, generateJwt } from "./jwt.js";
6
+ import { UserInputValidationError } from "../../errors.js";
6
7
  import { version } from "../../version.js";
7
8
 
8
9
  /**
@@ -100,7 +101,7 @@ export async function getAuthHeaders(
100
101
  // Add wallet auth if needed
101
102
  if (requiresWalletAuth(options.requestMethod, options.requestPath)) {
102
103
  if (!options.walletSecret) {
103
- throw new Error(
104
+ throw new UserInputValidationError(
104
105
  "Wallet Secret not configured. Please set the CDP_WALLET_SECRET environment variable, or pass it as an option to the CdpClient constructor.",
105
106
  );
106
107
  }
@@ -130,7 +131,9 @@ export async function getAuthHeaders(
130
131
  */
131
132
  function requiresWalletAuth(requestMethod: string, requestPath: string): boolean {
132
133
  return (
133
- (requestPath?.includes("/accounts") || requestPath?.includes("/spend-permissions")) &&
134
+ (requestPath?.includes("/accounts") ||
135
+ requestPath?.includes("/spend-permissions") ||
136
+ requestPath?.includes("/user-operations/prepare-and-send")) &&
134
137
  (requestMethod === "POST" || requestMethod === "DELETE" || requestMethod === "PUT")
135
138
  );
136
139
  }
package/auth/utils/jwt.ts CHANGED
@@ -138,7 +138,7 @@ export async function generateJwt(options: JwtOptions): Promise<string> {
138
138
  const claims: JWTPayload = {
139
139
  sub: options.apiKeyId,
140
140
  iss: "cdp",
141
- aud: options.audience || ["cdp_service"],
141
+ aud: options.audience,
142
142
  };
143
143
 
144
144
  // Add the uris claim only for REST API requests
package/client/evm/evm.ts CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  ListServerAccountsOptions,
26
26
  ListSmartAccountResult,
27
27
  ListSmartAccountsOptions,
28
+ PrepareAndSendUserOperationOptions,
28
29
  PrepareUserOperationOptions,
29
30
  ServerAccount,
30
31
  SignatureResult,
@@ -58,6 +59,7 @@ import {
58
59
  } from "../../actions/evm/requestFaucet.js";
59
60
  import { sendTransaction } from "../../actions/evm/sendTransaction.js";
60
61
  import {
62
+ PrepareAndSendUserOperationReturnType,
61
63
  sendUserOperation,
62
64
  SendUserOperationOptions,
63
65
  SendUserOperationReturnType,
@@ -75,6 +77,7 @@ import { UserInputValidationError } from "../../errors.js";
75
77
  import { APIError } from "../../openapi-client/errors.js";
76
78
  import {
77
79
  CdpOpenApiClient,
80
+ EvmUserOperationStatus,
78
81
  EIP712Message as OpenAPIEIP712Message,
79
82
  } from "../../openapi-client/index.js";
80
83
  import { SPEND_PERMISSION_MANAGER_ADDRESS } from "../../spend-permissions/constants.js";
@@ -892,6 +895,7 @@ export class EvmClient implements EvmClientInterface {
892
895
  to: call.to as Address,
893
896
  value: call.value.toString(),
894
897
  data: call.data as Hex,
898
+ overrideGasLimit: call.overrideGasLimit,
895
899
  })),
896
900
  paymasterUrl: options.paymasterUrl,
897
901
  });
@@ -908,6 +912,63 @@ export class EvmClient implements EvmClientInterface {
908
912
  };
909
913
  }
910
914
 
915
+ /**
916
+ * Prepares and sends a user operation for a smart account.
917
+ *
918
+ * @param {PrepareAndSendUserOperationOptions} options - Parameters for preparing and sending the user operation.
919
+ * @param {SmartAccount} options.smartAccount - The smart account signing the user operation.
920
+ * @param {string} options.network - The network to prepare and send the user operation on.
921
+ * @param {EvmCall[]} options.calls - The calls to include in the user operation.
922
+ * @param {string} [options.paymasterUrl] - The optional paymaster URL to use for the user operation.
923
+ *
924
+ * @returns A promise that resolves to the smart account address, user operation hash, and status of the user operation.
925
+ *
926
+ * @example
927
+ * ```ts
928
+ * const { userOpHash } = await cdp.evm.prepareAndSendUserOperation({
929
+ * smartAccount,
930
+ * network: "base-sepolia",
931
+ * calls: [
932
+ * {
933
+ * to: "0x1234567890123456789012345678901234567890",
934
+ * value: parseEther("0.000001"),
935
+ * data: "0x",
936
+ * },
937
+ * ],
938
+ * });
939
+ * ```
940
+ */
941
+ async prepareAndSendUserOperation(
942
+ options: PrepareAndSendUserOperationOptions,
943
+ ): Promise<PrepareAndSendUserOperationReturnType> {
944
+ Analytics.trackAction({
945
+ action: "prepare_and_send_user_operation",
946
+ properties: {
947
+ network: options.network,
948
+ },
949
+ });
950
+
951
+ const userOp = await CdpOpenApiClient.prepareAndSendUserOperation(
952
+ options.smartAccount.address,
953
+ {
954
+ network: options.network,
955
+ calls: options.calls.map(call => ({
956
+ to: call.to as Address,
957
+ value: call.value.toString(),
958
+ data: call.data as Hex,
959
+ })),
960
+ paymasterUrl: options.paymasterUrl,
961
+ },
962
+ options.idempotencyKey,
963
+ );
964
+
965
+ return {
966
+ smartAccountAddress: options.smartAccount.address as Address,
967
+ userOpHash: userOp.userOpHash as Hex,
968
+ status: userOp.status as typeof EvmUserOperationStatus.broadcast,
969
+ };
970
+ }
971
+
911
972
  /**
912
973
  * Requests funds from an EVM faucet.
913
974
  *
@@ -18,6 +18,7 @@ import type {
18
18
  SendTransactionOptions,
19
19
  } from "../../actions/evm/sendTransaction.js";
20
20
  import type {
21
+ PrepareAndSendUserOperationReturnType,
21
22
  SendUserOperationOptions,
22
23
  SendUserOperationReturnType,
23
24
  } from "../../actions/evm/sendUserOperation.js";
@@ -61,6 +62,7 @@ export type EvmClientInterface = Omit<
61
62
  | "listEvmSmartAccounts" // mapped to listSmartAccounts
62
63
  | "listEvmTokenBalances" // mapped to listTokenBalances
63
64
  | "prepareUserOperation"
65
+ | "prepareAndSendUserOperation"
64
66
  | "requestEvmFaucet" // mapped to requestFaucet
65
67
  | "sendUserOperation"
66
68
  | "signEvmHash" // mapped to signHash
@@ -102,6 +104,9 @@ export type EvmClientInterface = Omit<
102
104
  sendUserOperation: (
103
105
  options: SendUserOperationOptions<unknown[]>,
104
106
  ) => Promise<SendUserOperationReturnType>;
107
+ prepareAndSendUserOperation: (
108
+ options: PrepareAndSendUserOperationOptions,
109
+ ) => Promise<PrepareAndSendUserOperationReturnType>;
105
110
  signHash: (options: SignHashOptions) => Promise<SignatureResult>;
106
111
  signMessage: (options: SignMessageOptions) => Promise<SignatureResult>;
107
112
  signTypedData: (options: SignTypedDataOptions) => Promise<SignatureResult>;
@@ -293,6 +298,22 @@ export interface PrepareUserOperationOptions {
293
298
  paymasterUrl?: string;
294
299
  }
295
300
 
301
+ /**
302
+ * Options for preparing and sending a user operation.
303
+ */
304
+ export interface PrepareAndSendUserOperationOptions {
305
+ /** The smart account. */
306
+ smartAccount: SmartAccount;
307
+ /** The network. */
308
+ network: EvmUserOperationNetwork;
309
+ /** The calls. */
310
+ calls: Calls<EvmCall[]>;
311
+ /** The paymaster URL. */
312
+ paymasterUrl?: string;
313
+ /** An optional idempotency key. */
314
+ idempotencyKey?: string;
315
+ }
316
+
296
317
  /**
297
318
  * A call to be executed in a user operation.
298
319
  */
@@ -307,6 +328,8 @@ export interface EvmCall {
307
328
  * The call data to send. This is the hex-encoded data of the function call consisting of the method selector and the function arguments.
308
329
  */
309
330
  data: Hex;
331
+ /** The override gas limit. */
332
+ overrideGasLimit?: string;
310
333
  }
311
334
 
312
335
  /**
@@ -5,6 +5,7 @@ import axiosRetry, { exponentialDelay } from "axios-retry";
5
5
  import { withAuth } from "../auth/hooks/axios/index.js";
6
6
  import { ERROR_DOCS_PAGE_URL } from "../constants.js";
7
7
  import { isOpenAPIError, APIError, UnknownError, NetworkError } from "./errors.js";
8
+ import { UserInputValidationError } from "../errors.js";
8
9
 
9
10
  import type { Prettify } from "../types/utils.js";
10
11
 
@@ -132,6 +133,10 @@ export const cdpApiClient = async <T>(
132
133
  const response = await axiosInstance(configWithIdempotencyKey);
133
134
  return response.data as T;
134
135
  } catch (error) {
136
+ if (error instanceof UserInputValidationError) {
137
+ throw error;
138
+ }
139
+
135
140
  // eslint-disable-next-line import/no-named-as-default-member
136
141
  if (Axios.isAxiosError(error) && !error.response) {
137
142
  // Network-level errors (no response received)