@coinbase/cdp-sdk 1.17.0 → 1.18.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.
- package/CHANGELOG.md +6 -0
- package/_cjs/accounts/evm/resolveViemClients.js +204 -0
- package/_cjs/accounts/evm/resolveViemClients.js.map +1 -0
- package/_cjs/accounts/evm/toEvmServerAccount.js +1 -1
- package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
- package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js +32 -1
- package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/accounts/evm/resolveViemClients.js +168 -0
- package/_esm/accounts/evm/resolveViemClients.js.map +1 -0
- package/_esm/accounts/evm/toEvmServerAccount.js +1 -1
- package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
- package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +32 -1
- package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/accounts/evm/resolveViemClients.d.ts +47 -0
- package/_types/accounts/evm/resolveViemClients.d.ts.map +1 -0
- package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts +1 -1
- package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
- package/_types/accounts/evm/types.d.ts +11 -4
- package/_types/accounts/evm/types.d.ts.map +1 -1
- package/_types/policies/schema.d.ts +96 -96
- package/_types/version.d.ts +1 -1
- package/accounts/evm/resolveViemClients.ts +215 -0
- package/accounts/evm/toEvmServerAccount.ts +1 -1
- package/accounts/evm/toNetworkScopedEvmServerAccount.ts +43 -3
- package/accounts/evm/types.ts +24 -6
- package/package.json +1 -1
- package/version.ts +1 -1
package/_types/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.18.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Account,
|
|
3
|
+
createPublicClient,
|
|
4
|
+
createWalletClient,
|
|
5
|
+
http,
|
|
6
|
+
Transport,
|
|
7
|
+
type Chain,
|
|
8
|
+
type PublicClient,
|
|
9
|
+
type WalletClient,
|
|
10
|
+
} from "viem";
|
|
11
|
+
import { toAccount } from "viem/accounts";
|
|
12
|
+
import * as chains from "viem/chains";
|
|
13
|
+
|
|
14
|
+
import type { EvmAccount } from "./types.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Network identifier to viem chain mapping
|
|
18
|
+
*/
|
|
19
|
+
const NETWORK_TO_CHAIN_MAP: Record<string, Chain> = {
|
|
20
|
+
base: chains.base,
|
|
21
|
+
"base-sepolia": chains.baseSepolia,
|
|
22
|
+
ethereum: chains.mainnet,
|
|
23
|
+
"ethereum-sepolia": chains.sepolia,
|
|
24
|
+
polygon: chains.polygon,
|
|
25
|
+
"polygon-mumbai": chains.polygonMumbai,
|
|
26
|
+
arbitrum: chains.arbitrum,
|
|
27
|
+
"arbitrum-sepolia": chains.arbitrumSepolia,
|
|
28
|
+
optimism: chains.optimism,
|
|
29
|
+
"optimism-sepolia": chains.optimismSepolia,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get a chain from the viem chains object
|
|
34
|
+
*
|
|
35
|
+
* @param id - The chain ID
|
|
36
|
+
* @returns The chain
|
|
37
|
+
*/
|
|
38
|
+
function getChain(id: number): Chain {
|
|
39
|
+
const chainList = Object.values(chains) as Chain[];
|
|
40
|
+
const found = chainList.find(chain => chain.id === id);
|
|
41
|
+
if (!found) throw new Error(`Unsupported chain ID: ${id}`);
|
|
42
|
+
return found;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Determines if the input string is a network identifier or a Node URL
|
|
47
|
+
*
|
|
48
|
+
* @param input - The string to check
|
|
49
|
+
* @returns True if the input is a network identifier, false otherwise
|
|
50
|
+
*/
|
|
51
|
+
function isNetworkIdentifier(input: string): boolean {
|
|
52
|
+
const normalizedInput = input.toLowerCase();
|
|
53
|
+
return NETWORK_TO_CHAIN_MAP[normalizedInput] !== undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolves a network identifier to a viem chain
|
|
58
|
+
*
|
|
59
|
+
* @param network - The network identifier to resolve
|
|
60
|
+
* @returns The resolved viem chain
|
|
61
|
+
*/
|
|
62
|
+
function resolveNetworkToChain(network: string): Chain {
|
|
63
|
+
const chain = NETWORK_TO_CHAIN_MAP[network.toLowerCase()];
|
|
64
|
+
if (!chain) {
|
|
65
|
+
throw new Error(`Unsupported network identifier: ${network}`);
|
|
66
|
+
}
|
|
67
|
+
return chain;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolves a Node URL to a viem chain by making a getChainId call
|
|
72
|
+
*
|
|
73
|
+
* @param nodeUrl - The Node URL to resolve
|
|
74
|
+
* @returns Promise resolving to the viem chain
|
|
75
|
+
*/
|
|
76
|
+
async function resolveNodeUrlToChain(nodeUrl: string): Promise<Chain> {
|
|
77
|
+
// First validate that it's a proper URL
|
|
78
|
+
if (!isValidUrl(nodeUrl)) {
|
|
79
|
+
throw new Error(`Invalid URL format: ${nodeUrl}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Create a temporary public client to get the chain ID
|
|
83
|
+
const tempPublicClient = createPublicClient({
|
|
84
|
+
transport: http(nodeUrl),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const chainId = await tempPublicClient.getChainId();
|
|
89
|
+
const chain = getChain(Number(chainId));
|
|
90
|
+
return chain;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Failed to resolve chain ID from Node URL: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Determines if the input string is a valid URL
|
|
100
|
+
*
|
|
101
|
+
* @param input - The string to validate as a URL
|
|
102
|
+
* @returns True if the input is a valid URL, false otherwise
|
|
103
|
+
*/
|
|
104
|
+
function isValidUrl(input: string): boolean {
|
|
105
|
+
try {
|
|
106
|
+
new URL(input);
|
|
107
|
+
return true;
|
|
108
|
+
} catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Options for resolving viem clients
|
|
115
|
+
*/
|
|
116
|
+
export type ResolveViemClientsOptions = {
|
|
117
|
+
/** The network identifier (e.g., "base", "base-sepolia") or Node URL */
|
|
118
|
+
networkOrNodeUrl: string;
|
|
119
|
+
/** Optional account to use for the wallet client */
|
|
120
|
+
account: EvmAccount;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Result of resolving viem clients
|
|
125
|
+
*/
|
|
126
|
+
export type ResolvedViemClients = {
|
|
127
|
+
/** The resolved viem chain */
|
|
128
|
+
chain: Chain;
|
|
129
|
+
/** The public client for reading blockchain data */
|
|
130
|
+
publicClient: PublicClient<Transport, Chain>;
|
|
131
|
+
/** The wallet client for sending transactions */
|
|
132
|
+
walletClient: WalletClient<Transport, Chain, Account>;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Resolves viem clients based on a network identifier or Node URL.
|
|
137
|
+
*
|
|
138
|
+
* @param options - Configuration options
|
|
139
|
+
* @param options.networkOrNodeUrl - Either a network identifier (e.g., "base", "base-sepolia") or a full Node URL
|
|
140
|
+
* @param options.account - Optional account to use for the wallet client
|
|
141
|
+
* @returns Promise resolving to an object containing the chain, publicClient, and walletClient
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* // Using network identifier
|
|
146
|
+
* const clients = await resolveViemClients({
|
|
147
|
+
* networkOrNodeUrl: "base",
|
|
148
|
+
* account: myAccount
|
|
149
|
+
* });
|
|
150
|
+
*
|
|
151
|
+
* // Using Node URL
|
|
152
|
+
* const clients = await resolveViemClients({
|
|
153
|
+
* networkOrNodeUrl: "https://mainnet.base.org",
|
|
154
|
+
* account: myAccount
|
|
155
|
+
* });
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export async function resolveViemClients(
|
|
159
|
+
options: ResolveViemClientsOptions,
|
|
160
|
+
): Promise<ResolvedViemClients> {
|
|
161
|
+
const { networkOrNodeUrl } = options;
|
|
162
|
+
|
|
163
|
+
let chain: Chain;
|
|
164
|
+
|
|
165
|
+
// If it's a valid network identifier, use the mapping
|
|
166
|
+
if (isNetworkIdentifier(networkOrNodeUrl)) {
|
|
167
|
+
chain = resolveNetworkToChain(networkOrNodeUrl);
|
|
168
|
+
const publicClient = createPublicClient({
|
|
169
|
+
chain,
|
|
170
|
+
transport: http(),
|
|
171
|
+
});
|
|
172
|
+
const walletClient = createWalletClient({
|
|
173
|
+
account: toAccount(options.account),
|
|
174
|
+
chain,
|
|
175
|
+
transport: http(),
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
chain,
|
|
179
|
+
publicClient,
|
|
180
|
+
walletClient,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// If it's not a valid network identifier, try to treat it as a Node URL
|
|
185
|
+
try {
|
|
186
|
+
chain = await resolveNodeUrlToChain(networkOrNodeUrl);
|
|
187
|
+
const publicClient = createPublicClient({
|
|
188
|
+
chain,
|
|
189
|
+
transport: http(networkOrNodeUrl),
|
|
190
|
+
});
|
|
191
|
+
const walletClient = createWalletClient({
|
|
192
|
+
account: toAccount(options.account),
|
|
193
|
+
chain,
|
|
194
|
+
transport: http(networkOrNodeUrl),
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
chain,
|
|
198
|
+
publicClient,
|
|
199
|
+
walletClient,
|
|
200
|
+
};
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// If the error is from resolveNodeUrlToChain, re-throw it as-is
|
|
203
|
+
if (
|
|
204
|
+
error instanceof Error &&
|
|
205
|
+
(error.message.includes("Invalid URL format") ||
|
|
206
|
+
error.message.includes("Unsupported chain ID") ||
|
|
207
|
+
error.message.includes("Failed to resolve chain ID"))
|
|
208
|
+
) {
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Otherwise, throw a generic error about unsupported input
|
|
213
|
+
throw new Error(`Unsupported network identifier or invalid Node URL: ${networkOrNodeUrl}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -169,7 +169,7 @@ export function toEvmServerAccount(
|
|
|
169
169
|
name: options.account.name,
|
|
170
170
|
type: "evm-server",
|
|
171
171
|
policies: options.account.policies,
|
|
172
|
-
|
|
172
|
+
useNetwork: async (networkOrRpcUrl: string) => {
|
|
173
173
|
return toNetworkScopedEvmServerAccount(apiClient, {
|
|
174
174
|
account,
|
|
175
175
|
network: networkOrRpcUrl,
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { WaitForTransactionReceiptParameters } from "viem";
|
|
2
|
+
import { base, baseSepolia, sepolia } from "viem/chains";
|
|
3
|
+
|
|
4
|
+
import { resolveViemClients } from "./resolveViemClients.js";
|
|
5
|
+
import { RequestFaucetOptions } from "../../actions/evm/requestFaucet.js";
|
|
6
|
+
|
|
1
7
|
import type { EvmServerAccount, NetworkScopedEvmServerAccount } from "./types.js";
|
|
2
8
|
import type { CdpOpenApiClientType } from "../../openapi-client/index.js";
|
|
3
|
-
import type { Address } from "../../types/misc.js";
|
|
9
|
+
import type { Address, TransactionRequestEIP1559 } from "../../types/misc.js";
|
|
4
10
|
|
|
5
11
|
/**
|
|
6
12
|
* Options for converting a pre-existing EvmAccount to a NetworkScopedEvmServerAccount.
|
|
@@ -22,10 +28,17 @@ export type ToNetworkScopedEvmServerAccountOptions = {
|
|
|
22
28
|
* @param {string} options.network - The network to scope the account to.
|
|
23
29
|
* @returns {NetworkScopedEvmServerAccount} A configured NetworkScopedEvmServerAccount instance ready for signing.
|
|
24
30
|
*/
|
|
25
|
-
export function toNetworkScopedEvmServerAccount(
|
|
31
|
+
export async function toNetworkScopedEvmServerAccount(
|
|
26
32
|
apiClient: CdpOpenApiClientType,
|
|
27
33
|
options: ToNetworkScopedEvmServerAccountOptions,
|
|
28
|
-
): NetworkScopedEvmServerAccount {
|
|
34
|
+
): Promise<NetworkScopedEvmServerAccount> {
|
|
35
|
+
const { publicClient, walletClient, chain } = await resolveViemClients({
|
|
36
|
+
networkOrNodeUrl: options.network,
|
|
37
|
+
account: options.account,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const shouldUseApi = chain.id === base.id || chain.id === baseSepolia.id;
|
|
41
|
+
|
|
29
42
|
const account: NetworkScopedEvmServerAccount = {
|
|
30
43
|
address: options.account.address as Address,
|
|
31
44
|
network: options.network,
|
|
@@ -36,6 +49,33 @@ export function toNetworkScopedEvmServerAccount(
|
|
|
36
49
|
name: options.account.name,
|
|
37
50
|
type: "evm-server",
|
|
38
51
|
policies: options.account.policies,
|
|
52
|
+
requestFaucet: async (faucetOptions: Omit<RequestFaucetOptions, "address" | "network">) => {
|
|
53
|
+
if (chain.id !== baseSepolia.id && chain.id !== sepolia.id) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
"Requesting a faucet is supported only on base-sepolia or ethereum-sepolia",
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return options.account.requestFaucet({
|
|
59
|
+
...faucetOptions,
|
|
60
|
+
network: chain.id === baseSepolia.id ? "base-sepolia" : "ethereum-sepolia",
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
sendTransaction: async txOpts => {
|
|
64
|
+
if (shouldUseApi) {
|
|
65
|
+
return options.account.sendTransaction({
|
|
66
|
+
...txOpts,
|
|
67
|
+
network: chain.id === base.id ? "base" : "base-sepolia",
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
const hash = await walletClient.sendTransaction(
|
|
71
|
+
txOpts.transaction as TransactionRequestEIP1559,
|
|
72
|
+
);
|
|
73
|
+
return { transactionHash: hash };
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
waitForTransactionReceipt: async (options: WaitForTransactionReceiptParameters) => {
|
|
77
|
+
return publicClient.waitForTransactionReceipt(options);
|
|
78
|
+
},
|
|
39
79
|
};
|
|
40
80
|
|
|
41
81
|
return account;
|
package/accounts/evm/types.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import { RequestFaucetOptions, RequestFaucetResult } from "../../actions/evm/requestFaucet.js";
|
|
2
|
+
import { TransactionResult, SendTransactionOptions } from "../../actions/evm/sendTransaction.js";
|
|
3
|
+
|
|
1
4
|
import type { AccountActions, SmartAccountActions } from "../../actions/evm/types.js";
|
|
2
5
|
import type { Address, Hash, Hex } from "../../types/misc.js";
|
|
3
6
|
import type { Prettify } from "../../types/utils.js";
|
|
4
7
|
import type {
|
|
5
8
|
SignableMessage,
|
|
9
|
+
TransactionReceipt,
|
|
6
10
|
TransactionSerializable,
|
|
7
11
|
TypedData,
|
|
8
12
|
TypedDataDefinition,
|
|
13
|
+
WaitForTransactionReceiptParameters,
|
|
9
14
|
} from "viem";
|
|
10
15
|
|
|
11
16
|
/**
|
|
@@ -42,8 +47,8 @@ export type EvmServerAccount = Prettify<
|
|
|
42
47
|
name?: string;
|
|
43
48
|
/** Indicates this is a server-managed account. */
|
|
44
49
|
type: "evm-server";
|
|
45
|
-
/**
|
|
46
|
-
|
|
50
|
+
/** A function that returns a network-scoped server-managed account. */
|
|
51
|
+
useNetwork: (network: string) => Promise<NetworkScopedEvmServerAccount>;
|
|
47
52
|
}
|
|
48
53
|
>;
|
|
49
54
|
|
|
@@ -72,12 +77,25 @@ export type NetworkScopedEvmSmartAccount = Prettify<
|
|
|
72
77
|
}
|
|
73
78
|
>;
|
|
74
79
|
|
|
80
|
+
type NetworkScopedAccountActions = Prettify<{
|
|
81
|
+
requestFaucet: (
|
|
82
|
+
options: Omit<RequestFaucetOptions, "address" | "network">,
|
|
83
|
+
) => Promise<RequestFaucetResult>;
|
|
84
|
+
sendTransaction: (
|
|
85
|
+
options: Omit<SendTransactionOptions, "address" | "network">,
|
|
86
|
+
) => Promise<TransactionResult>;
|
|
87
|
+
waitForTransactionReceipt: (
|
|
88
|
+
options: WaitForTransactionReceiptParameters,
|
|
89
|
+
) => Promise<TransactionReceipt>;
|
|
90
|
+
}>;
|
|
91
|
+
|
|
75
92
|
/**
|
|
76
93
|
* A network-scoped server-managed ethereum account
|
|
77
94
|
*/
|
|
78
95
|
export type NetworkScopedEvmServerAccount = Prettify<
|
|
79
|
-
Omit<EvmServerAccount, keyof AccountActions | "
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
Omit<EvmServerAccount, keyof AccountActions | "useNetwork"> &
|
|
97
|
+
NetworkScopedAccountActions & {
|
|
98
|
+
/** The network this account is scoped to */
|
|
99
|
+
network: string;
|
|
100
|
+
}
|
|
83
101
|
>;
|
package/package.json
CHANGED
package/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "1.
|
|
1
|
+
export const version = "1.18.0";
|