@chainstream-io/cli 0.0.18 → 0.0.19
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/index.js +374 -291
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -84,19 +84,8 @@ var init_config = __esm({
|
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
// src/wallet/types.ts
|
|
88
|
-
function toSdkChain(chain) {
|
|
89
|
-
return isSolanaChain(chain) ? "solana" : "evm";
|
|
90
|
-
}
|
|
91
|
-
var init_types = __esm({
|
|
92
|
-
"src/wallet/types.ts"() {
|
|
93
|
-
"use strict";
|
|
94
|
-
init_config();
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
87
|
// src/wallet/raw-wallet.ts
|
|
99
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
88
|
+
import { privateKeyToAccount, signTypedData as viemSignTypedData } from "viem/accounts";
|
|
100
89
|
import { Keypair, VersionedTransaction } from "@solana/web3.js";
|
|
101
90
|
import { sign as ed25519Sign } from "crypto";
|
|
102
91
|
function bs58Decode(str) {
|
|
@@ -122,37 +111,64 @@ function bs58Decode(str) {
|
|
|
122
111
|
}
|
|
123
112
|
return new Uint8Array(result.reverse());
|
|
124
113
|
}
|
|
125
|
-
|
|
114
|
+
function toHexKey(key) {
|
|
115
|
+
return key.startsWith("0x") ? key : `0x${key}`;
|
|
116
|
+
}
|
|
117
|
+
function createRawKeyWallet(key, chain) {
|
|
118
|
+
return isEvmChain(chain) ? new RawEvmWallet(key, chain) : new RawSvmWallet(key, chain);
|
|
119
|
+
}
|
|
120
|
+
var RawEvmWallet, RawSvmWallet;
|
|
126
121
|
var init_raw_wallet = __esm({
|
|
127
122
|
"src/wallet/raw-wallet.ts"() {
|
|
128
123
|
"use strict";
|
|
129
|
-
init_types();
|
|
130
124
|
init_config();
|
|
131
|
-
|
|
132
|
-
chain;
|
|
125
|
+
RawEvmWallet = class {
|
|
126
|
+
chain = "evm";
|
|
133
127
|
paymentChain;
|
|
134
128
|
address;
|
|
135
129
|
privateKey;
|
|
136
130
|
constructor(key, chain) {
|
|
137
131
|
this.paymentChain = chain;
|
|
138
|
-
this.chain = toSdkChain(chain);
|
|
139
132
|
this.privateKey = key;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
const account = privateKeyToAccount(toHexKey(key));
|
|
134
|
+
this.address = account.address;
|
|
135
|
+
}
|
|
136
|
+
async signMessage(message) {
|
|
137
|
+
const account = privateKeyToAccount(toHexKey(this.privateKey));
|
|
138
|
+
return account.signMessage({ message });
|
|
139
|
+
}
|
|
140
|
+
async signTransaction(serializedTx) {
|
|
141
|
+
const txBytes = Buffer.from(serializedTx, "base64");
|
|
142
|
+
const account = privateKeyToAccount(toHexKey(this.privateKey));
|
|
143
|
+
const signedHex = await account.signTransaction({ type: "legacy" });
|
|
144
|
+
return Buffer.from(signedHex.slice(2), "hex").toString("base64");
|
|
145
|
+
}
|
|
146
|
+
async signTypedData(typedData) {
|
|
147
|
+
return viemSignTypedData({
|
|
148
|
+
privateKey: toHexKey(this.privateKey),
|
|
149
|
+
...typedData,
|
|
150
|
+
domain: typedData.domain,
|
|
151
|
+
types: typedData.types
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
async signRawHash(hash) {
|
|
155
|
+
const account = privateKeyToAccount(toHexKey(this.privateKey));
|
|
156
|
+
return account.sign({ hash });
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
RawSvmWallet = class {
|
|
160
|
+
chain = "solana";
|
|
161
|
+
paymentChain;
|
|
162
|
+
address;
|
|
163
|
+
privateKey;
|
|
164
|
+
constructor(key, chain) {
|
|
165
|
+
this.paymentChain = chain;
|
|
166
|
+
this.privateKey = key;
|
|
167
|
+
const decoded = bs58Decode(key);
|
|
168
|
+
const keypair = Keypair.fromSecretKey(decoded);
|
|
169
|
+
this.address = keypair.publicKey.toBase58();
|
|
149
170
|
}
|
|
150
171
|
async signMessage(message) {
|
|
151
|
-
if (isEvmChain(this.paymentChain)) {
|
|
152
|
-
const hex = this.privateKey.startsWith("0x") ? this.privateKey : `0x${this.privateKey}`;
|
|
153
|
-
const account = privateKeyToAccount(hex);
|
|
154
|
-
return account.signMessage({ message });
|
|
155
|
-
}
|
|
156
172
|
const decoded = bs58Decode(this.privateKey);
|
|
157
173
|
const secretKeyRaw = decoded.slice(0, 32);
|
|
158
174
|
const pkcs8Prefix = Buffer.from("302e020100300506032b657004220420", "hex");
|
|
@@ -163,17 +179,11 @@ var init_raw_wallet = __esm({
|
|
|
163
179
|
}
|
|
164
180
|
async signTransaction(serializedTx) {
|
|
165
181
|
const txBytes = Buffer.from(serializedTx, "base64");
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return Buffer.from(tx.serialize()).toString("base64");
|
|
172
|
-
}
|
|
173
|
-
const hex = this.privateKey.startsWith("0x") ? this.privateKey : `0x${this.privateKey}`;
|
|
174
|
-
const account = privateKeyToAccount(hex);
|
|
175
|
-
const signedHex = await account.signTransaction({ type: "legacy" });
|
|
176
|
-
return Buffer.from(signedHex.slice(2), "hex").toString("base64");
|
|
182
|
+
const tx = VersionedTransaction.deserialize(new Uint8Array(txBytes));
|
|
183
|
+
const decoded = bs58Decode(this.privateKey);
|
|
184
|
+
const keypair = Keypair.fromSecretKey(decoded);
|
|
185
|
+
tx.sign([keypair]);
|
|
186
|
+
return Buffer.from(tx.serialize()).toString("base64");
|
|
177
187
|
}
|
|
178
188
|
};
|
|
179
189
|
}
|
|
@@ -328,74 +338,131 @@ var init_turnkey = __esm({
|
|
|
328
338
|
});
|
|
329
339
|
|
|
330
340
|
// src/wallet/turnkey-wallet.ts
|
|
331
|
-
|
|
341
|
+
import { hashTypedData } from "viem";
|
|
342
|
+
async function turnkeySignRawPayload(creds, address, payloadHex, hashFunction) {
|
|
343
|
+
const result = await turnkeyRequest(
|
|
344
|
+
"/public/v1/submit/sign_raw_payload",
|
|
345
|
+
{
|
|
346
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
347
|
+
timestampMs: Date.now().toString(),
|
|
348
|
+
organizationId: creds.organizationId,
|
|
349
|
+
parameters: {
|
|
350
|
+
signWith: address,
|
|
351
|
+
payload: payloadHex,
|
|
352
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
353
|
+
hashFunction
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
creds
|
|
357
|
+
);
|
|
358
|
+
const sig = result.activity?.result?.signRawPayloadResult;
|
|
359
|
+
if (!sig) throw new Error("Turnkey sign: no signature in response");
|
|
360
|
+
return sig;
|
|
361
|
+
}
|
|
362
|
+
function formatEvmSignature(sig) {
|
|
363
|
+
const v = sig.v === "00" ? "1b" : "1c";
|
|
364
|
+
return `0x${sig.r}${sig.s}${v}`;
|
|
365
|
+
}
|
|
366
|
+
async function createTurnkeyWallets(creds) {
|
|
367
|
+
const [evmAddr, solAddr] = await Promise.all([
|
|
368
|
+
getEvmAddress(creds),
|
|
369
|
+
getSolanaAddress(creds)
|
|
370
|
+
]);
|
|
371
|
+
return {
|
|
372
|
+
base: new TurnkeyEvmWallet(creds, "base", evmAddr),
|
|
373
|
+
sol: new TurnkeySvmWallet(creds, "sol", solAddr)
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
var TurnkeyEvmWallet, TurnkeySvmWallet;
|
|
332
377
|
var init_turnkey_wallet = __esm({
|
|
333
378
|
"src/wallet/turnkey-wallet.ts"() {
|
|
334
379
|
"use strict";
|
|
335
|
-
init_types();
|
|
336
|
-
init_config();
|
|
337
380
|
init_turnkey();
|
|
338
|
-
|
|
339
|
-
chain;
|
|
381
|
+
TurnkeyEvmWallet = class {
|
|
382
|
+
chain = "evm";
|
|
340
383
|
paymentChain;
|
|
341
384
|
address;
|
|
342
385
|
creds;
|
|
343
386
|
constructor(creds, chain, address) {
|
|
344
387
|
this.creds = creds;
|
|
345
388
|
this.paymentChain = chain;
|
|
346
|
-
this.chain = toSdkChain(chain);
|
|
347
389
|
this.address = address;
|
|
348
390
|
}
|
|
349
|
-
static async create(creds) {
|
|
350
|
-
const [evmAddr, solAddr] = await Promise.all([
|
|
351
|
-
getEvmAddress(creds),
|
|
352
|
-
getSolanaAddress(creds)
|
|
353
|
-
]);
|
|
354
|
-
return {
|
|
355
|
-
base: new _TurnkeyWallet(creds, "base", evmAddr),
|
|
356
|
-
sol: new _TurnkeyWallet(creds, "sol", solAddr)
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
391
|
async signMessage(message) {
|
|
360
|
-
|
|
361
|
-
let hashFunction;
|
|
362
|
-
if (isEvmChain(this.paymentChain)) {
|
|
363
|
-
const prefix = `Ethereum Signed Message:
|
|
392
|
+
const prefix = `Ethereum Signed Message:
|
|
364
393
|
${message.length}`;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
394
|
+
const prefixed = Buffer.concat([Buffer.from(prefix, "utf-8"), Buffer.from(message, "utf-8")]);
|
|
395
|
+
const sig = await turnkeySignRawPayload(
|
|
396
|
+
this.creds,
|
|
397
|
+
this.address,
|
|
398
|
+
prefixed.toString("hex"),
|
|
399
|
+
"HASH_FUNCTION_KECCAK256"
|
|
400
|
+
);
|
|
401
|
+
return formatEvmSignature(sig);
|
|
402
|
+
}
|
|
403
|
+
async signTransaction(serializedTx) {
|
|
404
|
+
const txBytes = Buffer.from(serializedTx, "base64");
|
|
372
405
|
const result = await turnkeyRequest(
|
|
373
|
-
"/public/v1/submit/
|
|
406
|
+
"/public/v1/submit/sign_transaction",
|
|
374
407
|
{
|
|
375
|
-
type: "
|
|
408
|
+
type: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2",
|
|
376
409
|
timestampMs: Date.now().toString(),
|
|
377
410
|
organizationId: this.creds.organizationId,
|
|
378
411
|
parameters: {
|
|
379
412
|
signWith: this.address,
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
hashFunction
|
|
413
|
+
unsignedTransaction: txBytes.toString("hex"),
|
|
414
|
+
type: "TRANSACTION_TYPE_ETHEREUM"
|
|
383
415
|
}
|
|
384
416
|
},
|
|
385
417
|
this.creds
|
|
386
418
|
);
|
|
387
|
-
const
|
|
388
|
-
if (!
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
419
|
+
const signedHex = result.activity?.result?.signTransactionResult?.signedTransaction;
|
|
420
|
+
if (!signedHex) throw new Error("Turnkey signTransaction: no signed tx in response");
|
|
421
|
+
return Buffer.from(signedHex, "hex").toString("base64");
|
|
422
|
+
}
|
|
423
|
+
async signTypedData(typedData) {
|
|
424
|
+
const digest = hashTypedData(typedData);
|
|
425
|
+
const payloadHex = digest.slice(2);
|
|
426
|
+
const sig = await turnkeySignRawPayload(
|
|
427
|
+
this.creds,
|
|
428
|
+
this.address,
|
|
429
|
+
payloadHex,
|
|
430
|
+
"HASH_FUNCTION_NO_OP"
|
|
431
|
+
);
|
|
432
|
+
return formatEvmSignature(sig);
|
|
433
|
+
}
|
|
434
|
+
async signRawHash(hash) {
|
|
435
|
+
const payloadHex = hash.startsWith("0x") ? hash.slice(2) : hash;
|
|
436
|
+
const sig = await turnkeySignRawPayload(
|
|
437
|
+
this.creds,
|
|
438
|
+
this.address,
|
|
439
|
+
payloadHex,
|
|
440
|
+
"HASH_FUNCTION_NO_OP"
|
|
441
|
+
);
|
|
442
|
+
return formatEvmSignature(sig);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
TurnkeySvmWallet = class {
|
|
446
|
+
chain = "solana";
|
|
447
|
+
paymentChain;
|
|
448
|
+
address;
|
|
449
|
+
creds;
|
|
450
|
+
constructor(creds, chain, address) {
|
|
451
|
+
this.creds = creds;
|
|
452
|
+
this.paymentChain = chain;
|
|
453
|
+
this.address = address;
|
|
454
|
+
}
|
|
455
|
+
async signMessage(message) {
|
|
456
|
+
const sig = await turnkeySignRawPayload(
|
|
457
|
+
this.creds,
|
|
458
|
+
this.address,
|
|
459
|
+
Buffer.from(message, "utf-8").toString("hex"),
|
|
460
|
+
"HASH_FUNCTION_NOT_APPLICABLE"
|
|
461
|
+
);
|
|
462
|
+
return `${sig.r}${sig.s}`;
|
|
394
463
|
}
|
|
395
464
|
async signTransaction(serializedTx) {
|
|
396
465
|
const txBytes = Buffer.from(serializedTx, "base64");
|
|
397
|
-
const unsignedHex = txBytes.toString("hex");
|
|
398
|
-
const txType = isEvmChain(this.paymentChain) ? "TRANSACTION_TYPE_ETHEREUM" : "TRANSACTION_TYPE_SOLANA";
|
|
399
466
|
const result = await turnkeyRequest(
|
|
400
467
|
"/public/v1/submit/sign_transaction",
|
|
401
468
|
{
|
|
@@ -404,8 +471,8 @@ ${message.length}`;
|
|
|
404
471
|
organizationId: this.creds.organizationId,
|
|
405
472
|
parameters: {
|
|
406
473
|
signWith: this.address,
|
|
407
|
-
unsignedTransaction:
|
|
408
|
-
type:
|
|
474
|
+
unsignedTransaction: txBytes.toString("hex"),
|
|
475
|
+
type: "TRANSACTION_TYPE_SOLANA"
|
|
409
476
|
}
|
|
410
477
|
},
|
|
411
478
|
this.creds
|
|
@@ -426,7 +493,7 @@ __export(wallet_exports, {
|
|
|
426
493
|
});
|
|
427
494
|
function createWallet(config, mode) {
|
|
428
495
|
if (mode === "raw" && config.rawWallet) {
|
|
429
|
-
return
|
|
496
|
+
return createRawKeyWallet(config.rawWallet.key, config.rawWallet.chain);
|
|
430
497
|
}
|
|
431
498
|
if (mode === "turnkey" && config.turnkey) {
|
|
432
499
|
const chain = config.walletChain ?? "base";
|
|
@@ -437,7 +504,7 @@ function createWallet(config, mode) {
|
|
|
437
504
|
Please re-login to resolve addresses: chainstream login`
|
|
438
505
|
);
|
|
439
506
|
}
|
|
440
|
-
return new
|
|
507
|
+
return isEvmChain(chain) ? new TurnkeyEvmWallet(config.turnkey, chain, address) : new TurnkeySvmWallet(config.turnkey, chain, address);
|
|
441
508
|
}
|
|
442
509
|
throw new Error(
|
|
443
510
|
"No wallet configured. Run:\n chainstream login # Create Turnkey wallet\n chainstream wallet set-raw # Use raw private key (dev)"
|
|
@@ -445,11 +512,11 @@ Please re-login to resolve addresses: chainstream login`
|
|
|
445
512
|
}
|
|
446
513
|
async function createWalletWithAddresses(config, mode) {
|
|
447
514
|
if (mode === "raw" && config.rawWallet) {
|
|
448
|
-
const w =
|
|
515
|
+
const w = createRawKeyWallet(config.rawWallet.key, config.rawWallet.chain);
|
|
449
516
|
return isEvmChain(config.rawWallet.chain) ? { base: w } : { sol: w };
|
|
450
517
|
}
|
|
451
518
|
if (mode === "turnkey" && config.turnkey) {
|
|
452
|
-
const wallets = await
|
|
519
|
+
const wallets = await createTurnkeyWallets(config.turnkey);
|
|
453
520
|
return { base: wallets.base, sol: wallets.sol };
|
|
454
521
|
}
|
|
455
522
|
throw new Error("No wallet configured.");
|
|
@@ -476,7 +543,7 @@ import { wrapFetchWithPayment } from "@x402/fetch";
|
|
|
476
543
|
import { ExactEvmScheme } from "@x402/evm/exact/client";
|
|
477
544
|
import { ExactSvmScheme } from "@x402/svm/exact/client";
|
|
478
545
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
479
|
-
import { hashTypedData } from "viem";
|
|
546
|
+
import { hashTypedData as hashTypedData2 } from "viem";
|
|
480
547
|
import { createKeyPairSignerFromBytes } from "@solana/kit";
|
|
481
548
|
import * as readline from "readline/promises";
|
|
482
549
|
function createTurnkeyPaymentAccount(creds) {
|
|
@@ -487,7 +554,7 @@ function createTurnkeyPaymentAccount(creds) {
|
|
|
487
554
|
source: "custom",
|
|
488
555
|
publicKey: "0x",
|
|
489
556
|
async signTypedData(args) {
|
|
490
|
-
const digest =
|
|
557
|
+
const digest = hashTypedData2(args);
|
|
491
558
|
const result = await turnkeyRequest(
|
|
492
559
|
"/public/v1/submit/sign_raw_payload",
|
|
493
560
|
{
|
|
@@ -687,16 +754,6 @@ function createClient() {
|
|
|
687
754
|
"Not authenticated. Run one of:\n chainstream login # Create ChainStream Wallet (no email)\n chainstream login --email # Email OTP login\n chainstream wallet set-raw # Import private key (dev)\n chainstream config set --key apiKey --value <key> # API key only"
|
|
688
755
|
);
|
|
689
756
|
}
|
|
690
|
-
function requireWallet() {
|
|
691
|
-
const config = loadConfig();
|
|
692
|
-
const walletMode = getWalletMode(config);
|
|
693
|
-
if (!walletMode) {
|
|
694
|
-
throw new Error(
|
|
695
|
-
"Wallet required for this operation. Run:\n chainstream login # Create ChainStream Wallet\n chainstream wallet set-raw # Dev: use raw private key"
|
|
696
|
-
);
|
|
697
|
-
}
|
|
698
|
-
return createClient();
|
|
699
|
-
}
|
|
700
757
|
async function callWithAutoPayment(fn, retried = false) {
|
|
701
758
|
try {
|
|
702
759
|
return await fn();
|
|
@@ -817,11 +874,6 @@ function validateAddress(address, chain) {
|
|
|
817
874
|
throw new Error(`Invalid address for chain "${chain}": "${address}"`);
|
|
818
875
|
}
|
|
819
876
|
}
|
|
820
|
-
function validateSlippage(value) {
|
|
821
|
-
if (value < 1e-3 || value > 0.5) {
|
|
822
|
-
throw new Error(`Invalid slippage: ${value}. Must be between 0.001 (0.1%) and 0.5 (50%).`);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
877
|
function resolveCurrency(nameOrAddress, chain) {
|
|
826
878
|
const upper = nameOrAddress.toUpperCase();
|
|
827
879
|
const resolved = CURRENCY_MAP[chain]?.[upper];
|
|
@@ -830,13 +882,8 @@ function resolveCurrency(nameOrAddress, chain) {
|
|
|
830
882
|
}
|
|
831
883
|
|
|
832
884
|
// src/lib/output.ts
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
bsc: "https://bscscan.com/tx/",
|
|
836
|
-
eth: "https://etherscan.io/tx/"
|
|
837
|
-
};
|
|
838
|
-
function printResult(data, raw) {
|
|
839
|
-
if (raw) {
|
|
885
|
+
function printResult(data, json) {
|
|
886
|
+
if (json) {
|
|
840
887
|
process.stdout.write(JSON.stringify(data) + "\n");
|
|
841
888
|
} else {
|
|
842
889
|
process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
@@ -854,27 +901,23 @@ function exitOnError(err) {
|
|
|
854
901
|
}
|
|
855
902
|
process.exit(1);
|
|
856
903
|
}
|
|
857
|
-
function explorerUrl(chain, txHash) {
|
|
858
|
-
const base = EXPLORERS[chain] ?? EXPLORERS["eth"];
|
|
859
|
-
return `${base}${txHash}`;
|
|
860
|
-
}
|
|
861
904
|
|
|
862
905
|
// src/commands/token.ts
|
|
863
906
|
function registerTokenCommands(program2) {
|
|
864
907
|
const token = program2.command("token").description("Token information and analytics");
|
|
865
|
-
token.command("search").description("Search tokens by keyword").requiredOption("--keyword <keyword>", "Search keyword (name, symbol, or address)").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--limit <n>", "Max results", "20").
|
|
908
|
+
token.command("search").description("Search tokens by keyword").requiredOption("--keyword <keyword>", "Search keyword (name, symbol, or address)").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--limit <n>", "Max results", "20").action(async (opts, cmd) => {
|
|
866
909
|
try {
|
|
867
910
|
validateChain(opts.chain);
|
|
868
911
|
const client = createClient();
|
|
869
912
|
const result = await callWithAutoPayment(
|
|
870
913
|
() => client.token.search({ q: opts.keyword, chains: [opts.chain], limit: Number(opts.limit) })
|
|
871
914
|
);
|
|
872
|
-
printResult(result,
|
|
915
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
873
916
|
} catch (err) {
|
|
874
917
|
exitOnError(err);
|
|
875
918
|
}
|
|
876
919
|
});
|
|
877
|
-
token.command("info").description("Get full token detail").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").
|
|
920
|
+
token.command("info").description("Get full token detail").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").action(async (opts, cmd) => {
|
|
878
921
|
try {
|
|
879
922
|
validateChain(opts.chain);
|
|
880
923
|
validateAddress(opts.address, opts.chain);
|
|
@@ -882,12 +925,12 @@ function registerTokenCommands(program2) {
|
|
|
882
925
|
const result = await callWithAutoPayment(
|
|
883
926
|
() => client.token.getToken(opts.chain, opts.address)
|
|
884
927
|
);
|
|
885
|
-
printResult(result,
|
|
928
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
886
929
|
} catch (err) {
|
|
887
930
|
exitOnError(err);
|
|
888
931
|
}
|
|
889
932
|
});
|
|
890
|
-
token.command("security").description("Check token security (honeypot, mint auth, freeze auth)").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").
|
|
933
|
+
token.command("security").description("Check token security (honeypot, mint auth, freeze auth)").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").action(async (opts, cmd) => {
|
|
891
934
|
try {
|
|
892
935
|
validateChain(opts.chain);
|
|
893
936
|
validateAddress(opts.address, opts.chain);
|
|
@@ -895,12 +938,12 @@ function registerTokenCommands(program2) {
|
|
|
895
938
|
const result = await callWithAutoPayment(
|
|
896
939
|
() => client.token.getSecurity(opts.chain, opts.address)
|
|
897
940
|
);
|
|
898
|
-
printResult(result,
|
|
941
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
899
942
|
} catch (err) {
|
|
900
943
|
exitOnError(err);
|
|
901
944
|
}
|
|
902
945
|
});
|
|
903
|
-
token.command("holders").description("Get top token holders").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").option("--limit <n>", "Max results", "20").
|
|
946
|
+
token.command("holders").description("Get top token holders").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").option("--limit <n>", "Max results", "20").action(async (opts, cmd) => {
|
|
904
947
|
try {
|
|
905
948
|
validateChain(opts.chain);
|
|
906
949
|
validateAddress(opts.address, opts.chain);
|
|
@@ -908,12 +951,12 @@ function registerTokenCommands(program2) {
|
|
|
908
951
|
const result = await callWithAutoPayment(
|
|
909
952
|
() => client.token.getTopHolders(opts.chain, opts.address, { limit: Number(opts.limit) })
|
|
910
953
|
);
|
|
911
|
-
printResult(result,
|
|
954
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
912
955
|
} catch (err) {
|
|
913
956
|
exitOnError(err);
|
|
914
957
|
}
|
|
915
958
|
});
|
|
916
|
-
token.command("candles").description("Get OHLCV candlestick data").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").requiredOption("--resolution <res>", "Resolution: 1m/5m/15m/1h/4h/1d").option("--from <timestamp>", "Start time (Unix seconds)").option("--to <timestamp>", "End time (Unix seconds)").option("--limit <n>", "Max candles", "100").
|
|
959
|
+
token.command("candles").description("Get OHLCV candlestick data").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").requiredOption("--resolution <res>", "Resolution: 1m/5m/15m/1h/4h/1d").option("--from <timestamp>", "Start time (Unix seconds)").option("--to <timestamp>", "End time (Unix seconds)").option("--limit <n>", "Max candles", "100").action(async (opts, cmd) => {
|
|
917
960
|
try {
|
|
918
961
|
validateChain(opts.chain);
|
|
919
962
|
validateAddress(opts.address, opts.chain);
|
|
@@ -927,12 +970,12 @@ function registerTokenCommands(program2) {
|
|
|
927
970
|
const result = await callWithAutoPayment(
|
|
928
971
|
() => client.token.getCandles(opts.chain, opts.address, params)
|
|
929
972
|
);
|
|
930
|
-
printResult(result,
|
|
973
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
931
974
|
} catch (err) {
|
|
932
975
|
exitOnError(err);
|
|
933
976
|
}
|
|
934
977
|
});
|
|
935
|
-
token.command("pools").description("Get liquidity pools for a token").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").
|
|
978
|
+
token.command("pools").description("Get liquidity pools for a token").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Token contract address").action(async (opts, cmd) => {
|
|
936
979
|
try {
|
|
937
980
|
validateChain(opts.chain);
|
|
938
981
|
validateAddress(opts.address, opts.chain);
|
|
@@ -940,7 +983,7 @@ function registerTokenCommands(program2) {
|
|
|
940
983
|
const result = await callWithAutoPayment(
|
|
941
984
|
() => client.token.getPools(opts.chain, opts.address)
|
|
942
985
|
);
|
|
943
|
-
printResult(result,
|
|
986
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
944
987
|
} catch (err) {
|
|
945
988
|
exitOnError(err);
|
|
946
989
|
}
|
|
@@ -950,7 +993,7 @@ function registerTokenCommands(program2) {
|
|
|
950
993
|
// src/commands/market.ts
|
|
951
994
|
function registerMarketCommands(program2) {
|
|
952
995
|
const market = program2.command("market").description("Market data and trending tokens");
|
|
953
|
-
market.command("trending").description("Get hot/trending tokens").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--duration <dur>", "Duration: 1h/6h/24h").option("--limit <n>", "Max results").
|
|
996
|
+
market.command("trending").description("Get hot/trending tokens").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--duration <dur>", "Duration: 1h/6h/24h").option("--limit <n>", "Max results").action(async (opts, cmd) => {
|
|
954
997
|
try {
|
|
955
998
|
validateChain(opts.chain);
|
|
956
999
|
const client = createClient();
|
|
@@ -959,12 +1002,12 @@ function registerMarketCommands(program2) {
|
|
|
959
1002
|
const result = await callWithAutoPayment(
|
|
960
1003
|
() => client.ranking.getHotTokens(opts.chain, opts.duration, params)
|
|
961
1004
|
);
|
|
962
|
-
printResult(result,
|
|
1005
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
963
1006
|
} catch (err) {
|
|
964
1007
|
exitOnError(err);
|
|
965
1008
|
}
|
|
966
1009
|
});
|
|
967
|
-
market.command("new").description("Get newly created tokens").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--limit <n>", "Max results").
|
|
1010
|
+
market.command("new").description("Get newly created tokens").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--limit <n>", "Max results").action(async (opts, cmd) => {
|
|
968
1011
|
try {
|
|
969
1012
|
validateChain(opts.chain);
|
|
970
1013
|
const client = createClient();
|
|
@@ -973,12 +1016,12 @@ function registerMarketCommands(program2) {
|
|
|
973
1016
|
const result = await callWithAutoPayment(
|
|
974
1017
|
() => client.ranking.getNewTokens(opts.chain, params)
|
|
975
1018
|
);
|
|
976
|
-
printResult(result,
|
|
1019
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
977
1020
|
} catch (err) {
|
|
978
1021
|
exitOnError(err);
|
|
979
1022
|
}
|
|
980
1023
|
});
|
|
981
|
-
market.command("trades").description("Get recent trades").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--token <address>", "Filter by token address").option("--limit <n>", "Max results").
|
|
1024
|
+
market.command("trades").description("Get recent trades").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").option("--token <address>", "Filter by token address").option("--limit <n>", "Max results").action(async (opts, cmd) => {
|
|
982
1025
|
try {
|
|
983
1026
|
validateChain(opts.chain);
|
|
984
1027
|
const client = createClient();
|
|
@@ -988,7 +1031,7 @@ function registerMarketCommands(program2) {
|
|
|
988
1031
|
const result = await callWithAutoPayment(
|
|
989
1032
|
() => client.trade.getTrades(opts.chain, params)
|
|
990
1033
|
);
|
|
991
|
-
printResult(result,
|
|
1034
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
992
1035
|
} catch (err) {
|
|
993
1036
|
exitOnError(err);
|
|
994
1037
|
}
|
|
@@ -999,8 +1042,25 @@ function registerMarketCommands(program2) {
|
|
|
999
1042
|
init_config();
|
|
1000
1043
|
import * as readline2 from "readline/promises";
|
|
1001
1044
|
function registerWalletCommands(program2) {
|
|
1002
|
-
const wallet = program2.command("wallet").description("Wallet analytics and
|
|
1003
|
-
wallet.command("
|
|
1045
|
+
const wallet = program2.command("wallet").description("Wallet analytics, management, and signing");
|
|
1046
|
+
wallet.command("sign").description("Sign a serialized transaction").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--tx <base64>", "Base64-encoded unsigned transaction (serializedTx)").action(async (opts, cmd) => {
|
|
1047
|
+
try {
|
|
1048
|
+
validateChain(opts.chain);
|
|
1049
|
+
const { createWallet: createWallet2 } = await Promise.resolve().then(() => (init_wallet(), wallet_exports));
|
|
1050
|
+
const { getWalletMode: getWalletMode2, isSolanaChain: isSolanaChain2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1051
|
+
const config = loadConfig();
|
|
1052
|
+
const walletMode = getWalletMode2(config);
|
|
1053
|
+
if (!walletMode) throw new Error("Wallet required for signing. Run: chainstream login");
|
|
1054
|
+
const signChain = isSolanaChain2(opts.chain) ? "sol" : "base";
|
|
1055
|
+
const signConfig = { ...config, walletChain: signChain };
|
|
1056
|
+
const w = createWallet2(signConfig, walletMode);
|
|
1057
|
+
const signedTx = await w.signTransaction(opts.tx);
|
|
1058
|
+
printResult({ signedTx }, cmd.optsWithGlobals().json);
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
exitOnError(err);
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
wallet.command("profile").description("Wallet profile: PnL + net worth + top holdings").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").action(async (opts, cmd) => {
|
|
1004
1064
|
try {
|
|
1005
1065
|
validateChain(opts.chain);
|
|
1006
1066
|
validateAddress(opts.address, opts.chain);
|
|
@@ -1012,12 +1072,12 @@ function registerWalletCommands(program2) {
|
|
|
1012
1072
|
client.wallet.getTokensBalance(opts.chain, opts.address)
|
|
1013
1073
|
])
|
|
1014
1074
|
);
|
|
1015
|
-
printResult({ pnl, netWorth, balance },
|
|
1075
|
+
printResult({ pnl, netWorth, balance }, cmd.optsWithGlobals().json);
|
|
1016
1076
|
} catch (err) {
|
|
1017
1077
|
exitOnError(err);
|
|
1018
1078
|
}
|
|
1019
1079
|
});
|
|
1020
|
-
wallet.command("pnl").description("Get wallet PnL details").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").
|
|
1080
|
+
wallet.command("pnl").description("Get wallet PnL details").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").action(async (opts, cmd) => {
|
|
1021
1081
|
try {
|
|
1022
1082
|
validateChain(opts.chain);
|
|
1023
1083
|
validateAddress(opts.address, opts.chain);
|
|
@@ -1025,12 +1085,12 @@ function registerWalletCommands(program2) {
|
|
|
1025
1085
|
const result = await callWithAutoPayment(
|
|
1026
1086
|
() => client.wallet.getPnl(opts.chain, opts.address)
|
|
1027
1087
|
);
|
|
1028
|
-
printResult(result,
|
|
1088
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1029
1089
|
} catch (err) {
|
|
1030
1090
|
exitOnError(err);
|
|
1031
1091
|
}
|
|
1032
1092
|
});
|
|
1033
|
-
wallet.command("holdings").description("Get wallet token balances").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").option("--limit <n>", "Max results").
|
|
1093
|
+
wallet.command("holdings").description("Get wallet token balances").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").option("--limit <n>", "Max results").action(async (opts, cmd) => {
|
|
1034
1094
|
try {
|
|
1035
1095
|
validateChain(opts.chain);
|
|
1036
1096
|
validateAddress(opts.address, opts.chain);
|
|
@@ -1040,12 +1100,12 @@ function registerWalletCommands(program2) {
|
|
|
1040
1100
|
const result = await callWithAutoPayment(
|
|
1041
1101
|
() => client.wallet.getTokensBalance(opts.chain, opts.address, params)
|
|
1042
1102
|
);
|
|
1043
|
-
printResult(result,
|
|
1103
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1044
1104
|
} catch (err) {
|
|
1045
1105
|
exitOnError(err);
|
|
1046
1106
|
}
|
|
1047
1107
|
});
|
|
1048
|
-
wallet.command("activity").description("Get wallet transfer history").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").option("--limit <n>", "Max results").
|
|
1108
|
+
wallet.command("activity").description("Get wallet transfer history").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--address <address>", "Wallet address").option("--limit <n>", "Max results").action(async (opts, cmd) => {
|
|
1049
1109
|
try {
|
|
1050
1110
|
validateChain(opts.chain);
|
|
1051
1111
|
validateAddress(opts.address, opts.chain);
|
|
@@ -1055,42 +1115,46 @@ function registerWalletCommands(program2) {
|
|
|
1055
1115
|
const result = await callWithAutoPayment(
|
|
1056
1116
|
() => client.wallet.getWalletTransfers(opts.chain, opts.address, params)
|
|
1057
1117
|
);
|
|
1058
|
-
printResult(result,
|
|
1118
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1059
1119
|
} catch (err) {
|
|
1060
1120
|
exitOnError(err);
|
|
1061
1121
|
}
|
|
1062
1122
|
});
|
|
1063
|
-
wallet.command("address").description("Show current wallet addresses").action(async () => {
|
|
1123
|
+
wallet.command("address").description("Show current wallet addresses").action(async (_opts, cmd) => {
|
|
1064
1124
|
try {
|
|
1125
|
+
const json = cmd.optsWithGlobals().json;
|
|
1065
1126
|
const config = loadConfig();
|
|
1066
1127
|
const walletMode = (await Promise.resolve().then(() => (init_config(), config_exports))).getWalletMode(config);
|
|
1128
|
+
const addresses = {};
|
|
1067
1129
|
if (walletMode === "turnkey" && config.turnkey) {
|
|
1068
1130
|
if (config.turnkey.evmAddress || config.turnkey.solanaAddress) {
|
|
1069
|
-
if (config.turnkey.evmAddress)
|
|
1070
|
-
|
|
1071
|
-
if (config.turnkey.solanaAddress) process.stdout.write(`Solana: ${config.turnkey.solanaAddress}
|
|
1072
|
-
`);
|
|
1131
|
+
if (config.turnkey.evmAddress) addresses.base = config.turnkey.evmAddress;
|
|
1132
|
+
if (config.turnkey.solanaAddress) addresses.solana = config.turnkey.solanaAddress;
|
|
1073
1133
|
} else {
|
|
1074
1134
|
const { createWalletWithAddresses: createWalletWithAddresses2 } = await Promise.resolve().then(() => (init_wallet(), wallet_exports));
|
|
1075
1135
|
const wallets = await createWalletWithAddresses2(config, "turnkey");
|
|
1076
|
-
if (wallets.base)
|
|
1077
|
-
|
|
1078
|
-
if (wallets.sol) process.stdout.write(`Solana: ${wallets.sol.address}
|
|
1079
|
-
`);
|
|
1136
|
+
if (wallets.base) addresses.base = wallets.base.address;
|
|
1137
|
+
if (wallets.sol) addresses.solana = wallets.sol.address;
|
|
1080
1138
|
}
|
|
1081
1139
|
} else if (config.rawWallet) {
|
|
1082
1140
|
const { createWallet: createWallet2 } = await Promise.resolve().then(() => (init_wallet(), wallet_exports));
|
|
1083
1141
|
const w = createWallet2(config, "raw");
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1142
|
+
addresses[w.paymentChain] = w.address;
|
|
1143
|
+
}
|
|
1144
|
+
if (Object.keys(addresses).length === 0) {
|
|
1145
|
+
if (json) {
|
|
1146
|
+
printResult({ error: "No wallet configured" }, true);
|
|
1147
|
+
} else {
|
|
1148
|
+
process.stdout.write("No wallet configured. Run: chainstream login\n");
|
|
1149
|
+
}
|
|
1150
|
+
return;
|
|
1088
1151
|
}
|
|
1152
|
+
printResult(addresses, json);
|
|
1089
1153
|
} catch (err) {
|
|
1090
1154
|
exitOnError(err);
|
|
1091
1155
|
}
|
|
1092
1156
|
});
|
|
1093
|
-
wallet.command("balance").description("Show current wallet balance").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").
|
|
1157
|
+
wallet.command("balance").description("Show current wallet balance").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").action(async (opts, cmd) => {
|
|
1094
1158
|
try {
|
|
1095
1159
|
validateChain(opts.chain);
|
|
1096
1160
|
const config = loadConfig();
|
|
@@ -1112,34 +1176,38 @@ function registerWalletCommands(program2) {
|
|
|
1112
1176
|
const result = await callWithAutoPayment(
|
|
1113
1177
|
() => client.wallet.getTokensBalance(opts.chain, address)
|
|
1114
1178
|
);
|
|
1115
|
-
printResult(result,
|
|
1179
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1116
1180
|
} catch (err) {
|
|
1117
1181
|
exitOnError(err);
|
|
1118
1182
|
}
|
|
1119
1183
|
});
|
|
1120
|
-
wallet.command("set-raw").description("Set raw private key (dev/testing only)").requiredOption("--chain <chain>", "Chain: base/sol").action(async (opts) => {
|
|
1184
|
+
wallet.command("set-raw").description("Set raw private key (dev/testing only)").requiredOption("--chain <chain>", "Chain: base/sol").action(async (opts, cmd) => {
|
|
1121
1185
|
try {
|
|
1186
|
+
const json = cmd.optsWithGlobals().json;
|
|
1122
1187
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1188
|
+
if (!json) {
|
|
1189
|
+
process.stdout.write("WARNING: Raw private key will be stored in plaintext.\n");
|
|
1190
|
+
process.stdout.write(" Use Turnkey (chainstream login) for production.\n\n");
|
|
1191
|
+
}
|
|
1192
|
+
const key = await rl.question(json ? "" : "Enter private key: ");
|
|
1126
1193
|
rl.close();
|
|
1127
1194
|
if (!key.trim()) throw new Error("Empty key provided.");
|
|
1128
1195
|
updateConfig({
|
|
1129
1196
|
rawWallet: { key: key.trim(), chain: opts.chain }
|
|
1130
1197
|
});
|
|
1131
|
-
|
|
1132
|
-
|
|
1198
|
+
const { createWallet: createWallet2 } = await Promise.resolve().then(() => (init_wallet(), wallet_exports));
|
|
1199
|
+
const w = createWallet2(loadConfig(), "raw");
|
|
1200
|
+
printResult({ chain: opts.chain, address: w.address }, json);
|
|
1133
1201
|
} catch (err) {
|
|
1134
1202
|
exitOnError(err);
|
|
1135
1203
|
}
|
|
1136
1204
|
});
|
|
1137
|
-
wallet.command("pricing").description("Show available x402 quota plans").
|
|
1205
|
+
wallet.command("pricing").description("Show available x402 quota plans").action(async (_opts, cmd) => {
|
|
1138
1206
|
try {
|
|
1139
1207
|
const config = loadConfig();
|
|
1140
1208
|
const { getPricing: getPricing2 } = await Promise.resolve().then(() => (init_x402(), x402_exports));
|
|
1141
1209
|
const plans = await getPricing2(config.baseUrl);
|
|
1142
|
-
printResult(plans,
|
|
1210
|
+
printResult(plans, cmd.optsWithGlobals().json);
|
|
1143
1211
|
} catch (err) {
|
|
1144
1212
|
exitOnError(err);
|
|
1145
1213
|
}
|
|
@@ -1147,121 +1215,136 @@ function registerWalletCommands(program2) {
|
|
|
1147
1215
|
}
|
|
1148
1216
|
|
|
1149
1217
|
// src/commands/dex.ts
|
|
1150
|
-
import * as readline3 from "readline/promises";
|
|
1151
1218
|
function registerDexCommands(program2) {
|
|
1152
|
-
const dex = program2.command("dex").description("DEX
|
|
1153
|
-
dex.command("
|
|
1219
|
+
const dex = program2.command("dex").description("DEX route, swap, and token creation (returns unsigned transactions)");
|
|
1220
|
+
dex.command("route").description("Get aggregated route + build unsigned transaction").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--from <address>", "Sender wallet address").requiredOption("--input-token <addr>", "Input token (address or SOL/ETH/BNB/USDC)").requiredOption("--output-token <addr>", "Output token (address or SOL/ETH/BNB/USDC)").requiredOption("--amount <amount>", "Input amount (smallest unit)").option("--slippage <n>", "Slippage tolerance (0-100, e.g. 5 = 5%)", "5").option("--dex <dex>", "Specific DEX protocol (e.g. jupiter, kyberswap)").option("--recipient <addr>", "Recipient address (if different from sender)").option("--anti-mev", "Enable anti-MEV protection").option("--gas-price <n>", "Gas price (EVM, numeric string)").option("--gas-limit <n>", "Gas limit (EVM, numeric string)").option("--max-fee-per-gas <n>", "Max fee per gas (EVM EIP-1559)").option("--max-priority-fee-per-gas <n>", "Max priority fee per gas (EVM EIP-1559)").action(async (opts, cmd) => {
|
|
1154
1221
|
try {
|
|
1155
1222
|
validateChain(opts.chain);
|
|
1223
|
+
validateAddress(opts.from, opts.chain);
|
|
1156
1224
|
const inputToken = resolveCurrency(opts.inputToken, opts.chain);
|
|
1157
1225
|
const outputToken = resolveCurrency(opts.outputToken, opts.chain);
|
|
1158
1226
|
const client = createClient();
|
|
1227
|
+
const body = {
|
|
1228
|
+
dex: opts.dex ?? "jupiter",
|
|
1229
|
+
userAddress: opts.from,
|
|
1230
|
+
inputMint: inputToken,
|
|
1231
|
+
outputMint: outputToken,
|
|
1232
|
+
amount: opts.amount,
|
|
1233
|
+
swapMode: "ExactIn",
|
|
1234
|
+
slippage: Number(opts.slippage)
|
|
1235
|
+
};
|
|
1236
|
+
if (opts.recipient) body.recipientAddress = opts.recipient;
|
|
1237
|
+
if (opts.antiMev) body.isAntiMev = true;
|
|
1238
|
+
if (opts.gasPrice) body.gasPrice = opts.gasPrice;
|
|
1239
|
+
if (opts.gasLimit) body.gasLimit = opts.gasLimit;
|
|
1240
|
+
if (opts.maxFeePerGas) body.maxFeePerGas = opts.maxFeePerGas;
|
|
1241
|
+
if (opts.maxPriorityFeePerGas) body.maxPriorityFeePerGas = opts.maxPriorityFeePerGas;
|
|
1159
1242
|
const result = await callWithAutoPayment(
|
|
1160
|
-
() => client.dex.
|
|
1161
|
-
inputMint: inputToken,
|
|
1162
|
-
outputMint: outputToken,
|
|
1163
|
-
amount: opts.amount
|
|
1164
|
-
})
|
|
1243
|
+
() => client.dex.route(opts.chain, body)
|
|
1165
1244
|
);
|
|
1166
|
-
printResult(result,
|
|
1245
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1167
1246
|
} catch (err) {
|
|
1168
1247
|
exitOnError(err);
|
|
1169
1248
|
}
|
|
1170
1249
|
});
|
|
1171
|
-
dex.command("swap").description("
|
|
1250
|
+
dex.command("swap").description("Build unsigned swap transaction").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--from <address>", "Sender wallet address").requiredOption("--input-token <addr>", "Input token (address or SOL/ETH/BNB/USDC)").requiredOption("--output-token <addr>", "Output token (address or SOL/ETH/BNB/USDC)").requiredOption("--amount <amount>", "Input amount (smallest unit)").option("--slippage <n>", "Slippage tolerance (0-100, e.g. 5 = 5%)", "5").option("--dex <dex>", "Specific DEX protocol").action(async (opts, cmd) => {
|
|
1172
1251
|
try {
|
|
1173
1252
|
validateChain(opts.chain);
|
|
1174
1253
|
validateAddress(opts.from, opts.chain);
|
|
1175
|
-
if (opts.slippage) validateSlippage(Number(opts.slippage));
|
|
1176
1254
|
const inputToken = resolveCurrency(opts.inputToken, opts.chain);
|
|
1177
1255
|
const outputToken = resolveCurrency(opts.outputToken, opts.chain);
|
|
1178
|
-
const client =
|
|
1179
|
-
|
|
1180
|
-
const quote = await callWithAutoPayment(
|
|
1181
|
-
() => client.dex.quote(opts.chain, {
|
|
1182
|
-
inputMint: inputToken,
|
|
1183
|
-
outputMint: outputToken,
|
|
1184
|
-
amount: opts.amount
|
|
1185
|
-
})
|
|
1186
|
-
);
|
|
1187
|
-
process.stderr.write("\n--- Swap Summary ---\n");
|
|
1188
|
-
process.stderr.write(`Chain: ${opts.chain}
|
|
1189
|
-
`);
|
|
1190
|
-
process.stderr.write(`Input: ${inputToken}
|
|
1191
|
-
`);
|
|
1192
|
-
process.stderr.write(`Output: ${outputToken}
|
|
1193
|
-
`);
|
|
1194
|
-
process.stderr.write(`Amount: ${opts.amount}
|
|
1195
|
-
`);
|
|
1196
|
-
process.stderr.write(`Slippage: ${opts.slippage}
|
|
1197
|
-
`);
|
|
1198
|
-
process.stderr.write(`Quote: ${JSON.stringify(quote)}
|
|
1199
|
-
`);
|
|
1200
|
-
process.stderr.write("--------------------\n\n");
|
|
1201
|
-
if (!opts.yes) {
|
|
1202
|
-
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
1203
|
-
const answer = await rl.question("Confirm swap? (y/N): ");
|
|
1204
|
-
rl.close();
|
|
1205
|
-
if (answer.toLowerCase() !== "y") {
|
|
1206
|
-
process.stderr.write("Swap cancelled.\n");
|
|
1207
|
-
return;
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
process.stderr.write("Building transaction...\n");
|
|
1211
|
-
const swapResult = await callWithAutoPayment(
|
|
1256
|
+
const client = createClient();
|
|
1257
|
+
const result = await callWithAutoPayment(
|
|
1212
1258
|
() => client.dex.swap(opts.chain, {
|
|
1259
|
+
dex: opts.dex ?? "jupiter",
|
|
1213
1260
|
userAddress: opts.from,
|
|
1214
1261
|
inputMint: inputToken,
|
|
1215
1262
|
outputMint: outputToken,
|
|
1216
1263
|
amount: opts.amount,
|
|
1264
|
+
swapMode: "ExactIn",
|
|
1217
1265
|
slippage: Number(opts.slippage)
|
|
1218
1266
|
})
|
|
1219
1267
|
);
|
|
1220
|
-
|
|
1221
|
-
const { loadConfig: loadConfig2, getWalletMode: getWalletMode2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1222
|
-
const config = loadConfig2();
|
|
1223
|
-
const walletMode = getWalletMode2(config);
|
|
1224
|
-
if (!walletMode) throw new Error("Wallet required for swap.");
|
|
1225
|
-
const wallet = createWallet2(config, walletMode);
|
|
1226
|
-
process.stderr.write("Signing transaction...\n");
|
|
1227
|
-
const signedTx = await wallet.signTransaction(swapResult.serializedTx);
|
|
1228
|
-
process.stderr.write("Broadcasting transaction...\n");
|
|
1229
|
-
const sendResult = await client.transaction.send(opts.chain, {
|
|
1230
|
-
signedTx
|
|
1231
|
-
});
|
|
1232
|
-
if (sendResult.jobId) {
|
|
1233
|
-
process.stderr.write(`Job ${sendResult.jobId} submitted. Waiting for confirmation...
|
|
1234
|
-
`);
|
|
1235
|
-
const jobResult = await client.waitForJob(sendResult.jobId);
|
|
1236
|
-
const result = {
|
|
1237
|
-
...jobResult,
|
|
1238
|
-
explorer: explorerUrl(opts.chain, (sendResult.signature ?? jobResult.hash) || "")
|
|
1239
|
-
};
|
|
1240
|
-
printResult(result, opts.raw);
|
|
1241
|
-
} else {
|
|
1242
|
-
const result = {
|
|
1243
|
-
...sendResult,
|
|
1244
|
-
explorer: explorerUrl(opts.chain, sendResult.signature ?? "")
|
|
1245
|
-
};
|
|
1246
|
-
printResult(result, opts.raw);
|
|
1247
|
-
}
|
|
1268
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1248
1269
|
} catch (err) {
|
|
1249
1270
|
exitOnError(err);
|
|
1250
1271
|
}
|
|
1251
1272
|
});
|
|
1252
|
-
dex.command("create").description("
|
|
1273
|
+
dex.command("create").description("Build unsigned token creation transaction").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--from <address>", "Creator wallet address").requiredOption("--name <name>", "Token name").requiredOption("--symbol <symbol>", "Token symbol").option("--dex <dex>", "Launchpad: pumpfun/raydium", "pumpfun").option("--uri <uri>", "Metadata URI (IPFS/HTTP)").option("--image <url>", "Token image URL").action(async (opts, cmd) => {
|
|
1253
1274
|
try {
|
|
1254
1275
|
validateChain(opts.chain);
|
|
1255
|
-
|
|
1276
|
+
validateAddress(opts.from, opts.chain);
|
|
1277
|
+
const client = createClient();
|
|
1256
1278
|
const result = await callWithAutoPayment(
|
|
1257
1279
|
() => client.dex.createToken(opts.chain, {
|
|
1280
|
+
dex: opts.dex,
|
|
1281
|
+
userAddress: opts.from,
|
|
1258
1282
|
name: opts.name,
|
|
1259
1283
|
symbol: opts.symbol,
|
|
1260
1284
|
uri: opts.uri,
|
|
1261
|
-
|
|
1285
|
+
image: opts.image
|
|
1262
1286
|
})
|
|
1263
1287
|
);
|
|
1264
|
-
printResult(result,
|
|
1288
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1289
|
+
} catch (err) {
|
|
1290
|
+
exitOnError(err);
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
// src/commands/transaction.ts
|
|
1296
|
+
var EVM_ONLY_CHAINS = /* @__PURE__ */ new Set(["eth", "bsc"]);
|
|
1297
|
+
function validateEvmChain(chain) {
|
|
1298
|
+
validateChain(chain);
|
|
1299
|
+
if (!EVM_ONLY_CHAINS.has(chain)) {
|
|
1300
|
+
throw new Error(`Chain "${chain}" is not supported for this operation. Only EVM chains: ${[...EVM_ONLY_CHAINS].join(", ")}`);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
function registerTransactionCommands(program2) {
|
|
1304
|
+
const tx = program2.command("tx").description("Transaction broadcast, gas estimation");
|
|
1305
|
+
tx.command("send").description("Broadcast a signed transaction").requiredOption("--chain <chain>", "Chain: sol/bsc/eth").requiredOption("--signed-tx <base64>", "Base64-encoded signed transaction").option("--submit-type <type>", "Submit type: default/priority", "default").option("--anti-mev", "Enable anti-MEV protection").action(async (opts, cmd) => {
|
|
1306
|
+
try {
|
|
1307
|
+
validateChain(opts.chain);
|
|
1308
|
+
const client = createClient();
|
|
1309
|
+
const body = {
|
|
1310
|
+
signedTx: opts.signedTx
|
|
1311
|
+
};
|
|
1312
|
+
if (opts.submitType && opts.submitType !== "default") body.submitType = opts.submitType;
|
|
1313
|
+
if (opts.antiMev) body.options = { isAntiMev: true };
|
|
1314
|
+
const result = await callWithAutoPayment(
|
|
1315
|
+
() => client.transaction.send(opts.chain, body)
|
|
1316
|
+
);
|
|
1317
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1318
|
+
} catch (err) {
|
|
1319
|
+
exitOnError(err);
|
|
1320
|
+
}
|
|
1321
|
+
});
|
|
1322
|
+
tx.command("gas-price").description("Get current gas price (EVM only)").requiredOption("--chain <chain>", "Chain: eth/bsc").action(async (opts, cmd) => {
|
|
1323
|
+
try {
|
|
1324
|
+
validateEvmChain(opts.chain);
|
|
1325
|
+
const client = createClient();
|
|
1326
|
+
const result = await callWithAutoPayment(
|
|
1327
|
+
() => client.transaction.getGasPrice(opts.chain)
|
|
1328
|
+
);
|
|
1329
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1330
|
+
} catch (err) {
|
|
1331
|
+
exitOnError(err);
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
tx.command("estimate-gas").description("Estimate gas limit for a transaction (EVM only)").requiredOption("--chain <chain>", "Chain: eth/bsc").requiredOption("--from <address>", "From address").requiredOption("--to <address>", "To address").requiredOption("--data <hex>", "Transaction data (hex)").option("--value <hex>", "Value in wei (hex string)", "0x0").action(async (opts, cmd) => {
|
|
1335
|
+
try {
|
|
1336
|
+
validateEvmChain(opts.chain);
|
|
1337
|
+
const client = createClient();
|
|
1338
|
+
const body = {
|
|
1339
|
+
from: opts.from,
|
|
1340
|
+
to: opts.to,
|
|
1341
|
+
data: opts.data
|
|
1342
|
+
};
|
|
1343
|
+
if (opts.value && opts.value !== "0x0") body.value = opts.value;
|
|
1344
|
+
const result = await callWithAutoPayment(
|
|
1345
|
+
() => client.transaction.getGasLimit(opts.chain, body)
|
|
1346
|
+
);
|
|
1347
|
+
printResult(result, cmd.optsWithGlobals().json);
|
|
1265
1348
|
} catch (err) {
|
|
1266
1349
|
exitOnError(err);
|
|
1267
1350
|
}
|
|
@@ -1271,8 +1354,9 @@ function registerDexCommands(program2) {
|
|
|
1271
1354
|
// src/commands/job.ts
|
|
1272
1355
|
function registerJobCommands(program2) {
|
|
1273
1356
|
const job = program2.command("job").description("Job status polling");
|
|
1274
|
-
job.command("status").description("Check job status").requiredOption("--id <jobId>", "Job ID").option("--wait", "Wait for job completion via SSE").option("--timeout <ms>", "Wait timeout in milliseconds", "60000").
|
|
1357
|
+
job.command("status").description("Check job status").requiredOption("--id <jobId>", "Job ID").option("--wait", "Wait for job completion via SSE").option("--timeout <ms>", "Wait timeout in milliseconds", "60000").action(async (opts, cmd) => {
|
|
1275
1358
|
try {
|
|
1359
|
+
const json = cmd.optsWithGlobals().json;
|
|
1276
1360
|
const client = createClient();
|
|
1277
1361
|
if (opts.wait) {
|
|
1278
1362
|
process.stderr.write(`Waiting for job ${opts.id}...
|
|
@@ -1280,12 +1364,12 @@ function registerJobCommands(program2) {
|
|
|
1280
1364
|
const result = await callWithAutoPayment(
|
|
1281
1365
|
() => client.waitForJob(opts.id, Number(opts.timeout))
|
|
1282
1366
|
);
|
|
1283
|
-
printResult(result,
|
|
1367
|
+
printResult(result, json);
|
|
1284
1368
|
} else {
|
|
1285
1369
|
const result = await callWithAutoPayment(
|
|
1286
1370
|
() => client.job.get(opts.id)
|
|
1287
1371
|
);
|
|
1288
|
-
printResult(result,
|
|
1372
|
+
printResult(result, json);
|
|
1289
1373
|
}
|
|
1290
1374
|
} catch (err) {
|
|
1291
1375
|
exitOnError(err);
|
|
@@ -1354,7 +1438,7 @@ function saveKey(keyPair, profile = DEFAULT_PROFILE) {
|
|
|
1354
1438
|
// src/commands/auth.ts
|
|
1355
1439
|
init_turnkey();
|
|
1356
1440
|
init_constants();
|
|
1357
|
-
import * as
|
|
1441
|
+
import * as readline3 from "readline/promises";
|
|
1358
1442
|
async function resolveAndStoreAddresses(turnkeyCreds) {
|
|
1359
1443
|
process.stderr.write("Resolving wallet addresses...\n");
|
|
1360
1444
|
const [evmAddress, solanaAddress] = await Promise.all([
|
|
@@ -1384,14 +1468,22 @@ function registerAuthCommands(program2) {
|
|
|
1384
1468
|
exitOnError(err);
|
|
1385
1469
|
}
|
|
1386
1470
|
});
|
|
1387
|
-
program2.command("logout").description("Clear session (P-256 keys preserved)").action(() => {
|
|
1471
|
+
program2.command("logout").description("Clear session (P-256 keys preserved)").action((_opts, cmd) => {
|
|
1472
|
+
const json = cmd.optsWithGlobals().json;
|
|
1388
1473
|
const config = loadConfig();
|
|
1389
|
-
|
|
1474
|
+
const wasLoggedIn = !!config.turnkey;
|
|
1475
|
+
if (wasLoggedIn) {
|
|
1390
1476
|
updateConfig({ turnkey: void 0 });
|
|
1391
|
-
|
|
1392
|
-
|
|
1477
|
+
}
|
|
1478
|
+
if (json) {
|
|
1479
|
+
printResult({ success: true, wasLoggedIn }, true);
|
|
1393
1480
|
} else {
|
|
1394
|
-
|
|
1481
|
+
if (wasLoggedIn) {
|
|
1482
|
+
process.stdout.write("Logged out. P-256 keys preserved in ~/.config/chainstream/keys/\n");
|
|
1483
|
+
process.stdout.write("Run 'chainstream login' to re-authenticate.\n");
|
|
1484
|
+
} else {
|
|
1485
|
+
process.stdout.write("Not logged in via Turnkey.\n");
|
|
1486
|
+
}
|
|
1395
1487
|
}
|
|
1396
1488
|
});
|
|
1397
1489
|
program2.command("bind-email").description("Bind an email to your wallet (for account recovery)").argument("[email]", "Email address to bind").action(async (emailArg) => {
|
|
@@ -1552,7 +1644,7 @@ async function doKeyLogin() {
|
|
|
1552
1644
|
}
|
|
1553
1645
|
async function doEmailLogin(email) {
|
|
1554
1646
|
if (!email) {
|
|
1555
|
-
const rl2 =
|
|
1647
|
+
const rl2 = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
1556
1648
|
email = await rl2.question("Enter your email: ");
|
|
1557
1649
|
rl2.close();
|
|
1558
1650
|
if (!email?.trim()) throw new Error("Email required.");
|
|
@@ -1568,7 +1660,7 @@ async function doEmailLogin(email) {
|
|
|
1568
1660
|
`);
|
|
1569
1661
|
return;
|
|
1570
1662
|
}
|
|
1571
|
-
const rl =
|
|
1663
|
+
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
1572
1664
|
const code = await rl.question("Enter OTP code: ");
|
|
1573
1665
|
rl.close();
|
|
1574
1666
|
if (!code?.trim()) throw new Error("OTP code required.");
|
|
@@ -1617,7 +1709,7 @@ async function doBindEmail(email) {
|
|
|
1617
1709
|
throw new Error("No wallet found. Run 'chainstream login' first.");
|
|
1618
1710
|
}
|
|
1619
1711
|
if (!email) {
|
|
1620
|
-
const rl2 =
|
|
1712
|
+
const rl2 = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
1621
1713
|
email = await rl2.question("Enter email to bind: ");
|
|
1622
1714
|
rl2.close();
|
|
1623
1715
|
if (!email?.trim()) throw new Error("Email required.");
|
|
@@ -1633,7 +1725,7 @@ async function doBindEmail(email) {
|
|
|
1633
1725
|
`);
|
|
1634
1726
|
return;
|
|
1635
1727
|
}
|
|
1636
|
-
const rl =
|
|
1728
|
+
const rl = readline3.createInterface({ input: process.stdin, output: process.stderr });
|
|
1637
1729
|
const code = await rl.question("Enter verification code: ");
|
|
1638
1730
|
rl.close();
|
|
1639
1731
|
if (!code?.trim()) throw new Error("Verification code required.");
|
|
@@ -1654,70 +1746,60 @@ async function doBindEmail(email) {
|
|
|
1654
1746
|
init_config();
|
|
1655
1747
|
function registerConfigCommands(program2) {
|
|
1656
1748
|
const config = program2.command("config").description("Configuration management");
|
|
1657
|
-
config.command("set").description("Set a configuration value").requiredOption("--key <key>", "Config key (apiKey, baseUrl)").requiredOption("--value <value>", "Config value").action((opts) => {
|
|
1749
|
+
config.command("set").description("Set a configuration value").requiredOption("--key <key>", "Config key (apiKey, baseUrl)").requiredOption("--value <value>", "Config value").action((opts, cmd) => {
|
|
1658
1750
|
try {
|
|
1751
|
+
const json = cmd.optsWithGlobals().json;
|
|
1659
1752
|
const allowedKeys = ["apiKey", "baseUrl", "walletChain"];
|
|
1660
1753
|
if (!allowedKeys.includes(opts.key)) {
|
|
1661
1754
|
throw new Error(`Invalid key "${opts.key}". Allowed: ${allowedKeys.join(", ")}`);
|
|
1662
1755
|
}
|
|
1663
1756
|
updateConfig({ [opts.key]: opts.value });
|
|
1664
|
-
|
|
1665
|
-
`);
|
|
1757
|
+
printResult({ key: opts.key, value: opts.key === "apiKey" ? "(set)" : opts.value }, json);
|
|
1666
1758
|
} catch (err) {
|
|
1667
1759
|
exitOnError(err);
|
|
1668
1760
|
}
|
|
1669
1761
|
});
|
|
1670
|
-
config.command("get").description("Show configuration").option("--key <key>", "Specific key to show").action((opts) => {
|
|
1762
|
+
config.command("get").description("Show configuration").option("--key <key>", "Specific key to show").action((opts, cmd) => {
|
|
1671
1763
|
try {
|
|
1764
|
+
const json = cmd.optsWithGlobals().json;
|
|
1672
1765
|
const cfg = loadConfig();
|
|
1673
1766
|
if (opts.key) {
|
|
1674
1767
|
const value = cfg[opts.key];
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
`);
|
|
1678
|
-
} else if (opts.key === "apiKey" && typeof value === "string") {
|
|
1679
|
-
process.stdout.write(`${opts.key}: ${value.slice(0, 8)}...${value.slice(-4)}
|
|
1680
|
-
`);
|
|
1681
|
-
} else {
|
|
1682
|
-
process.stdout.write(`${opts.key}: ${JSON.stringify(value)}
|
|
1683
|
-
`);
|
|
1684
|
-
}
|
|
1768
|
+
const displayValue = value === void 0 ? null : opts.key === "apiKey" && typeof value === "string" ? `${value.slice(0, 8)}...${value.slice(-4)}` : value;
|
|
1769
|
+
printResult({ key: opts.key, value: displayValue }, json);
|
|
1685
1770
|
} else {
|
|
1686
1771
|
const display = {
|
|
1687
|
-
apiKey: cfg.apiKey ? `${cfg.apiKey.slice(0, 8)}...` :
|
|
1772
|
+
apiKey: cfg.apiKey ? `${cfg.apiKey.slice(0, 8)}...` : null,
|
|
1688
1773
|
baseUrl: cfg.baseUrl,
|
|
1689
|
-
walletMode: getWalletMode(cfg),
|
|
1690
|
-
|
|
1691
|
-
rawWallet: cfg.rawWallet ? { chain: cfg.rawWallet.chain } : void 0
|
|
1774
|
+
walletMode: getWalletMode(cfg) ?? null,
|
|
1775
|
+
walletChain: cfg.walletChain ?? null
|
|
1692
1776
|
};
|
|
1693
|
-
|
|
1777
|
+
printResult(display, json);
|
|
1694
1778
|
}
|
|
1695
1779
|
} catch (err) {
|
|
1696
1780
|
exitOnError(err);
|
|
1697
1781
|
}
|
|
1698
1782
|
});
|
|
1699
|
-
config.command("auth").description("Show current authentication status").action(() => {
|
|
1783
|
+
config.command("auth").description("Show current authentication status").action((_opts, cmd) => {
|
|
1700
1784
|
try {
|
|
1785
|
+
const json = cmd.optsWithGlobals().json;
|
|
1701
1786
|
const cfg = loadConfig();
|
|
1702
1787
|
const mode = getWalletMode(cfg);
|
|
1788
|
+
const status = { mode: mode ?? "none" };
|
|
1703
1789
|
if (mode === "turnkey") {
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1790
|
+
status.organizationId = cfg.turnkey.organizationId;
|
|
1791
|
+
status.evmAddress = cfg.turnkey.evmAddress ?? null;
|
|
1792
|
+
status.solanaAddress = cfg.turnkey.solanaAddress ?? null;
|
|
1707
1793
|
const expired = Date.now() > cfg.turnkey.sessionExpiry * 1e3;
|
|
1708
|
-
|
|
1709
|
-
|
|
1794
|
+
status.session = expired ? "expired" : "active";
|
|
1795
|
+
status.sessionExpiry = new Date(cfg.turnkey.sessionExpiry * 1e3).toISOString();
|
|
1710
1796
|
} else if (mode === "raw") {
|
|
1711
|
-
|
|
1712
|
-
`);
|
|
1797
|
+
status.chain = cfg.rawWallet.chain;
|
|
1713
1798
|
} else if (cfg.apiKey) {
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
} else {
|
|
1717
|
-
process.stdout.write("Auth: Not configured\n");
|
|
1718
|
-
process.stdout.write(" Run: chainstream login # Turnkey wallet\n");
|
|
1719
|
-
process.stdout.write(" Run: chainstream config set --key apiKey --value <key> # API key\n");
|
|
1799
|
+
status.mode = "apiKey";
|
|
1800
|
+
status.apiKey = `${cfg.apiKey.slice(0, 8)}...`;
|
|
1720
1801
|
}
|
|
1802
|
+
printResult(status, json);
|
|
1721
1803
|
} catch (err) {
|
|
1722
1804
|
exitOnError(err);
|
|
1723
1805
|
}
|
|
@@ -1726,11 +1808,12 @@ function registerConfigCommands(program2) {
|
|
|
1726
1808
|
|
|
1727
1809
|
// src/index.ts
|
|
1728
1810
|
var program = new Command();
|
|
1729
|
-
program.name("chainstream").version("0.
|
|
1811
|
+
program.name("chainstream").version("0.0.19").description("ChainStream CLI \u2014 on-chain data and DeFi execution for AI agents").option("--json", "Output as single-line JSON (machine-readable)");
|
|
1730
1812
|
registerTokenCommands(program);
|
|
1731
1813
|
registerMarketCommands(program);
|
|
1732
1814
|
registerWalletCommands(program);
|
|
1733
1815
|
registerDexCommands(program);
|
|
1816
|
+
registerTransactionCommands(program);
|
|
1734
1817
|
registerJobCommands(program);
|
|
1735
1818
|
registerAuthCommands(program);
|
|
1736
1819
|
registerConfigCommands(program);
|