@alchemy/cli 0.1.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/README.md +336 -0
- package/dist/chunk-F7KTEZFZ.js +282 -0
- package/dist/chunk-PH4BPYSY.js +1145 -0
- package/dist/chunk-QKXQW4OF.js +1113 -0
- package/dist/index.js +1897 -0
- package/dist/interactive-2ITFWH3B.js +406 -0
- package/dist/onboarding-3J4EXZMG.js +178 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Alchemy CLI
|
|
2
|
+
|
|
3
|
+
Alchemy CLI is a command-line tool for querying blockchain data and managing Alchemy apps/configuration.
|
|
4
|
+
It supports both human-friendly terminal output and JSON output for automation.
|
|
5
|
+
You can use API keys, access keys, or x402 wallet auth depending on the command.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
The current repository workflow is source install:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/alchemyplatform/alchemy-cli.git
|
|
13
|
+
cd alchemy-cli
|
|
14
|
+
pnpm install
|
|
15
|
+
pnpm build
|
|
16
|
+
pnpm link --global
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This makes the `alchemy` command available globally.
|
|
20
|
+
To unlink later: `pnpm unlink --global`.
|
|
21
|
+
|
|
22
|
+
## Command Reference
|
|
23
|
+
|
|
24
|
+
Run commands as `alchemy <command>`.
|
|
25
|
+
Use `alchemy help` or `alchemy help <command>` for generated command help.
|
|
26
|
+
|
|
27
|
+
### Node
|
|
28
|
+
|
|
29
|
+
| Command | What it does | Example |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `balance [address]` (`bal [address]`) | Gets ETH balance for an address | `alchemy bal 0x...` |
|
|
32
|
+
| `tx [hash]` | Gets transaction + receipt by hash | `alchemy tx 0x...` |
|
|
33
|
+
| `block <number>` | Gets block details (`latest`, decimal, or hex) | `alchemy block latest` |
|
|
34
|
+
| `rpc <method> [params...]` | Makes raw JSON-RPC call | `alchemy rpc eth_blockNumber` |
|
|
35
|
+
| `trace <method> [params...]` | Calls Trace API methods | `alchemy trace call '{"to":"0x..."}' '["trace"]' latest` |
|
|
36
|
+
| `debug <method> [params...]` | Calls Debug API methods | `alchemy debug traceTransaction "0x..."` |
|
|
37
|
+
|
|
38
|
+
### Data
|
|
39
|
+
|
|
40
|
+
| Command | What it does | Example |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `tokens [address]` | Lists ERC-20 balances for an address | `alchemy tokens 0x...` |
|
|
43
|
+
| `tokens metadata <contract>` | Gets ERC-20 metadata | `alchemy tokens metadata 0x...` |
|
|
44
|
+
| `tokens allowance --owner --spender --contract` | Gets ERC-20 allowance | `alchemy tokens allowance --owner 0x... --spender 0x... --contract 0x...` |
|
|
45
|
+
| `nfts [address]` | Lists NFTs owned by an address | `alchemy nfts 0x...` |
|
|
46
|
+
| `nfts metadata --contract <addr> --token-id <id>` | Gets NFT metadata by contract/token | `alchemy nfts metadata --contract 0x... --token-id 1` |
|
|
47
|
+
| `nfts contract <address>` | Gets NFT contract metadata | `alchemy nfts contract 0x...` |
|
|
48
|
+
| `transfers [address]` | Gets transfer history (`alchemy_getAssetTransfers`) | `alchemy transfers 0x... --category erc20,erc721` |
|
|
49
|
+
| `prices symbol <symbols>` | Gets current token prices by symbol | `alchemy prices symbol ETH,USDC` |
|
|
50
|
+
| `prices address --addresses <json>` | Gets current token prices by address/network pairs | `alchemy prices address --addresses '[{"network":"eth-mainnet","address":"0x..."}]'` |
|
|
51
|
+
| `prices historical --body <json>` | Gets historical prices | `alchemy prices historical --body '{"symbol":"ETH","startTime":"...","endTime":"..."}'` |
|
|
52
|
+
| `portfolio tokens --body <json>` | Gets token portfolio data | `alchemy portfolio tokens --body '{...}'` |
|
|
53
|
+
| `portfolio token-balances --body <json>` | Gets token balance snapshots | `alchemy portfolio token-balances --body '{...}'` |
|
|
54
|
+
| `portfolio nfts --body <json>` | Gets NFT portfolio data | `alchemy portfolio nfts --body '{...}'` |
|
|
55
|
+
| `portfolio nft-contracts --body <json>` | Gets NFT contract portfolio data | `alchemy portfolio nft-contracts --body '{...}'` |
|
|
56
|
+
| `portfolio transactions --body <json>` | Gets portfolio transaction history | `alchemy portfolio transactions --body '{...}'` |
|
|
57
|
+
| `simulate asset-changes --tx <json>` | Simulates asset changes | `alchemy simulate asset-changes --tx '{"from":"0x...","to":"0x..."}'` |
|
|
58
|
+
| `simulate execution --tx <json>` | Simulates execution traces | `alchemy simulate execution --tx '{"from":"0x...","to":"0x..."}'` |
|
|
59
|
+
| `simulate asset-changes-bundle --txs <json>` | Simulates bundle asset changes | `alchemy simulate asset-changes-bundle --txs '[{...}]'` |
|
|
60
|
+
| `simulate execution-bundle --txs <json>` | Simulates bundle execution traces | `alchemy simulate execution-bundle --txs '[{...}]'` |
|
|
61
|
+
|
|
62
|
+
### Wallets
|
|
63
|
+
|
|
64
|
+
| Command | What it does | Example |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `wallet generate` | Generates wallet for x402 and saves to config | `alchemy wallet generate` |
|
|
67
|
+
| `wallet import <path>` | Imports wallet key file for x402 | `alchemy wallet import ./private-key.txt` |
|
|
68
|
+
| `wallet address` | Prints configured wallet address | `alchemy wallet address` |
|
|
69
|
+
| `bundler send-user-operation ...` | Sends ERC-4337 user op | `alchemy bundler send-user-operation --user-op '{...}' --entry-point 0x...` |
|
|
70
|
+
| `bundler estimate-user-operation-gas ...` | Estimates ERC-4337 user op gas | `alchemy bundler estimate-user-operation-gas --user-op '{...}' --entry-point 0x...` |
|
|
71
|
+
| `bundler get-user-operation-receipt ...` | Gets ERC-4337 user op receipt | `alchemy bundler get-user-operation-receipt --user-op-hash 0x...` |
|
|
72
|
+
| `gas-manager request-gas-and-paymaster --body <json>` | Requests paymaster data | `alchemy gas-manager request-gas-and-paymaster --body '{...}'` |
|
|
73
|
+
| `gas-manager request-paymaster-token-quote --body <json>` | Gets paymaster token quote | `alchemy gas-manager request-paymaster-token-quote --body '{...}'` |
|
|
74
|
+
| `webhooks list` | Lists Notify webhooks | `alchemy webhooks list --webhook-api-key <key>` |
|
|
75
|
+
| `webhooks create --body <json>` | Creates Notify webhook | `alchemy webhooks create --body '{...}' --webhook-api-key <key>` |
|
|
76
|
+
| `webhooks update --body <json>` | Updates Notify webhook | `alchemy webhooks update --body '{...}' --webhook-api-key <key>` |
|
|
77
|
+
| `webhooks delete <id>` | Deletes Notify webhook | `alchemy webhooks delete <id> --webhook-api-key <key>` |
|
|
78
|
+
|
|
79
|
+
### Chains
|
|
80
|
+
|
|
81
|
+
| Command | What it does | Example |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `network list` | Lists supported RPC networks | `alchemy network list --configured` |
|
|
84
|
+
| `chains list` | Lists Admin API chain enums | `alchemy chains list` |
|
|
85
|
+
| `solana rpc <method> [params...]` | Calls Solana JSON-RPC methods | `alchemy solana rpc getBalance '"<pubkey>"'` |
|
|
86
|
+
| `solana das <method> [params...]` | Calls Solana DAS methods | `alchemy solana das getAssetsByOwner '{"ownerAddress":"<pubkey>"}'` |
|
|
87
|
+
|
|
88
|
+
### CLI Admin
|
|
89
|
+
|
|
90
|
+
| Command | What it does | Example |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `(no command)` | Starts interactive REPL mode (TTY only) | `alchemy` |
|
|
93
|
+
| `apps list` | Lists apps (supports pagination/filtering) | `alchemy apps list --all` |
|
|
94
|
+
| `apps get <id>` | Gets app details | `alchemy apps get <app-id>` |
|
|
95
|
+
| `apps create` | Creates app | `alchemy apps create --name "My App" --networks eth-mainnet` |
|
|
96
|
+
| `apps update <id>` | Updates app name/description | `alchemy apps update <app-id> --name "New Name"` |
|
|
97
|
+
| `apps delete <id>` | Deletes app | `alchemy apps delete <app-id>` |
|
|
98
|
+
| `apps networks <id>` | Updates app network allowlist | `alchemy apps networks <app-id> --networks eth-mainnet,polygon-mainnet` |
|
|
99
|
+
| `apps address-allowlist <id>` | Updates app address allowlist | `alchemy apps address-allowlist <app-id> --addresses 0xabc,0xdef` |
|
|
100
|
+
| `apps origin-allowlist <id>` | Updates app origin allowlist | `alchemy apps origin-allowlist <app-id> --origins https://example.com` |
|
|
101
|
+
| `apps ip-allowlist <id>` | Updates app IP allowlist | `alchemy apps ip-allowlist <app-id> --ips 1.2.3.4,5.6.7.8` |
|
|
102
|
+
| `setup status` | Shows setup status + next commands | `alchemy setup status` |
|
|
103
|
+
| `config set ...` | Sets config values | `alchemy config set api-key <key>` |
|
|
104
|
+
| `config get <key>` | Gets one config value | `alchemy config get network` |
|
|
105
|
+
| `config list` | Lists all config values | `alchemy config list` |
|
|
106
|
+
| `config reset [key]` | Resets one or all config values | `alchemy config reset --yes` |
|
|
107
|
+
| `version` | Prints CLI version | `alchemy version` |
|
|
108
|
+
|
|
109
|
+
## Flags
|
|
110
|
+
|
|
111
|
+
### Global flags
|
|
112
|
+
|
|
113
|
+
These apply to all commands.
|
|
114
|
+
|
|
115
|
+
#### Auth & network
|
|
116
|
+
|
|
117
|
+
| Flag | Env var | Description |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| `--api-key <key>` | `ALCHEMY_API_KEY` | API key for blockchain query commands |
|
|
120
|
+
| `--access-key <key>` | `ALCHEMY_ACCESS_KEY` | Access key for Admin API operations |
|
|
121
|
+
| `-n, --network <network>` | `ALCHEMY_NETWORK` | Target network (default: `eth-mainnet`) |
|
|
122
|
+
| `--x402` | — | Enable x402 wallet-based gateway auth |
|
|
123
|
+
| `--wallet-key-file <path>` | — | Wallet private key file for x402 auth |
|
|
124
|
+
|
|
125
|
+
#### Output & formatting
|
|
126
|
+
|
|
127
|
+
| Flag | Env var | Description |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| `--json` | — | Force JSON output |
|
|
130
|
+
| `-q, --quiet` | — | Suppress non-essential output |
|
|
131
|
+
| `-v, --verbose` | — | Enable verbose output |
|
|
132
|
+
| `--no-color` | `NO_COLOR` | Disable color output |
|
|
133
|
+
| `--reveal` | — | Show secrets in plain text (TTY only) |
|
|
134
|
+
|
|
135
|
+
#### Runtime & behavior
|
|
136
|
+
|
|
137
|
+
| Flag | Env var | Description |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `--timeout <ms>` | — | Request timeout in milliseconds |
|
|
140
|
+
| `--debug` | — | Enable internal debug diagnostics |
|
|
141
|
+
| `--no-interactive` | — | Disable REPL and prompt-driven interactions |
|
|
142
|
+
|
|
143
|
+
Additional env vars:
|
|
144
|
+
|
|
145
|
+
| Env var | Description |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `ALCHEMY_CONFIG` | Custom path to config file |
|
|
148
|
+
| `ALCHEMY_WALLET_KEY` | Wallet private key for x402 auth |
|
|
149
|
+
| `ALCHEMY_WEBHOOK_API_KEY` | Webhook API key for Notify commands |
|
|
150
|
+
|
|
151
|
+
### Command-specific flags
|
|
152
|
+
|
|
153
|
+
| Command | Flags |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `nfts` | `--limit <n>`, `--page-key <key>` |
|
|
156
|
+
| `nfts metadata` | `--contract <address>` (required), `--token-id <id>` (required) |
|
|
157
|
+
| `tokens` | `--page-key <key>` |
|
|
158
|
+
| `tokens allowance` | `--owner <address>` (required), `--spender <address>` (required), `--contract <address>` (required) |
|
|
159
|
+
| `transfers` | `--from-address <address>`, `--to-address <address>`, `--from-block <block>`, `--to-block <block>`, `--category <list>`, `--max-count <n>`, `--page-key <key>` |
|
|
160
|
+
| `prices address` | `--addresses <json>` (required) |
|
|
161
|
+
| `prices historical` | `--body <json>` (required) |
|
|
162
|
+
| `portfolio *` | `--body <json>` (required per subcommand) |
|
|
163
|
+
| `simulate *` | `--tx <json>` or `--txs <json>` (required) |
|
|
164
|
+
| `webhooks *` | `--webhook-api-key <key>` (or `ALCHEMY_WEBHOOK_API_KEY`, `ALCHEMY_NOTIFY_AUTH_TOKEN`, config `webhook-api-key`, or app webhook key) |
|
|
165
|
+
| `bundler send-user-operation` | `--user-op <json>` (required), `--entry-point <address>` (required) |
|
|
166
|
+
| `bundler estimate-user-operation-gas` | `--user-op <json>` (required), `--entry-point <address>` (required), `--state-override <json>` |
|
|
167
|
+
| `bundler get-user-operation-receipt` | `--user-op-hash <hash>` (required) |
|
|
168
|
+
| `gas-manager *` | `--body <json>` (required) |
|
|
169
|
+
| `apps list` | `--cursor <cursor>`, `--limit <n>`, `--all`, `--search <query>`, `--id <appId>` |
|
|
170
|
+
| `apps create` | `--name <name>` (required), `--networks <networks>` (required), `--description <desc>`, `--products <products>`, `--dry-run` |
|
|
171
|
+
| `apps update` | `--name <name>`, `--description <desc>`, `--dry-run` |
|
|
172
|
+
| `apps delete` | `--dry-run` |
|
|
173
|
+
| `apps networks` | `--networks <networks>` (required), `--dry-run` |
|
|
174
|
+
| `apps address-allowlist` | `--addresses <addrs>` (required), `--dry-run` |
|
|
175
|
+
| `apps origin-allowlist` | `--origins <origins>` (required), `--dry-run` |
|
|
176
|
+
| `apps ip-allowlist` | `--ips <ips>` (required), `--dry-run` |
|
|
177
|
+
| `network list` | `--configured`, `--app-id <id>` |
|
|
178
|
+
| `config reset` | `-y, --yes` |
|
|
179
|
+
|
|
180
|
+
## Authentication
|
|
181
|
+
|
|
182
|
+
The CLI supports three auth inputs:
|
|
183
|
+
|
|
184
|
+
- API key for blockchain queries (`balance`, `tx`, `block`, `nfts`, `tokens`, `rpc`)
|
|
185
|
+
- Access key for Admin API operations (`apps`, `chains`, configured network lookups)
|
|
186
|
+
- x402 wallet key for wallet-authenticated blockchain queries
|
|
187
|
+
|
|
188
|
+
Notify/webhook commands use a webhook API key with resolution order:
|
|
189
|
+
`--webhook-api-key` -> `ALCHEMY_WEBHOOK_API_KEY` -> `ALCHEMY_NOTIFY_AUTH_TOKEN` -> config `webhook-api-key` -> configured app webhook key.
|
|
190
|
+
|
|
191
|
+
Get API/access keys at [alchemy.com](https://dashboard.alchemy.com/).
|
|
192
|
+
|
|
193
|
+
#### API key
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Config
|
|
197
|
+
alchemy config set api-key <your-key>
|
|
198
|
+
|
|
199
|
+
# Environment variable
|
|
200
|
+
export ALCHEMY_API_KEY=<your-key>
|
|
201
|
+
|
|
202
|
+
# Per-command override
|
|
203
|
+
alchemy balance 0x... --api-key <your-key>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Resolution order: `--api-key` -> `ALCHEMY_API_KEY` -> config file -> configured app API key.
|
|
207
|
+
|
|
208
|
+
#### Access key
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Config (in TTY, this may trigger app setup flow)
|
|
212
|
+
alchemy config set access-key <your-key>
|
|
213
|
+
|
|
214
|
+
# Environment variable
|
|
215
|
+
export ALCHEMY_ACCESS_KEY=<your-key>
|
|
216
|
+
|
|
217
|
+
# Per-command override
|
|
218
|
+
alchemy apps list --access-key <your-key>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Resolution order: `--access-key` -> `ALCHEMY_ACCESS_KEY` -> config file.
|
|
222
|
+
|
|
223
|
+
#### x402 wallet auth
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Generate/import a wallet managed by CLI
|
|
227
|
+
alchemy wallet generate
|
|
228
|
+
# or
|
|
229
|
+
alchemy wallet import ./private-key.txt
|
|
230
|
+
|
|
231
|
+
# Use x402 per command
|
|
232
|
+
alchemy balance 0x... --x402
|
|
233
|
+
|
|
234
|
+
# Or enable by default
|
|
235
|
+
alchemy config set x402 true
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Generated/imported wallets are stored as unique key files under `~/.config/alchemy/wallet-keys/` so creating another wallet does not overwrite prior private keys.
|
|
239
|
+
|
|
240
|
+
You can also provide wallet key directly:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
export ALCHEMY_WALLET_KEY=0x...
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Wallet key resolution order: `--wallet-key-file` -> `ALCHEMY_WALLET_KEY` -> `wallet-key-file` in config.
|
|
247
|
+
|
|
248
|
+
## REPL Mode
|
|
249
|
+
|
|
250
|
+
Run `alchemy` with no command in an interactive terminal:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
alchemy
|
|
254
|
+
alchemy ◆ balance 0x...
|
|
255
|
+
alchemy ◆ block latest
|
|
256
|
+
alchemy ◆ exit
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Use `--no-interactive` to disable REPL/prompts in automation.
|
|
260
|
+
|
|
261
|
+
## Output Modes
|
|
262
|
+
|
|
263
|
+
- TTY: formatted human output
|
|
264
|
+
- Non-TTY: JSON output (script-friendly)
|
|
265
|
+
- `--json`: forces JSON output in any context
|
|
266
|
+
- `--verbose` or `alchemy config set verbose true`: includes richer payload output on supported commands
|
|
267
|
+
|
|
268
|
+
## Error Format
|
|
269
|
+
|
|
270
|
+
Errors are structured JSON in JSON mode:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"error": {
|
|
275
|
+
"code": "AUTH_REQUIRED",
|
|
276
|
+
"message": "Not authenticated. Set ALCHEMY_API_KEY or run 'alchemy config set api-key <key>'.",
|
|
277
|
+
"hint": "alchemy config set api-key <your-key>"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Development
|
|
283
|
+
|
|
284
|
+
Prerequisites:
|
|
285
|
+
|
|
286
|
+
- [Node.js 18+](https://nodejs.org/)
|
|
287
|
+
- [pnpm](https://pnpm.io/)
|
|
288
|
+
|
|
289
|
+
Run during development:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# Run without building
|
|
293
|
+
npx tsx src/index.ts balance 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
|
|
294
|
+
|
|
295
|
+
# Build in watch mode
|
|
296
|
+
pnpm dev
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Build:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
pnpm build
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Test:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
pnpm test
|
|
309
|
+
pnpm test:e2e
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Type check:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
pnpm lint
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Coverage:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
pnpm test:coverage
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Endpoint Override Env Vars (Local Testing Only)
|
|
325
|
+
|
|
326
|
+
These are for local/mock testing, not normal production usage:
|
|
327
|
+
|
|
328
|
+
- `ALCHEMY_RPC_BASE_URL`
|
|
329
|
+
- `ALCHEMY_ADMIN_API_BASE_URL`
|
|
330
|
+
- `ALCHEMY_X402_BASE_URL`
|
|
331
|
+
|
|
332
|
+
Safety constraints:
|
|
333
|
+
|
|
334
|
+
- Only localhost targets are accepted (`localhost`, `127.0.0.1`, `::1`)
|
|
335
|
+
- Non-HTTPS transport is allowed only for localhost
|
|
336
|
+
- Production defaults are unchanged when unset
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
if(process.argv.includes("--no-color"))process.env.NO_COLOR="1";
|
|
3
|
+
import {
|
|
4
|
+
isInteractiveAllowed
|
|
5
|
+
} from "./chunk-QKXQW4OF.js";
|
|
6
|
+
|
|
7
|
+
// src/lib/networks.ts
|
|
8
|
+
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;
|
|
9
|
+
var FAMILY_ALIASES = {
|
|
10
|
+
arb: "Arbitrum",
|
|
11
|
+
arbnova: "Arbitrum Nova",
|
|
12
|
+
avax: "Avalanche",
|
|
13
|
+
bnb: "BNB Smart Chain",
|
|
14
|
+
eth: "Ethereum",
|
|
15
|
+
opt: "OP Mainnet",
|
|
16
|
+
polygonzkevm: "Polygon zkEVM"
|
|
17
|
+
};
|
|
18
|
+
var NAME_ALIASES = {
|
|
19
|
+
arb: "Arbitrum",
|
|
20
|
+
avax: "Avalanche",
|
|
21
|
+
bnb: "BNB",
|
|
22
|
+
eth: "Ethereum",
|
|
23
|
+
opbnb: "opBNB",
|
|
24
|
+
opt: "OP Mainnet",
|
|
25
|
+
sui: "SUI",
|
|
26
|
+
xmtp: "XMTP",
|
|
27
|
+
zksync: "ZKsync"
|
|
28
|
+
};
|
|
29
|
+
var RPC_NETWORK_IDS = [
|
|
30
|
+
"abstract-mainnet",
|
|
31
|
+
"abstract-testnet",
|
|
32
|
+
"adi-mainnet",
|
|
33
|
+
"adi-testnet",
|
|
34
|
+
"alchemy-internal",
|
|
35
|
+
"alchemy-sepolia",
|
|
36
|
+
"alchemyarb-fam",
|
|
37
|
+
"alchemyarb-sepolia",
|
|
38
|
+
"alterscope-mainnet",
|
|
39
|
+
"anime-mainnet",
|
|
40
|
+
"anime-sepolia",
|
|
41
|
+
"apechain-curtis",
|
|
42
|
+
"apechain-mainnet",
|
|
43
|
+
"aptos-mainnet",
|
|
44
|
+
"aptos-testnet",
|
|
45
|
+
"arb-mainnet",
|
|
46
|
+
"arb-sepolia",
|
|
47
|
+
"arbnova-mainnet",
|
|
48
|
+
"arc-testnet",
|
|
49
|
+
"astar-mainnet",
|
|
50
|
+
"avax-fuji",
|
|
51
|
+
"avax-mainnet",
|
|
52
|
+
"base-mainnet",
|
|
53
|
+
"base-sepolia",
|
|
54
|
+
"berachain-bepolia",
|
|
55
|
+
"berachain-mainnet",
|
|
56
|
+
"bitcoin-mainnet",
|
|
57
|
+
"bitcoin-signet",
|
|
58
|
+
"bitcoin-testnet",
|
|
59
|
+
"blast-mainnet",
|
|
60
|
+
"blast-sepolia",
|
|
61
|
+
"bnb-mainnet",
|
|
62
|
+
"bnb-testnet",
|
|
63
|
+
"bob-mainnet",
|
|
64
|
+
"bob-sepolia",
|
|
65
|
+
"boba-mainnet",
|
|
66
|
+
"boba-sepolia",
|
|
67
|
+
"botanix-mainnet",
|
|
68
|
+
"botanix-testnet",
|
|
69
|
+
"celestiabridge-mainnet",
|
|
70
|
+
"celestiabridge-mocha",
|
|
71
|
+
"celo-mainnet",
|
|
72
|
+
"celo-sepolia",
|
|
73
|
+
"citrea-mainnet",
|
|
74
|
+
"citrea-testnet",
|
|
75
|
+
"clankermon-mainnet",
|
|
76
|
+
"commons-mainnet",
|
|
77
|
+
"crossfi-mainnet",
|
|
78
|
+
"crossfi-testnet",
|
|
79
|
+
"degen-mainnet",
|
|
80
|
+
"degen-sepolia",
|
|
81
|
+
"earnm-mainnet",
|
|
82
|
+
"earnm-sepolia",
|
|
83
|
+
"edge-mainnet",
|
|
84
|
+
"edge-testnet",
|
|
85
|
+
"eth-holesky",
|
|
86
|
+
"eth-holeskybeacon",
|
|
87
|
+
"eth-hoodi",
|
|
88
|
+
"eth-hoodibeacon",
|
|
89
|
+
"eth-mainnet",
|
|
90
|
+
"eth-mainnetbeacon",
|
|
91
|
+
"eth-sepolia",
|
|
92
|
+
"eth-sepoliabeacon",
|
|
93
|
+
"flow-mainnet",
|
|
94
|
+
"flow-testnet",
|
|
95
|
+
"frax-hoodi",
|
|
96
|
+
"frax-mainnet",
|
|
97
|
+
"galactica-cassiopeia",
|
|
98
|
+
"galactica-mainnet",
|
|
99
|
+
"gensyn-mainnet",
|
|
100
|
+
"gensyn-testnet",
|
|
101
|
+
"gnosis-chiado",
|
|
102
|
+
"gnosis-mainnet",
|
|
103
|
+
"humanity-mainnet",
|
|
104
|
+
"humanity-testnet",
|
|
105
|
+
"hyperliquid-mainnet",
|
|
106
|
+
"hyperliquid-testnet",
|
|
107
|
+
"ink-mainnet",
|
|
108
|
+
"ink-sepolia",
|
|
109
|
+
"lens-mainnet",
|
|
110
|
+
"lens-sepolia",
|
|
111
|
+
"linea-mainnet",
|
|
112
|
+
"linea-sepolia",
|
|
113
|
+
"mantle-mainnet",
|
|
114
|
+
"mantle-sepolia",
|
|
115
|
+
"megaeth-mainnet",
|
|
116
|
+
"megaeth-testnet",
|
|
117
|
+
"metis-mainnet",
|
|
118
|
+
"mode-mainnet",
|
|
119
|
+
"mode-sepolia",
|
|
120
|
+
"monad-mainnet",
|
|
121
|
+
"monad-testnet",
|
|
122
|
+
"moonbeam-mainnet",
|
|
123
|
+
"mythos-mainnet",
|
|
124
|
+
"opbnb-mainnet",
|
|
125
|
+
"opbnb-testnet",
|
|
126
|
+
"openloot-sepolia",
|
|
127
|
+
"opt-mainnet",
|
|
128
|
+
"opt-sepolia",
|
|
129
|
+
"plasma-mainnet",
|
|
130
|
+
"plasma-testnet",
|
|
131
|
+
"polygon-amoy",
|
|
132
|
+
"polygon-mainnet",
|
|
133
|
+
"polygonzkevm-cardona",
|
|
134
|
+
"polygonzkevm-mainnet",
|
|
135
|
+
"polynomial-mainnet",
|
|
136
|
+
"polynomial-sepolia",
|
|
137
|
+
"race-mainnet",
|
|
138
|
+
"race-sepolia",
|
|
139
|
+
"risa-testnet",
|
|
140
|
+
"rise-testnet",
|
|
141
|
+
"ronin-mainnet",
|
|
142
|
+
"ronin-saigon",
|
|
143
|
+
"rootstock-mainnet",
|
|
144
|
+
"rootstock-testnet",
|
|
145
|
+
"scroll-mainnet",
|
|
146
|
+
"scroll-sepolia",
|
|
147
|
+
"sei-mainnet",
|
|
148
|
+
"sei-testnet",
|
|
149
|
+
"settlus-mainnet",
|
|
150
|
+
"settlus-septestnet",
|
|
151
|
+
"shape-mainnet",
|
|
152
|
+
"shape-sepolia",
|
|
153
|
+
"solana-devnet",
|
|
154
|
+
"solana-mainnet",
|
|
155
|
+
"soneium-mainnet",
|
|
156
|
+
"soneium-minato",
|
|
157
|
+
"sonic-blaze",
|
|
158
|
+
"sonic-mainnet",
|
|
159
|
+
"sonic-testnet",
|
|
160
|
+
"stable-mainnet",
|
|
161
|
+
"stable-testnet",
|
|
162
|
+
"standard-mainnet",
|
|
163
|
+
"starknet-mainnet",
|
|
164
|
+
"starknet-sepolia",
|
|
165
|
+
"story-aeneid",
|
|
166
|
+
"story-mainnet",
|
|
167
|
+
"sui-mainnet",
|
|
168
|
+
"sui-testnet",
|
|
169
|
+
"superseed-mainnet",
|
|
170
|
+
"superseed-sepolia",
|
|
171
|
+
"synd-mainnet",
|
|
172
|
+
"syndicate-manchego",
|
|
173
|
+
"tea-sepolia",
|
|
174
|
+
"tempo-testnet",
|
|
175
|
+
"tron-mainnet",
|
|
176
|
+
"tron-testnet",
|
|
177
|
+
"unichain-mainnet",
|
|
178
|
+
"unichain-sepolia",
|
|
179
|
+
"unite-mainnet",
|
|
180
|
+
"unite-testnet",
|
|
181
|
+
"worldchain-mainnet",
|
|
182
|
+
"worldchain-sepolia",
|
|
183
|
+
"worldl3-devnet",
|
|
184
|
+
"worldmobile-devnet",
|
|
185
|
+
"worldmobile-testnet",
|
|
186
|
+
"worldmobilechain-mainnet",
|
|
187
|
+
"xmtp-mainnet",
|
|
188
|
+
"xmtp-ropsten",
|
|
189
|
+
"xprotocol-mainnet",
|
|
190
|
+
"zetachain-mainnet",
|
|
191
|
+
"zetachain-testnet",
|
|
192
|
+
"zksync-mainnet",
|
|
193
|
+
"zksync-sepolia",
|
|
194
|
+
"zora-mainnet",
|
|
195
|
+
"zora-sepolia"
|
|
196
|
+
];
|
|
197
|
+
function isTestnetNetwork(id) {
|
|
198
|
+
return TESTNET_TOKEN_RE.test(id);
|
|
199
|
+
}
|
|
200
|
+
function tokenToName(token) {
|
|
201
|
+
const alias = NAME_ALIASES[token];
|
|
202
|
+
if (alias) return alias;
|
|
203
|
+
return token.charAt(0).toUpperCase() + token.slice(1);
|
|
204
|
+
}
|
|
205
|
+
function toFamily(id) {
|
|
206
|
+
const [head] = id.split("-");
|
|
207
|
+
return FAMILY_ALIASES[head] ?? tokenToName(head);
|
|
208
|
+
}
|
|
209
|
+
function toDisplayName(id) {
|
|
210
|
+
return id.split("-").map((part) => tokenToName(part)).join(" ");
|
|
211
|
+
}
|
|
212
|
+
function toHttpsUrlTemplate(id) {
|
|
213
|
+
if (id === "starknet-mainnet" || id === "starknet-sepolia") {
|
|
214
|
+
return `https://${id}.g.alchemy.com/starknet/version/rpc/v0_10/{apiKey}`;
|
|
215
|
+
}
|
|
216
|
+
return `https://${id}.g.alchemy.com/v2/{apiKey}`;
|
|
217
|
+
}
|
|
218
|
+
function getRPCNetworks() {
|
|
219
|
+
return RPC_NETWORK_IDS.map((id) => ({
|
|
220
|
+
id,
|
|
221
|
+
name: toDisplayName(id),
|
|
222
|
+
family: toFamily(id),
|
|
223
|
+
isTestnet: isTestnetNetwork(id),
|
|
224
|
+
httpsUrlTemplate: toHttpsUrlTemplate(id)
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
function getRPCNetworkIds() {
|
|
228
|
+
return [...RPC_NETWORK_IDS];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/lib/onboarding.ts
|
|
232
|
+
function hasAPIKey(cfg) {
|
|
233
|
+
return Boolean(cfg.api_key?.trim());
|
|
234
|
+
}
|
|
235
|
+
function hasAccessKeyAndApp(cfg) {
|
|
236
|
+
return Boolean(cfg.access_key?.trim() && cfg.app?.id && cfg.app.apiKey);
|
|
237
|
+
}
|
|
238
|
+
function hasX402Wallet(cfg) {
|
|
239
|
+
return cfg.x402 === true && Boolean(cfg.wallet_key_file?.trim());
|
|
240
|
+
}
|
|
241
|
+
function getSetupMethod(cfg) {
|
|
242
|
+
if (hasAPIKey(cfg)) return "api_key";
|
|
243
|
+
if (hasAccessKeyAndApp(cfg)) return "access_key_app";
|
|
244
|
+
if (hasX402Wallet(cfg)) return "x402_wallet";
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
function isSetupComplete(cfg) {
|
|
248
|
+
return getSetupMethod(cfg) !== null;
|
|
249
|
+
}
|
|
250
|
+
function getSetupStatus(cfg) {
|
|
251
|
+
const satisfiedBy = getSetupMethod(cfg);
|
|
252
|
+
if (satisfiedBy) {
|
|
253
|
+
return {
|
|
254
|
+
complete: true,
|
|
255
|
+
satisfiedBy,
|
|
256
|
+
missing: [],
|
|
257
|
+
nextCommands: []
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
complete: false,
|
|
262
|
+
satisfiedBy: null,
|
|
263
|
+
missing: ["Provide one auth path: api-key OR access-key+app OR x402+wallet-key-file"],
|
|
264
|
+
nextCommands: [
|
|
265
|
+
"alchemy config set api-key <key>",
|
|
266
|
+
"alchemy config set access-key <key> && alchemy config set app <app-id>",
|
|
267
|
+
"alchemy wallet generate && alchemy config set x402 true"
|
|
268
|
+
]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function shouldRunOnboarding(program, cfg) {
|
|
272
|
+
return isInteractiveAllowed(program) && !isSetupComplete(cfg);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
getRPCNetworks,
|
|
277
|
+
getRPCNetworkIds,
|
|
278
|
+
getSetupMethod,
|
|
279
|
+
isSetupComplete,
|
|
280
|
+
getSetupStatus,
|
|
281
|
+
shouldRunOnboarding
|
|
282
|
+
};
|