@alchemy/cli 0.7.1 → 0.7.2-alpha.26
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/dist/auth-F2IXC6CM.js +16 -0
- package/dist/{auth-JGON2JU6.js → auth-GD7BJOMK.js} +2 -2
- package/dist/{chunk-QEDAULQ2.js → chunk-2BALTY22.js} +6 -19
- package/dist/{chunk-5IFXLC2S.js → chunk-5IL2PMZ6.js} +1 -1
- package/dist/{chunk-HYCRHNPX.js → chunk-64A5W4M2.js} +1 -1
- package/dist/{chunk-HSKKIATB.js → chunk-C5HNQOLB.js} +1 -1
- package/dist/{chunk-7WD3YLRK.js → chunk-JUCUKTP3.js} +1 -1
- package/dist/{chunk-TOEVZMIP.js → chunk-K6V3R7SH.js} +514 -509
- package/dist/chunk-R4W44A6E.js +134 -0
- package/dist/{chunk-SYP6KKP6.js → chunk-XSN4XA5Z.js} +6 -6
- package/dist/{chunk-RS3DSL3X.js → chunk-YQZLLSGS.js} +3 -3
- package/dist/{errors-3CNFGAXT.js → errors-E2P6WHTX.js} +3 -1
- package/dist/index.js +395 -81
- package/dist/{interactive-N33RCX33.js → interactive-3L4IXWXJ.js} +13 -10
- package/dist/{onboarding-S6HKWOEA.js → onboarding-6FSQLTHP.js} +6 -6
- package/dist/{resolve-R4JZZCCF.js → resolve-WXT5ZCUK.js} +3 -3
- package/package.json +18 -24
- package/scripts/postinstall.cjs +2 -0
- package/dist/auth-BNT5Z5GZ.js +0 -16
- package/dist/chunk-V4IK4CJN.js +0 -64
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
configDir,
|
|
5
5
|
load,
|
|
6
6
|
save
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JUCUKTP3.js";
|
|
8
8
|
import {
|
|
9
9
|
CLIError,
|
|
10
10
|
ErrorCode,
|
|
@@ -29,11 +29,275 @@ import {
|
|
|
29
29
|
parseBaseURLOverride,
|
|
30
30
|
redactSensitiveText,
|
|
31
31
|
verbose
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-2BALTY22.js";
|
|
33
33
|
|
|
34
34
|
// src/lib/resolve.ts
|
|
35
35
|
import { readFileSync as readFileSync2 } from "fs";
|
|
36
36
|
|
|
37
|
+
// src/lib/networks.ts
|
|
38
|
+
var TESTNET_TOKEN_RE = /(testnet|sepolia|holesky|hoodi|devnet|minato|amoy|fuji|saigon|cardona|aeneid|curtis|chiado|cassiopeia|blaze|ropsten|signet|mocha|fam|bepolia)$/i;
|
|
39
|
+
var FAMILY_ALIASES = {
|
|
40
|
+
arb: "Arbitrum",
|
|
41
|
+
arbnova: "Arbitrum Nova",
|
|
42
|
+
avax: "Avalanche",
|
|
43
|
+
bnb: "BNB Smart Chain",
|
|
44
|
+
eth: "Ethereum",
|
|
45
|
+
opt: "OP Mainnet",
|
|
46
|
+
polygonzkevm: "Polygon zkEVM"
|
|
47
|
+
};
|
|
48
|
+
var NAME_ALIASES = {
|
|
49
|
+
arb: "Arbitrum",
|
|
50
|
+
avax: "Avalanche",
|
|
51
|
+
bnb: "BNB",
|
|
52
|
+
eth: "Ethereum",
|
|
53
|
+
opbnb: "opBNB",
|
|
54
|
+
opt: "OP Mainnet",
|
|
55
|
+
sui: "SUI",
|
|
56
|
+
xmtp: "XMTP",
|
|
57
|
+
zksync: "ZKsync"
|
|
58
|
+
};
|
|
59
|
+
var RPC_NETWORK_IDS = [
|
|
60
|
+
"abstract-mainnet",
|
|
61
|
+
"abstract-testnet",
|
|
62
|
+
"adi-mainnet",
|
|
63
|
+
"adi-testnet",
|
|
64
|
+
"alchemy-internal",
|
|
65
|
+
"alchemy-sepolia",
|
|
66
|
+
"alchemyarb-fam",
|
|
67
|
+
"alchemyarb-sepolia",
|
|
68
|
+
"alterscope-mainnet",
|
|
69
|
+
"anime-mainnet",
|
|
70
|
+
"anime-sepolia",
|
|
71
|
+
"apechain-curtis",
|
|
72
|
+
"apechain-mainnet",
|
|
73
|
+
"aptos-mainnet",
|
|
74
|
+
"aptos-testnet",
|
|
75
|
+
"arb-mainnet",
|
|
76
|
+
"arb-sepolia",
|
|
77
|
+
"arbnova-mainnet",
|
|
78
|
+
"arc-testnet",
|
|
79
|
+
"astar-mainnet",
|
|
80
|
+
"avax-fuji",
|
|
81
|
+
"avax-mainnet",
|
|
82
|
+
"base-mainnet",
|
|
83
|
+
"base-sepolia",
|
|
84
|
+
"berachain-bepolia",
|
|
85
|
+
"berachain-mainnet",
|
|
86
|
+
"bitcoin-mainnet",
|
|
87
|
+
"bitcoin-signet",
|
|
88
|
+
"bitcoin-testnet",
|
|
89
|
+
"blast-mainnet",
|
|
90
|
+
"blast-sepolia",
|
|
91
|
+
"bnb-mainnet",
|
|
92
|
+
"bnb-testnet",
|
|
93
|
+
"bob-mainnet",
|
|
94
|
+
"bob-sepolia",
|
|
95
|
+
"boba-mainnet",
|
|
96
|
+
"boba-sepolia",
|
|
97
|
+
"botanix-mainnet",
|
|
98
|
+
"botanix-testnet",
|
|
99
|
+
"celestiabridge-mainnet",
|
|
100
|
+
"celestiabridge-mocha",
|
|
101
|
+
"celo-mainnet",
|
|
102
|
+
"celo-sepolia",
|
|
103
|
+
"citrea-mainnet",
|
|
104
|
+
"citrea-testnet",
|
|
105
|
+
"clankermon-mainnet",
|
|
106
|
+
"commons-mainnet",
|
|
107
|
+
"crossfi-mainnet",
|
|
108
|
+
"crossfi-testnet",
|
|
109
|
+
"degen-mainnet",
|
|
110
|
+
"degen-sepolia",
|
|
111
|
+
"earnm-mainnet",
|
|
112
|
+
"earnm-sepolia",
|
|
113
|
+
"edge-mainnet",
|
|
114
|
+
"edge-testnet",
|
|
115
|
+
"eth-holesky",
|
|
116
|
+
"eth-holeskybeacon",
|
|
117
|
+
"eth-hoodi",
|
|
118
|
+
"eth-hoodibeacon",
|
|
119
|
+
"eth-mainnet",
|
|
120
|
+
"eth-mainnetbeacon",
|
|
121
|
+
"eth-sepolia",
|
|
122
|
+
"eth-sepoliabeacon",
|
|
123
|
+
"flow-mainnet",
|
|
124
|
+
"flow-testnet",
|
|
125
|
+
"frax-hoodi",
|
|
126
|
+
"frax-mainnet",
|
|
127
|
+
"galactica-cassiopeia",
|
|
128
|
+
"galactica-mainnet",
|
|
129
|
+
"gensyn-mainnet",
|
|
130
|
+
"gensyn-testnet",
|
|
131
|
+
"gnosis-chiado",
|
|
132
|
+
"gnosis-mainnet",
|
|
133
|
+
"humanity-mainnet",
|
|
134
|
+
"humanity-testnet",
|
|
135
|
+
"hyperliquid-mainnet",
|
|
136
|
+
"hyperliquid-testnet",
|
|
137
|
+
"ink-mainnet",
|
|
138
|
+
"ink-sepolia",
|
|
139
|
+
"lens-mainnet",
|
|
140
|
+
"lens-sepolia",
|
|
141
|
+
"linea-mainnet",
|
|
142
|
+
"linea-sepolia",
|
|
143
|
+
"mantle-mainnet",
|
|
144
|
+
"mantle-sepolia",
|
|
145
|
+
"megaeth-mainnet",
|
|
146
|
+
"megaeth-testnet",
|
|
147
|
+
"metis-mainnet",
|
|
148
|
+
"mode-mainnet",
|
|
149
|
+
"mode-sepolia",
|
|
150
|
+
"monad-mainnet",
|
|
151
|
+
"monad-testnet",
|
|
152
|
+
"moonbeam-mainnet",
|
|
153
|
+
"mythos-mainnet",
|
|
154
|
+
"opbnb-mainnet",
|
|
155
|
+
"opbnb-testnet",
|
|
156
|
+
"openloot-sepolia",
|
|
157
|
+
"opt-mainnet",
|
|
158
|
+
"opt-sepolia",
|
|
159
|
+
"plasma-mainnet",
|
|
160
|
+
"plasma-testnet",
|
|
161
|
+
"polygon-amoy",
|
|
162
|
+
"polygon-mainnet",
|
|
163
|
+
"polygonzkevm-cardona",
|
|
164
|
+
"polygonzkevm-mainnet",
|
|
165
|
+
"polynomial-mainnet",
|
|
166
|
+
"polynomial-sepolia",
|
|
167
|
+
"race-mainnet",
|
|
168
|
+
"race-sepolia",
|
|
169
|
+
"risa-testnet",
|
|
170
|
+
"rise-testnet",
|
|
171
|
+
"ronin-mainnet",
|
|
172
|
+
"ronin-saigon",
|
|
173
|
+
"rootstock-mainnet",
|
|
174
|
+
"rootstock-testnet",
|
|
175
|
+
"scroll-mainnet",
|
|
176
|
+
"scroll-sepolia",
|
|
177
|
+
"sei-mainnet",
|
|
178
|
+
"sei-testnet",
|
|
179
|
+
"settlus-mainnet",
|
|
180
|
+
"settlus-septestnet",
|
|
181
|
+
"shape-mainnet",
|
|
182
|
+
"shape-sepolia",
|
|
183
|
+
"solana-devnet",
|
|
184
|
+
"solana-mainnet",
|
|
185
|
+
"soneium-mainnet",
|
|
186
|
+
"soneium-minato",
|
|
187
|
+
"sonic-blaze",
|
|
188
|
+
"sonic-mainnet",
|
|
189
|
+
"sonic-testnet",
|
|
190
|
+
"stable-mainnet",
|
|
191
|
+
"stable-testnet",
|
|
192
|
+
"standard-mainnet",
|
|
193
|
+
"starknet-mainnet",
|
|
194
|
+
"starknet-sepolia",
|
|
195
|
+
"story-aeneid",
|
|
196
|
+
"story-mainnet",
|
|
197
|
+
"sui-mainnet",
|
|
198
|
+
"sui-testnet",
|
|
199
|
+
"superseed-mainnet",
|
|
200
|
+
"superseed-sepolia",
|
|
201
|
+
"synd-mainnet",
|
|
202
|
+
"syndicate-manchego",
|
|
203
|
+
"tea-sepolia",
|
|
204
|
+
"tempo-testnet",
|
|
205
|
+
"tron-mainnet",
|
|
206
|
+
"tron-testnet",
|
|
207
|
+
"unichain-mainnet",
|
|
208
|
+
"unichain-sepolia",
|
|
209
|
+
"unite-mainnet",
|
|
210
|
+
"unite-testnet",
|
|
211
|
+
"worldchain-mainnet",
|
|
212
|
+
"worldchain-sepolia",
|
|
213
|
+
"worldl3-devnet",
|
|
214
|
+
"worldmobile-devnet",
|
|
215
|
+
"worldmobile-testnet",
|
|
216
|
+
"worldmobilechain-mainnet",
|
|
217
|
+
"xmtp-mainnet",
|
|
218
|
+
"xmtp-ropsten",
|
|
219
|
+
"xprotocol-mainnet",
|
|
220
|
+
"zetachain-mainnet",
|
|
221
|
+
"zetachain-testnet",
|
|
222
|
+
"zksync-mainnet",
|
|
223
|
+
"zksync-sepolia",
|
|
224
|
+
"zora-mainnet",
|
|
225
|
+
"zora-sepolia"
|
|
226
|
+
];
|
|
227
|
+
function isTestnetNetwork(id) {
|
|
228
|
+
return TESTNET_TOKEN_RE.test(id);
|
|
229
|
+
}
|
|
230
|
+
function tokenToName(token) {
|
|
231
|
+
const alias = NAME_ALIASES[token];
|
|
232
|
+
if (alias) return alias;
|
|
233
|
+
return token.charAt(0).toUpperCase() + token.slice(1);
|
|
234
|
+
}
|
|
235
|
+
function toFamily(id) {
|
|
236
|
+
const [head] = id.split("-");
|
|
237
|
+
return FAMILY_ALIASES[head] ?? tokenToName(head);
|
|
238
|
+
}
|
|
239
|
+
function toDisplayName(id) {
|
|
240
|
+
return id.split("-").map((part) => tokenToName(part)).join(" ");
|
|
241
|
+
}
|
|
242
|
+
function toHttpsUrlTemplate(id) {
|
|
243
|
+
const domain = getBaseDomain();
|
|
244
|
+
if (id === "starknet-mainnet" || id === "starknet-sepolia") {
|
|
245
|
+
return `https://${id}.g.${domain}/starknet/version/rpc/v0_10/{apiKey}`;
|
|
246
|
+
}
|
|
247
|
+
return `https://${id}.g.${domain}/v2/{apiKey}`;
|
|
248
|
+
}
|
|
249
|
+
function getRPCNetworks() {
|
|
250
|
+
return RPC_NETWORK_IDS.map((id) => ({
|
|
251
|
+
id,
|
|
252
|
+
name: toDisplayName(id),
|
|
253
|
+
family: toFamily(id),
|
|
254
|
+
isTestnet: isTestnetNetwork(id),
|
|
255
|
+
httpsUrlTemplate: toHttpsUrlTemplate(id)
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
function getRPCNetworkIds() {
|
|
259
|
+
return [...RPC_NETWORK_IDS];
|
|
260
|
+
}
|
|
261
|
+
var NATIVE_TOKEN_SYMBOLS = {
|
|
262
|
+
eth: "ETH",
|
|
263
|
+
arb: "ETH",
|
|
264
|
+
arbnova: "ETH",
|
|
265
|
+
opt: "ETH",
|
|
266
|
+
base: "ETH",
|
|
267
|
+
zksync: "ETH",
|
|
268
|
+
scroll: "ETH",
|
|
269
|
+
blast: "ETH",
|
|
270
|
+
linea: "ETH",
|
|
271
|
+
zora: "ETH",
|
|
272
|
+
shape: "ETH",
|
|
273
|
+
polygon: "POL",
|
|
274
|
+
polygonzkevm: "ETH",
|
|
275
|
+
bnb: "BNB",
|
|
276
|
+
opbnb: "BNB",
|
|
277
|
+
avax: "AVAX",
|
|
278
|
+
solana: "SOL",
|
|
279
|
+
starknet: "ETH",
|
|
280
|
+
fantom: "FTM",
|
|
281
|
+
metis: "METIS",
|
|
282
|
+
mantle: "MNT",
|
|
283
|
+
celo: "CELO",
|
|
284
|
+
gnosis: "xDAI",
|
|
285
|
+
frax: "frxETH",
|
|
286
|
+
worldchain: "ETH",
|
|
287
|
+
berachain: "BERA",
|
|
288
|
+
flow: "FLOW",
|
|
289
|
+
rootstock: "RBTC",
|
|
290
|
+
zetachain: "ZETA",
|
|
291
|
+
sui: "SUI"
|
|
292
|
+
};
|
|
293
|
+
function isSolanaNetwork(networkId) {
|
|
294
|
+
return networkId.startsWith("solana-");
|
|
295
|
+
}
|
|
296
|
+
function nativeTokenSymbol(networkId) {
|
|
297
|
+
const prefix = networkId.replace(/-(mainnet|testnet|sepolia|holesky|hoodi|devnet|amoy|fuji|cardona|saigon|chiado|signet|mocha|blaze|curtis|bepolia).*$/, "");
|
|
298
|
+
return NATIVE_TOKEN_SYMBOLS[prefix] ?? "ETH";
|
|
299
|
+
}
|
|
300
|
+
|
|
37
301
|
// src/lib/client.ts
|
|
38
302
|
var Client = class _Client {
|
|
39
303
|
apiKey;
|
|
@@ -49,6 +313,11 @@ var Client = class _Client {
|
|
|
49
313
|
if (this.rpcBaseURLOverride()) {
|
|
50
314
|
return;
|
|
51
315
|
}
|
|
316
|
+
if (!getRPCNetworkIds().includes(network)) {
|
|
317
|
+
throw errInvalidArgs(
|
|
318
|
+
`Unknown network '${network}'. Run 'alchemy evm network list' to see available networks.`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
52
321
|
const domain = getBaseDomain();
|
|
53
322
|
const hostname = `${network}.g.${domain}`;
|
|
54
323
|
let parsed;
|
|
@@ -346,516 +615,252 @@ var X402Client = class _X402Client {
|
|
|
346
615
|
if (!resp.ok) {
|
|
347
616
|
const text = await resp.text().catch(() => "");
|
|
348
617
|
throw errNetwork(`HTTP ${resp.status}: ${text}`);
|
|
349
|
-
}
|
|
350
|
-
return resp.json();
|
|
351
|
-
}
|
|
352
|
-
async doFetch(url, init) {
|
|
353
|
-
return fetchWithTimeout(url, init);
|
|
354
|
-
}
|
|
355
|
-
async parsePaymentError(resp) {
|
|
356
|
-
const text = await resp.text().catch(() => "");
|
|
357
|
-
try {
|
|
358
|
-
const body = JSON.parse(text);
|
|
359
|
-
const reason = body?.extensions?.paymentError?.info?.reason;
|
|
360
|
-
const message = body?.extensions?.paymentError?.info?.message;
|
|
361
|
-
const payer = body?.extensions?.paymentError?.info?.payer;
|
|
362
|
-
if (reason === "insufficient_funds") {
|
|
363
|
-
const network = body?.accepts?.[0]?.network;
|
|
364
|
-
const asset = body?.accepts?.[0]?.extra?.name ?? "USDC";
|
|
365
|
-
const networkLabel = network === "eip155:8453" ? "Base" : network ?? "the payment network";
|
|
366
|
-
return new CLIError(
|
|
367
|
-
ErrorCode.PAYMENT_REQUIRED,
|
|
368
|
-
`Insufficient ${asset} balance on ${networkLabel}. ${message ?? ""}`.trim(),
|
|
369
|
-
`Fund wallet ${payer ?? ""} with ${asset} on ${networkLabel} to use x402.`.trim()
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
return new CLIError(
|
|
373
|
-
ErrorCode.PAYMENT_REQUIRED,
|
|
374
|
-
`x402 payment failed: ${message || body?.error || text}`
|
|
375
|
-
);
|
|
376
|
-
} catch {
|
|
377
|
-
return new CLIError(
|
|
378
|
-
ErrorCode.PAYMENT_REQUIRED,
|
|
379
|
-
`x402 payment failed: ${text}`
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
async handleAuthAndPayment(resp, retries) {
|
|
384
|
-
if (resp.status === 401) {
|
|
385
|
-
const detail = await resp.text().catch(() => "");
|
|
386
|
-
if (detail.includes("MESSAGE_EXPIRED")) {
|
|
387
|
-
return retries.authRetry();
|
|
388
|
-
}
|
|
389
|
-
throw new CLIError(
|
|
390
|
-
ErrorCode.AUTH_REQUIRED,
|
|
391
|
-
`x402 authentication failed: ${detail || "unauthorized"}`,
|
|
392
|
-
"Check your wallet key and try again."
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
if (resp.status === 402) {
|
|
396
|
-
const paymentRequiredHeader = resp.headers.get("payment-required");
|
|
397
|
-
if (!paymentRequiredHeader) {
|
|
398
|
-
throw new CLIError(
|
|
399
|
-
ErrorCode.PAYMENT_REQUIRED,
|
|
400
|
-
"x402 payment required but no Payment-Required header received."
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
const paymentSignature = await createPayment({
|
|
404
|
-
privateKey: this.privateKey,
|
|
405
|
-
paymentRequiredHeader
|
|
406
|
-
});
|
|
407
|
-
return retries.paymentRetry(paymentSignature);
|
|
408
|
-
}
|
|
409
|
-
return resp;
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
// src/lib/admin-client.ts
|
|
414
|
-
var STAGING_ADMIN_API_HOST = "admin-api.alchemypreview.com";
|
|
415
|
-
var AdminClient = class _AdminClient {
|
|
416
|
-
static get ADMIN_API_HOST() {
|
|
417
|
-
return `admin-api.${getBaseDomain()}`;
|
|
418
|
-
}
|
|
419
|
-
// Test/debug only: used by mock E2E to route admin requests locally.
|
|
420
|
-
static ADMIN_API_BASE_URL_ENV = "ALCHEMY_ADMIN_API_BASE_URL";
|
|
421
|
-
credential;
|
|
422
|
-
constructor(credential) {
|
|
423
|
-
if (typeof credential === "string") {
|
|
424
|
-
this.validateAccessKey(credential);
|
|
425
|
-
this.credential = { type: "access_key", key: credential };
|
|
426
|
-
} else {
|
|
427
|
-
if (credential.type === "access_key") {
|
|
428
|
-
this.validateAccessKey(credential.key);
|
|
429
|
-
} else if (!credential.token.trim()) {
|
|
430
|
-
throw errAuthRequired();
|
|
431
|
-
}
|
|
432
|
-
this.credential = credential;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
baseURL() {
|
|
436
|
-
const override = this.baseURLOverride();
|
|
437
|
-
if (override) return override.toString().replace(/\/$/, "");
|
|
438
|
-
return `https://admin-api.${getBaseDomain()}`;
|
|
439
|
-
}
|
|
440
|
-
allowedHosts() {
|
|
441
|
-
const hosts = /* @__PURE__ */ new Set([_AdminClient.ADMIN_API_HOST]);
|
|
442
|
-
const override = this.baseURLOverride();
|
|
443
|
-
if (override) hosts.add(override.hostname);
|
|
444
|
-
return hosts;
|
|
445
|
-
}
|
|
446
|
-
allowInsecureTransport(hostname) {
|
|
447
|
-
return isLocalhost(hostname);
|
|
448
|
-
}
|
|
449
|
-
baseURLOverride() {
|
|
450
|
-
return parseBaseURLOverride(_AdminClient.ADMIN_API_BASE_URL_ENV, {
|
|
451
|
-
allowedHostnames: [STAGING_ADMIN_API_HOST]
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
validateAccessKey(accessKey) {
|
|
455
|
-
if (!accessKey.trim() || /\s/.test(accessKey)) {
|
|
456
|
-
throw errInvalidAccessKey();
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
assertSafeRequestTarget(url) {
|
|
460
|
-
let parsed;
|
|
461
|
-
try {
|
|
462
|
-
parsed = new URL(url);
|
|
463
|
-
} catch {
|
|
464
|
-
throw errInvalidArgs("Invalid admin API URL.");
|
|
465
|
-
}
|
|
466
|
-
if (!this.allowedHosts().has(parsed.hostname)) {
|
|
467
|
-
throw errInvalidArgs(`Refusing to send credentials to unexpected host: ${parsed.hostname}`);
|
|
468
|
-
}
|
|
469
|
-
if (parsed.protocol !== "https:" && !this.allowInsecureTransport(parsed.hostname)) {
|
|
470
|
-
throw errInvalidArgs("Refusing to send credentials over non-HTTPS connection.");
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
async request(method, path, body) {
|
|
474
|
-
const url = `${this.baseURL()}${path}`;
|
|
475
|
-
debug(`${method} ${url}`);
|
|
476
|
-
this.assertSafeRequestTarget(url);
|
|
477
|
-
const resp = await fetchWithTimeout(url, {
|
|
478
|
-
method,
|
|
479
|
-
redirect: "error",
|
|
480
|
-
headers: {
|
|
481
|
-
Authorization: `Bearer ${this.credential.type === "access_key" ? this.credential.key : this.credential.token}`,
|
|
482
|
-
"Content-Type": "application/json",
|
|
483
|
-
Accept: "application/json"
|
|
484
|
-
},
|
|
485
|
-
...body !== void 0 && { body: JSON.stringify(body) }
|
|
486
|
-
});
|
|
487
|
-
if (resp.status === 401) {
|
|
488
|
-
debug(`401 Unauthorized from ${url}`);
|
|
489
|
-
throw errInvalidAccessKey();
|
|
490
|
-
}
|
|
491
|
-
if (resp.status === 403) {
|
|
492
|
-
const detail = await resp.text().catch(() => "");
|
|
493
|
-
let reason;
|
|
494
|
-
try {
|
|
495
|
-
const parsed = JSON.parse(detail);
|
|
496
|
-
reason = parsed?.message || parsed?.error?.message || parsed?.error || void 0;
|
|
497
|
-
} catch {
|
|
498
|
-
reason = detail || void 0;
|
|
499
|
-
}
|
|
500
|
-
throw errAccessDenied(typeof reason === "string" ? reason : void 0);
|
|
501
|
-
}
|
|
502
|
-
if (resp.status === 404) {
|
|
503
|
-
const text = await resp.text().catch(() => "");
|
|
504
|
-
throw errNotFound(text || path);
|
|
505
|
-
}
|
|
506
|
-
if (resp.status === 429) throw errRateLimited();
|
|
507
|
-
if (!resp.ok) {
|
|
508
|
-
const text = await resp.text().catch(() => "");
|
|
509
|
-
throw errAdminAPI(resp.status, text);
|
|
510
|
-
}
|
|
511
|
-
return resp.json();
|
|
512
|
-
}
|
|
513
|
-
async listChains() {
|
|
514
|
-
const result = await this.request("GET", "/v1/chains");
|
|
515
|
-
const chains = (Array.isArray(result.data) ? result.data : void 0) ?? (!Array.isArray(result.data) ? result.data?.networks : void 0) ?? (!Array.isArray(result.data) ? result.data?.chains : void 0) ?? result.networks ?? result.chains;
|
|
516
|
-
if (!Array.isArray(chains)) {
|
|
517
|
-
throw errAdminAPI(200, "Unexpected response shape for /v1/chains.");
|
|
518
|
-
}
|
|
519
|
-
return chains;
|
|
520
|
-
}
|
|
521
|
-
async listApps(opts) {
|
|
522
|
-
const params = new URLSearchParams();
|
|
523
|
-
if (opts?.cursor) params.set("cursor", opts.cursor);
|
|
524
|
-
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
525
|
-
const qs = params.toString();
|
|
526
|
-
const resp = await this.request(
|
|
527
|
-
"GET",
|
|
528
|
-
`/v1/apps${qs ? `?${qs}` : ""}`
|
|
529
|
-
);
|
|
530
|
-
return resp.data;
|
|
531
|
-
}
|
|
532
|
-
async listAllApps(opts) {
|
|
533
|
-
const apps = [];
|
|
534
|
-
const seenCursors = /* @__PURE__ */ new Set();
|
|
535
|
-
let cursor;
|
|
536
|
-
let pages = 0;
|
|
537
|
-
do {
|
|
538
|
-
const page = await this.listApps({
|
|
539
|
-
...cursor && { cursor },
|
|
540
|
-
...opts?.limit !== void 0 && { limit: opts.limit }
|
|
541
|
-
});
|
|
542
|
-
pages += 1;
|
|
543
|
-
apps.push(...page.apps);
|
|
544
|
-
cursor = page.cursor;
|
|
545
|
-
if (cursor && seenCursors.has(cursor)) break;
|
|
546
|
-
if (cursor) seenCursors.add(cursor);
|
|
547
|
-
} while (cursor);
|
|
548
|
-
return { apps, pages };
|
|
549
|
-
}
|
|
550
|
-
async getApp(id) {
|
|
551
|
-
const resp = await this.request("GET", `/v1/apps/${id}`);
|
|
552
|
-
return resp.data;
|
|
553
|
-
}
|
|
554
|
-
async createApp(opts) {
|
|
555
|
-
const resp = await this.request("POST", "/v1/apps", {
|
|
556
|
-
name: opts.name,
|
|
557
|
-
chainNetworks: opts.networks,
|
|
558
|
-
...opts.description && { description: opts.description },
|
|
559
|
-
...opts.products && { products: opts.products }
|
|
560
|
-
});
|
|
561
|
-
return resp.data;
|
|
562
|
-
}
|
|
563
|
-
async deleteApp(id) {
|
|
564
|
-
await this.request("DELETE", `/v1/apps/${id}`);
|
|
565
|
-
}
|
|
566
|
-
async updateApp(id, opts) {
|
|
567
|
-
const resp = await this.request("PATCH", `/v1/apps/${id}`, opts);
|
|
568
|
-
return resp.data;
|
|
569
|
-
}
|
|
570
|
-
async updateNetworkAllowlist(id, networks) {
|
|
571
|
-
const resp = await this.request("PUT", `/v1/apps/${id}/networks`, {
|
|
572
|
-
chainNetworks: networks
|
|
573
|
-
});
|
|
574
|
-
return resp.data;
|
|
575
|
-
}
|
|
576
|
-
async updateAddressAllowlist(id, addresses) {
|
|
577
|
-
const resp = await this.request("PUT", `/v1/apps/${id}/address-allowlist`, {
|
|
578
|
-
addressAllowlist: addresses
|
|
579
|
-
});
|
|
580
|
-
return resp.data;
|
|
581
|
-
}
|
|
582
|
-
async updateOriginAllowlist(id, origins) {
|
|
583
|
-
const resp = await this.request("PUT", `/v1/apps/${id}/origin-allowlist`, {
|
|
584
|
-
originAllowlist: origins
|
|
585
|
-
});
|
|
586
|
-
return resp.data;
|
|
618
|
+
}
|
|
619
|
+
return resp.json();
|
|
587
620
|
}
|
|
588
|
-
async
|
|
589
|
-
|
|
590
|
-
ipAllowlist: ips
|
|
591
|
-
});
|
|
592
|
-
return resp.data;
|
|
621
|
+
async doFetch(url, init) {
|
|
622
|
+
return fetchWithTimeout(url, init);
|
|
593
623
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
"
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
624
|
+
async parsePaymentError(resp) {
|
|
625
|
+
const text = await resp.text().catch(() => "");
|
|
626
|
+
try {
|
|
627
|
+
const body = JSON.parse(text);
|
|
628
|
+
const reason = body?.extensions?.paymentError?.info?.reason;
|
|
629
|
+
const message = body?.extensions?.paymentError?.info?.message;
|
|
630
|
+
const payer = body?.extensions?.paymentError?.info?.payer;
|
|
631
|
+
if (reason === "insufficient_funds") {
|
|
632
|
+
const network = body?.accepts?.[0]?.network;
|
|
633
|
+
const asset = body?.accepts?.[0]?.extra?.name ?? "USDC";
|
|
634
|
+
const networkLabel = network === "eip155:8453" ? "Base" : network ?? "the payment network";
|
|
635
|
+
return new CLIError(
|
|
636
|
+
ErrorCode.PAYMENT_REQUIRED,
|
|
637
|
+
`Insufficient ${asset} balance on ${networkLabel}. ${message ?? ""}`.trim(),
|
|
638
|
+
`Fund wallet ${payer ?? ""} with ${asset} on ${networkLabel} to use x402.`.trim()
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
return new CLIError(
|
|
642
|
+
ErrorCode.PAYMENT_REQUIRED,
|
|
643
|
+
`x402 payment failed: ${message || body?.error || text}`
|
|
644
|
+
);
|
|
645
|
+
} catch {
|
|
646
|
+
return new CLIError(
|
|
647
|
+
ErrorCode.PAYMENT_REQUIRED,
|
|
648
|
+
`x402 payment failed: ${text}`
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
async handleAuthAndPayment(resp, retries) {
|
|
653
|
+
if (resp.status === 401) {
|
|
654
|
+
const detail = await resp.text().catch(() => "");
|
|
655
|
+
if (detail.includes("MESSAGE_EXPIRED")) {
|
|
656
|
+
return retries.authRetry();
|
|
657
|
+
}
|
|
658
|
+
throw new CLIError(
|
|
659
|
+
ErrorCode.AUTH_REQUIRED,
|
|
660
|
+
`x402 authentication failed: ${detail || "unauthorized"}`,
|
|
661
|
+
"Check your wallet key and try again."
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
if (resp.status === 402) {
|
|
665
|
+
const paymentRequiredHeader = resp.headers.get("payment-required");
|
|
666
|
+
if (!paymentRequiredHeader) {
|
|
667
|
+
throw new CLIError(
|
|
668
|
+
ErrorCode.PAYMENT_REQUIRED,
|
|
669
|
+
"x402 payment required but no Payment-Required header received."
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
const paymentSignature = await createPayment({
|
|
673
|
+
privateKey: this.privateKey,
|
|
674
|
+
paymentRequiredHeader
|
|
675
|
+
});
|
|
676
|
+
return retries.paymentRetry(paymentSignature);
|
|
677
|
+
}
|
|
678
|
+
return resp;
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
// src/lib/admin-client.ts
|
|
683
|
+
var STAGING_ADMIN_API_HOST = "admin-api.alchemypreview.com";
|
|
684
|
+
var AdminClient = class _AdminClient {
|
|
685
|
+
static get ADMIN_API_HOST() {
|
|
686
|
+
return `admin-api.${getBaseDomain()}`;
|
|
687
|
+
}
|
|
688
|
+
// Test/debug only: used by mock E2E to route admin requests locally.
|
|
689
|
+
static ADMIN_API_BASE_URL_ENV = "ALCHEMY_ADMIN_API_BASE_URL";
|
|
690
|
+
credential;
|
|
691
|
+
constructor(credential) {
|
|
692
|
+
if (typeof credential === "string") {
|
|
693
|
+
this.validateAccessKey(credential);
|
|
694
|
+
this.credential = { type: "access_key", key: credential };
|
|
695
|
+
} else {
|
|
696
|
+
if (credential.type === "access_key") {
|
|
697
|
+
this.validateAccessKey(credential.key);
|
|
698
|
+
} else if (!credential.token.trim()) {
|
|
699
|
+
throw errAuthRequired();
|
|
700
|
+
}
|
|
701
|
+
this.credential = credential;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
baseURL() {
|
|
705
|
+
const override = this.baseURLOverride();
|
|
706
|
+
if (override) return override.toString().replace(/\/$/, "");
|
|
707
|
+
return `https://admin-api.${getBaseDomain()}`;
|
|
708
|
+
}
|
|
709
|
+
allowedHosts() {
|
|
710
|
+
const hosts = /* @__PURE__ */ new Set([_AdminClient.ADMIN_API_HOST]);
|
|
711
|
+
const override = this.baseURLOverride();
|
|
712
|
+
if (override) hosts.add(override.hostname);
|
|
713
|
+
return hosts;
|
|
714
|
+
}
|
|
715
|
+
allowInsecureTransport(hostname) {
|
|
716
|
+
return isLocalhost(hostname);
|
|
717
|
+
}
|
|
718
|
+
baseURLOverride() {
|
|
719
|
+
return parseBaseURLOverride(_AdminClient.ADMIN_API_BASE_URL_ENV, {
|
|
720
|
+
allowedHostnames: [STAGING_ADMIN_API_HOST]
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
validateAccessKey(accessKey) {
|
|
724
|
+
if (!accessKey.trim() || /\s/.test(accessKey)) {
|
|
725
|
+
throw errInvalidAccessKey();
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
assertSafeRequestTarget(url) {
|
|
729
|
+
let parsed;
|
|
730
|
+
try {
|
|
731
|
+
parsed = new URL(url);
|
|
732
|
+
} catch {
|
|
733
|
+
throw errInvalidArgs("Invalid admin API URL.");
|
|
734
|
+
}
|
|
735
|
+
if (!this.allowedHosts().has(parsed.hostname)) {
|
|
736
|
+
throw errInvalidArgs(`Refusing to send credentials to unexpected host: ${parsed.hostname}`);
|
|
737
|
+
}
|
|
738
|
+
if (parsed.protocol !== "https:" && !this.allowInsecureTransport(parsed.hostname)) {
|
|
739
|
+
throw errInvalidArgs("Refusing to send credentials over non-HTTPS connection.");
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async request(method, path, body) {
|
|
743
|
+
const url = `${this.baseURL()}${path}`;
|
|
744
|
+
debug(`${method} ${url}`);
|
|
745
|
+
this.assertSafeRequestTarget(url);
|
|
746
|
+
const resp = await fetchWithTimeout(url, {
|
|
747
|
+
method,
|
|
748
|
+
redirect: "error",
|
|
749
|
+
headers: {
|
|
750
|
+
Authorization: `Bearer ${this.credential.type === "access_key" ? this.credential.key : this.credential.token}`,
|
|
751
|
+
"Content-Type": "application/json",
|
|
752
|
+
Accept: "application/json"
|
|
753
|
+
},
|
|
754
|
+
...body !== void 0 && { body: JSON.stringify(body) }
|
|
755
|
+
});
|
|
756
|
+
if (resp.status === 401) {
|
|
757
|
+
debug(`401 Unauthorized from ${url}`);
|
|
758
|
+
throw errInvalidAccessKey();
|
|
759
|
+
}
|
|
760
|
+
if (resp.status === 403) {
|
|
761
|
+
const detail = await resp.text().catch(() => "");
|
|
762
|
+
let reason;
|
|
763
|
+
try {
|
|
764
|
+
const parsed = JSON.parse(detail);
|
|
765
|
+
reason = parsed?.message || parsed?.error?.message || parsed?.error || void 0;
|
|
766
|
+
} catch {
|
|
767
|
+
reason = detail || void 0;
|
|
768
|
+
}
|
|
769
|
+
throw errAccessDenied(typeof reason === "string" ? reason : void 0);
|
|
770
|
+
}
|
|
771
|
+
if (resp.status === 404) {
|
|
772
|
+
const text = await resp.text().catch(() => "");
|
|
773
|
+
throw errNotFound(text || path);
|
|
774
|
+
}
|
|
775
|
+
if (resp.status === 429) throw errRateLimited();
|
|
776
|
+
if (!resp.ok) {
|
|
777
|
+
const text = await resp.text().catch(() => "");
|
|
778
|
+
throw errAdminAPI(resp.status, text);
|
|
779
|
+
}
|
|
780
|
+
return resp.json();
|
|
781
|
+
}
|
|
782
|
+
async listChains() {
|
|
783
|
+
const result = await this.request("GET", "/v1/chains");
|
|
784
|
+
const chains = (Array.isArray(result.data) ? result.data : void 0) ?? (!Array.isArray(result.data) ? result.data?.networks : void 0) ?? (!Array.isArray(result.data) ? result.data?.chains : void 0) ?? result.networks ?? result.chains;
|
|
785
|
+
if (!Array.isArray(chains)) {
|
|
786
|
+
throw errAdminAPI(200, "Unexpected response shape for /v1/chains.");
|
|
787
|
+
}
|
|
788
|
+
return chains;
|
|
789
|
+
}
|
|
790
|
+
async listApps(opts) {
|
|
791
|
+
const params = new URLSearchParams();
|
|
792
|
+
if (opts?.cursor) params.set("cursor", opts.cursor);
|
|
793
|
+
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
794
|
+
const qs = params.toString();
|
|
795
|
+
const resp = await this.request(
|
|
796
|
+
"GET",
|
|
797
|
+
`/v1/apps${qs ? `?${qs}` : ""}`
|
|
798
|
+
);
|
|
799
|
+
return resp.data;
|
|
800
|
+
}
|
|
801
|
+
async listAllApps(opts) {
|
|
802
|
+
const apps = [];
|
|
803
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
804
|
+
let cursor;
|
|
805
|
+
let pages = 0;
|
|
806
|
+
do {
|
|
807
|
+
const page = await this.listApps({
|
|
808
|
+
...cursor && { cursor },
|
|
809
|
+
...opts?.limit !== void 0 && { limit: opts.limit }
|
|
810
|
+
});
|
|
811
|
+
pages += 1;
|
|
812
|
+
apps.push(...page.apps);
|
|
813
|
+
cursor = page.cursor;
|
|
814
|
+
if (cursor && seenCursors.has(cursor)) break;
|
|
815
|
+
if (cursor) seenCursors.add(cursor);
|
|
816
|
+
} while (cursor);
|
|
817
|
+
return { apps, pages };
|
|
818
|
+
}
|
|
819
|
+
async getApp(id) {
|
|
820
|
+
const resp = await this.request("GET", `/v1/apps/${id}`);
|
|
821
|
+
return resp.data;
|
|
822
|
+
}
|
|
823
|
+
async createApp(opts) {
|
|
824
|
+
const resp = await this.request("POST", "/v1/apps", {
|
|
825
|
+
name: opts.name,
|
|
826
|
+
chainNetworks: opts.networks,
|
|
827
|
+
...opts.description && { description: opts.description },
|
|
828
|
+
...opts.products && { products: opts.products }
|
|
829
|
+
});
|
|
830
|
+
return resp.data;
|
|
831
|
+
}
|
|
832
|
+
async deleteApp(id) {
|
|
833
|
+
await this.request("DELETE", `/v1/apps/${id}`);
|
|
834
|
+
}
|
|
835
|
+
async updateApp(id, opts) {
|
|
836
|
+
const resp = await this.request("PATCH", `/v1/apps/${id}`, opts);
|
|
837
|
+
return resp.data;
|
|
838
|
+
}
|
|
839
|
+
async updateNetworkAllowlist(id, networks) {
|
|
840
|
+
const resp = await this.request("PUT", `/v1/apps/${id}/networks`, {
|
|
841
|
+
chainNetworks: networks
|
|
842
|
+
});
|
|
843
|
+
return resp.data;
|
|
844
|
+
}
|
|
845
|
+
async updateAddressAllowlist(id, addresses) {
|
|
846
|
+
const resp = await this.request("PUT", `/v1/apps/${id}/address-allowlist`, {
|
|
847
|
+
addressAllowlist: addresses
|
|
848
|
+
});
|
|
849
|
+
return resp.data;
|
|
850
|
+
}
|
|
851
|
+
async updateOriginAllowlist(id, origins) {
|
|
852
|
+
const resp = await this.request("PUT", `/v1/apps/${id}/origin-allowlist`, {
|
|
853
|
+
originAllowlist: origins
|
|
854
|
+
});
|
|
855
|
+
return resp.data;
|
|
856
|
+
}
|
|
857
|
+
async updateIpAllowlist(id, ips) {
|
|
858
|
+
const resp = await this.request("PUT", `/v1/apps/${id}/ip-allowlist`, {
|
|
859
|
+
ipAllowlist: ips
|
|
860
|
+
});
|
|
861
|
+
return resp.data;
|
|
805
862
|
}
|
|
806
|
-
return `https://${id}.g.${domain}/v2/{apiKey}`;
|
|
807
|
-
}
|
|
808
|
-
function getRPCNetworks() {
|
|
809
|
-
return RPC_NETWORK_IDS.map((id) => ({
|
|
810
|
-
id,
|
|
811
|
-
name: toDisplayName(id),
|
|
812
|
-
family: toFamily(id),
|
|
813
|
-
isTestnet: isTestnetNetwork(id),
|
|
814
|
-
httpsUrlTemplate: toHttpsUrlTemplate(id)
|
|
815
|
-
}));
|
|
816
|
-
}
|
|
817
|
-
function getRPCNetworkIds() {
|
|
818
|
-
return [...RPC_NETWORK_IDS];
|
|
819
|
-
}
|
|
820
|
-
var NATIVE_TOKEN_SYMBOLS = {
|
|
821
|
-
eth: "ETH",
|
|
822
|
-
arb: "ETH",
|
|
823
|
-
arbnova: "ETH",
|
|
824
|
-
opt: "ETH",
|
|
825
|
-
base: "ETH",
|
|
826
|
-
zksync: "ETH",
|
|
827
|
-
scroll: "ETH",
|
|
828
|
-
blast: "ETH",
|
|
829
|
-
linea: "ETH",
|
|
830
|
-
zora: "ETH",
|
|
831
|
-
shape: "ETH",
|
|
832
|
-
polygon: "POL",
|
|
833
|
-
polygonzkevm: "ETH",
|
|
834
|
-
bnb: "BNB",
|
|
835
|
-
opbnb: "BNB",
|
|
836
|
-
avax: "AVAX",
|
|
837
|
-
solana: "SOL",
|
|
838
|
-
starknet: "ETH",
|
|
839
|
-
fantom: "FTM",
|
|
840
|
-
metis: "METIS",
|
|
841
|
-
mantle: "MNT",
|
|
842
|
-
celo: "CELO",
|
|
843
|
-
gnosis: "xDAI",
|
|
844
|
-
frax: "frxETH",
|
|
845
|
-
worldchain: "ETH",
|
|
846
|
-
berachain: "BERA",
|
|
847
|
-
flow: "FLOW",
|
|
848
|
-
rootstock: "RBTC",
|
|
849
|
-
zetachain: "ZETA",
|
|
850
|
-
sui: "SUI"
|
|
851
863
|
};
|
|
852
|
-
function isSolanaNetwork(networkId) {
|
|
853
|
-
return networkId.startsWith("solana-");
|
|
854
|
-
}
|
|
855
|
-
function nativeTokenSymbol(networkId) {
|
|
856
|
-
const prefix = networkId.replace(/-(mainnet|testnet|sepolia|holesky|hoodi|devnet|amoy|fuji|cardona|saigon|chiado|signet|mocha|blaze|curtis|bepolia).*$/, "");
|
|
857
|
-
return NATIVE_TOKEN_SYMBOLS[prefix] ?? "ETH";
|
|
858
|
-
}
|
|
859
864
|
|
|
860
865
|
// src/lib/wallet-session.ts
|
|
861
866
|
import { generateKeyPairSync, randomUUID } from "crypto";
|
|
@@ -1232,11 +1237,11 @@ function resolveWalletSession() {
|
|
|
1232
1237
|
var resolveDelegatedSession = resolveWalletSession;
|
|
1233
1238
|
|
|
1234
1239
|
export {
|
|
1235
|
-
AdminClient,
|
|
1236
1240
|
getRPCNetworks,
|
|
1237
1241
|
getRPCNetworkIds,
|
|
1238
1242
|
isSolanaNetwork,
|
|
1239
1243
|
nativeTokenSymbol,
|
|
1244
|
+
AdminClient,
|
|
1240
1245
|
createPendingSession,
|
|
1241
1246
|
loadSession,
|
|
1242
1247
|
loadStoredSession,
|