@alchemy/cli 0.9.3 → 0.10.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
CHANGED
|
@@ -137,7 +137,8 @@ Per-command override: pass `--signer <session\|local>` to `evm send`, `evm appro
|
|
|
137
137
|
| `solana rpc <method> [params...]` | Calls Solana JSON-RPC methods | `alchemy solana rpc getBalance '"<pubkey>"'` |
|
|
138
138
|
| `solana das <method> [params...]` | Calls Solana DAS methods | `alchemy solana das getAssetsByOwner '{"ownerAddress":"<pubkey>"}'` |
|
|
139
139
|
| `solana network list` | Lists networks from the Solana namespace | `alchemy solana network list --search solana` |
|
|
140
|
-
| `solana send <to> <amount>` | Sends SOL to an address | `alchemy solana send <pubkey> 0.1` |
|
|
140
|
+
| `solana send <to> <amount>` | Sends SOL or SPL tokens to an address | `alchemy solana send <pubkey> 0.1` |
|
|
141
|
+
| `solana send <to> <amount> --token <mint>` | Sends an SPL token and creates the recipient ATA if needed | `alchemy solana send <pubkey> 10 --token <mint>` |
|
|
141
142
|
| `solana program accounts/account/show` | Inspects Solana program accounts and account metadata | `alchemy solana program accounts <program-id>` |
|
|
142
143
|
| `solana delegate approve/revoke` | Approves or revokes SPL token delegates | `alchemy solana delegate approve --token-account <addr> --mint <mint> --delegate <addr> --amount 1 --decimals 6` |
|
|
143
144
|
| `solana status [id]` | Checks Solana transaction or operation status | `alchemy solana status <signature>` |
|
|
@@ -254,7 +255,7 @@ Additional env vars:
|
|
|
254
255
|
| `wallet connect` | `--mode <session\|local>`, `--chain <evm\|solana\|both>`, `--import <path>`, `--instance-name <name>`, `--force` |
|
|
255
256
|
| `wallet status` | `--verify` |
|
|
256
257
|
| `wallet qr` | `--type <evm\|solana>`, `--solana` |
|
|
257
|
-
| `solana send` | `--fee-sponsored`, `--fee-policy-id <id>`, `--signer <local>`
|
|
258
|
+
| `solana send` | `--token <mint>`, `--dry-run`, `--fail-if-associated-token-account-missing`, `--from-token-account <address>`, `--recipient-token-account <address>`, `--fee-sponsored`, `--fee-policy-id <id>`, `--signer <session\|local>` |
|
|
258
259
|
| `solana program accounts` | `--filters <json>`, `--encoding <encoding>`, `--limit <n>` |
|
|
259
260
|
| `solana delegate approve` | `--token-account <address>`, `--mint <address>`, `--delegate <address>`, `--amount <number>`, `--decimals <n>`, `--fee-sponsored`, `--fee-policy-id <id>` |
|
|
260
261
|
| `solana delegate revoke` | `--token-account <address>`, `--fee-sponsored`, `--fee-policy-id <id>` |
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
getAvailableUpdate,
|
|
66
66
|
getUpdateStatus,
|
|
67
67
|
printUpdateNotice
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-HRWD4V2P.js";
|
|
69
69
|
import {
|
|
70
70
|
bold,
|
|
71
71
|
brand,
|
|
@@ -222,11 +222,11 @@ async function resolveENS(name, client) {
|
|
|
222
222
|
if (dataHex.length < 64) {
|
|
223
223
|
throw errInvalidArgs(`ENS name "${name}" could not be resolved.`);
|
|
224
224
|
}
|
|
225
|
-
const
|
|
226
|
-
if (
|
|
225
|
+
const address3 = "0x" + dataHex.slice(24, 64);
|
|
226
|
+
if (address3 === "0x0000000000000000000000000000000000000000") {
|
|
227
227
|
throw errInvalidArgs(`ENS name "${name}" is not registered or has no address set.`);
|
|
228
228
|
}
|
|
229
|
-
return
|
|
229
|
+
return address3;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// src/lib/validators.ts
|
|
@@ -267,10 +267,10 @@ async function readStdinLines(name) {
|
|
|
267
267
|
}
|
|
268
268
|
return lines;
|
|
269
269
|
}
|
|
270
|
-
function validateAddress(
|
|
271
|
-
if (!ADDRESS_RE.test(
|
|
270
|
+
function validateAddress(address3) {
|
|
271
|
+
if (!ADDRESS_RE.test(address3)) {
|
|
272
272
|
throw errInvalidArgs(
|
|
273
|
-
`Invalid address "${
|
|
273
|
+
`Invalid address "${address3}". Expected 0x-prefixed 40-hex-character address.`
|
|
274
274
|
);
|
|
275
275
|
}
|
|
276
276
|
}
|
|
@@ -2034,14 +2034,14 @@ function formatWalletStatus(value) {
|
|
|
2034
2034
|
function walletKeysDirPath() {
|
|
2035
2035
|
return join(configDir(), WALLET_KEYS_DIR);
|
|
2036
2036
|
}
|
|
2037
|
-
function walletKeyPath(prefix,
|
|
2038
|
-
const addr =
|
|
2037
|
+
function walletKeyPath(prefix, address3) {
|
|
2038
|
+
const addr = address3.trim().toLowerCase().replace(/^0x/, "").replace(/[^a-z0-9]/g, "").slice(0, ADDRESS_SLICE_LEN);
|
|
2039
2039
|
const addressTag = addr || "unknown";
|
|
2040
2040
|
const fileName = `${prefix}-${addressTag}-${Date.now()}-${randomUUID().slice(0, UUID_SLICE_LEN)}.txt`;
|
|
2041
2041
|
return join(walletKeysDirPath(), fileName);
|
|
2042
2042
|
}
|
|
2043
|
-
function persistWalletKey(prefix, privateKey,
|
|
2044
|
-
const keyPath = walletKeyPath(prefix,
|
|
2043
|
+
function persistWalletKey(prefix, privateKey, address3) {
|
|
2044
|
+
const keyPath = walletKeyPath(prefix, address3);
|
|
2045
2045
|
mkdirSync(dirname(keyPath), { recursive: true, mode: 493 });
|
|
2046
2046
|
writeFileSync(keyPath, privateKey + "\n", { mode: 384, flag: "wx" });
|
|
2047
2047
|
return keyPath;
|
|
@@ -2152,11 +2152,11 @@ function importAndPersistWallet(path) {
|
|
|
2152
2152
|
} catch {
|
|
2153
2153
|
throw errInvalidArgs(`Could not read key file: ${path}`);
|
|
2154
2154
|
}
|
|
2155
|
-
const
|
|
2156
|
-
const keyPath = persistWalletKey("wallet-key", key,
|
|
2155
|
+
const address3 = getEvmWalletAddress(key);
|
|
2156
|
+
const keyPath = persistWalletKey("wallet-key", key, address3);
|
|
2157
2157
|
const cfg = load();
|
|
2158
|
-
save({ ...cfg, wallet_key_file: keyPath, wallet_address:
|
|
2159
|
-
return { address:
|
|
2158
|
+
save({ ...cfg, wallet_key_file: keyPath, wallet_address: address3 });
|
|
2159
|
+
return { address: address3, keyFile: keyPath };
|
|
2160
2160
|
}
|
|
2161
2161
|
function hasValidSessionWithEvm() {
|
|
2162
2162
|
const session = resolveWalletSession();
|
|
@@ -2596,21 +2596,20 @@ async function runConnectFlow(program2, opts) {
|
|
|
2596
2596
|
}
|
|
2597
2597
|
if (!mode) {
|
|
2598
2598
|
if (!isInteractiveAllowed(program2)) {
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2599
|
+
mode = "session";
|
|
2600
|
+
} else {
|
|
2601
|
+
const choice = await promptSelect({
|
|
2602
|
+
message: "Choose a wallet to connect",
|
|
2603
|
+
options: [
|
|
2604
|
+
{ value: "session", label: "Session wallet", hint: "Recommended \u2014 Alchemy-managed, more secure" },
|
|
2605
|
+
{ value: "local", label: "Local wallet", hint: "Private key stored on this machine" }
|
|
2606
|
+
],
|
|
2607
|
+
initialValue: "session",
|
|
2608
|
+
cancelMessage: "Wallet connect cancelled."
|
|
2609
|
+
});
|
|
2610
|
+
if (choice === null) throw new WalletConnectInterruptedError();
|
|
2611
|
+
mode = choice;
|
|
2602
2612
|
}
|
|
2603
|
-
const choice = await promptSelect({
|
|
2604
|
-
message: "Choose a wallet to connect",
|
|
2605
|
-
options: [
|
|
2606
|
-
{ value: "session", label: "Session wallet", hint: "Recommended \u2014 Alchemy-managed, more secure" },
|
|
2607
|
-
{ value: "local", label: "Local wallet", hint: "Private key stored on this machine" }
|
|
2608
|
-
],
|
|
2609
|
-
initialValue: "session",
|
|
2610
|
-
cancelMessage: "Wallet connect cancelled."
|
|
2611
|
-
});
|
|
2612
|
-
if (choice === null) throw new WalletConnectInterruptedError();
|
|
2613
|
-
mode = choice;
|
|
2614
2613
|
}
|
|
2615
2614
|
if (mode === "session") {
|
|
2616
2615
|
await runSessionConnect({
|
|
@@ -4127,15 +4126,176 @@ function printAccountSummary(args) {
|
|
|
4127
4126
|
|
|
4128
4127
|
// src/commands/send-solana.ts
|
|
4129
4128
|
import { address as solAddress2 } from "@solana/kit";
|
|
4129
|
+
|
|
4130
|
+
// src/lib/solana-token.ts
|
|
4131
|
+
import {
|
|
4132
|
+
AccountRole as AccountRole2,
|
|
4133
|
+
address as address2,
|
|
4134
|
+
getAddressEncoder,
|
|
4135
|
+
getProgramDerivedAddress
|
|
4136
|
+
} from "@solana/kit";
|
|
4137
|
+
var SPL_TOKEN_PROGRAM_ADDRESS2 = address2("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
4138
|
+
var SPL_TOKEN_2022_PROGRAM_ADDRESS = address2("TokenzQdBNbLqP5VEhdkAS6EPYdWnYARjfkM8GoyZ2G");
|
|
4139
|
+
var ASSOCIATED_TOKEN_PROGRAM_ADDRESS = address2("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
|
|
4140
|
+
var SYSTEM_PROGRAM_ADDRESS2 = address2("11111111111111111111111111111111");
|
|
4141
|
+
var SUPPORTED_TOKEN_PROGRAMS = /* @__PURE__ */ new Set([
|
|
4142
|
+
SPL_TOKEN_PROGRAM_ADDRESS2,
|
|
4143
|
+
SPL_TOKEN_2022_PROGRAM_ADDRESS
|
|
4144
|
+
]);
|
|
4145
|
+
async function deriveAssociatedTokenAccount(args) {
|
|
4146
|
+
const addressEncoder = getAddressEncoder();
|
|
4147
|
+
const [associatedTokenAccount] = await getProgramDerivedAddress({
|
|
4148
|
+
programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
4149
|
+
seeds: [
|
|
4150
|
+
addressEncoder.encode(args.owner),
|
|
4151
|
+
addressEncoder.encode(args.tokenProgramAddress),
|
|
4152
|
+
addressEncoder.encode(args.mint)
|
|
4153
|
+
]
|
|
4154
|
+
});
|
|
4155
|
+
return associatedTokenAccount;
|
|
4156
|
+
}
|
|
4157
|
+
async function fetchSplMintInfo(client, mint) {
|
|
4158
|
+
const account = await fetchParsedAccount(client, mint);
|
|
4159
|
+
if (!account) {
|
|
4160
|
+
throw errInvalidArgs(`SPL token mint ${mint} was not found on this network.`);
|
|
4161
|
+
}
|
|
4162
|
+
const tokenProgramAddress = address2(account.owner);
|
|
4163
|
+
assertSupportedTokenProgram(tokenProgramAddress);
|
|
4164
|
+
const data = parseAccountData(account.data);
|
|
4165
|
+
const decimals = data?.parsed?.info?.decimals;
|
|
4166
|
+
if (typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0 || decimals > 255) {
|
|
4167
|
+
throw errInvalidArgs(`Could not read decimals for SPL token mint ${mint}.`);
|
|
4168
|
+
}
|
|
4169
|
+
return {
|
|
4170
|
+
mint,
|
|
4171
|
+
decimals,
|
|
4172
|
+
tokenProgramAddress
|
|
4173
|
+
};
|
|
4174
|
+
}
|
|
4175
|
+
async function fetchSplTokenAccountInfo(client, tokenAccount) {
|
|
4176
|
+
const account = await fetchParsedAccount(client, tokenAccount);
|
|
4177
|
+
if (!account) return null;
|
|
4178
|
+
const tokenProgramAddress = address2(account.owner);
|
|
4179
|
+
assertSupportedTokenProgram(tokenProgramAddress);
|
|
4180
|
+
const data = parseAccountData(account.data);
|
|
4181
|
+
const info = data?.parsed?.info;
|
|
4182
|
+
if (!info || data?.parsed?.type !== "account") {
|
|
4183
|
+
throw errInvalidArgs(`Account ${tokenAccount} is not an SPL token account.`);
|
|
4184
|
+
}
|
|
4185
|
+
const mint = readAddressField(info, "mint", `Account ${tokenAccount} is missing token mint metadata.`);
|
|
4186
|
+
const owner = readAddressField(info, "owner", `Account ${tokenAccount} is missing token owner metadata.`);
|
|
4187
|
+
return {
|
|
4188
|
+
address: tokenAccount,
|
|
4189
|
+
mint,
|
|
4190
|
+
owner,
|
|
4191
|
+
tokenProgramAddress
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
function buildCreateAssociatedTokenAccountIdempotentInstruction(args) {
|
|
4195
|
+
return {
|
|
4196
|
+
programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
|
|
4197
|
+
accounts: [
|
|
4198
|
+
{ address: args.payer.address, role: AccountRole2.WRITABLE_SIGNER },
|
|
4199
|
+
{ address: args.associatedTokenAccount, role: AccountRole2.WRITABLE },
|
|
4200
|
+
{ address: args.owner, role: AccountRole2.READONLY },
|
|
4201
|
+
{ address: args.mint, role: AccountRole2.READONLY },
|
|
4202
|
+
{ address: SYSTEM_PROGRAM_ADDRESS2, role: AccountRole2.READONLY },
|
|
4203
|
+
{ address: args.tokenProgramAddress, role: AccountRole2.READONLY }
|
|
4204
|
+
],
|
|
4205
|
+
data: new Uint8Array([1])
|
|
4206
|
+
};
|
|
4207
|
+
}
|
|
4208
|
+
function buildSplTokenTransferCheckedInstruction(args) {
|
|
4209
|
+
if (!Number.isInteger(args.decimals) || args.decimals < 0 || args.decimals > 255) {
|
|
4210
|
+
throw errInvalidArgs("Token decimals must be an integer between 0 and 255.");
|
|
4211
|
+
}
|
|
4212
|
+
return {
|
|
4213
|
+
programAddress: args.tokenProgramAddress,
|
|
4214
|
+
accounts: [
|
|
4215
|
+
{ address: args.sourceTokenAccount, role: AccountRole2.WRITABLE },
|
|
4216
|
+
{ address: args.mint, role: AccountRole2.READONLY },
|
|
4217
|
+
{ address: args.destinationTokenAccount, role: AccountRole2.WRITABLE },
|
|
4218
|
+
{ address: args.owner.address, role: AccountRole2.READONLY_SIGNER }
|
|
4219
|
+
],
|
|
4220
|
+
data: new Uint8Array([
|
|
4221
|
+
12,
|
|
4222
|
+
...encodeU64LE2(args.amount),
|
|
4223
|
+
args.decimals
|
|
4224
|
+
])
|
|
4225
|
+
};
|
|
4226
|
+
}
|
|
4227
|
+
function assertTokenAccountMatches(args) {
|
|
4228
|
+
if (args.account.mint !== args.expectedMint) {
|
|
4229
|
+
throw errInvalidArgs(
|
|
4230
|
+
`${args.label} ${args.account.address} is for mint ${args.account.mint}, expected ${args.expectedMint}.`
|
|
4231
|
+
);
|
|
4232
|
+
}
|
|
4233
|
+
if (args.expectedOwner && args.account.owner !== args.expectedOwner) {
|
|
4234
|
+
throw errInvalidArgs(
|
|
4235
|
+
`${args.label} ${args.account.address} is owned by ${args.account.owner}, expected ${args.expectedOwner}.`
|
|
4236
|
+
);
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
4239
|
+
function assertSupportedTokenProgram(tokenProgramAddress) {
|
|
4240
|
+
if (!SUPPORTED_TOKEN_PROGRAMS.has(tokenProgramAddress)) {
|
|
4241
|
+
throw errInvalidArgs(
|
|
4242
|
+
`Unsupported Solana token program ${tokenProgramAddress}. Only SPL Token and Token-2022 mints are supported.`
|
|
4243
|
+
);
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
async function fetchParsedAccount(client, accountAddress) {
|
|
4247
|
+
const result = await client.call("getAccountInfo", [
|
|
4248
|
+
accountAddress,
|
|
4249
|
+
{ encoding: "jsonParsed" }
|
|
4250
|
+
]);
|
|
4251
|
+
return result.value;
|
|
4252
|
+
}
|
|
4253
|
+
function parseAccountData(data) {
|
|
4254
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return null;
|
|
4255
|
+
return data;
|
|
4256
|
+
}
|
|
4257
|
+
function readAddressField(info, field, errorMessage) {
|
|
4258
|
+
const value = info[field];
|
|
4259
|
+
if (typeof value !== "string") {
|
|
4260
|
+
throw errInvalidArgs(errorMessage);
|
|
4261
|
+
}
|
|
4262
|
+
return address2(value);
|
|
4263
|
+
}
|
|
4264
|
+
function encodeU64LE2(value) {
|
|
4265
|
+
if (value < 0n || value > 0xffffffffffffffffn) {
|
|
4266
|
+
throw errInvalidArgs("Amount must fit in an unsigned 64-bit integer.");
|
|
4267
|
+
}
|
|
4268
|
+
const bytes = new Uint8Array(8);
|
|
4269
|
+
let remaining = value;
|
|
4270
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
4271
|
+
bytes[i] = Number(remaining & 0xffn);
|
|
4272
|
+
remaining >>= 8n;
|
|
4273
|
+
}
|
|
4274
|
+
return bytes;
|
|
4275
|
+
}
|
|
4276
|
+
|
|
4277
|
+
// src/commands/send-solana.ts
|
|
4130
4278
|
function registerSolanaSend(program2) {
|
|
4131
|
-
const sendCmd = program2.command("send <to> <amount>").description("Send SOL to an address").option("--token <address>", "SPL token
|
|
4279
|
+
const sendCmd = program2.command("send <to> <amount>").description("Send SOL or SPL tokens to an address").option("--token <mint>", "SPL token mint address (omit for native SOL)").option("--dry-run", "Preview transaction without signing or sending").option("--fail-if-associated-token-account-missing", "Fail if the recipient associated token account is missing").option("--from-token-account <address>", "Source SPL token account (defaults to sender associated token account)").option("--recipient-token-account <address>", "Destination SPL token account (defaults to recipient associated token account)").option("--fee-sponsored", "Enable Solana fee sponsorship").option("--fee-policy-id <id>", "Solana fee policy ID for sponsorship").addHelpText(
|
|
4280
|
+
"after",
|
|
4281
|
+
`
|
|
4282
|
+
Examples:
|
|
4283
|
+
alchemy solana send <pubkey> 0.1
|
|
4284
|
+
alchemy solana send <pubkey> 10 --token <mint>
|
|
4285
|
+
alchemy solana send <pubkey> 10 --token <mint> --dry-run
|
|
4286
|
+
alchemy solana send <pubkey> 10 --token <mint> --fail-if-associated-token-account-missing`
|
|
4287
|
+
);
|
|
4132
4288
|
addSignerOption(sendCmd);
|
|
4133
4289
|
sendCmd.action(
|
|
4134
4290
|
async (toArg, amountArg, _opts, actionCommand) => {
|
|
4135
4291
|
try {
|
|
4136
4292
|
const opts = actionCommand.opts();
|
|
4137
4293
|
await performSolanaSend(actionCommand, toArg, amountArg, opts.token, {
|
|
4138
|
-
signer: parseSignerOpt(opts.signer)
|
|
4294
|
+
signer: parseSignerOpt(opts.signer),
|
|
4295
|
+
dryRun: opts.dryRun,
|
|
4296
|
+
failIfAssociatedTokenAccountMissing: opts.failIfAssociatedTokenAccountMissing,
|
|
4297
|
+
fromTokenAccount: opts.fromTokenAccount,
|
|
4298
|
+
recipientTokenAccount: opts.recipientTokenAccount
|
|
4139
4299
|
});
|
|
4140
4300
|
} catch (err) {
|
|
4141
4301
|
exitWithError(err);
|
|
@@ -4144,75 +4304,378 @@ function registerSolanaSend(program2) {
|
|
|
4144
4304
|
);
|
|
4145
4305
|
}
|
|
4146
4306
|
async function performSolanaSend(program2, toArg, amountArg, tokenAddress, opts = {}) {
|
|
4147
|
-
|
|
4148
|
-
throw errInvalidArgs("SPL token transfers are not yet supported. Omit --token for native SOL transfers.");
|
|
4149
|
-
}
|
|
4307
|
+
validateSolanaTokenOptions(tokenAddress, opts);
|
|
4150
4308
|
const signer = await resolveSolanaSigner(program2, opts.signer);
|
|
4151
4309
|
validateSolanaAddress(toArg);
|
|
4152
4310
|
const to = solAddress2(toArg);
|
|
4153
4311
|
const network = resolveSolanaNetwork(program2);
|
|
4154
|
-
const
|
|
4155
|
-
const
|
|
4156
|
-
|
|
4157
|
-
|
|
4312
|
+
const { sponsored, feePolicyId } = await resolveSolanaFeeSponsorship(program2);
|
|
4313
|
+
const client = clientFromFlags(program2, { forceNetwork: network });
|
|
4314
|
+
if (tokenAddress) {
|
|
4315
|
+
await performSplTokenSend({
|
|
4316
|
+
client,
|
|
4317
|
+
signer,
|
|
4318
|
+
to,
|
|
4319
|
+
toArg,
|
|
4320
|
+
amountArg,
|
|
4321
|
+
tokenAddress,
|
|
4322
|
+
network,
|
|
4323
|
+
sponsored,
|
|
4324
|
+
feePolicyId,
|
|
4325
|
+
opts
|
|
4326
|
+
});
|
|
4327
|
+
return;
|
|
4328
|
+
}
|
|
4329
|
+
await performNativeSolSend({
|
|
4330
|
+
client,
|
|
4331
|
+
signer,
|
|
4158
4332
|
to,
|
|
4333
|
+
toArg,
|
|
4334
|
+
amountArg,
|
|
4335
|
+
network,
|
|
4336
|
+
sponsored,
|
|
4337
|
+
feePolicyId,
|
|
4338
|
+
dryRun: opts.dryRun
|
|
4339
|
+
});
|
|
4340
|
+
}
|
|
4341
|
+
async function performNativeSolSend(args) {
|
|
4342
|
+
const symbol = nativeTokenSymbol(args.network);
|
|
4343
|
+
const lamports = parseAmount(args.amountArg, SOL_DECIMALS);
|
|
4344
|
+
const instruction = buildSolTransferInstruction(
|
|
4345
|
+
{ address: solAddress2(args.signer.address) },
|
|
4346
|
+
args.to,
|
|
4159
4347
|
lamports
|
|
4160
4348
|
);
|
|
4161
|
-
|
|
4162
|
-
|
|
4349
|
+
if (args.dryRun) {
|
|
4350
|
+
printNativeDryRun({
|
|
4351
|
+
from: args.signer.address,
|
|
4352
|
+
to: args.toArg,
|
|
4353
|
+
amount: args.amountArg,
|
|
4354
|
+
symbol,
|
|
4355
|
+
network: args.network,
|
|
4356
|
+
sponsored: args.sponsored
|
|
4357
|
+
});
|
|
4358
|
+
return;
|
|
4359
|
+
}
|
|
4163
4360
|
const result = await withSpinner(
|
|
4164
4361
|
"Sending transaction\u2026",
|
|
4165
4362
|
"Transaction submitted",
|
|
4166
4363
|
async () => {
|
|
4167
|
-
if (signer.type === "session") {
|
|
4364
|
+
if (args.signer.type === "session") {
|
|
4168
4365
|
return await buildAndSendSolanaTransactionWithSession({
|
|
4169
|
-
client,
|
|
4366
|
+
client: args.client,
|
|
4170
4367
|
instructions: [instruction],
|
|
4171
|
-
session: signer.session,
|
|
4172
|
-
authToken: signer.authToken,
|
|
4173
|
-
sponsored,
|
|
4174
|
-
gasPolicyId: feePolicyId
|
|
4368
|
+
session: args.signer.session,
|
|
4369
|
+
authToken: args.signer.authToken,
|
|
4370
|
+
sponsored: args.sponsored,
|
|
4371
|
+
gasPolicyId: args.feePolicyId
|
|
4175
4372
|
});
|
|
4176
4373
|
}
|
|
4177
4374
|
return await buildAndSendSolanaTransaction({
|
|
4178
|
-
client,
|
|
4375
|
+
client: args.client,
|
|
4179
4376
|
instructions: [instruction],
|
|
4180
|
-
senderKeyBytes: signer.keyBytes,
|
|
4181
|
-
sponsored,
|
|
4182
|
-
gasPolicyId: feePolicyId
|
|
4377
|
+
senderKeyBytes: args.signer.keyBytes,
|
|
4378
|
+
sponsored: args.sponsored,
|
|
4379
|
+
gasPolicyId: args.feePolicyId
|
|
4183
4380
|
});
|
|
4184
4381
|
}
|
|
4185
4382
|
);
|
|
4186
4383
|
const confirmed = await withSpinner(
|
|
4187
4384
|
"Waiting for confirmation\u2026",
|
|
4188
4385
|
"Confirmation status received",
|
|
4189
|
-
() => waitForSolanaConfirmation(client, result.signature)
|
|
4386
|
+
() => waitForSolanaConfirmation(args.client, result.signature)
|
|
4387
|
+
);
|
|
4388
|
+
printNativeResult({
|
|
4389
|
+
result,
|
|
4390
|
+
to: args.toArg,
|
|
4391
|
+
amount: args.amountArg,
|
|
4392
|
+
symbol,
|
|
4393
|
+
network: args.network,
|
|
4394
|
+
sponsored: args.sponsored,
|
|
4395
|
+
status: confirmed ? "confirmed" : "pending"
|
|
4396
|
+
});
|
|
4397
|
+
}
|
|
4398
|
+
function validateSolanaTokenOptions(tokenAddress, opts) {
|
|
4399
|
+
if (tokenAddress) return;
|
|
4400
|
+
const splOnlyFlags = [
|
|
4401
|
+
opts.fromTokenAccount ? "--from-token-account" : void 0,
|
|
4402
|
+
opts.recipientTokenAccount ? "--recipient-token-account" : void 0,
|
|
4403
|
+
opts.failIfAssociatedTokenAccountMissing ? "--fail-if-associated-token-account-missing" : void 0
|
|
4404
|
+
].filter((flag) => flag !== void 0);
|
|
4405
|
+
if (splOnlyFlags.length === 0) return;
|
|
4406
|
+
throw errInvalidArgs(
|
|
4407
|
+
`${splOnlyFlags.join(", ")} ${splOnlyFlags.length === 1 ? "requires" : "require"} --token <mint>.`
|
|
4408
|
+
);
|
|
4409
|
+
}
|
|
4410
|
+
async function performSplTokenSend(args) {
|
|
4411
|
+
validateSolanaAddress(args.tokenAddress);
|
|
4412
|
+
if (args.opts.fromTokenAccount) validateSolanaAddress(args.opts.fromTokenAccount);
|
|
4413
|
+
if (args.opts.recipientTokenAccount) validateSolanaAddress(args.opts.recipientTokenAccount);
|
|
4414
|
+
const mint = solAddress2(args.tokenAddress);
|
|
4415
|
+
const owner = solAddress2(args.signer.address);
|
|
4416
|
+
const mintInfo = await fetchSplMintInfo(args.client, mint);
|
|
4417
|
+
const amount = parseAmount(args.amountArg, mintInfo.decimals);
|
|
4418
|
+
const plan = await buildSplSendPlan({
|
|
4419
|
+
client: args.client,
|
|
4420
|
+
owner,
|
|
4421
|
+
recipient: args.to,
|
|
4422
|
+
mint,
|
|
4423
|
+
amount,
|
|
4424
|
+
decimals: mintInfo.decimals,
|
|
4425
|
+
tokenProgramAddress: mintInfo.tokenProgramAddress,
|
|
4426
|
+
failIfAssociatedTokenAccountMissing: Boolean(args.opts.failIfAssociatedTokenAccountMissing),
|
|
4427
|
+
fromTokenAccount: args.opts.fromTokenAccount ? solAddress2(args.opts.fromTokenAccount) : void 0,
|
|
4428
|
+
recipientTokenAccount: args.opts.recipientTokenAccount ? solAddress2(args.opts.recipientTokenAccount) : void 0
|
|
4429
|
+
});
|
|
4430
|
+
if (args.opts.dryRun) {
|
|
4431
|
+
printSplDryRun({
|
|
4432
|
+
from: args.signer.address,
|
|
4433
|
+
to: args.toArg,
|
|
4434
|
+
amount: args.amountArg,
|
|
4435
|
+
network: args.network,
|
|
4436
|
+
sponsored: args.sponsored,
|
|
4437
|
+
plan
|
|
4438
|
+
});
|
|
4439
|
+
return;
|
|
4440
|
+
}
|
|
4441
|
+
const result = await submitSolanaInstructions({
|
|
4442
|
+
client: args.client,
|
|
4443
|
+
signer: args.signer,
|
|
4444
|
+
instructions: plan.instructions,
|
|
4445
|
+
sponsored: args.sponsored,
|
|
4446
|
+
feePolicyId: args.feePolicyId
|
|
4447
|
+
});
|
|
4448
|
+
const confirmed = await withSpinner(
|
|
4449
|
+
"Waiting for confirmation\u2026",
|
|
4450
|
+
"Confirmation status received",
|
|
4451
|
+
() => waitForSolanaConfirmation(args.client, result.signature)
|
|
4452
|
+
);
|
|
4453
|
+
printSplResult({
|
|
4454
|
+
result,
|
|
4455
|
+
to: args.toArg,
|
|
4456
|
+
amount: args.amountArg,
|
|
4457
|
+
network: args.network,
|
|
4458
|
+
sponsored: args.sponsored,
|
|
4459
|
+
plan,
|
|
4460
|
+
status: confirmed ? "confirmed" : "pending"
|
|
4461
|
+
});
|
|
4462
|
+
}
|
|
4463
|
+
async function buildSplSendPlan(args) {
|
|
4464
|
+
const sourceTokenAccount = args.fromTokenAccount ?? await deriveAssociatedTokenAccount({
|
|
4465
|
+
owner: args.owner,
|
|
4466
|
+
mint: args.mint,
|
|
4467
|
+
tokenProgramAddress: args.tokenProgramAddress
|
|
4468
|
+
});
|
|
4469
|
+
const sourceAccount = await fetchSplTokenAccountInfo(args.client, sourceTokenAccount);
|
|
4470
|
+
if (!sourceAccount) {
|
|
4471
|
+
throw errInvalidArgs(
|
|
4472
|
+
`Source token account ${sourceTokenAccount} was not found. Fund the sender's associated token account for mint ${args.mint} and retry.`
|
|
4473
|
+
);
|
|
4474
|
+
}
|
|
4475
|
+
assertTokenAccountMatches({
|
|
4476
|
+
account: sourceAccount,
|
|
4477
|
+
expectedMint: args.mint,
|
|
4478
|
+
expectedOwner: args.owner,
|
|
4479
|
+
label: "Source token account"
|
|
4480
|
+
});
|
|
4481
|
+
const destinationTokenAccount = args.recipientTokenAccount ?? await deriveAssociatedTokenAccount({
|
|
4482
|
+
owner: args.recipient,
|
|
4483
|
+
mint: args.mint,
|
|
4484
|
+
tokenProgramAddress: args.tokenProgramAddress
|
|
4485
|
+
});
|
|
4486
|
+
const destinationAccount = await fetchSplTokenAccountInfo(args.client, destinationTokenAccount);
|
|
4487
|
+
const createDestinationTokenAccount = !destinationAccount && !args.recipientTokenAccount && !args.failIfAssociatedTokenAccountMissing;
|
|
4488
|
+
if (!destinationAccount && args.recipientTokenAccount) {
|
|
4489
|
+
throw errInvalidArgs(`Recipient token account ${destinationTokenAccount} was not found.`);
|
|
4490
|
+
}
|
|
4491
|
+
if (!destinationAccount && args.failIfAssociatedTokenAccountMissing) {
|
|
4492
|
+
throw errInvalidArgs(
|
|
4493
|
+
`Recipient associated token account ${destinationTokenAccount} does not exist. Omit --fail-if-associated-token-account-missing to create it automatically.`
|
|
4494
|
+
);
|
|
4495
|
+
}
|
|
4496
|
+
if (destinationAccount) {
|
|
4497
|
+
assertTokenAccountMatches({
|
|
4498
|
+
account: destinationAccount,
|
|
4499
|
+
expectedMint: args.mint,
|
|
4500
|
+
...args.recipientTokenAccount ? {} : { expectedOwner: args.recipient },
|
|
4501
|
+
label: "Recipient token account"
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
const instructions = [];
|
|
4505
|
+
if (createDestinationTokenAccount) {
|
|
4506
|
+
instructions.push(buildCreateAssociatedTokenAccountIdempotentInstruction({
|
|
4507
|
+
payer: { address: args.owner },
|
|
4508
|
+
associatedTokenAccount: destinationTokenAccount,
|
|
4509
|
+
owner: args.recipient,
|
|
4510
|
+
mint: args.mint,
|
|
4511
|
+
tokenProgramAddress: args.tokenProgramAddress
|
|
4512
|
+
}));
|
|
4513
|
+
}
|
|
4514
|
+
instructions.push(buildSplTokenTransferCheckedInstruction({
|
|
4515
|
+
sourceTokenAccount,
|
|
4516
|
+
mint: args.mint,
|
|
4517
|
+
destinationTokenAccount,
|
|
4518
|
+
owner: { address: args.owner },
|
|
4519
|
+
amount: args.amount,
|
|
4520
|
+
decimals: args.decimals,
|
|
4521
|
+
tokenProgramAddress: args.tokenProgramAddress
|
|
4522
|
+
}));
|
|
4523
|
+
return {
|
|
4524
|
+
instructions,
|
|
4525
|
+
mint: args.mint,
|
|
4526
|
+
tokenProgramAddress: args.tokenProgramAddress,
|
|
4527
|
+
sourceTokenAccount,
|
|
4528
|
+
destinationTokenAccount,
|
|
4529
|
+
createdDestinationTokenAccount: createDestinationTokenAccount,
|
|
4530
|
+
decimals: args.decimals
|
|
4531
|
+
};
|
|
4532
|
+
}
|
|
4533
|
+
async function submitSolanaInstructions(args) {
|
|
4534
|
+
const result = await withSpinner(
|
|
4535
|
+
"Sending transaction\u2026",
|
|
4536
|
+
"Transaction submitted",
|
|
4537
|
+
async () => {
|
|
4538
|
+
if (args.signer.type === "session") {
|
|
4539
|
+
return await buildAndSendSolanaTransactionWithSession({
|
|
4540
|
+
client: args.client,
|
|
4541
|
+
instructions: args.instructions,
|
|
4542
|
+
session: args.signer.session,
|
|
4543
|
+
authToken: args.signer.authToken,
|
|
4544
|
+
sponsored: args.sponsored,
|
|
4545
|
+
gasPolicyId: args.feePolicyId
|
|
4546
|
+
});
|
|
4547
|
+
}
|
|
4548
|
+
return await buildAndSendSolanaTransaction({
|
|
4549
|
+
client: args.client,
|
|
4550
|
+
instructions: args.instructions,
|
|
4551
|
+
senderKeyBytes: args.signer.keyBytes,
|
|
4552
|
+
sponsored: args.sponsored,
|
|
4553
|
+
gasPolicyId: args.feePolicyId
|
|
4554
|
+
});
|
|
4555
|
+
}
|
|
4190
4556
|
);
|
|
4557
|
+
return result;
|
|
4558
|
+
}
|
|
4559
|
+
function printNativeDryRun(args) {
|
|
4191
4560
|
if (isJSONMode()) {
|
|
4192
4561
|
printJSON({
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4562
|
+
dryRun: true,
|
|
4563
|
+
action: "solana-send",
|
|
4564
|
+
from: args.from,
|
|
4565
|
+
to: args.to,
|
|
4566
|
+
amount: args.amount,
|
|
4567
|
+
token: args.symbol,
|
|
4568
|
+
network: args.network,
|
|
4569
|
+
sponsored: args.sponsored,
|
|
4570
|
+
instructions: ["transferSol"]
|
|
4201
4571
|
});
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
]
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4572
|
+
return;
|
|
4573
|
+
}
|
|
4574
|
+
const pairs = [
|
|
4575
|
+
["Dry Run", "yes"],
|
|
4576
|
+
["From", args.from],
|
|
4577
|
+
["To", args.to],
|
|
4578
|
+
["Amount", green(`${args.amount} ${args.symbol}`)],
|
|
4579
|
+
["Network", args.network],
|
|
4580
|
+
["Instructions", "transferSol"]
|
|
4581
|
+
];
|
|
4582
|
+
if (args.sponsored) pairs.push(["Fee", green("Sponsored")]);
|
|
4583
|
+
printKeyValue(pairs);
|
|
4584
|
+
}
|
|
4585
|
+
function printNativeResult(args) {
|
|
4586
|
+
if (isJSONMode()) {
|
|
4587
|
+
printJSON({
|
|
4588
|
+
from: args.result.fromAddress,
|
|
4589
|
+
to: args.to,
|
|
4590
|
+
amount: args.amount,
|
|
4591
|
+
token: args.symbol,
|
|
4592
|
+
network: args.network,
|
|
4593
|
+
sponsored: args.sponsored,
|
|
4594
|
+
signature: args.result.signature,
|
|
4595
|
+
status: args.status
|
|
4596
|
+
});
|
|
4597
|
+
return;
|
|
4215
4598
|
}
|
|
4599
|
+
const pairs = [
|
|
4600
|
+
["From", args.result.fromAddress],
|
|
4601
|
+
["To", args.to],
|
|
4602
|
+
["Amount", green(`${args.amount} ${args.symbol}`)],
|
|
4603
|
+
["Network", args.network]
|
|
4604
|
+
];
|
|
4605
|
+
if (args.sponsored) pairs.push(["Fee", green("Sponsored")]);
|
|
4606
|
+
pairs.push(["Signature", args.result.signature]);
|
|
4607
|
+
pairs.push(["Status", args.status === "confirmed" ? `${successBadge()} ${green("Confirmed")}` : "Pending"]);
|
|
4608
|
+
printKeyValue(pairs);
|
|
4609
|
+
}
|
|
4610
|
+
function printSplDryRun(args) {
|
|
4611
|
+
const instructions = args.plan.createdDestinationTokenAccount ? ["createAssociatedTokenAccountIdempotent", "transferChecked"] : ["transferChecked"];
|
|
4612
|
+
if (isJSONMode()) {
|
|
4613
|
+
printJSON({
|
|
4614
|
+
dryRun: true,
|
|
4615
|
+
action: "solana-send",
|
|
4616
|
+
from: args.from,
|
|
4617
|
+
to: args.to,
|
|
4618
|
+
amount: args.amount,
|
|
4619
|
+
token: args.plan.mint,
|
|
4620
|
+
tokenAddress: args.plan.mint,
|
|
4621
|
+
network: args.network,
|
|
4622
|
+
sponsored: args.sponsored,
|
|
4623
|
+
tokenProgramAddress: args.plan.tokenProgramAddress,
|
|
4624
|
+
sourceTokenAccount: args.plan.sourceTokenAccount,
|
|
4625
|
+
destinationTokenAccount: args.plan.destinationTokenAccount,
|
|
4626
|
+
createdDestinationTokenAccount: args.plan.createdDestinationTokenAccount,
|
|
4627
|
+
instructions
|
|
4628
|
+
});
|
|
4629
|
+
return;
|
|
4630
|
+
}
|
|
4631
|
+
const pairs = [
|
|
4632
|
+
["Dry Run", "yes"],
|
|
4633
|
+
["From", args.from],
|
|
4634
|
+
["To", args.to],
|
|
4635
|
+
["Amount", green(`${args.amount} ${args.plan.mint}`)],
|
|
4636
|
+
["Mint", args.plan.mint],
|
|
4637
|
+
["Source Token Account", args.plan.sourceTokenAccount],
|
|
4638
|
+
["Destination Token Account", args.plan.destinationTokenAccount],
|
|
4639
|
+
["Created Destination Token Account", args.plan.createdDestinationTokenAccount ? "yes" : "no"],
|
|
4640
|
+
["Network", args.network],
|
|
4641
|
+
["Instructions", instructions.join(", ")]
|
|
4642
|
+
];
|
|
4643
|
+
if (args.sponsored) pairs.push(["Fee", green("Sponsored")]);
|
|
4644
|
+
printKeyValue(pairs);
|
|
4645
|
+
}
|
|
4646
|
+
function printSplResult(args) {
|
|
4647
|
+
if (isJSONMode()) {
|
|
4648
|
+
printJSON({
|
|
4649
|
+
from: args.result.fromAddress,
|
|
4650
|
+
to: args.to,
|
|
4651
|
+
amount: args.amount,
|
|
4652
|
+
token: args.plan.mint,
|
|
4653
|
+
tokenAddress: args.plan.mint,
|
|
4654
|
+
network: args.network,
|
|
4655
|
+
sponsored: args.sponsored,
|
|
4656
|
+
tokenProgramAddress: args.plan.tokenProgramAddress,
|
|
4657
|
+
sourceTokenAccount: args.plan.sourceTokenAccount,
|
|
4658
|
+
destinationTokenAccount: args.plan.destinationTokenAccount,
|
|
4659
|
+
createdDestinationTokenAccount: args.plan.createdDestinationTokenAccount,
|
|
4660
|
+
signature: args.result.signature,
|
|
4661
|
+
status: args.status
|
|
4662
|
+
});
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4665
|
+
const pairs = [
|
|
4666
|
+
["From", args.result.fromAddress],
|
|
4667
|
+
["To", args.to],
|
|
4668
|
+
["Amount", green(`${args.amount} ${args.plan.mint}`)],
|
|
4669
|
+
["Mint", args.plan.mint],
|
|
4670
|
+
["Source Token Account", args.plan.sourceTokenAccount],
|
|
4671
|
+
["Destination Token Account", args.plan.destinationTokenAccount],
|
|
4672
|
+
["Created Destination Token Account", args.plan.createdDestinationTokenAccount ? "yes" : "no"],
|
|
4673
|
+
["Network", args.network]
|
|
4674
|
+
];
|
|
4675
|
+
if (args.sponsored) pairs.push(["Fee", green("Sponsored")]);
|
|
4676
|
+
pairs.push(["Signature", args.result.signature]);
|
|
4677
|
+
pairs.push(["Status", args.status === "confirmed" ? `${successBadge()} ${green("Confirmed")}` : "Pending"]);
|
|
4678
|
+
printKeyValue(pairs);
|
|
4216
4679
|
}
|
|
4217
4680
|
async function resolveSolanaSigner(program2, signer) {
|
|
4218
4681
|
if (signer === "session") {
|
|
@@ -4466,9 +4929,9 @@ async function debugRecoveredTypedDataAddress(args) {
|
|
|
4466
4929
|
}
|
|
4467
4930
|
function createDelegatedAccount(args) {
|
|
4468
4931
|
const sessionBinding = buildSessionBindingInput(args.session);
|
|
4469
|
-
const
|
|
4932
|
+
const address3 = args.session.evmAddress;
|
|
4470
4933
|
return toAccount({
|
|
4471
|
-
address:
|
|
4934
|
+
address: address3,
|
|
4472
4935
|
async signTransaction() {
|
|
4473
4936
|
throw errInvalidArgs(
|
|
4474
4937
|
"Delegated signer does not support direct transaction signing. Use wallet commands that execute through Alchemy smart wallets."
|
|
@@ -4499,7 +4962,7 @@ function createDelegatedAccount(args) {
|
|
|
4499
4962
|
message: remoteMessage.message,
|
|
4500
4963
|
encoding: remoteMessage.encoding,
|
|
4501
4964
|
signature: signedMessage,
|
|
4502
|
-
expectedAddress:
|
|
4965
|
+
expectedAddress: address3
|
|
4503
4966
|
});
|
|
4504
4967
|
return signedMessage;
|
|
4505
4968
|
},
|
|
@@ -4535,7 +4998,7 @@ function createDelegatedAccount(args) {
|
|
|
4535
4998
|
await debugRecoveredTypedDataAddress({
|
|
4536
4999
|
typedData: serializedTypedData,
|
|
4537
5000
|
signature: typedDataSignature,
|
|
4538
|
-
expectedAddress:
|
|
5001
|
+
expectedAddress: address3
|
|
4539
5002
|
});
|
|
4540
5003
|
return typedDataSignature;
|
|
4541
5004
|
},
|
|
@@ -6174,8 +6637,8 @@ function registrySymbolSuggestions(network) {
|
|
|
6174
6637
|
}
|
|
6175
6638
|
|
|
6176
6639
|
// src/commands/approve.ts
|
|
6177
|
-
function isNativeToken(
|
|
6178
|
-
return
|
|
6640
|
+
function isNativeToken(address3) {
|
|
6641
|
+
return address3.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();
|
|
6179
6642
|
}
|
|
6180
6643
|
function buildApprovalRequest(opts, tokenMeta) {
|
|
6181
6644
|
validateApprovalMode(opts);
|
|
@@ -6847,18 +7310,18 @@ async function performContractCall(program2, addressArg, functionArg, opts) {
|
|
|
6847
7310
|
// src/commands/balance.ts
|
|
6848
7311
|
async function fetchBalance(program2, addressInput, blockParam) {
|
|
6849
7312
|
const client = clientFromFlags(program2);
|
|
6850
|
-
const
|
|
7313
|
+
const address3 = await resolveAddress(addressInput, client);
|
|
6851
7314
|
const result = await withSpinner(
|
|
6852
7315
|
"Fetching balance\u2026",
|
|
6853
7316
|
"Balance fetched",
|
|
6854
|
-
() => client.call("eth_getBalance", [
|
|
7317
|
+
() => client.call("eth_getBalance", [address3, blockParam])
|
|
6855
7318
|
);
|
|
6856
7319
|
const wei = BigInt(result);
|
|
6857
7320
|
const network = resolveNetwork(program2);
|
|
6858
7321
|
const symbol = nativeTokenSymbol(network);
|
|
6859
7322
|
if (isJSONMode()) {
|
|
6860
7323
|
printJSON({
|
|
6861
|
-
address:
|
|
7324
|
+
address: address3,
|
|
6862
7325
|
wei: wei.toString(),
|
|
6863
7326
|
balance: weiToEth(wei),
|
|
6864
7327
|
symbol,
|
|
@@ -6866,7 +7329,7 @@ async function fetchBalance(program2, addressInput, blockParam) {
|
|
|
6866
7329
|
});
|
|
6867
7330
|
} else {
|
|
6868
7331
|
printKeyValue([
|
|
6869
|
-
["Address",
|
|
7332
|
+
["Address", address3],
|
|
6870
7333
|
["Balance", green(`${weiToEth(wei)} ${symbol}`)],
|
|
6871
7334
|
["Network", network]
|
|
6872
7335
|
]);
|
|
@@ -6874,7 +7337,7 @@ async function fetchBalance(program2, addressInput, blockParam) {
|
|
|
6874
7337
|
console.log("");
|
|
6875
7338
|
printJSON({
|
|
6876
7339
|
rpcMethod: "eth_getBalance",
|
|
6877
|
-
rpcParams: [
|
|
7340
|
+
rpcParams: [address3, blockParam],
|
|
6878
7341
|
rpcResult: result
|
|
6879
7342
|
});
|
|
6880
7343
|
}
|
|
@@ -6959,9 +7422,9 @@ Examples:
|
|
|
6959
7422
|
try {
|
|
6960
7423
|
const addressInput = addressArg ?? await readStdinArg("address");
|
|
6961
7424
|
const client = clientFromFlags(program2);
|
|
6962
|
-
const
|
|
7425
|
+
const address3 = await resolveAddress(addressInput, client);
|
|
6963
7426
|
const params = {
|
|
6964
|
-
owner:
|
|
7427
|
+
owner: address3,
|
|
6965
7428
|
withMetadata: "true"
|
|
6966
7429
|
};
|
|
6967
7430
|
if (opts.limit) params.pageSize = String(opts.limit);
|
|
@@ -6995,7 +7458,7 @@ Examples:
|
|
|
6995
7458
|
break;
|
|
6996
7459
|
}
|
|
6997
7460
|
const nextParams = {
|
|
6998
|
-
owner:
|
|
7461
|
+
owner: address3,
|
|
6999
7462
|
withMetadata: "true",
|
|
7000
7463
|
pageKey
|
|
7001
7464
|
};
|
|
@@ -7037,15 +7500,15 @@ Examples:
|
|
|
7037
7500
|
exitWithError(err);
|
|
7038
7501
|
}
|
|
7039
7502
|
});
|
|
7040
|
-
cmd.command("contract <address>").description("Get NFT contract metadata").action(async (
|
|
7503
|
+
cmd.command("contract <address>").description("Get NFT contract metadata").action(async (address3) => {
|
|
7041
7504
|
try {
|
|
7042
|
-
validateAddress(
|
|
7505
|
+
validateAddress(address3);
|
|
7043
7506
|
const client = clientFromFlags(program2);
|
|
7044
7507
|
const result = await withSpinner(
|
|
7045
7508
|
"Fetching contract metadata\u2026",
|
|
7046
7509
|
"Contract metadata fetched",
|
|
7047
7510
|
() => client.callEnhanced("getContractMetadata", {
|
|
7048
|
-
contractAddress:
|
|
7511
|
+
contractAddress: address3
|
|
7049
7512
|
})
|
|
7050
7513
|
);
|
|
7051
7514
|
if (isJSONMode()) printJSON(result);
|
|
@@ -7182,8 +7645,8 @@ Examples:
|
|
|
7182
7645
|
try {
|
|
7183
7646
|
const addressInput = addressArg ?? await readStdinArg("address");
|
|
7184
7647
|
const client = clientFromFlags(program2);
|
|
7185
|
-
const
|
|
7186
|
-
const params = [
|
|
7648
|
+
const address3 = await resolveAddress(addressInput, client);
|
|
7649
|
+
const params = [address3];
|
|
7187
7650
|
if (opts.pageKey) {
|
|
7188
7651
|
params.push("erc20", { pageKey: opts.pageKey });
|
|
7189
7652
|
}
|
|
@@ -7220,7 +7683,7 @@ Examples:
|
|
|
7220
7683
|
}
|
|
7221
7684
|
let totalShown = nonZero.length;
|
|
7222
7685
|
printKeyValue([
|
|
7223
|
-
["Address",
|
|
7686
|
+
["Address", address3],
|
|
7224
7687
|
["Network", client.network],
|
|
7225
7688
|
["Tokens", String(totalShown)]
|
|
7226
7689
|
]);
|
|
@@ -7246,7 +7709,7 @@ Examples:
|
|
|
7246
7709
|
const nextResult = await withSpinner(
|
|
7247
7710
|
"Fetching next page\u2026",
|
|
7248
7711
|
"Page fetched",
|
|
7249
|
-
() => client.call("alchemy_getTokenBalances", [
|
|
7712
|
+
() => client.call("alchemy_getTokenBalances", [address3, "erc20", { pageKey }])
|
|
7250
7713
|
);
|
|
7251
7714
|
if (isJSONMode()) {
|
|
7252
7715
|
printJSON(nextResult);
|
|
@@ -7366,7 +7829,7 @@ Examples:
|
|
|
7366
7829
|
).action(async (addressArg, opts) => {
|
|
7367
7830
|
try {
|
|
7368
7831
|
const client = clientFromFlags(program2);
|
|
7369
|
-
const
|
|
7832
|
+
const address3 = addressArg ? await resolveAddress(addressArg, client) : void 0;
|
|
7370
7833
|
if (opts.fromAddress) opts.fromAddress = await resolveAddress(opts.fromAddress, client);
|
|
7371
7834
|
if (opts.toAddress) opts.toAddress = await resolveAddress(opts.toAddress, client);
|
|
7372
7835
|
const baseFilter = {
|
|
@@ -7382,8 +7845,8 @@ Examples:
|
|
|
7382
7845
|
}
|
|
7383
7846
|
if (opts.pageKey) baseFilter.pageKey = opts.pageKey;
|
|
7384
7847
|
const filter = { ...baseFilter };
|
|
7385
|
-
if (
|
|
7386
|
-
filter.fromAddress =
|
|
7848
|
+
if (address3 && !opts.fromAddress && !opts.toAddress) {
|
|
7849
|
+
filter.fromAddress = address3;
|
|
7387
7850
|
} else {
|
|
7388
7851
|
if (opts.fromAddress) filter.fromAddress = opts.fromAddress;
|
|
7389
7852
|
if (opts.toAddress) filter.toAddress = opts.toAddress;
|
|
@@ -8145,14 +8608,14 @@ import {
|
|
|
8145
8608
|
// src/lib/wallet-quote-client.ts
|
|
8146
8609
|
import { createClient } from "viem";
|
|
8147
8610
|
import { parseAccount } from "viem/accounts";
|
|
8148
|
-
function buildWalletQuoteClient(program2,
|
|
8611
|
+
function buildWalletQuoteClient(program2, address3) {
|
|
8149
8612
|
const apiKey = resolveAPIKey(program2);
|
|
8150
8613
|
if (!apiKey) throw errAuthRequired();
|
|
8151
8614
|
const cfg = load();
|
|
8152
8615
|
const network = resolveNetwork(program2, cfg);
|
|
8153
8616
|
const chain = networkToChain(network);
|
|
8154
8617
|
const client = createClient({
|
|
8155
|
-
account: parseAccount(
|
|
8618
|
+
account: parseAccount(address3),
|
|
8156
8619
|
transport: createAlchemyWalletTransport(apiKey),
|
|
8157
8620
|
chain,
|
|
8158
8621
|
name: "alchemyQuoteClient"
|
|
@@ -8164,7 +8627,7 @@ function buildWalletQuoteClient(program2, address2) {
|
|
|
8164
8627
|
client,
|
|
8165
8628
|
network,
|
|
8166
8629
|
chain,
|
|
8167
|
-
address:
|
|
8630
|
+
address: address3,
|
|
8168
8631
|
paymaster: void 0
|
|
8169
8632
|
};
|
|
8170
8633
|
}
|
|
@@ -8241,8 +8704,8 @@ function normalizeQuoteError(err, flow) {
|
|
|
8241
8704
|
|
|
8242
8705
|
// src/commands/swap.ts
|
|
8243
8706
|
var NATIVE_DECIMALS = 18;
|
|
8244
|
-
function isNativeToken2(
|
|
8245
|
-
return
|
|
8707
|
+
function isNativeToken2(address3) {
|
|
8708
|
+
return address3.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();
|
|
8246
8709
|
}
|
|
8247
8710
|
function slippagePercentToBasisPoints(percent) {
|
|
8248
8711
|
return BigInt(Math.round(percent * 100));
|
|
@@ -8934,8 +9397,8 @@ import {
|
|
|
8934
9397
|
swapActions as swapActions2
|
|
8935
9398
|
} from "@alchemy/wallet-apis/experimental";
|
|
8936
9399
|
var NATIVE_DECIMALS2 = 18;
|
|
8937
|
-
function isNativeToken3(
|
|
8938
|
-
return
|
|
9400
|
+
function isNativeToken3(address3) {
|
|
9401
|
+
return address3.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();
|
|
8939
9402
|
}
|
|
8940
9403
|
function slippagePercentToBasisPoints2(percent) {
|
|
8941
9404
|
return BigInt(Math.round(percent * 100));
|
|
@@ -9888,7 +10351,7 @@ async function flushProcessOutput() {
|
|
|
9888
10351
|
}
|
|
9889
10352
|
program.name("alchemy").description(
|
|
9890
10353
|
"The Alchemy CLI lets you query blockchain data, call JSON-RPC methods, and manage your Alchemy configuration."
|
|
9891
|
-
).version("0.
|
|
10354
|
+
).version("0.10.0", "-v, --version", "display CLI version").option("--api-key <key>", "Alchemy API key (env: ALCHEMY_API_KEY)").option(
|
|
9892
10355
|
"-n, --network <network>",
|
|
9893
10356
|
"Target network (default: eth-mainnet) (env: ALCHEMY_NETWORK)"
|
|
9894
10357
|
).option("--x402", "Use x402 wallet-based gateway auth").option(
|
|
@@ -10114,7 +10577,7 @@ ${styledLine}`;
|
|
|
10114
10577
|
if (isInteractiveAllowed(program)) {
|
|
10115
10578
|
let latestForInteractiveStartup = null;
|
|
10116
10579
|
if (shouldRunOnboarding(program, cfg)) {
|
|
10117
|
-
const { runOnboarding } = await import("./onboarding-
|
|
10580
|
+
const { runOnboarding } = await import("./onboarding-A7IOH2MX.js");
|
|
10118
10581
|
const latest = getAvailableUpdateOnce();
|
|
10119
10582
|
const completed = await runOnboarding(program, latest);
|
|
10120
10583
|
updateShownDuringInteractiveStartup = Boolean(latest);
|
|
@@ -10128,7 +10591,7 @@ ${styledLine}`;
|
|
|
10128
10591
|
latestForInteractiveStartup
|
|
10129
10592
|
);
|
|
10130
10593
|
}
|
|
10131
|
-
const { startREPL } = await import("./interactive-
|
|
10594
|
+
const { startREPL } = await import("./interactive-D34T7RI6.js");
|
|
10132
10595
|
program.exitOverride();
|
|
10133
10596
|
program.configureOutput({
|
|
10134
10597
|
writeErr: () => {
|