@coinbase/cdp-sdk 1.26.0 → 1.27.0

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 (161) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +58 -2
  3. package/_cjs/accounts/evm/resolveViemClients.js +3 -2
  4. package/_cjs/accounts/evm/resolveViemClients.js.map +1 -1
  5. package/_cjs/accounts/evm/toEvmServerAccount.js +84 -0
  6. package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
  7. package/_cjs/accounts/evm/toEvmSmartAccount.js +83 -0
  8. package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
  9. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js +19 -0
  10. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  11. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js +65 -0
  12. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  13. package/_cjs/accounts/solana/toSolanaAccount.js +20 -0
  14. package/_cjs/accounts/solana/toSolanaAccount.js.map +1 -1
  15. package/_cjs/actions/evm/fund/fund.js +3 -2
  16. package/_cjs/actions/evm/fund/fund.js.map +1 -1
  17. package/_cjs/actions/evm/fund/quoteFund.js +3 -2
  18. package/_cjs/actions/evm/fund/quoteFund.js.map +1 -1
  19. package/_cjs/actions/solana/sendTransaction.js +32 -0
  20. package/_cjs/actions/solana/sendTransaction.js.map +1 -0
  21. package/_cjs/analytics.js +39 -3
  22. package/_cjs/analytics.js.map +1 -1
  23. package/_cjs/auth/utils/jwt.js +6 -5
  24. package/_cjs/auth/utils/jwt.js.map +1 -1
  25. package/_cjs/client/cdp.js +4 -1
  26. package/_cjs/client/cdp.js.map +1 -1
  27. package/_cjs/client/evm/evm.js +116 -10
  28. package/_cjs/client/evm/evm.js.map +1 -1
  29. package/_cjs/client/policies/policies.js +22 -0
  30. package/_cjs/client/policies/policies.js.map +1 -1
  31. package/_cjs/client/solana/solana.js +83 -6
  32. package/_cjs/client/solana/solana.js.map +1 -1
  33. package/_cjs/constants.js +1 -1
  34. package/_cjs/constants.js.map +1 -1
  35. package/_cjs/errors.js +19 -1
  36. package/_cjs/errors.js.map +1 -1
  37. package/_cjs/index.js +3 -1
  38. package/_cjs/index.js.map +1 -1
  39. package/_cjs/openapi-client/cdpApiClient.js +46 -6
  40. package/_cjs/openapi-client/cdpApiClient.js.map +1 -1
  41. package/_cjs/openapi-client/errors.js +38 -9
  42. package/_cjs/openapi-client/errors.js.map +1 -1
  43. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +6 -1
  44. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  45. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.js +34 -1
  46. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  47. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.msw.js +18 -1
  48. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.msw.js.map +1 -1
  49. package/_cjs/version.js +1 -1
  50. package/_esm/accounts/evm/resolveViemClients.js +3 -2
  51. package/_esm/accounts/evm/resolveViemClients.js.map +1 -1
  52. package/_esm/accounts/evm/toEvmServerAccount.js +84 -0
  53. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  54. package/_esm/accounts/evm/toEvmSmartAccount.js +83 -0
  55. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  56. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +19 -0
  57. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  58. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js +65 -0
  59. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  60. package/_esm/accounts/solana/toSolanaAccount.js +20 -0
  61. package/_esm/accounts/solana/toSolanaAccount.js.map +1 -1
  62. package/_esm/actions/evm/fund/fund.js +3 -2
  63. package/_esm/actions/evm/fund/fund.js.map +1 -1
  64. package/_esm/actions/evm/fund/quoteFund.js +3 -2
  65. package/_esm/actions/evm/fund/quoteFund.js.map +1 -1
  66. package/_esm/actions/solana/sendTransaction.js +29 -0
  67. package/_esm/actions/solana/sendTransaction.js.map +1 -0
  68. package/_esm/analytics.js +39 -3
  69. package/_esm/analytics.js.map +1 -1
  70. package/_esm/auth/utils/jwt.js +3 -2
  71. package/_esm/auth/utils/jwt.js.map +1 -1
  72. package/_esm/client/cdp.js +4 -1
  73. package/_esm/client/cdp.js.map +1 -1
  74. package/_esm/client/evm/evm.js +110 -4
  75. package/_esm/client/evm/evm.js.map +1 -1
  76. package/_esm/client/policies/policies.js +22 -0
  77. package/_esm/client/policies/policies.js.map +1 -1
  78. package/_esm/client/solana/solana.js +80 -3
  79. package/_esm/client/solana/solana.js.map +1 -1
  80. package/_esm/constants.js +1 -1
  81. package/_esm/constants.js.map +1 -1
  82. package/_esm/errors.js +17 -0
  83. package/_esm/errors.js.map +1 -1
  84. package/_esm/index.js +1 -0
  85. package/_esm/index.js.map +1 -1
  86. package/_esm/openapi-client/cdpApiClient.js +47 -7
  87. package/_esm/openapi-client/cdpApiClient.js.map +1 -1
  88. package/_esm/openapi-client/errors.js +36 -8
  89. package/_esm/openapi-client/errors.js.map +1 -1
  90. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +5 -0
  91. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  92. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js +32 -0
  93. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  94. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.msw.js +15 -0
  95. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.msw.js.map +1 -1
  96. package/_esm/version.js +1 -1
  97. package/_types/accounts/evm/resolveViemClients.d.ts.map +1 -1
  98. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  99. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  100. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
  101. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts.map +1 -1
  102. package/_types/accounts/solana/toSolanaAccount.d.ts.map +1 -1
  103. package/_types/actions/evm/fund/fund.d.ts.map +1 -1
  104. package/_types/actions/evm/fund/quoteFund.d.ts.map +1 -1
  105. package/_types/actions/solana/sendTransaction.d.ts +23 -0
  106. package/_types/actions/solana/sendTransaction.d.ts.map +1 -0
  107. package/_types/analytics.d.ts +36 -1
  108. package/_types/analytics.d.ts.map +1 -1
  109. package/_types/auth/utils/jwt.d.ts.map +1 -1
  110. package/_types/client/cdp.d.ts.map +1 -1
  111. package/_types/client/evm/evm.d.ts +1 -0
  112. package/_types/client/evm/evm.d.ts.map +1 -1
  113. package/_types/client/policies/policies.d.ts.map +1 -1
  114. package/_types/client/solana/solana.d.ts +20 -1
  115. package/_types/client/solana/solana.d.ts.map +1 -1
  116. package/_types/client/solana/solana.types.d.ts +21 -2
  117. package/_types/client/solana/solana.types.d.ts.map +1 -1
  118. package/_types/constants.d.ts +1 -1
  119. package/_types/constants.d.ts.map +1 -1
  120. package/_types/errors.d.ts +11 -0
  121. package/_types/errors.d.ts.map +1 -1
  122. package/_types/index.d.ts +1 -0
  123. package/_types/index.d.ts.map +1 -1
  124. package/_types/openapi-client/cdpApiClient.d.ts.map +1 -1
  125. package/_types/openapi-client/errors.d.ts +46 -9
  126. package/_types/openapi-client/errors.d.ts.map +1 -1
  127. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +18 -0
  128. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
  129. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts +27 -1
  130. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts.map +1 -1
  131. package/_types/openapi-client/generated/solana-accounts/solana-accounts.msw.d.ts +3 -1
  132. package/_types/openapi-client/generated/solana-accounts/solana-accounts.msw.d.ts.map +1 -1
  133. package/_types/openapi-client/index.d.ts +2 -0
  134. package/_types/openapi-client/index.d.ts.map +1 -1
  135. package/_types/version.d.ts +1 -1
  136. package/accounts/evm/resolveViemClients.ts +5 -2
  137. package/accounts/evm/toEvmServerAccount.ts +98 -0
  138. package/accounts/evm/toEvmSmartAccount.ts +96 -0
  139. package/accounts/evm/toNetworkScopedEvmServerAccount.ts +22 -0
  140. package/accounts/evm/toNetworkScopedEvmSmartAccount.ts +75 -0
  141. package/accounts/solana/toSolanaAccount.ts +24 -0
  142. package/actions/evm/fund/fund.ts +3 -2
  143. package/actions/evm/fund/quoteFund.ts +3 -2
  144. package/actions/solana/sendTransaction.ts +38 -0
  145. package/analytics.ts +73 -4
  146. package/auth/utils/jwt.ts +5 -2
  147. package/client/cdp.ts +7 -1
  148. package/client/evm/evm.ts +135 -6
  149. package/client/policies/policies.ts +28 -0
  150. package/client/solana/solana.ts +95 -3
  151. package/client/solana/solana.types.ts +24 -0
  152. package/constants.ts +1 -1
  153. package/errors.ts +18 -0
  154. package/index.ts +1 -0
  155. package/openapi-client/cdpApiClient.ts +87 -17
  156. package/openapi-client/errors.ts +65 -10
  157. package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +24 -0
  158. package/openapi-client/generated/solana-accounts/solana-accounts.msw.ts +32 -0
  159. package/openapi-client/generated/solana-accounts/solana-accounts.ts +43 -0
  160. package/package.json +1 -1
  161. package/version.ts +1 -1
@@ -13,6 +13,7 @@ import * as chains from "viem/chains";
13
13
 
14
14
  import { getBaseNodeRpcUrl } from "./getBaseNodeRpcUrl.js";
15
15
  import { NETWORK_TO_CHAIN_MAP, resolveNetworkToChain } from "./networkToChainResolver.js";
16
+ import { UserInputValidationError } from "../../errors.js";
16
17
 
17
18
  import type { EvmAccount } from "./types.js";
18
19
 
@@ -49,7 +50,7 @@ function isNetworkIdentifier(input: string): boolean {
49
50
  async function resolveNodeUrlToChain(nodeUrl: string): Promise<Chain> {
50
51
  // First validate that it's a proper URL
51
52
  if (!isValidUrl(nodeUrl)) {
52
- throw new Error(`Invalid URL format: ${nodeUrl}`);
53
+ throw new UserInputValidationError(`Invalid URL format: ${nodeUrl}`);
53
54
  }
54
55
 
55
56
  // Create a temporary public client to get the chain ID
@@ -188,6 +189,8 @@ export async function resolveViemClients(
188
189
  }
189
190
 
190
191
  // Otherwise, throw a generic error about unsupported input
191
- throw new Error(`Unsupported network identifier or invalid Node URL: ${networkOrNodeUrl}`);
192
+ throw new UserInputValidationError(
193
+ `Unsupported network identifier or invalid Node URL: ${networkOrNodeUrl}`,
194
+ );
192
195
  }
193
196
  }
@@ -32,6 +32,7 @@ import { createSwapQuote } from "../../actions/evm/swap/createSwapQuote.js";
32
32
  import { sendSwapTransaction } from "../../actions/evm/swap/sendSwapTransaction.js";
33
33
  import { accountTransferStrategy } from "../../actions/evm/transfer/accountTransferStrategy.js";
34
34
  import { transfer } from "../../actions/evm/transfer/transfer.js";
35
+ import { Analytics } from "../../analytics.js";
35
36
 
36
37
  import type { EvmServerAccount, NetworkOrRpcUrl } from "./types.js";
37
38
  import type {
@@ -71,6 +72,11 @@ export function toEvmServerAccount(
71
72
  const account: EvmServerAccount = {
72
73
  address: options.account.address as Address,
73
74
  async signMessage({ message }) {
75
+ Analytics.trackAction({
76
+ action: "sign_message",
77
+ accountType: "evm_server",
78
+ });
79
+
74
80
  const result = await apiClient.signEvmMessage(options.account.address, {
75
81
  message: message.toString(),
76
82
  });
@@ -78,6 +84,11 @@ export function toEvmServerAccount(
78
84
  },
79
85
 
80
86
  async sign(parameters: { hash: Hash }) {
87
+ Analytics.trackAction({
88
+ action: "sign",
89
+ accountType: "evm_server",
90
+ });
91
+
81
92
  const result = await apiClient.signEvmHash(options.account.address, {
82
93
  hash: parameters.hash,
83
94
  });
@@ -85,6 +96,11 @@ export function toEvmServerAccount(
85
96
  },
86
97
 
87
98
  async signTransaction(transaction: TransactionSerializable) {
99
+ Analytics.trackAction({
100
+ action: "sign_transaction",
101
+ accountType: "evm_server",
102
+ });
103
+
88
104
  const result = await apiClient.signEvmTransaction(options.account.address, {
89
105
  transaction: serializeTransaction(transaction),
90
106
  });
@@ -95,6 +111,11 @@ export function toEvmServerAccount(
95
111
  const typedData extends TypedData | Record<string, unknown>,
96
112
  primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
97
113
  >(parameters: TypedDataDefinition<typedData, primaryType>) {
114
+ Analytics.trackAction({
115
+ action: "sign_typed_data",
116
+ accountType: "evm_server",
117
+ });
118
+
98
119
  const { domain = {}, message, primaryType } = parameters as HashTypedDataParameters;
99
120
  const types = {
100
121
  EIP712Domain: getTypesForEIP712Domain({ domain }),
@@ -112,11 +133,27 @@ export function toEvmServerAccount(
112
133
  return result.signature as Hex;
113
134
  },
114
135
  async transfer(transferArgs): Promise<TransactionResult> {
136
+ Analytics.trackAction({
137
+ action: "transfer",
138
+ accountType: "evm_server",
139
+ properties: {
140
+ network: transferArgs.network,
141
+ },
142
+ });
143
+
115
144
  return transfer(apiClient, account, transferArgs, accountTransferStrategy);
116
145
  },
117
146
  async listTokenBalances(
118
147
  options: Omit<ListTokenBalancesOptions, "address">,
119
148
  ): Promise<ListTokenBalancesResult> {
149
+ Analytics.trackAction({
150
+ action: "list_token_balances",
151
+ accountType: "evm_server",
152
+ properties: {
153
+ network: options.network,
154
+ },
155
+ });
156
+
120
157
  return listTokenBalances(apiClient, {
121
158
  ...options,
122
159
  address: this.address,
@@ -125,24 +162,56 @@ export function toEvmServerAccount(
125
162
  async requestFaucet(
126
163
  options: Omit<RequestFaucetOptions, "address">,
127
164
  ): Promise<RequestFaucetResult> {
165
+ Analytics.trackAction({
166
+ action: "request_faucet",
167
+ accountType: "evm_server",
168
+ properties: {
169
+ network: options.network,
170
+ },
171
+ });
172
+
128
173
  return requestFaucet(apiClient, {
129
174
  ...options,
130
175
  address: this.address,
131
176
  });
132
177
  },
133
178
  async sendTransaction(options: Omit<SendTransactionOptions, "address">) {
179
+ Analytics.trackAction({
180
+ action: "send_transaction",
181
+ accountType: "evm_server",
182
+ properties: {
183
+ network: options.network,
184
+ },
185
+ });
186
+
134
187
  return sendTransaction(apiClient, {
135
188
  ...options,
136
189
  address: this.address,
137
190
  });
138
191
  },
139
192
  async quoteFund(options: Omit<QuoteFundOptions, "address">): Promise<Quote> {
193
+ Analytics.trackAction({
194
+ action: "quote_fund",
195
+ accountType: "evm_server",
196
+ properties: {
197
+ network: options.network,
198
+ },
199
+ });
200
+
140
201
  return quoteFund(apiClient, {
141
202
  ...options,
142
203
  address: this.address,
143
204
  });
144
205
  },
145
206
  async fund(options: Omit<FundOptions, "address">): Promise<FundOperationResult> {
207
+ Analytics.trackAction({
208
+ action: "fund",
209
+ accountType: "evm_server",
210
+ properties: {
211
+ network: options.network,
212
+ },
213
+ });
214
+
146
215
  return fund(apiClient, {
147
216
  ...options,
148
217
  address: this.address,
@@ -151,15 +220,36 @@ export function toEvmServerAccount(
151
220
  async waitForFundOperationReceipt(
152
221
  options: WaitForFundOperationOptions,
153
222
  ): Promise<WaitForFundOperationResult> {
223
+ Analytics.trackAction({
224
+ action: "wait_for_fund_operation_receipt",
225
+ accountType: "evm_server",
226
+ });
227
+
154
228
  return waitForFundOperationReceipt(apiClient, options);
155
229
  },
156
230
  async quoteSwap(options: AccountQuoteSwapOptions): Promise<AccountQuoteSwapResult> {
231
+ Analytics.trackAction({
232
+ action: "quote_swap",
233
+ accountType: "evm_server",
234
+ properties: {
235
+ network: options.network,
236
+ },
237
+ });
238
+
157
239
  return createSwapQuote(apiClient, {
158
240
  ...options,
159
241
  taker: this.address,
160
242
  });
161
243
  },
162
244
  async swap(options: AccountSwapOptions): Promise<AccountSwapResult> {
245
+ Analytics.trackAction({
246
+ action: "swap",
247
+ accountType: "evm_server",
248
+ properties: {
249
+ network: "network" in options ? options.network : undefined,
250
+ },
251
+ });
252
+
163
253
  return sendSwapTransaction(apiClient, {
164
254
  ...options,
165
255
  address: this.address,
@@ -170,6 +260,14 @@ export function toEvmServerAccount(
170
260
  type: "evm-server",
171
261
  policies: options.account.policies,
172
262
  useNetwork: async <Network extends NetworkOrRpcUrl>(networkOrRpcUrl: Network) => {
263
+ Analytics.trackAction({
264
+ action: "use_network",
265
+ accountType: "evm_server",
266
+ properties: {
267
+ network: networkOrRpcUrl,
268
+ },
269
+ });
270
+
173
271
  return toNetworkScopedEvmServerAccount({
174
272
  account,
175
273
  network: networkOrRpcUrl,
@@ -35,6 +35,7 @@ import {
35
35
  WaitForUserOperationOptions,
36
36
  WaitForUserOperationReturnType,
37
37
  } from "../../actions/evm/waitForUserOperation.js";
38
+ import { Analytics } from "../../analytics.js";
38
39
  import {
39
40
  GetUserOperationOptions,
40
41
  SignTypedDataOptions,
@@ -85,11 +86,27 @@ export function toEvmSmartAccount(
85
86
  owners: [options.owner],
86
87
  policies: options.smartAccount.policies,
87
88
  async transfer(transferArgs): Promise<SendUserOperationReturnType> {
89
+ Analytics.trackAction({
90
+ action: "transfer",
91
+ accountType: "evm_smart",
92
+ properties: {
93
+ network: transferArgs.network,
94
+ },
95
+ });
96
+
88
97
  return transfer(apiClient, account, transferArgs, smartAccountTransferStrategy);
89
98
  },
90
99
  async listTokenBalances(
91
100
  options: Omit<ListTokenBalancesOptions, "address">,
92
101
  ): Promise<ListTokenBalancesResult> {
102
+ Analytics.trackAction({
103
+ action: "list_token_balances",
104
+ accountType: "evm_smart",
105
+ properties: {
106
+ network: options.network,
107
+ },
108
+ });
109
+
93
110
  return listTokenBalances(apiClient, {
94
111
  ...options,
95
112
  address: this.address,
@@ -98,6 +115,14 @@ export function toEvmSmartAccount(
98
115
  async sendUserOperation(
99
116
  options: Omit<SendUserOperationOptions<unknown[]>, "smartAccount">,
100
117
  ): Promise<SendUserOperationReturnType> {
118
+ Analytics.trackAction({
119
+ action: "send_user_operation",
120
+ accountType: "evm_smart",
121
+ properties: {
122
+ network: options.network,
123
+ },
124
+ });
125
+
101
126
  return sendUserOperation(apiClient, {
102
127
  ...options,
103
128
  smartAccount: account,
@@ -106,6 +131,11 @@ export function toEvmSmartAccount(
106
131
  async waitForUserOperation(
107
132
  options: Omit<WaitForUserOperationOptions, "smartAccountAddress">,
108
133
  ): Promise<WaitForUserOperationReturnType> {
134
+ Analytics.trackAction({
135
+ action: "wait_for_user_operation",
136
+ accountType: "evm_smart",
137
+ });
138
+
109
139
  return waitForUserOperation(apiClient, {
110
140
  ...options,
111
141
  smartAccountAddress: account.address,
@@ -114,6 +144,11 @@ export function toEvmSmartAccount(
114
144
  async getUserOperation(
115
145
  options: Omit<GetUserOperationOptions, "smartAccount">,
116
146
  ): Promise<UserOperation> {
147
+ Analytics.trackAction({
148
+ action: "get_user_operation",
149
+ accountType: "evm_smart",
150
+ });
151
+
117
152
  return getUserOperation(apiClient, {
118
153
  ...options,
119
154
  smartAccount: account,
@@ -122,18 +157,42 @@ export function toEvmSmartAccount(
122
157
  async requestFaucet(
123
158
  options: Omit<RequestFaucetOptions, "address">,
124
159
  ): Promise<RequestFaucetResult> {
160
+ Analytics.trackAction({
161
+ action: "request_faucet",
162
+ accountType: "evm_smart",
163
+ properties: {
164
+ network: options.network,
165
+ },
166
+ });
167
+
125
168
  return requestFaucet(apiClient, {
126
169
  ...options,
127
170
  address: account.address,
128
171
  });
129
172
  },
130
173
  async quoteFund(options: Omit<QuoteFundOptions, "address">): Promise<Quote> {
174
+ Analytics.trackAction({
175
+ action: "quote_fund",
176
+ accountType: "evm_smart",
177
+ properties: {
178
+ network: options.network,
179
+ },
180
+ });
181
+
131
182
  return quoteFund(apiClient, {
132
183
  ...options,
133
184
  address: this.address,
134
185
  });
135
186
  },
136
187
  async fund(options: Omit<FundOptions, "address">): Promise<FundOperationResult> {
188
+ Analytics.trackAction({
189
+ action: "fund",
190
+ accountType: "evm_smart",
191
+ properties: {
192
+ network: options.network,
193
+ },
194
+ });
195
+
137
196
  return fund(apiClient, {
138
197
  ...options,
139
198
  address: this.address,
@@ -142,9 +201,22 @@ export function toEvmSmartAccount(
142
201
  async waitForFundOperationReceipt(
143
202
  options: WaitForFundOperationOptions,
144
203
  ): Promise<WaitForFundOperationResult> {
204
+ Analytics.trackAction({
205
+ action: "wait_for_fund_operation_receipt",
206
+ accountType: "evm_smart",
207
+ });
208
+
145
209
  return waitForFundOperationReceipt(apiClient, options);
146
210
  },
147
211
  async quoteSwap(options: SmartAccountQuoteSwapOptions): Promise<SmartAccountQuoteSwapResult> {
212
+ Analytics.trackAction({
213
+ action: "quote_swap",
214
+ accountType: "evm_smart",
215
+ properties: {
216
+ network: options.network,
217
+ },
218
+ });
219
+
148
220
  return createSwapQuote(apiClient, {
149
221
  ...options,
150
222
  taker: this.address, // Always use smart account's address as taker
@@ -153,6 +225,14 @@ export function toEvmSmartAccount(
153
225
  });
154
226
  },
155
227
  async swap(options: SmartAccountSwapOptions): Promise<SmartAccountSwapResult> {
228
+ Analytics.trackAction({
229
+ action: "swap",
230
+ accountType: "evm_smart",
231
+ properties: {
232
+ network: "network" in options ? options.network : undefined,
233
+ },
234
+ });
235
+
156
236
  return sendSwapOperation(apiClient, {
157
237
  ...options,
158
238
  smartAccount: account,
@@ -163,6 +243,14 @@ export function toEvmSmartAccount(
163
243
  async signTypedData(
164
244
  options: Omit<SignTypedDataOptions, "address"> & { network: KnownEvmNetworks },
165
245
  ): Promise<Hex> {
246
+ Analytics.trackAction({
247
+ action: "sign_typed_data",
248
+ accountType: "evm_smart",
249
+ properties: {
250
+ network: options.network,
251
+ },
252
+ });
253
+
166
254
  const result = await signAndWrapTypedDataForSmartAccount(apiClient, {
167
255
  chainId: BigInt(resolveNetworkToChain(options.network).id),
168
256
  smartAccount: account,
@@ -174,6 +262,14 @@ export function toEvmSmartAccount(
174
262
  name: options.smartAccount.name,
175
263
  type: "evm-smart",
176
264
  useNetwork: async <Network extends KnownEvmNetworks>(network: Network) => {
265
+ Analytics.trackAction({
266
+ action: "use_network",
267
+ accountType: "evm_smart",
268
+ properties: {
269
+ network,
270
+ },
271
+ });
272
+
177
273
  return toNetworkScopedEvmSmartAccount(apiClient, {
178
274
  smartAccount: account,
179
275
  owner: options.owner,
@@ -5,6 +5,7 @@ import { mapChainToNetwork } from "./chainToNetworkMapper.js";
5
5
  import { isMethodSupportedOnNetwork } from "./networkCapabilities.js";
6
6
  import { resolveViemClients } from "./resolveViemClients.js";
7
7
  import { transferWithViem } from "../../actions/evm/transfer/transferWithViem.js";
8
+ import { Analytics } from "../../analytics.js";
8
9
 
9
10
  import type { EvmServerAccount, NetworkScopedEvmServerAccount } from "./types.js";
10
11
  import type { FundOptions } from "../../actions/evm/fund/fund.js";
@@ -74,6 +75,14 @@ export async function toNetworkScopedEvmServerAccount<Network extends string>(
74
75
  network: mapChainToNetwork(chain) as SendEvmTransactionBodyNetwork,
75
76
  });
76
77
  } else {
78
+ Analytics.trackAction({
79
+ action: "send_transaction",
80
+ accountType: "evm_server",
81
+ properties: {
82
+ network: options.network,
83
+ },
84
+ });
85
+
77
86
  const hash = await walletClient.sendTransaction(
78
87
  txOpts.transaction as TransactionRequestEIP1559,
79
88
  );
@@ -87,12 +96,25 @@ export async function toNetworkScopedEvmServerAccount<Network extends string>(
87
96
  network: mapChainToNetwork(chain) as SendEvmTransactionBodyNetwork,
88
97
  });
89
98
  } else {
99
+ Analytics.trackAction({
100
+ action: "transfer",
101
+ accountType: "evm_server",
102
+ properties: {
103
+ network: options.network,
104
+ },
105
+ });
106
+
90
107
  return transferWithViem(walletClient, account, transferArgs);
91
108
  }
92
109
  },
93
110
  waitForTransactionReceipt: async (
94
111
  waitOptions: WaitForTransactionReceiptParameters | TransactionResult,
95
112
  ) => {
113
+ Analytics.trackAction({
114
+ action: "wait_for_transaction_receipt",
115
+ accountType: "evm_server",
116
+ });
117
+
96
118
  if ("transactionHash" in waitOptions) {
97
119
  return publicClient.waitForTransactionReceipt({
98
120
  hash: waitOptions.transactionHash,
@@ -12,6 +12,7 @@ import { sendSwapOperation } from "../../actions/evm/swap/sendSwapOperation.js";
12
12
  import { smartAccountTransferStrategy } from "../../actions/evm/transfer/smartAccountTransferStrategy.js";
13
13
  import { transfer } from "../../actions/evm/transfer/transfer.js";
14
14
  import { waitForUserOperation } from "../../actions/evm/waitForUserOperation.js";
15
+ import { Analytics } from "../../analytics.js";
15
16
 
16
17
  import type {
17
18
  EvmAccount,
@@ -84,6 +85,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
84
85
  sendUserOperation: async (
85
86
  userOpOptions: Omit<SendUserOperationOptions<unknown[]>, "smartAccount" | "network">,
86
87
  ) => {
88
+ Analytics.trackAction({
89
+ action: "send_user_operation",
90
+ accountType: "evm_smart",
91
+ properties: {
92
+ network: options.network,
93
+ },
94
+ });
95
+
87
96
  return sendUserOperation(apiClient, {
88
97
  ...userOpOptions,
89
98
  smartAccount: options.smartAccount,
@@ -94,12 +103,22 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
94
103
  waitForUserOperation: async (
95
104
  waitOptions: Omit<WaitForUserOperationOptions, "smartAccountAddress">,
96
105
  ) => {
106
+ Analytics.trackAction({
107
+ action: "wait_for_user_operation",
108
+ accountType: "evm_smart",
109
+ });
110
+
97
111
  return waitForUserOperation(apiClient, {
98
112
  ...waitOptions,
99
113
  smartAccountAddress: options.smartAccount.address,
100
114
  });
101
115
  },
102
116
  getUserOperation: async (getOptions: Omit<GetUserOperationOptions, "smartAccount">) => {
117
+ Analytics.trackAction({
118
+ action: "get_user_operation",
119
+ accountType: "evm_smart",
120
+ });
121
+
103
122
  return getUserOperation(apiClient, {
104
123
  ...getOptions,
105
124
  smartAccount: options.smartAccount,
@@ -110,6 +129,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
110
129
  if (isMethodSupportedOnNetwork("transfer", options.network)) {
111
130
  Object.assign(account, {
112
131
  transfer: async (transferOptions: Omit<SmartAccountTransferOptions, "network">) => {
132
+ Analytics.trackAction({
133
+ action: "transfer",
134
+ accountType: "evm_smart",
135
+ properties: {
136
+ network: options.network,
137
+ },
138
+ });
139
+
113
140
  return transfer(
114
141
  apiClient,
115
142
  options.smartAccount,
@@ -129,6 +156,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
129
156
  listTokenBalances: async (
130
157
  listOptions: Omit<ListTokenBalancesOptions, "address" | "network">,
131
158
  ) => {
159
+ Analytics.trackAction({
160
+ action: "list_token_balances",
161
+ accountType: "evm_smart",
162
+ properties: {
163
+ network: options.network,
164
+ },
165
+ });
166
+
132
167
  return listTokenBalances(apiClient, {
133
168
  ...listOptions,
134
169
  address: options.smartAccount.address,
@@ -141,6 +176,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
141
176
  if (isMethodSupportedOnNetwork("requestFaucet", options.network)) {
142
177
  Object.assign(account, {
143
178
  requestFaucet: async (faucetOptions: Omit<RequestFaucetOptions, "address" | "network">) => {
179
+ Analytics.trackAction({
180
+ action: "request_faucet",
181
+ accountType: "evm_smart",
182
+ properties: {
183
+ network: options.network,
184
+ },
185
+ });
186
+
144
187
  return requestFaucet(apiClient, {
145
188
  ...faucetOptions,
146
189
  address: options.smartAccount.address,
@@ -153,6 +196,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
153
196
  if (isMethodSupportedOnNetwork("quoteFund", options.network)) {
154
197
  Object.assign(account, {
155
198
  quoteFund: async (quoteOptions: Omit<QuoteFundOptions, "address">) => {
199
+ Analytics.trackAction({
200
+ action: "quote_fund",
201
+ accountType: "evm_smart",
202
+ properties: {
203
+ network: options.network,
204
+ },
205
+ });
206
+
156
207
  return quoteFund(apiClient, {
157
208
  ...quoteOptions,
158
209
  address: options.smartAccount.address,
@@ -164,6 +215,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
164
215
  if (isMethodSupportedOnNetwork("fund", options.network)) {
165
216
  Object.assign(account, {
166
217
  fund: async (fundOptions: Omit<FundOptions, "address">) => {
218
+ Analytics.trackAction({
219
+ action: "fund",
220
+ accountType: "evm_smart",
221
+ properties: {
222
+ network: options.network,
223
+ },
224
+ });
225
+
167
226
  return fund(apiClient, {
168
227
  ...fundOptions,
169
228
  address: options.smartAccount.address,
@@ -178,6 +237,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
178
237
  if (isMethodSupportedOnNetwork("quoteSwap", options.network)) {
179
238
  Object.assign(account, {
180
239
  quoteSwap: async (quoteSwapOptions: SmartAccountQuoteSwapOptions) => {
240
+ Analytics.trackAction({
241
+ action: "quote_swap",
242
+ accountType: "evm_smart",
243
+ properties: {
244
+ network: options.network,
245
+ },
246
+ });
247
+
181
248
  return createSwapQuote(apiClient, {
182
249
  ...quoteSwapOptions,
183
250
  taker: options.smartAccount.address,
@@ -192,6 +259,14 @@ export async function toNetworkScopedEvmSmartAccount<Network extends KnownEvmNet
192
259
  if (isMethodSupportedOnNetwork("swap", options.network)) {
193
260
  Object.assign(account, {
194
261
  swap: async (swapOptions: SmartAccountSwapOptions) => {
262
+ Analytics.trackAction({
263
+ action: "swap",
264
+ accountType: "evm_smart",
265
+ properties: {
266
+ network: options.network,
267
+ },
268
+ });
269
+
195
270
  return sendSwapOperation(apiClient, {
196
271
  ...swapOptions,
197
272
  smartAccount: options.smartAccount,
@@ -3,6 +3,7 @@ import { requestFaucet } from "../../actions/solana/requestFaucet.js";
3
3
  import { signMessage } from "../../actions/solana/signMessage.js";
4
4
  import { signTransaction } from "../../actions/solana/signTransaction.js";
5
5
  import { transfer, type TransferOptions } from "../../actions/solana/transfer.js";
6
+ import { Analytics } from "../../analytics.js";
6
7
  import {
7
8
  RequestFaucetOptions,
8
9
  SignatureResult,
@@ -35,12 +36,22 @@ export function toSolanaAccount(
35
36
  address: options.account.address,
36
37
  name: options.account.name,
37
38
  async requestFaucet(options: Omit<RequestFaucetOptions, "address">): Promise<SignatureResult> {
39
+ Analytics.trackAction({
40
+ action: "request_faucet",
41
+ accountType: "solana",
42
+ });
43
+
38
44
  return requestFaucet(apiClient, {
39
45
  ...options,
40
46
  address: account.address,
41
47
  });
42
48
  },
43
49
  async signMessage(options: Omit<SignMessageOptions, "address">): Promise<SignatureResult> {
50
+ Analytics.trackAction({
51
+ action: "sign_message",
52
+ accountType: "solana",
53
+ });
54
+
44
55
  return signMessage(apiClient, {
45
56
  ...options,
46
57
  address: account.address,
@@ -49,6 +60,11 @@ export function toSolanaAccount(
49
60
  async signTransaction(
50
61
  options: Omit<SignTransactionOptions, "address">,
51
62
  ): Promise<SignatureResult> {
63
+ Analytics.trackAction({
64
+ action: "sign_transaction",
65
+ accountType: "solana",
66
+ });
67
+
52
68
  return signTransaction(apiClient, {
53
69
  ...options,
54
70
  address: account.address,
@@ -56,6 +72,14 @@ export function toSolanaAccount(
56
72
  },
57
73
  policies: options.account.policies,
58
74
  async transfer(options: Omit<TransferOptions, "from">): Promise<SignatureResult> {
75
+ Analytics.trackAction({
76
+ action: "transfer",
77
+ accountType: "solana",
78
+ properties: {
79
+ network: options.network,
80
+ },
81
+ });
82
+
59
83
  return transfer(apiClient, {
60
84
  ...options,
61
85
  from: account.address,
@@ -1,6 +1,7 @@
1
1
  import { formatUnits } from "viem";
2
2
 
3
3
  import { FundOperationResult } from "./types.js";
4
+ import { UserInputValidationError } from "../../../errors.js";
4
5
  import {
5
6
  CreatePaymentTransferQuoteBodySourceType,
6
7
  CreatePaymentTransferQuoteBodyTargetType,
@@ -42,8 +43,8 @@ export async function fund(
42
43
  throw new Error("No card found to fund account");
43
44
  }
44
45
 
45
- if (options.token.toLowerCase() !== "eth" && options.token.toLowerCase() !== "usdc") {
46
- throw new Error("Invalid currency, must be eth or usdc");
46
+ if (options.token !== "eth" && options.token !== "usdc") {
47
+ throw new UserInputValidationError("Invalid token, must be eth or usdc");
47
48
  }
48
49
 
49
50
  const decimals = options.token === "eth" ? 18 : 6;
@@ -1,6 +1,7 @@
1
1
  import { formatUnits } from "viem";
2
2
 
3
3
  import { Quote } from "./Quote.js";
4
+ import { UserInputValidationError } from "../../../errors.js";
4
5
  import {
5
6
  CreatePaymentTransferQuoteBodySourceType,
6
7
  CreatePaymentTransferQuoteBodyTargetType,
@@ -42,8 +43,8 @@ export async function quoteFund(
42
43
  throw new Error("No card found to fund account");
43
44
  }
44
45
 
45
- if (options.token.toLowerCase() !== "eth" && options.token.toLowerCase() !== "usdc") {
46
- throw new Error("Invalid currency, must be eth or usdc");
46
+ if (options.token !== "eth" && options.token !== "usdc") {
47
+ throw new UserInputValidationError("Invalid token, must be eth or usdc");
47
48
  }
48
49
 
49
50
  const decimals = options.token === "eth" ? 18 : 6;