@trustwallet/cli 0.18.0 → 0.19.1
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/automation-runner.d.ts +1 -1
- package/dist/automation-runner.d.ts.map +1 -1
- package/dist/commands/erc8183.d.ts.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/index.js +1145 -920
- package/package.json +13 -13
package/dist/index.js
CHANGED
|
@@ -3237,10 +3237,10 @@ function getChainDomainId(chainKey) {
|
|
|
3237
3237
|
if (!entry) throw new Error(`Unsupported chain: ${chainKey}`);
|
|
3238
3238
|
return entry[1].id;
|
|
3239
3239
|
}
|
|
3240
|
-
function getExplorerTxUrl(chainKey,
|
|
3240
|
+
function getExplorerTxUrl(chainKey, hash) {
|
|
3241
3241
|
const chain2 = getChainById(chainKey);
|
|
3242
3242
|
if (!chain2) return "";
|
|
3243
|
-
return `${chain2.explorerUrl}/tx/${
|
|
3243
|
+
return `${chain2.explorerUrl}/tx/${hash}`;
|
|
3244
3244
|
}
|
|
3245
3245
|
function getSampleAccount(chainKey) {
|
|
3246
3246
|
return getChainById(chainKey)?.sampleAccount || "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
|
|
@@ -3344,6 +3344,9 @@ function classifyApiError(err) {
|
|
|
3344
3344
|
return { code: "NETWORK_ERROR", message: err.message };
|
|
3345
3345
|
}
|
|
3346
3346
|
if (err instanceof TwakNetworkError) {
|
|
3347
|
+
if (EXECUTION_REVERTED_RE.test(err.message)) {
|
|
3348
|
+
return { code: "TX_FAILED", message: err.message };
|
|
3349
|
+
}
|
|
3347
3350
|
return { code: "NETWORK_ERROR", message: err.message };
|
|
3348
3351
|
}
|
|
3349
3352
|
if (err instanceof TwakValidationError) {
|
|
@@ -3355,6 +3358,9 @@ function classifyApiError(err) {
|
|
|
3355
3358
|
}
|
|
3356
3359
|
return { code: "NETWORK_ERROR", message: err.message };
|
|
3357
3360
|
}
|
|
3361
|
+
if (err instanceof Error && EXECUTION_REVERTED_RE.test(err.message)) {
|
|
3362
|
+
return { code: "TX_FAILED", message: err.message };
|
|
3363
|
+
}
|
|
3358
3364
|
return null;
|
|
3359
3365
|
}
|
|
3360
3366
|
function classifyStorageError(err) {
|
|
@@ -3729,7 +3735,7 @@ async function fetchBalance(httpClient, assetId, address, currency = "USD") {
|
|
|
3729
3735
|
throw new BalanceError("NETWORK_ERROR", "Could not fetch balance. Please try again later.");
|
|
3730
3736
|
}
|
|
3731
3737
|
}
|
|
3732
|
-
var import_crypto, NATIVE_TOKEN_ADDRESS, SOLANA_NATIVE_ADDRESS, CHAINS, TESTNET_CHAINS, COMMON_TOKENS, NATIVE_SYMBOLS, CELO_NATIVE_ADDRESS, TwakError, TwakApiError, TwakNetworkError, TwakValidationError, CommandError, COMMON_ERROR_CODES, FS_ERRNO_CODES, SWAP_ERROR_CODES, SwapError, TRANSFER_ERROR_CODES, TransferError, WALLET_ERROR_CODES, WalletError, QUERY_ERROR_CODES, QueryError, BALANCE_ERROR_CODES, BalanceError, ALERT_ERROR_CODES, AlertError, ERC20_ERROR_CODES, Erc20Error, WATCH_ERROR_CODES, WatchError, AUTOMATION_ERROR_CODES, AutomationError, X402_ERROR_CODES, X402Error, RESOLVABLE_CHAINS, ALIASES, DECIMAL_AMOUNT_RE, UNSAFE_KEYS, NAMING_API, EVM_ADDRESS_RE, ERC20_TRANSFER_SIG, ZERO_ADDRESS, DEFAULT_GATEWAY_URL, DEFAULT_MARKET_URL, DEFAULT_TIMEOUT, DEFAULT_USER_AGENT, DEFAULT_X_ORIGIN, TwakHttpClient, ALLOWED_OFFRAMP_PROVIDERS, McpResponse;
|
|
3738
|
+
var import_crypto, NATIVE_TOKEN_ADDRESS, SOLANA_NATIVE_ADDRESS, CHAINS, TESTNET_CHAINS, COMMON_TOKENS, NATIVE_SYMBOLS, CELO_NATIVE_ADDRESS, TwakError, TwakApiError, TwakNetworkError, TwakValidationError, CommandError, COMMON_ERROR_CODES, EXECUTION_REVERTED_RE, FS_ERRNO_CODES, SWAP_ERROR_CODES, SwapError, TRANSFER_ERROR_CODES, TransferError, WALLET_ERROR_CODES, WalletError, QUERY_ERROR_CODES, QueryError, BALANCE_ERROR_CODES, BalanceError, ALERT_ERROR_CODES, AlertError, ERC20_ERROR_CODES, Erc20Error, WATCH_ERROR_CODES, WatchError, AUTOMATION_ERROR_CODES, AutomationError, X402_ERROR_CODES, X402Error, RESOLVABLE_CHAINS, ALIASES, DECIMAL_AMOUNT_RE, UNSAFE_KEYS, NAMING_API, EVM_ADDRESS_RE, ERC20_TRANSFER_SIG, ZERO_ADDRESS, DEFAULT_GATEWAY_URL, DEFAULT_MARKET_URL, DEFAULT_TIMEOUT, DEFAULT_USER_AGENT, DEFAULT_X_ORIGIN, TwakHttpClient, ALLOWED_OFFRAMP_PROVIDERS, McpResponse;
|
|
3733
3739
|
var init_dist = __esm({
|
|
3734
3740
|
"../core/dist/index.mjs"() {
|
|
3735
3741
|
"use strict";
|
|
@@ -4230,6 +4236,7 @@ var init_dist = __esm({
|
|
|
4230
4236
|
WALLET_AUTH_FAILED: "WALLET_AUTH_FAILED",
|
|
4231
4237
|
STORAGE_ERROR: "STORAGE_ERROR"
|
|
4232
4238
|
};
|
|
4239
|
+
EXECUTION_REVERTED_RE = /\bexecution reverted\b/i;
|
|
4233
4240
|
FS_ERRNO_CODES = /* @__PURE__ */ new Set([
|
|
4234
4241
|
"EACCES",
|
|
4235
4242
|
"EEXIST",
|
|
@@ -6772,13 +6779,47 @@ function patchNodeStubs() {
|
|
|
6772
6779
|
if (resolvedUrl.includes("gateway.us.trustwallet.com")) {
|
|
6773
6780
|
resolvedUrl = resolvedUrl.replace("gateway.us.trustwallet.com", "tws.trustwallet.com");
|
|
6774
6781
|
}
|
|
6782
|
+
let finalInput = input2;
|
|
6775
6783
|
if (resolvedUrl !== url) {
|
|
6776
|
-
|
|
6777
|
-
return originalFetch(finalInput, init3);
|
|
6784
|
+
finalInput = typeof input2 === "string" ? resolvedUrl : input2 instanceof URL ? new URL(resolvedUrl) : new Request(resolvedUrl, input2);
|
|
6778
6785
|
}
|
|
6779
|
-
|
|
6786
|
+
const bodyText = typeof init3?.body === "string" ? init3.body : init3?.body instanceof Uint8Array ? new TextDecoder().decode(init3.body) : void 0;
|
|
6787
|
+
if (bodyText && /"method":"eth_(call|estimateGas|sendRawTransaction)"/.test(bodyText)) {
|
|
6788
|
+
return originalFetch(finalInput, init3).then(appendRpcRevertData);
|
|
6789
|
+
}
|
|
6790
|
+
return originalFetch(finalInput, init3);
|
|
6780
6791
|
};
|
|
6781
6792
|
}
|
|
6793
|
+
function revertDataSuffix(message, data) {
|
|
6794
|
+
return typeof data === "string" && /^0x[0-9a-fA-F]+$/.test(data) && !message.includes(data) ? `: ${data}` : "";
|
|
6795
|
+
}
|
|
6796
|
+
async function appendRpcRevertData(response) {
|
|
6797
|
+
const text = await response.text();
|
|
6798
|
+
let body = text;
|
|
6799
|
+
if (text.includes('"error"') && text.includes('"data":"0x')) {
|
|
6800
|
+
try {
|
|
6801
|
+
const json = JSON.parse(text);
|
|
6802
|
+
const error2 = json.error;
|
|
6803
|
+
if (error2 && typeof error2.message === "string") {
|
|
6804
|
+
const suffix = revertDataSuffix(error2.message, error2.data);
|
|
6805
|
+
if (suffix) {
|
|
6806
|
+
error2.message = `${error2.message}${suffix}`;
|
|
6807
|
+
body = JSON.stringify(json);
|
|
6808
|
+
}
|
|
6809
|
+
}
|
|
6810
|
+
} catch {
|
|
6811
|
+
}
|
|
6812
|
+
}
|
|
6813
|
+
const headers = new Headers(response.headers);
|
|
6814
|
+
if (body !== text) {
|
|
6815
|
+
headers.delete("content-length");
|
|
6816
|
+
}
|
|
6817
|
+
return new Response(body === "" ? null : body, {
|
|
6818
|
+
status: response.status,
|
|
6819
|
+
statusText: response.statusText,
|
|
6820
|
+
headers
|
|
6821
|
+
});
|
|
6822
|
+
}
|
|
6782
6823
|
function patchNaasSession(sessionId) {
|
|
6783
6824
|
if (naasSessionPatched) return;
|
|
6784
6825
|
naasSessionPatched = true;
|
|
@@ -7008,11 +7049,11 @@ function humanAmountToWei(amount, decimals = 18) {
|
|
|
7008
7049
|
const frac = parts[1].padEnd(decimals, "0").slice(0, decimals);
|
|
7009
7050
|
return whole * 10n ** BigInt(decimals) + BigInt(frac);
|
|
7010
7051
|
}
|
|
7011
|
-
function createPendingTransaction(client, chainKey,
|
|
7052
|
+
function createPendingTransaction(client, chainKey, hash) {
|
|
7012
7053
|
return {
|
|
7013
|
-
|
|
7054
|
+
hash,
|
|
7014
7055
|
chainKey,
|
|
7015
|
-
wait: (opts) => client.waitForReceipt(chainKey,
|
|
7056
|
+
wait: (opts) => client.waitForReceipt(chainKey, hash, opts)
|
|
7016
7057
|
};
|
|
7017
7058
|
}
|
|
7018
7059
|
function bscSponsoredBaseUrl() {
|
|
@@ -7433,7 +7474,7 @@ var init_dist3 = __esm({
|
|
|
7433
7474
|
* `receiptTimeoutMs` config when set, otherwise the global constants
|
|
7434
7475
|
* (1.5s poll, 60s timeout). Caller-supplied opts override both.
|
|
7435
7476
|
*/
|
|
7436
|
-
async waitForReceipt(chainKey,
|
|
7477
|
+
async waitForReceipt(chainKey, hash, opts) {
|
|
7437
7478
|
const { chain: chain2, chainConfig } = chainKeyToDefinedChain(chainKey);
|
|
7438
7479
|
if (chainConfig?.namespace && chainConfig.namespace !== "eip155") {
|
|
7439
7480
|
throw new TwakValidationError(
|
|
@@ -7459,15 +7500,15 @@ var init_dist3 = __esm({
|
|
|
7459
7500
|
const deadline = Date.now() + timeoutMs;
|
|
7460
7501
|
while (Date.now() < deadline) {
|
|
7461
7502
|
const remainingMs = Math.max(1, deadline - Date.now());
|
|
7462
|
-
const result = await this.postJsonRpc(rpcUrl, "eth_getTransactionReceipt", [
|
|
7503
|
+
const result = await this.postJsonRpc(rpcUrl, "eth_getTransactionReceipt", [hash], {
|
|
7463
7504
|
timeoutMs: Math.min(RPC_TIMEOUT_MS, remainingMs)
|
|
7464
7505
|
});
|
|
7465
7506
|
const receipt = result ?? null;
|
|
7466
7507
|
if (receipt) return receipt;
|
|
7467
7508
|
await new Promise((resolve2) => setTimeout(resolve2, pollMs));
|
|
7468
7509
|
}
|
|
7469
|
-
throw new TwakNetworkError(`Timed out waiting for receipt ${
|
|
7470
|
-
|
|
7510
|
+
throw new TwakNetworkError(`Timed out waiting for receipt ${hash} on ${chainKey}`, {
|
|
7511
|
+
hash,
|
|
7471
7512
|
chainKey
|
|
7472
7513
|
});
|
|
7473
7514
|
}
|
|
@@ -7505,7 +7546,8 @@ var init_dist3 = __esm({
|
|
|
7505
7546
|
throw new Error(`Unsupported chain: ${chainKey}`);
|
|
7506
7547
|
}
|
|
7507
7548
|
const ct5 = requireCoinType(coinId);
|
|
7508
|
-
|
|
7549
|
+
const payload = getChainById(chainKey)?.isEVM ? `0x${Buffer.from(message, "utf8").toString("hex")}` : message;
|
|
7550
|
+
return import_trust_sdk2.BlockchainService.signMessage(ct5, payload, import_trust_sdk2.MessageType.Message, privateKey);
|
|
7509
7551
|
}
|
|
7510
7552
|
async signTypedData(params) {
|
|
7511
7553
|
const coinId = chainKeyToCoinType(params.chainKey);
|
|
@@ -7558,13 +7600,13 @@ var init_dist3 = __esm({
|
|
|
7558
7600
|
currency: chainKey
|
|
7559
7601
|
};
|
|
7560
7602
|
}
|
|
7561
|
-
async findTransactionStatus(chainKey, address,
|
|
7603
|
+
async findTransactionStatus(chainKey, address, hash) {
|
|
7562
7604
|
const coinId = chainKeyToCoinType(chainKey);
|
|
7563
7605
|
if (coinId === void 0) throw new Error(`Unsupported chain: ${chainKey}`);
|
|
7564
7606
|
const account = this.createAccountForAddress(coinId, address);
|
|
7565
7607
|
let result;
|
|
7566
7608
|
try {
|
|
7567
|
-
result = await import_trust_sdk2.BlockchainService.findTransaction(account,
|
|
7609
|
+
result = await import_trust_sdk2.BlockchainService.findTransaction(account, hash);
|
|
7568
7610
|
} catch {
|
|
7569
7611
|
return { confirmed: false, pending: false, failed: false, error: "Transaction not found" };
|
|
7570
7612
|
}
|
|
@@ -7986,7 +8028,9 @@ var init_dist3 = __esm({
|
|
|
7986
8028
|
);
|
|
7987
8029
|
}
|
|
7988
8030
|
if (json.error) {
|
|
7989
|
-
|
|
8031
|
+
const { message, data } = json.error;
|
|
8032
|
+
const suffix = revertDataSuffix(message, data);
|
|
8033
|
+
throw new TwakNetworkError(`RPC error on ${method}: ${message}${suffix}`, {
|
|
7990
8034
|
method,
|
|
7991
8035
|
rpcUrl,
|
|
7992
8036
|
rpcError: json.error
|
|
@@ -8294,7 +8338,7 @@ var init_dist3 = __esm({
|
|
|
8294
8338
|
serializedMessage: params.data,
|
|
8295
8339
|
hdWallet
|
|
8296
8340
|
});
|
|
8297
|
-
return result2.
|
|
8341
|
+
return result2.hash;
|
|
8298
8342
|
}
|
|
8299
8343
|
if (hasCalldata || hasValue) {
|
|
8300
8344
|
const result2 = await this.blockchainClient.executeContract({
|
|
@@ -8305,7 +8349,7 @@ var init_dist3 = __esm({
|
|
|
8305
8349
|
hdWallet,
|
|
8306
8350
|
chainKey
|
|
8307
8351
|
});
|
|
8308
|
-
return result2.
|
|
8352
|
+
return result2.hash;
|
|
8309
8353
|
}
|
|
8310
8354
|
const result = await this.blockchainClient.transfer({
|
|
8311
8355
|
assetId,
|
|
@@ -8314,7 +8358,7 @@ var init_dist3 = __esm({
|
|
|
8314
8358
|
hdWallet,
|
|
8315
8359
|
chainKey
|
|
8316
8360
|
});
|
|
8317
|
-
return result.
|
|
8361
|
+
return result.hash;
|
|
8318
8362
|
}
|
|
8319
8363
|
supportsChain(chainId) {
|
|
8320
8364
|
return isChainSupported(chainId);
|
|
@@ -39400,12 +39444,13 @@ var WalletConnectProvider = class extends WalletProvider {
|
|
|
39400
39444
|
const session = this.getActiveSession();
|
|
39401
39445
|
if (!session) throw new WalletError("WC_NOT_CONNECTED", WC_NOT_CONNECTED_MSG);
|
|
39402
39446
|
const client = await this.ensureClient();
|
|
39447
|
+
const hexMessage = `0x${Buffer.from(message, "utf8").toString("hex")}`;
|
|
39403
39448
|
return client.request({
|
|
39404
39449
|
topic: session.topic,
|
|
39405
39450
|
chainId,
|
|
39406
39451
|
request: {
|
|
39407
39452
|
method: "personal_sign",
|
|
39408
|
-
params: [
|
|
39453
|
+
params: [hexMessage, this.resolveFromAddress(chainId)]
|
|
39409
39454
|
}
|
|
39410
39455
|
});
|
|
39411
39456
|
}
|
|
@@ -40603,762 +40648,139 @@ init_dist2();
|
|
|
40603
40648
|
var import_chalk6 = __toESM(require_source());
|
|
40604
40649
|
init_dist();
|
|
40605
40650
|
|
|
40606
|
-
//
|
|
40607
|
-
|
|
40608
|
-
|
|
40609
|
-
|
|
40610
|
-
|
|
40611
|
-
|
|
40612
|
-
|
|
40613
|
-
|
|
40614
|
-
|
|
40615
|
-
|
|
40616
|
-
|
|
40617
|
-
|
|
40618
|
-
" @@@@@@@@@@@@@@@@********++++++++ ",
|
|
40619
|
-
" @@@@@@@@@@@@@@@@**************++ ",
|
|
40620
|
-
" @@@@@@@@@@@@@@@@#####*********** ",
|
|
40621
|
-
" @@@@@@@@@@@@@@@###########**** ",
|
|
40622
|
-
" @@@@@@@@@@@@@@%############## ",
|
|
40623
|
-
" @@@@@@@@@@@@@@%%%%%%%####### ",
|
|
40624
|
-
" @@@@@@@@@@@@@%%%%%%%%%%%%% ",
|
|
40625
|
-
" @@@@@@@@@@@%%%%%%%%%%% ",
|
|
40626
|
-
" @@@@@@@@@@@@@%%%%% ",
|
|
40627
|
-
" @@@@@@@@@@@@@@ ",
|
|
40628
|
-
" @@@@@@@@@@ ",
|
|
40629
|
-
" @@ "
|
|
40630
|
-
];
|
|
40631
|
-
function printBanner(version3) {
|
|
40632
|
-
const logo = SHIELD.map((l4) => import_chalk5.default.green(l4)).join("\n");
|
|
40633
|
-
const title = import_chalk5.default.green.bold(" Trust Wallet Agent Kit");
|
|
40634
|
-
const ver = import_chalk5.default.dim(` v${version3}`);
|
|
40635
|
-
console.log(
|
|
40636
|
-
boxen(`${logo}
|
|
40637
|
-
|
|
40638
|
-
${title}
|
|
40639
|
-
${ver}`, {
|
|
40640
|
-
borderColor: "green",
|
|
40641
|
-
borderStyle: "round",
|
|
40642
|
-
padding: { top: 1, bottom: 1, left: 2, right: 2 }
|
|
40643
|
-
})
|
|
40644
|
-
);
|
|
40651
|
+
// ../contracts/dist/index.mjs
|
|
40652
|
+
init_dist();
|
|
40653
|
+
init_dist();
|
|
40654
|
+
init_dist();
|
|
40655
|
+
init_dist();
|
|
40656
|
+
init_dist3();
|
|
40657
|
+
init_dist();
|
|
40658
|
+
init_dist();
|
|
40659
|
+
init_dist();
|
|
40660
|
+
var HEX_PATTERN = /^0x[0-9a-fA-F]*$/;
|
|
40661
|
+
function isHex(value) {
|
|
40662
|
+
return HEX_PATTERN.test(value);
|
|
40645
40663
|
}
|
|
40646
|
-
function
|
|
40647
|
-
|
|
40648
|
-
|
|
40649
|
-
|
|
40650
|
-
|
|
40651
|
-
|
|
40664
|
+
function hexToBytes3(hex2) {
|
|
40665
|
+
if (!isHex(hex2)) {
|
|
40666
|
+
throw new TwakValidationError(`Invalid hex string: ${hex2}`, { kind: "invalidHex" });
|
|
40667
|
+
}
|
|
40668
|
+
const clean2 = hex2.slice(2);
|
|
40669
|
+
if (clean2.length % 2 !== 0) {
|
|
40670
|
+
throw new TwakValidationError(`Hex string has odd length: ${hex2}`, { kind: "invalidHex" });
|
|
40671
|
+
}
|
|
40672
|
+
const out = new Uint8Array(clean2.length / 2);
|
|
40673
|
+
for (let i2 = 0; i2 < out.length; i2++) {
|
|
40674
|
+
out[i2] = parseInt(clean2.slice(i2 * 2, i2 * 2 + 2), 16);
|
|
40675
|
+
}
|
|
40676
|
+
return out;
|
|
40652
40677
|
}
|
|
40653
|
-
|
|
40654
|
-
|
|
40655
|
-
|
|
40656
|
-
|
|
40657
|
-
const qrcode = require("qrcode-terminal");
|
|
40658
|
-
let result = "";
|
|
40659
|
-
qrcode.generate(address, { small: true }, (code2) => {
|
|
40660
|
-
result = code2;
|
|
40661
|
-
});
|
|
40662
|
-
return result;
|
|
40663
|
-
} catch {
|
|
40664
|
-
return "";
|
|
40678
|
+
function bytesToHex3(bytes) {
|
|
40679
|
+
let out = "0x";
|
|
40680
|
+
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
40681
|
+
out += bytes[i2].toString(16).padStart(2, "0");
|
|
40665
40682
|
}
|
|
40683
|
+
return out;
|
|
40666
40684
|
}
|
|
40667
|
-
function
|
|
40668
|
-
const
|
|
40669
|
-
|
|
40670
|
-
|
|
40671
|
-
|
|
40672
|
-
|
|
40673
|
-
|
|
40674
|
-
|
|
40675
|
-
|
|
40676
|
-
}
|
|
40677
|
-
await ensureTrustSDK();
|
|
40678
|
-
const store = new WalletConfigStore();
|
|
40679
|
-
if (await store.exists()) {
|
|
40680
|
-
throw new WalletError(
|
|
40681
|
-
"WALLET_EXISTS",
|
|
40682
|
-
"Wallet already exists. Back up ~/.twak/wallet.json, then delete it to create a new one."
|
|
40683
|
-
);
|
|
40684
|
-
}
|
|
40685
|
-
const provider = await AgentWalletProvider.create(opts.password);
|
|
40686
|
-
const addresses = await provider.getAddresses();
|
|
40687
|
-
if (opts.keychain !== false) {
|
|
40688
|
-
const kc2 = new KeychainManager();
|
|
40689
|
-
if (kc2.isAvailable()) {
|
|
40690
|
-
await kc2.saveWalletPassword(opts.password);
|
|
40691
|
-
if (!opts.json) info("Password saved to OS keychain (use --no-keychain to skip)");
|
|
40692
|
-
}
|
|
40693
|
-
}
|
|
40694
|
-
if (!opts.json) success("Agent wallet created successfully");
|
|
40695
|
-
try {
|
|
40696
|
-
const creds = await getCredentials();
|
|
40697
|
-
await registerWalletWithBackend(creds, provider);
|
|
40698
|
-
if (!opts.json) info("Wallet registered with backend");
|
|
40699
|
-
} catch {
|
|
40700
|
-
if (!opts.json) warn("Backend registration failed (holdings may be limited)");
|
|
40701
|
-
}
|
|
40702
|
-
if (opts.json) {
|
|
40703
|
-
output({ addresses }, true);
|
|
40704
|
-
} else {
|
|
40705
|
-
info(`Generated addresses for ${addresses.length} chains`);
|
|
40706
|
-
}
|
|
40707
|
-
} catch (err) {
|
|
40708
|
-
handleCommandError(err, opts.json, "Wallet creation failed");
|
|
40709
|
-
}
|
|
40710
|
-
safeExit();
|
|
40711
|
-
});
|
|
40712
|
-
wallet.command("address").description("Get wallet address for a chain").requiredOption("--chain <key>", "Chain key (e.g., ethereum, solana)").option(
|
|
40713
|
-
"--password <password>",
|
|
40714
|
-
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
40715
|
-
).option("--json", "JSON output").action(async (opts) => {
|
|
40716
|
-
try {
|
|
40717
|
-
if (!getChainById(opts.chain)) {
|
|
40718
|
-
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
40719
|
-
}
|
|
40720
|
-
await ensureTrustSDK();
|
|
40721
|
-
const password3 = await resolvePassword(opts);
|
|
40722
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
40723
|
-
const address = await provider.getAddress(opts.chain);
|
|
40724
|
-
if (opts.json) {
|
|
40725
|
-
output({ chain: opts.chain, address }, true);
|
|
40726
|
-
} else {
|
|
40727
|
-
const qr3 = getQRString(address);
|
|
40728
|
-
const content = `${import_chalk6.default.dim("Chain")} ${import_chalk6.default.bold(opts.chain)}
|
|
40729
|
-
${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
|
|
40730
|
-
|
|
40731
|
-
${qr3}`;
|
|
40732
|
-
console.log(box(content));
|
|
40733
|
-
}
|
|
40734
|
-
} catch (err) {
|
|
40735
|
-
handleCommandError(err, opts.json, "Wallet address failed");
|
|
40736
|
-
}
|
|
40737
|
-
safeExit();
|
|
40738
|
-
});
|
|
40739
|
-
wallet.command("addresses").description("List all wallet addresses").option(
|
|
40740
|
-
"--password <password>",
|
|
40741
|
-
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
40742
|
-
).option("--json", "JSON output").action(async (opts) => {
|
|
40743
|
-
try {
|
|
40744
|
-
await ensureTrustSDK();
|
|
40745
|
-
const password3 = await resolvePassword(opts);
|
|
40746
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
40747
|
-
const addresses = await provider.getAddresses();
|
|
40748
|
-
if (opts.json) {
|
|
40749
|
-
output({ addresses }, true);
|
|
40750
|
-
} else {
|
|
40751
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
40752
|
-
for (const addr of addresses) {
|
|
40753
|
-
const chains = grouped.get(addr.address) ?? [];
|
|
40754
|
-
chains.push(addr.chainId);
|
|
40755
|
-
grouped.set(addr.address, chains);
|
|
40756
|
-
}
|
|
40757
|
-
for (const [address, chains] of grouped) {
|
|
40758
|
-
const qr3 = getQRString(address);
|
|
40759
|
-
const maxWidth = Math.max(address.length + 9, 50);
|
|
40760
|
-
const chainLabel = `${import_chalk6.default.dim("Chains")} `;
|
|
40761
|
-
const chainLabelLen = 9;
|
|
40762
|
-
const chainLines = [];
|
|
40763
|
-
let line = "";
|
|
40764
|
-
for (const c3 of chains) {
|
|
40765
|
-
const sep2 = line ? ", " : "";
|
|
40766
|
-
if (line && line.length + sep2.length + c3.length + chainLabelLen > maxWidth) {
|
|
40767
|
-
chainLines.push(line);
|
|
40768
|
-
line = c3;
|
|
40769
|
-
} else {
|
|
40770
|
-
line += sep2 + c3;
|
|
40771
|
-
}
|
|
40772
|
-
}
|
|
40773
|
-
if (line) chainLines.push(line);
|
|
40774
|
-
const chainsStr = chainLines.map((l4, i2) => (i2 === 0 ? chainLabel : " ".repeat(chainLabelLen)) + import_chalk6.default.bold(l4)).join("\n");
|
|
40775
|
-
const content = `${chainsStr}
|
|
40776
|
-
${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
|
|
40777
|
-
|
|
40778
|
-
${qr3}`;
|
|
40779
|
-
console.log(box(content));
|
|
40780
|
-
}
|
|
40781
|
-
}
|
|
40782
|
-
} catch (err) {
|
|
40783
|
-
handleCommandError(err, opts.json, "Wallet addresses failed");
|
|
40685
|
+
function hexOrUtf8ToBytesHex(value) {
|
|
40686
|
+
const looksHex = value.length >= 2 && value[0] === "0" && (value[1] === "x" || value[1] === "X");
|
|
40687
|
+
if (looksHex) {
|
|
40688
|
+
const canonical = "0x" + value.slice(2);
|
|
40689
|
+
if (!isHex(canonical)) {
|
|
40690
|
+
throw new TwakValidationError(
|
|
40691
|
+
`Value starts with "0x" but is not valid hex: ${value}. Use only [0-9a-fA-F] characters, or drop the "0x" prefix to send a UTF-8 string.`,
|
|
40692
|
+
{ kind: "invalidHex" }
|
|
40693
|
+
);
|
|
40784
40694
|
}
|
|
40785
|
-
|
|
40786
|
-
|
|
40787
|
-
|
|
40788
|
-
|
|
40789
|
-
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
40790
|
-
).option("--no-tokens", "Skip token balance lookup").option("--json", "JSON output").action(async (opts) => {
|
|
40791
|
-
try {
|
|
40792
|
-
if (opts.all && opts.chain) {
|
|
40793
|
-
throw new WalletError("VALIDATION_ERROR", "--all and --chain are mutually exclusive");
|
|
40794
|
-
}
|
|
40795
|
-
if (!opts.all && !opts.chain) {
|
|
40796
|
-
throw new WalletError("VALIDATION_ERROR", "Provide --chain <key> or --all");
|
|
40797
|
-
}
|
|
40798
|
-
await ensureTrustSDK();
|
|
40799
|
-
const password3 = await resolvePassword(opts);
|
|
40800
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
40801
|
-
const httpClient = await getClient();
|
|
40802
|
-
if (!opts.all) {
|
|
40803
|
-
const chain2 = getChainById(opts.chain);
|
|
40804
|
-
if (!chain2) {
|
|
40805
|
-
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
40806
|
-
}
|
|
40807
|
-
}
|
|
40808
|
-
const allAddresses = await provider.getAddresses();
|
|
40809
|
-
const addressMap = /* @__PURE__ */ new Map();
|
|
40810
|
-
for (const a3 of allAddresses) addressMap.set(a3.chainId, a3.address);
|
|
40811
|
-
const requestedChains = opts.all ? Object.keys(CHAINS) : [opts.chain];
|
|
40812
|
-
const skipTokens = opts.tokens === false;
|
|
40813
|
-
const chainEntries = requestedChains.flatMap((chainKey) => {
|
|
40814
|
-
const chain2 = getChainById(chainKey);
|
|
40815
|
-
const address = addressMap.get(chainKey);
|
|
40816
|
-
if (!chain2 || !address) return [];
|
|
40817
|
-
return [{ chainKey, chain: chain2, address }];
|
|
40818
|
-
});
|
|
40819
|
-
if (!opts.all && chainEntries.length === 0) {
|
|
40820
|
-
throw new WalletError(
|
|
40821
|
-
"CHAIN_UNSUPPORTED",
|
|
40822
|
-
`Wallet does not have an address for chain: ${opts.chain}`
|
|
40823
|
-
);
|
|
40824
|
-
}
|
|
40825
|
-
const nativeAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
|
|
40826
|
-
chainKey,
|
|
40827
|
-
chain: chain2,
|
|
40828
|
-
token: void 0,
|
|
40829
|
-
assetId: `c${chain2.coinId}`,
|
|
40830
|
-
userAddress: address
|
|
40831
|
-
}));
|
|
40832
|
-
const tokenAssets = skipTokens ? [] : chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
|
|
40833
|
-
const knownTokens = COMMON_TOKENS[chainKey];
|
|
40834
|
-
if (!knownTokens) return [];
|
|
40835
|
-
return Object.keys(knownTokens).flatMap((sym) => {
|
|
40836
|
-
const resolved = resolveToken(sym, chainKey);
|
|
40837
|
-
if (!resolved) return [];
|
|
40838
|
-
return [
|
|
40839
|
-
{
|
|
40840
|
-
chainKey,
|
|
40841
|
-
chain: chain2,
|
|
40842
|
-
token: { ...resolved, symbol: sym },
|
|
40843
|
-
assetId: `c${chain2.coinId}_t${resolved.address}`,
|
|
40844
|
-
userAddress: address
|
|
40845
|
-
}
|
|
40846
|
-
];
|
|
40847
|
-
});
|
|
40848
|
-
});
|
|
40849
|
-
const allAssets = [...nativeAssets, ...tokenAssets];
|
|
40850
|
-
const balances = await fetchBalances(
|
|
40851
|
-
httpClient,
|
|
40852
|
-
allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
|
|
40695
|
+
if ((canonical.length - 2) % 2 !== 0) {
|
|
40696
|
+
throw new TwakValidationError(
|
|
40697
|
+
`Hex value has odd length: ${value}. Solidity bytes must be byte-aligned.`,
|
|
40698
|
+
{ kind: "invalidHex" }
|
|
40853
40699
|
);
|
|
40854
|
-
const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
|
|
40855
|
-
const resultsByChain = /* @__PURE__ */ new Map();
|
|
40856
|
-
for (const { chainKey, chain: chain2, address } of chainEntries) {
|
|
40857
|
-
resultsByChain.set(chainKey, {
|
|
40858
|
-
chain: chainKey,
|
|
40859
|
-
address,
|
|
40860
|
-
symbol: chain2.symbol,
|
|
40861
|
-
available: "0",
|
|
40862
|
-
total: "0",
|
|
40863
|
-
totalUsd: null,
|
|
40864
|
-
tokens: []
|
|
40865
|
-
});
|
|
40866
|
-
}
|
|
40867
|
-
for (const balance of balances) {
|
|
40868
|
-
const assetInfo = assetsById.get(balance.assetId);
|
|
40869
|
-
if (!assetInfo) {
|
|
40870
|
-
throw new WalletError(
|
|
40871
|
-
"NETWORK_ERROR",
|
|
40872
|
-
"Could not fetch balances. Please try again later."
|
|
40873
|
-
);
|
|
40874
|
-
}
|
|
40875
|
-
const result = resultsByChain.get(assetInfo.chainKey);
|
|
40876
|
-
if (!result) continue;
|
|
40877
|
-
const { token, chain: chain2 } = assetInfo;
|
|
40878
|
-
const amts = balance.amounts;
|
|
40879
|
-
if (token) {
|
|
40880
|
-
const human = formatAmount(amts.total ?? "0", token.decimals);
|
|
40881
|
-
if (human !== "0") {
|
|
40882
|
-
result.tokens.push({
|
|
40883
|
-
symbol: token.symbol,
|
|
40884
|
-
contract: token.address,
|
|
40885
|
-
balance: human
|
|
40886
|
-
});
|
|
40887
|
-
}
|
|
40888
|
-
} else {
|
|
40889
|
-
result.available = formatAmount(amts.available ?? "0", chain2.decimals);
|
|
40890
|
-
result.total = formatAmount(amts.total ?? "0", chain2.decimals);
|
|
40891
|
-
const lockedHuman = formatAmount(amts.locked ?? "0", chain2.decimals);
|
|
40892
|
-
if (lockedHuman !== "0") result.staked = lockedHuman;
|
|
40893
|
-
const fiat = amts.totalInFiat;
|
|
40894
|
-
result.totalUsd = fiat && fiat !== "" ? parseFloat(fiat) : null;
|
|
40895
|
-
}
|
|
40896
|
-
}
|
|
40897
|
-
const orderedResults = chainEntries.map((e2) => resultsByChain.get(e2.chainKey)).filter((r3) => r3 !== void 0);
|
|
40898
|
-
const visible = opts.all ? orderedResults.filter((r3) => r3.total !== "0" || r3.tokens.length > 0) : orderedResults;
|
|
40899
|
-
const renderBlock = (r3, withSeparator) => {
|
|
40900
|
-
if (withSeparator) console.log("");
|
|
40901
|
-
console.log(import_chalk6.default.bold.underline(`${r3.chain} (${r3.symbol})`));
|
|
40902
|
-
console.log(` ${import_chalk6.default.dim("Address")} ${r3.address}`);
|
|
40903
|
-
console.log(` ${import_chalk6.default.dim("Available")} ${r3.available}`);
|
|
40904
|
-
if (r3.staked) console.log(` ${import_chalk6.default.dim("Staked")} ${r3.staked}`);
|
|
40905
|
-
const usdSuffix = r3.totalUsd !== null ? ` (\u2248 $${r3.totalUsd.toFixed(2)})` : "";
|
|
40906
|
-
console.log(` ${import_chalk6.default.dim("Total")} ${r3.total}${usdSuffix}`);
|
|
40907
|
-
if (r3.tokens.length > 0) {
|
|
40908
|
-
console.log(` ${import_chalk6.default.dim("Tokens:")}`);
|
|
40909
|
-
for (const t of r3.tokens) {
|
|
40910
|
-
console.log(` ${import_chalk6.default.bold(t.symbol.padEnd(10))} ${t.balance}`);
|
|
40911
|
-
}
|
|
40912
|
-
}
|
|
40913
|
-
};
|
|
40914
|
-
if (opts.all) {
|
|
40915
|
-
if (opts.json) {
|
|
40916
|
-
output(visible, true);
|
|
40917
|
-
} else if (visible.length === 0) {
|
|
40918
|
-
info("No chains with non-zero native balance found.");
|
|
40919
|
-
} else {
|
|
40920
|
-
visible.forEach((r3, i2) => renderBlock(r3, i2 > 0));
|
|
40921
|
-
}
|
|
40922
|
-
} else {
|
|
40923
|
-
const single = visible[0];
|
|
40924
|
-
if (opts.json) {
|
|
40925
|
-
output(single, true);
|
|
40926
|
-
} else {
|
|
40927
|
-
renderBlock(single, false);
|
|
40928
|
-
}
|
|
40929
|
-
}
|
|
40930
|
-
} catch (err) {
|
|
40931
|
-
handleCommandError(err, opts.json, "Balance check failed");
|
|
40932
40700
|
}
|
|
40933
|
-
|
|
40934
|
-
}
|
|
40935
|
-
|
|
40936
|
-
|
|
40937
|
-
|
|
40938
|
-
|
|
40939
|
-
|
|
40940
|
-
|
|
40941
|
-
|
|
40942
|
-
|
|
40943
|
-
|
|
40944
|
-
|
|
40945
|
-
handleCommandError(err, opts.json, "Keychain save failed");
|
|
40701
|
+
return canonical;
|
|
40702
|
+
}
|
|
40703
|
+
return bytesToHex3(new TextEncoder().encode(value));
|
|
40704
|
+
}
|
|
40705
|
+
function wc2() {
|
|
40706
|
+
return getWalletCore();
|
|
40707
|
+
}
|
|
40708
|
+
var BRIDGE = {
|
|
40709
|
+
createAbiFunction(name2) {
|
|
40710
|
+
const ctor = wc2().EthereumAbiFunction;
|
|
40711
|
+
if (typeof ctor?.createWithString === "function") {
|
|
40712
|
+
return ctor.createWithString(name2);
|
|
40946
40713
|
}
|
|
40947
|
-
|
|
40714
|
+
return new ctor(name2);
|
|
40715
|
+
},
|
|
40716
|
+
encode(fn2) {
|
|
40717
|
+
return wc2().EthereumAbi.encode(fn2);
|
|
40718
|
+
},
|
|
40719
|
+
decodeOutput(fn2, data) {
|
|
40720
|
+
return wc2().EthereumAbi.decodeOutput(fn2, data);
|
|
40721
|
+
},
|
|
40722
|
+
keccak256(data) {
|
|
40723
|
+
return wc2().Hash.keccak256(data);
|
|
40724
|
+
}
|
|
40725
|
+
};
|
|
40726
|
+
function getAbiBridge() {
|
|
40727
|
+
return BRIDGE;
|
|
40728
|
+
}
|
|
40729
|
+
function findAbiFunction(abi, methodName, argCount) {
|
|
40730
|
+
const matches = abi.filter(
|
|
40731
|
+
(e2) => e2.type === "function" && e2.name === methodName
|
|
40732
|
+
);
|
|
40733
|
+
if (matches.length === 0) {
|
|
40734
|
+
throw new TwakValidationError(`Unknown ABI method: ${methodName}`, {
|
|
40735
|
+
kind: "unknownMethod",
|
|
40736
|
+
methodName
|
|
40737
|
+
});
|
|
40738
|
+
}
|
|
40739
|
+
if (matches.length === 1 || argCount === void 0) {
|
|
40740
|
+
return matches[0];
|
|
40741
|
+
}
|
|
40742
|
+
const byArity = matches.filter((m2) => m2.inputs.length === argCount);
|
|
40743
|
+
if (byArity.length === 1) {
|
|
40744
|
+
return byArity[0];
|
|
40745
|
+
}
|
|
40746
|
+
throw new TwakValidationError(`No unique ${methodName} overload taking ${argCount} argument(s)`, {
|
|
40747
|
+
kind: "unknownMethod",
|
|
40748
|
+
methodName
|
|
40948
40749
|
});
|
|
40949
|
-
|
|
40950
|
-
|
|
40951
|
-
|
|
40952
|
-
|
|
40953
|
-
|
|
40750
|
+
}
|
|
40751
|
+
function encodeFunctionCall(abi, methodName, args) {
|
|
40752
|
+
const fnDef = findAbiFunction(abi, methodName, args.length);
|
|
40753
|
+
if (args.length !== fnDef.inputs.length) {
|
|
40754
|
+
throw new TwakValidationError(
|
|
40755
|
+
`Wrong arg count for ${methodName}: expected ${fnDef.inputs.length}, got ${args.length}`,
|
|
40756
|
+
{
|
|
40757
|
+
kind: "wrongArgCount",
|
|
40758
|
+
methodName,
|
|
40759
|
+
expected: fnDef.inputs.length,
|
|
40760
|
+
actual: args.length
|
|
40954
40761
|
}
|
|
40955
|
-
|
|
40956
|
-
|
|
40957
|
-
|
|
40958
|
-
|
|
40959
|
-
|
|
40960
|
-
|
|
40762
|
+
);
|
|
40763
|
+
}
|
|
40764
|
+
if (encoderRequiresHandRoll(fnDef.inputs)) {
|
|
40765
|
+
return encodeFunctionCallHandRoll(methodName, fnDef.inputs, args);
|
|
40766
|
+
}
|
|
40767
|
+
const bridge = getAbiBridge();
|
|
40768
|
+
const fn2 = bridge.createAbiFunction(methodName);
|
|
40769
|
+
fnDef.inputs.forEach((param, i2) => {
|
|
40770
|
+
pushParam(fn2, param, args[i2], methodName);
|
|
40961
40771
|
});
|
|
40962
|
-
|
|
40963
|
-
|
|
40964
|
-
|
|
40965
|
-
|
|
40966
|
-
|
|
40967
|
-
|
|
40968
|
-
|
|
40969
|
-
|
|
40970
|
-
|
|
40971
|
-
|
|
40972
|
-
|
|
40973
|
-
|
|
40974
|
-
const pw = await kc2.getWalletPassword();
|
|
40975
|
-
if (opts.json) {
|
|
40976
|
-
output({ available: true, stored: !!pw }, true);
|
|
40977
|
-
} else if (pw) {
|
|
40978
|
-
success("Wallet password is stored in OS keychain");
|
|
40979
|
-
} else {
|
|
40980
|
-
info("No wallet password found in OS keychain");
|
|
40981
|
-
}
|
|
40982
|
-
} catch (err) {
|
|
40983
|
-
handleCommandError(err, opts.json, "Keychain check failed");
|
|
40984
|
-
}
|
|
40985
|
-
safeExit();
|
|
40986
|
-
});
|
|
40987
|
-
wallet.command("connect").description("Connect external wallet via WalletConnect").option("--project-id <id>", "WalletConnect project ID (or set WALLETCONNECT_PROJECT_ID)").option(
|
|
40988
|
-
"--chains <list>",
|
|
40989
|
-
"Comma-separated CAIP-2 chain IDs",
|
|
40990
|
-
"eip155:1,eip155:56,eip155:137,eip155:8453,eip155:42161"
|
|
40991
|
-
).option("--timeout <seconds>", "Connection timeout in seconds", "300").option("--json", "JSON output").action(async (opts) => {
|
|
40992
|
-
try {
|
|
40993
|
-
const projectId = opts.projectId || process.env.WALLETCONNECT_PROJECT_ID;
|
|
40994
|
-
if (!projectId) {
|
|
40995
|
-
throw new WalletError(
|
|
40996
|
-
"VALIDATION_ERROR",
|
|
40997
|
-
"WalletConnect project ID required. Use --project-id or set WALLETCONNECT_PROJECT_ID"
|
|
40998
|
-
);
|
|
40999
|
-
}
|
|
41000
|
-
const provider = new WalletConnectProvider({ projectId });
|
|
41001
|
-
const chains = opts.chains.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
41002
|
-
info("Connecting via WalletConnect...");
|
|
41003
|
-
const result = await provider.connect(chains);
|
|
41004
|
-
const qr3 = getQRString(result.uri);
|
|
41005
|
-
if (qr3) {
|
|
41006
|
-
console.log(qr3);
|
|
41007
|
-
}
|
|
41008
|
-
info(`Trust Wallet: ${result.deepLinks.native}`);
|
|
41009
|
-
info(`Universal: ${result.deepLinks.universal}`);
|
|
41010
|
-
info("\nWaiting for wallet approval...");
|
|
41011
|
-
const timeoutMs = parseInt(opts.timeout, 10) * 1e3;
|
|
41012
|
-
const session = await provider.waitForSession(timeoutMs);
|
|
41013
|
-
if (opts.json) {
|
|
41014
|
-
output(
|
|
41015
|
-
{
|
|
41016
|
-
connected: true,
|
|
41017
|
-
address: session.address,
|
|
41018
|
-
chainId: session.chainId,
|
|
41019
|
-
peer: session.peerName
|
|
41020
|
-
},
|
|
41021
|
-
true
|
|
41022
|
-
);
|
|
41023
|
-
} else {
|
|
41024
|
-
success(`Connected to ${session.peerName || "wallet"}`);
|
|
41025
|
-
info(` Address: ${session.address}`);
|
|
41026
|
-
info(` Chain: ${session.chainId}`);
|
|
41027
|
-
}
|
|
41028
|
-
} catch (err) {
|
|
41029
|
-
handleCommandError(err, opts.json, "WalletConnect failed");
|
|
41030
|
-
}
|
|
41031
|
-
safeExit();
|
|
41032
|
-
});
|
|
41033
|
-
wallet.command("status").description("Check wallet configuration status").option("--json", "JSON output").action(async (opts) => {
|
|
41034
|
-
try {
|
|
41035
|
-
const store = new WalletConfigStore();
|
|
41036
|
-
const exists = await store.exists();
|
|
41037
|
-
const kc2 = new KeychainManager();
|
|
41038
|
-
const keychainHasPassword = kc2.isAvailable() ? !!await kc2.getWalletPassword() : false;
|
|
41039
|
-
const totalChains = Object.keys(CHAINS).length;
|
|
41040
|
-
let createdAt;
|
|
41041
|
-
let addressCount;
|
|
41042
|
-
if (exists) {
|
|
41043
|
-
const config = await store.getConfig();
|
|
41044
|
-
createdAt = config?.createdAt;
|
|
41045
|
-
addressCount = config?.chains?.length ?? totalChains;
|
|
41046
|
-
}
|
|
41047
|
-
const result = {
|
|
41048
|
-
agentWallet: exists ? "configured" : "not configured",
|
|
41049
|
-
keychainPassword: keychainHasPassword ? "stored" : "not stored",
|
|
41050
|
-
chains: totalChains,
|
|
41051
|
-
supportedChains: totalChains,
|
|
41052
|
-
...createdAt ? { createdAt } : {},
|
|
41053
|
-
...addressCount !== void 0 ? { addressCount } : {}
|
|
41054
|
-
};
|
|
41055
|
-
if (opts.json) {
|
|
41056
|
-
output(result, true);
|
|
41057
|
-
} else {
|
|
41058
|
-
console.log(
|
|
41059
|
-
` ${import_chalk6.default.dim("Wallet")} ${exists ? import_chalk6.default.green("configured") : import_chalk6.default.yellow("not configured")}`
|
|
41060
|
-
);
|
|
41061
|
-
if (createdAt) console.log(` ${import_chalk6.default.dim("Created")} ${createdAt}`);
|
|
41062
|
-
console.log(
|
|
41063
|
-
` ${import_chalk6.default.dim("Keychain")} ${keychainHasPassword ? import_chalk6.default.green("password stored") : import_chalk6.default.yellow("no password")}`
|
|
41064
|
-
);
|
|
41065
|
-
console.log(` ${import_chalk6.default.dim("Chains")} ${totalChains} supported`);
|
|
41066
|
-
if (addressCount !== void 0)
|
|
41067
|
-
console.log(` ${import_chalk6.default.dim("Addresses")} ${addressCount}`);
|
|
41068
|
-
if (!exists) info("\nRun `twak wallet create --password <pw>` to create a wallet.");
|
|
41069
|
-
}
|
|
41070
|
-
} catch (err) {
|
|
41071
|
-
handleCommandError(err, opts.json, "Status failed");
|
|
41072
|
-
}
|
|
41073
|
-
safeExit();
|
|
41074
|
-
});
|
|
41075
|
-
wallet.command("portfolio").description("Show portfolio balances and USD values across chains, including token holdings").option("--chains <list>", "Comma-separated chain keys (default: all supported chains)").option(
|
|
41076
|
-
"--password <password>",
|
|
41077
|
-
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
41078
|
-
).option("--json", "JSON output").action(async (opts) => {
|
|
41079
|
-
try {
|
|
41080
|
-
await ensureTrustSDK();
|
|
41081
|
-
const password3 = await resolvePassword(opts);
|
|
41082
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
41083
|
-
const httpClient = await getClient();
|
|
41084
|
-
const allAddresses = await provider.getAddresses();
|
|
41085
|
-
const chainsArg = opts.chains ?? Object.keys(CHAINS).join(",");
|
|
41086
|
-
const requestedChains = chainsArg.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
41087
|
-
if (requestedChains.length === 0) {
|
|
41088
|
-
throw new WalletError("VALIDATION_ERROR", "--chains must include at least one chain key");
|
|
41089
|
-
}
|
|
41090
|
-
const chainEntries = requestedChains.flatMap((chainKey) => {
|
|
41091
|
-
const chain2 = getChainById(chainKey);
|
|
41092
|
-
const addrEntry = allAddresses.find((a3) => a3.chainId === chainKey);
|
|
41093
|
-
if (!chain2 || !addrEntry) return [];
|
|
41094
|
-
return [{ chainKey, chain: chain2, address: addrEntry.address }];
|
|
41095
|
-
});
|
|
41096
|
-
if (chainEntries.length === 0) {
|
|
41097
|
-
throw new WalletError(
|
|
41098
|
-
"CHAIN_UNSUPPORTED",
|
|
41099
|
-
`No supported chains found in --chains "${opts.chains}"`
|
|
41100
|
-
);
|
|
41101
|
-
}
|
|
41102
|
-
const chainAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
|
|
41103
|
-
chainKey,
|
|
41104
|
-
chain: chain2,
|
|
41105
|
-
token: void 0,
|
|
41106
|
-
assetId: `c${chain2.coinId}`,
|
|
41107
|
-
userAddress: address
|
|
41108
|
-
}));
|
|
41109
|
-
const tokenAssets = chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
|
|
41110
|
-
const knownTokens = COMMON_TOKENS[chainKey];
|
|
41111
|
-
if (!knownTokens) return [];
|
|
41112
|
-
return Object.keys(knownTokens).flatMap((sym) => {
|
|
41113
|
-
const resolved = resolveToken(sym, chainKey);
|
|
41114
|
-
if (!resolved) return [];
|
|
41115
|
-
return [
|
|
41116
|
-
{
|
|
41117
|
-
chainKey,
|
|
41118
|
-
chain: chain2,
|
|
41119
|
-
token: { ...resolved, symbol: sym },
|
|
41120
|
-
assetId: `c${chain2.coinId}_t${resolved.address}`,
|
|
41121
|
-
userAddress: address
|
|
41122
|
-
}
|
|
41123
|
-
];
|
|
41124
|
-
});
|
|
41125
|
-
});
|
|
41126
|
-
const allAssets = [...chainAssets, ...tokenAssets];
|
|
41127
|
-
const balances = await fetchBalances(
|
|
41128
|
-
httpClient,
|
|
41129
|
-
allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
|
|
41130
|
-
);
|
|
41131
|
-
const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
|
|
41132
|
-
const allRows = [];
|
|
41133
|
-
for (const balance of balances) {
|
|
41134
|
-
const assetInfo = assetsById.get(balance.assetId);
|
|
41135
|
-
if (!assetInfo) {
|
|
41136
|
-
throw new WalletError(
|
|
41137
|
-
"NETWORK_ERROR",
|
|
41138
|
-
"Could not fetch balances. Please try again later."
|
|
41139
|
-
);
|
|
41140
|
-
}
|
|
41141
|
-
const { token, chain: chain2, chainKey, userAddress } = assetInfo;
|
|
41142
|
-
const decimals = token ? token.decimals : chain2.decimals;
|
|
41143
|
-
const symbol = token ? token.symbol ?? token.address : chain2.symbol;
|
|
41144
|
-
const isToken = token !== void 0;
|
|
41145
|
-
const humanAmount = formatAmount(balance.amounts.total, decimals);
|
|
41146
|
-
const fiatRaw = balance.amounts.totalInFiat;
|
|
41147
|
-
const usdValue = fiatRaw && fiatRaw !== "" ? parseFloat(fiatRaw) : null;
|
|
41148
|
-
allRows.push({
|
|
41149
|
-
chain: chainKey,
|
|
41150
|
-
type: isToken ? "token" : "native",
|
|
41151
|
-
symbol,
|
|
41152
|
-
address: userAddress,
|
|
41153
|
-
...token ? { contract: token.address } : {},
|
|
41154
|
-
balance: humanAmount,
|
|
41155
|
-
usdValue
|
|
41156
|
-
});
|
|
41157
|
-
}
|
|
41158
|
-
const rows = allRows.filter((r3) => r3.type === "native" || r3.balance !== "0");
|
|
41159
|
-
rows.sort((a3, b3) => {
|
|
41160
|
-
const chainCmp = String(a3.chain).localeCompare(String(b3.chain));
|
|
41161
|
-
if (chainCmp !== 0) return chainCmp;
|
|
41162
|
-
return String(a3.type).localeCompare(String(b3.type));
|
|
41163
|
-
});
|
|
41164
|
-
if (opts.json) {
|
|
41165
|
-
output(rows, true);
|
|
41166
|
-
} else {
|
|
41167
|
-
const totalUsd = rows.reduce(
|
|
41168
|
-
(sum, r3) => sum + (typeof r3.usdValue === "number" ? r3.usdValue : 0),
|
|
41169
|
-
0
|
|
41170
|
-
);
|
|
41171
|
-
console.log("Chain Type Symbol Balance USD");
|
|
41172
|
-
console.log("\u2500".repeat(72));
|
|
41173
|
-
for (const r3 of rows) {
|
|
41174
|
-
const usd = r3.usdValue !== null ? `$${r3.usdValue.toFixed(2)}` : "";
|
|
41175
|
-
console.log(
|
|
41176
|
-
`${String(r3.chain).padEnd(12)} ${String(r3.type).padEnd(7)} ${String(r3.symbol).padEnd(17)} ${String(r3.balance).padEnd(20)} ${usd}`
|
|
41177
|
-
);
|
|
41178
|
-
}
|
|
41179
|
-
console.log("\u2500".repeat(72));
|
|
41180
|
-
console.log(`Total USD: $${totalUsd.toFixed(2)}`);
|
|
41181
|
-
}
|
|
41182
|
-
} catch (err) {
|
|
41183
|
-
handleCommandError(err, opts.json, "Portfolio failed");
|
|
41184
|
-
}
|
|
41185
|
-
safeExit();
|
|
41186
|
-
});
|
|
41187
|
-
wallet.command("sign-message").description("Sign a message with the agent wallet").requiredOption("--chain <key>", "Chain key (e.g., ethereum, solana)").requiredOption("--message <text>", "Message to sign").option(
|
|
41188
|
-
"--password <password>",
|
|
41189
|
-
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
41190
|
-
).option("--json", "JSON output").action(async (opts) => {
|
|
41191
|
-
try {
|
|
41192
|
-
if (!getChainById(opts.chain)) {
|
|
41193
|
-
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
41194
|
-
}
|
|
41195
|
-
await ensureTrustSDK();
|
|
41196
|
-
const password3 = await resolvePassword(opts);
|
|
41197
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
41198
|
-
const address = await provider.getAddress(opts.chain);
|
|
41199
|
-
const signature = await provider.signMessage(opts.chain, opts.message);
|
|
41200
|
-
output({ chain: opts.chain, address, message: opts.message, signature }, opts.json);
|
|
41201
|
-
} catch (err) {
|
|
41202
|
-
handleCommandError(err, opts.json, "Sign failed");
|
|
41203
|
-
}
|
|
41204
|
-
safeExit();
|
|
41205
|
-
});
|
|
41206
|
-
wallet.command("register").description("Register wallet addresses with Trust Wallet backend (enables token holdings)").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (opts) => {
|
|
41207
|
-
try {
|
|
41208
|
-
const creds = await ensureTrustSDK();
|
|
41209
|
-
const password3 = await resolvePassword(opts);
|
|
41210
|
-
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
41211
|
-
await registerWalletWithBackend(creds, provider);
|
|
41212
|
-
if (!opts.json) success("Wallet registered with backend");
|
|
41213
|
-
const addresses = await provider.getAddresses();
|
|
41214
|
-
output({ registered: true, chains: addresses.length }, opts.json);
|
|
41215
|
-
} catch (err) {
|
|
41216
|
-
handleCommandError(err, opts.json, "Registration failed");
|
|
41217
|
-
}
|
|
41218
|
-
safeExit();
|
|
41219
|
-
});
|
|
41220
|
-
}
|
|
41221
|
-
|
|
41222
|
-
// src/commands/transfer.ts
|
|
41223
|
-
init_dist();
|
|
41224
|
-
|
|
41225
|
-
// ../swap/dist/index.mjs
|
|
41226
|
-
init_dist();
|
|
41227
|
-
init_dist();
|
|
41228
|
-
|
|
41229
|
-
// ../contracts/dist/index.mjs
|
|
41230
|
-
init_dist();
|
|
41231
|
-
init_dist();
|
|
41232
|
-
init_dist();
|
|
41233
|
-
init_dist();
|
|
41234
|
-
init_dist3();
|
|
41235
|
-
init_dist();
|
|
41236
|
-
init_dist();
|
|
41237
|
-
init_dist();
|
|
41238
|
-
var HEX_PATTERN = /^0x[0-9a-fA-F]*$/;
|
|
41239
|
-
function isHex(value) {
|
|
41240
|
-
return HEX_PATTERN.test(value);
|
|
41241
|
-
}
|
|
41242
|
-
function hexToBytes3(hex2) {
|
|
41243
|
-
if (!isHex(hex2)) {
|
|
41244
|
-
throw new TwakValidationError(`Invalid hex string: ${hex2}`, { kind: "invalidHex" });
|
|
41245
|
-
}
|
|
41246
|
-
const clean2 = hex2.slice(2);
|
|
41247
|
-
if (clean2.length % 2 !== 0) {
|
|
41248
|
-
throw new TwakValidationError(`Hex string has odd length: ${hex2}`, { kind: "invalidHex" });
|
|
41249
|
-
}
|
|
41250
|
-
const out = new Uint8Array(clean2.length / 2);
|
|
41251
|
-
for (let i2 = 0; i2 < out.length; i2++) {
|
|
41252
|
-
out[i2] = parseInt(clean2.slice(i2 * 2, i2 * 2 + 2), 16);
|
|
41253
|
-
}
|
|
41254
|
-
return out;
|
|
41255
|
-
}
|
|
41256
|
-
function bytesToHex3(bytes) {
|
|
41257
|
-
let out = "0x";
|
|
41258
|
-
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
41259
|
-
out += bytes[i2].toString(16).padStart(2, "0");
|
|
41260
|
-
}
|
|
41261
|
-
return out;
|
|
41262
|
-
}
|
|
41263
|
-
function hexOrUtf8ToBytesHex(value) {
|
|
41264
|
-
const looksHex = value.length >= 2 && value[0] === "0" && (value[1] === "x" || value[1] === "X");
|
|
41265
|
-
if (looksHex) {
|
|
41266
|
-
const canonical = "0x" + value.slice(2);
|
|
41267
|
-
if (!isHex(canonical)) {
|
|
41268
|
-
throw new TwakValidationError(
|
|
41269
|
-
`Value starts with "0x" but is not valid hex: ${value}. Use only [0-9a-fA-F] characters, or drop the "0x" prefix to send a UTF-8 string.`,
|
|
41270
|
-
{ kind: "invalidHex" }
|
|
41271
|
-
);
|
|
41272
|
-
}
|
|
41273
|
-
if ((canonical.length - 2) % 2 !== 0) {
|
|
41274
|
-
throw new TwakValidationError(
|
|
41275
|
-
`Hex value has odd length: ${value}. Solidity bytes must be byte-aligned.`,
|
|
41276
|
-
{ kind: "invalidHex" }
|
|
41277
|
-
);
|
|
41278
|
-
}
|
|
41279
|
-
return canonical;
|
|
41280
|
-
}
|
|
41281
|
-
return bytesToHex3(new TextEncoder().encode(value));
|
|
41282
|
-
}
|
|
41283
|
-
function wc2() {
|
|
41284
|
-
return getWalletCore();
|
|
41285
|
-
}
|
|
41286
|
-
var BRIDGE = {
|
|
41287
|
-
createAbiFunction(name2) {
|
|
41288
|
-
const ctor = wc2().EthereumAbiFunction;
|
|
41289
|
-
if (typeof ctor?.createWithString === "function") {
|
|
41290
|
-
return ctor.createWithString(name2);
|
|
41291
|
-
}
|
|
41292
|
-
return new ctor(name2);
|
|
41293
|
-
},
|
|
41294
|
-
encode(fn2) {
|
|
41295
|
-
return wc2().EthereumAbi.encode(fn2);
|
|
41296
|
-
},
|
|
41297
|
-
decodeOutput(fn2, data) {
|
|
41298
|
-
return wc2().EthereumAbi.decodeOutput(fn2, data);
|
|
41299
|
-
},
|
|
41300
|
-
keccak256(data) {
|
|
41301
|
-
return wc2().Hash.keccak256(data);
|
|
41302
|
-
}
|
|
41303
|
-
};
|
|
41304
|
-
function getAbiBridge() {
|
|
41305
|
-
return BRIDGE;
|
|
41306
|
-
}
|
|
41307
|
-
function findAbiFunction(abi, methodName, argCount) {
|
|
41308
|
-
const matches = abi.filter(
|
|
41309
|
-
(e2) => e2.type === "function" && e2.name === methodName
|
|
41310
|
-
);
|
|
41311
|
-
if (matches.length === 0) {
|
|
41312
|
-
throw new TwakValidationError(`Unknown ABI method: ${methodName}`, {
|
|
41313
|
-
kind: "unknownMethod",
|
|
41314
|
-
methodName
|
|
41315
|
-
});
|
|
41316
|
-
}
|
|
41317
|
-
if (matches.length === 1 || argCount === void 0) {
|
|
41318
|
-
return matches[0];
|
|
41319
|
-
}
|
|
41320
|
-
const byArity = matches.filter((m2) => m2.inputs.length === argCount);
|
|
41321
|
-
if (byArity.length === 1) {
|
|
41322
|
-
return byArity[0];
|
|
41323
|
-
}
|
|
41324
|
-
throw new TwakValidationError(`No unique ${methodName} overload taking ${argCount} argument(s)`, {
|
|
41325
|
-
kind: "unknownMethod",
|
|
41326
|
-
methodName
|
|
41327
|
-
});
|
|
41328
|
-
}
|
|
41329
|
-
function encodeFunctionCall(abi, methodName, args) {
|
|
41330
|
-
const fnDef = findAbiFunction(abi, methodName, args.length);
|
|
41331
|
-
if (args.length !== fnDef.inputs.length) {
|
|
41332
|
-
throw new TwakValidationError(
|
|
41333
|
-
`Wrong arg count for ${methodName}: expected ${fnDef.inputs.length}, got ${args.length}`,
|
|
41334
|
-
{
|
|
41335
|
-
kind: "wrongArgCount",
|
|
41336
|
-
methodName,
|
|
41337
|
-
expected: fnDef.inputs.length,
|
|
41338
|
-
actual: args.length
|
|
41339
|
-
}
|
|
41340
|
-
);
|
|
41341
|
-
}
|
|
41342
|
-
if (encoderRequiresHandRoll(fnDef.inputs)) {
|
|
41343
|
-
return encodeFunctionCallHandRoll(methodName, fnDef.inputs, args);
|
|
41344
|
-
}
|
|
41345
|
-
const bridge = getAbiBridge();
|
|
41346
|
-
const fn2 = bridge.createAbiFunction(methodName);
|
|
41347
|
-
fnDef.inputs.forEach((param, i2) => {
|
|
41348
|
-
pushParam(fn2, param, args[i2], methodName);
|
|
41349
|
-
});
|
|
41350
|
-
return bytesToHex3(bridge.encode(fn2));
|
|
41351
|
-
}
|
|
41352
|
-
function pushParam(fn2, param, value, methodName) {
|
|
41353
|
-
const type = param.type;
|
|
41354
|
-
const isOutput = false;
|
|
41355
|
-
if (type === "address") {
|
|
41356
|
-
fn2.addParamAddress(toAddressBytes(value, param, methodName), isOutput);
|
|
41357
|
-
return;
|
|
41358
|
-
}
|
|
41359
|
-
if (type === "bool") {
|
|
41360
|
-
if (typeof value !== "boolean") {
|
|
41361
|
-
throw argTypeMismatch(methodName, param, value, "boolean");
|
|
40772
|
+
return bytesToHex3(bridge.encode(fn2));
|
|
40773
|
+
}
|
|
40774
|
+
function pushParam(fn2, param, value, methodName) {
|
|
40775
|
+
const type = param.type;
|
|
40776
|
+
const isOutput = false;
|
|
40777
|
+
if (type === "address") {
|
|
40778
|
+
fn2.addParamAddress(toAddressBytes(value, param, methodName), isOutput);
|
|
40779
|
+
return;
|
|
40780
|
+
}
|
|
40781
|
+
if (type === "bool") {
|
|
40782
|
+
if (typeof value !== "boolean") {
|
|
40783
|
+
throw argTypeMismatch(methodName, param, value, "boolean");
|
|
41362
40784
|
}
|
|
41363
40785
|
fn2.addParamBool(value, isOutput);
|
|
41364
40786
|
return;
|
|
@@ -42012,14 +41434,14 @@ function buildWriteProxy(abi, address, chainKey, client) {
|
|
|
42012
41434
|
});
|
|
42013
41435
|
}
|
|
42014
41436
|
const data = encodeFunctionCall(abi, prop, args);
|
|
42015
|
-
const
|
|
41437
|
+
const hash = await signer.sendTransaction({
|
|
42016
41438
|
chainId: chainKeyToCaip2(chainKey),
|
|
42017
41439
|
to: address,
|
|
42018
41440
|
data,
|
|
42019
41441
|
value: "0x0"
|
|
42020
41442
|
});
|
|
42021
41443
|
return makeContractPendingTransaction({
|
|
42022
|
-
|
|
41444
|
+
hash,
|
|
42023
41445
|
abi,
|
|
42024
41446
|
address,
|
|
42025
41447
|
chainKey,
|
|
@@ -42031,22 +41453,22 @@ function buildWriteProxy(abi, address, chainKey, client) {
|
|
|
42031
41453
|
});
|
|
42032
41454
|
}
|
|
42033
41455
|
function makeContractPendingTransaction(opts) {
|
|
42034
|
-
const {
|
|
41456
|
+
const { hash, abi, address, chainKey, client, methodName } = opts;
|
|
42035
41457
|
return {
|
|
42036
|
-
|
|
41458
|
+
hash,
|
|
42037
41459
|
async wait(waitOpts) {
|
|
42038
|
-
const receipt = await client.waitForReceipt(chainKey,
|
|
41460
|
+
const receipt = await client.waitForReceipt(chainKey, hash, {
|
|
42039
41461
|
timeoutMs: waitOpts?.timeoutMs
|
|
42040
41462
|
});
|
|
42041
41463
|
if (receipt.status === "0x0") {
|
|
42042
41464
|
throw new TwakError(
|
|
42043
41465
|
`Transaction reverted on-chain: ${receipt.transactionHash}`,
|
|
42044
41466
|
"TX_FAILED",
|
|
42045
|
-
{
|
|
41467
|
+
{ hash: receipt.transactionHash, methodName, receipt }
|
|
42046
41468
|
);
|
|
42047
41469
|
}
|
|
42048
41470
|
return {
|
|
42049
|
-
|
|
41471
|
+
hash: receipt.transactionHash,
|
|
42050
41472
|
blockNumber: hexToSafeNumber(receipt.blockNumber, "blockNumber"),
|
|
42051
41473
|
events: extractEvents(abi, receipt.logs, address)
|
|
42052
41474
|
};
|
|
@@ -42143,6 +41565,17 @@ function lookupAddress(id, addresses, chainKey) {
|
|
|
42143
41565
|
}
|
|
42144
41566
|
return address;
|
|
42145
41567
|
}
|
|
41568
|
+
function eip191Digest(message) {
|
|
41569
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
41570
|
+
const prefixBytes = new TextEncoder().encode(
|
|
41571
|
+
`Ethereum Signed Message:
|
|
41572
|
+
${messageBytes.length}`
|
|
41573
|
+
);
|
|
41574
|
+
const data = new Uint8Array(prefixBytes.length + messageBytes.length);
|
|
41575
|
+
data.set(prefixBytes);
|
|
41576
|
+
data.set(messageBytes, prefixBytes.length);
|
|
41577
|
+
return bytesToHex3(getAbiBridge().keccak256(data));
|
|
41578
|
+
}
|
|
42146
41579
|
var ERC20_ABI = [
|
|
42147
41580
|
{
|
|
42148
41581
|
type: "function",
|
|
@@ -42722,6 +42155,29 @@ var ERC8183_POLICY_ABI = [
|
|
|
42722
42155
|
outputs: [],
|
|
42723
42156
|
stateMutability: "nonpayable"
|
|
42724
42157
|
},
|
|
42158
|
+
{
|
|
42159
|
+
type: "function",
|
|
42160
|
+
name: "disputeWindow",
|
|
42161
|
+
inputs: [],
|
|
42162
|
+
outputs: [{ name: "", type: "uint64" }],
|
|
42163
|
+
stateMutability: "view"
|
|
42164
|
+
},
|
|
42165
|
+
{
|
|
42166
|
+
// When the policy recorded the job's submission (0 if not submitted).
|
|
42167
|
+
type: "function",
|
|
42168
|
+
name: "submittedAt",
|
|
42169
|
+
inputs: [{ name: "jobId", type: "uint256" }],
|
|
42170
|
+
outputs: [{ name: "", type: "uint64" }],
|
|
42171
|
+
stateMutability: "view"
|
|
42172
|
+
},
|
|
42173
|
+
{
|
|
42174
|
+
// Vote quorum snapshotted for the job when its dispute was raised.
|
|
42175
|
+
type: "function",
|
|
42176
|
+
name: "disputeQuorumSnapshot",
|
|
42177
|
+
inputs: [{ name: "jobId", type: "uint256" }],
|
|
42178
|
+
outputs: [{ name: "", type: "uint16" }],
|
|
42179
|
+
stateMutability: "view"
|
|
42180
|
+
},
|
|
42725
42181
|
{
|
|
42726
42182
|
type: "function",
|
|
42727
42183
|
name: "disputed",
|
|
@@ -42833,8 +42289,640 @@ function resolveErc8183Contracts(client, chainInput) {
|
|
|
42833
42289
|
};
|
|
42834
42290
|
}
|
|
42835
42291
|
|
|
42292
|
+
// src/branding.ts
|
|
42293
|
+
var import_chalk5 = __toESM(require_source());
|
|
42294
|
+
var boxen = require_boxen();
|
|
42295
|
+
var SHIELD = [
|
|
42296
|
+
" @@=+ ",
|
|
42297
|
+
" @@@@@@@======= ",
|
|
42298
|
+
" @@@@@@@@@@@@@============+ ",
|
|
42299
|
+
" @@@@@@@@@@@@@@@@================ ",
|
|
42300
|
+
" @@@@@@@@@@@@@@@@+=============== ",
|
|
42301
|
+
" @@@@@@@@@@@@@@@@++++============ ",
|
|
42302
|
+
" @@@@@@@@@@@@@@@@++++++++++=====+ ",
|
|
42303
|
+
" @@@@@@@@@@@@@@@@**++++++++++++++ ",
|
|
42304
|
+
" @@@@@@@@@@@@@@@@********++++++++ ",
|
|
42305
|
+
" @@@@@@@@@@@@@@@@**************++ ",
|
|
42306
|
+
" @@@@@@@@@@@@@@@@#####*********** ",
|
|
42307
|
+
" @@@@@@@@@@@@@@@###########**** ",
|
|
42308
|
+
" @@@@@@@@@@@@@@%############## ",
|
|
42309
|
+
" @@@@@@@@@@@@@@%%%%%%%####### ",
|
|
42310
|
+
" @@@@@@@@@@@@@%%%%%%%%%%%%% ",
|
|
42311
|
+
" @@@@@@@@@@@%%%%%%%%%%% ",
|
|
42312
|
+
" @@@@@@@@@@@@@%%%%% ",
|
|
42313
|
+
" @@@@@@@@@@@@@@ ",
|
|
42314
|
+
" @@@@@@@@@@ ",
|
|
42315
|
+
" @@ "
|
|
42316
|
+
];
|
|
42317
|
+
function printBanner(version3) {
|
|
42318
|
+
const logo = SHIELD.map((l4) => import_chalk5.default.green(l4)).join("\n");
|
|
42319
|
+
const title = import_chalk5.default.green.bold(" Trust Wallet Agent Kit");
|
|
42320
|
+
const ver = import_chalk5.default.dim(` v${version3}`);
|
|
42321
|
+
console.log(
|
|
42322
|
+
boxen(`${logo}
|
|
42323
|
+
|
|
42324
|
+
${title}
|
|
42325
|
+
${ver}`, {
|
|
42326
|
+
borderColor: "green",
|
|
42327
|
+
borderStyle: "round",
|
|
42328
|
+
padding: { top: 1, bottom: 1, left: 2, right: 2 }
|
|
42329
|
+
})
|
|
42330
|
+
);
|
|
42331
|
+
}
|
|
42332
|
+
function box(content) {
|
|
42333
|
+
return boxen(content, {
|
|
42334
|
+
borderColor: "green",
|
|
42335
|
+
borderStyle: "round",
|
|
42336
|
+
padding: { top: 0, bottom: 0, left: 1, right: 1 }
|
|
42337
|
+
});
|
|
42338
|
+
}
|
|
42339
|
+
|
|
42340
|
+
// src/commands/wallet.ts
|
|
42341
|
+
function getQRString(address) {
|
|
42342
|
+
try {
|
|
42343
|
+
const qrcode = require("qrcode-terminal");
|
|
42344
|
+
let result = "";
|
|
42345
|
+
qrcode.generate(address, { small: true }, (code2) => {
|
|
42346
|
+
result = code2;
|
|
42347
|
+
});
|
|
42348
|
+
return result;
|
|
42349
|
+
} catch {
|
|
42350
|
+
return "";
|
|
42351
|
+
}
|
|
42352
|
+
}
|
|
42353
|
+
function registerWalletCommand(program3) {
|
|
42354
|
+
const wallet = program3.command("wallet").description("Manage agent wallet");
|
|
42355
|
+
wallet.command("create").description("Create a new agent wallet").requiredOption("--password <password>", "Password to encrypt the wallet").option("--no-keychain", "Do not save password to OS keychain").option("--skip-password-check", "Skip password strength validation").option("--json", "JSON output").action(async (opts) => {
|
|
42356
|
+
try {
|
|
42357
|
+
if (!opts.skipPasswordCheck) {
|
|
42358
|
+
const weakness = getPasswordWeaknesses(opts.password);
|
|
42359
|
+
if (weakness) {
|
|
42360
|
+
throw new WalletError("VALIDATION_ERROR", `Password too weak: must ${weakness}.`);
|
|
42361
|
+
}
|
|
42362
|
+
}
|
|
42363
|
+
await ensureTrustSDK();
|
|
42364
|
+
const store = new WalletConfigStore();
|
|
42365
|
+
if (await store.exists()) {
|
|
42366
|
+
throw new WalletError(
|
|
42367
|
+
"WALLET_EXISTS",
|
|
42368
|
+
"Wallet already exists. Back up ~/.twak/wallet.json, then delete it to create a new one."
|
|
42369
|
+
);
|
|
42370
|
+
}
|
|
42371
|
+
const provider = await AgentWalletProvider.create(opts.password);
|
|
42372
|
+
const addresses = await provider.getAddresses();
|
|
42373
|
+
if (opts.keychain !== false) {
|
|
42374
|
+
const kc2 = new KeychainManager();
|
|
42375
|
+
if (kc2.isAvailable()) {
|
|
42376
|
+
await kc2.saveWalletPassword(opts.password);
|
|
42377
|
+
if (!opts.json) info("Password saved to OS keychain (use --no-keychain to skip)");
|
|
42378
|
+
}
|
|
42379
|
+
}
|
|
42380
|
+
if (!opts.json) success("Agent wallet created successfully");
|
|
42381
|
+
try {
|
|
42382
|
+
const creds = await getCredentials();
|
|
42383
|
+
await registerWalletWithBackend(creds, provider);
|
|
42384
|
+
if (!opts.json) info("Wallet registered with backend");
|
|
42385
|
+
} catch {
|
|
42386
|
+
if (!opts.json) warn("Backend registration failed (holdings may be limited)");
|
|
42387
|
+
}
|
|
42388
|
+
if (opts.json) {
|
|
42389
|
+
output({ addresses }, true);
|
|
42390
|
+
} else {
|
|
42391
|
+
info(`Generated addresses for ${addresses.length} chains`);
|
|
42392
|
+
}
|
|
42393
|
+
} catch (err) {
|
|
42394
|
+
handleCommandError(err, opts.json, "Wallet creation failed");
|
|
42395
|
+
}
|
|
42396
|
+
safeExit();
|
|
42397
|
+
});
|
|
42398
|
+
wallet.command("address").description("Get wallet address for a chain").requiredOption("--chain <key>", "Chain key (e.g., ethereum, solana)").option(
|
|
42399
|
+
"--password <password>",
|
|
42400
|
+
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
42401
|
+
).option("--json", "JSON output").action(async (opts) => {
|
|
42402
|
+
try {
|
|
42403
|
+
if (!getChainById(opts.chain)) {
|
|
42404
|
+
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
42405
|
+
}
|
|
42406
|
+
await ensureTrustSDK();
|
|
42407
|
+
const password3 = await resolvePassword(opts);
|
|
42408
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42409
|
+
const address = await provider.getAddress(opts.chain);
|
|
42410
|
+
if (opts.json) {
|
|
42411
|
+
output({ chain: opts.chain, address }, true);
|
|
42412
|
+
} else {
|
|
42413
|
+
const qr3 = getQRString(address);
|
|
42414
|
+
const content = `${import_chalk6.default.dim("Chain")} ${import_chalk6.default.bold(opts.chain)}
|
|
42415
|
+
${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
|
|
42416
|
+
|
|
42417
|
+
${qr3}`;
|
|
42418
|
+
console.log(box(content));
|
|
42419
|
+
}
|
|
42420
|
+
} catch (err) {
|
|
42421
|
+
handleCommandError(err, opts.json, "Wallet address failed");
|
|
42422
|
+
}
|
|
42423
|
+
safeExit();
|
|
42424
|
+
});
|
|
42425
|
+
wallet.command("addresses").description("List all wallet addresses").option(
|
|
42426
|
+
"--password <password>",
|
|
42427
|
+
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
42428
|
+
).option("--json", "JSON output").action(async (opts) => {
|
|
42429
|
+
try {
|
|
42430
|
+
await ensureTrustSDK();
|
|
42431
|
+
const password3 = await resolvePassword(opts);
|
|
42432
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42433
|
+
const addresses = await provider.getAddresses();
|
|
42434
|
+
if (opts.json) {
|
|
42435
|
+
output({ addresses }, true);
|
|
42436
|
+
} else {
|
|
42437
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
42438
|
+
for (const addr of addresses) {
|
|
42439
|
+
const chains = grouped.get(addr.address) ?? [];
|
|
42440
|
+
chains.push(addr.chainId);
|
|
42441
|
+
grouped.set(addr.address, chains);
|
|
42442
|
+
}
|
|
42443
|
+
for (const [address, chains] of grouped) {
|
|
42444
|
+
const qr3 = getQRString(address);
|
|
42445
|
+
const maxWidth = Math.max(address.length + 9, 50);
|
|
42446
|
+
const chainLabel = `${import_chalk6.default.dim("Chains")} `;
|
|
42447
|
+
const chainLabelLen = 9;
|
|
42448
|
+
const chainLines = [];
|
|
42449
|
+
let line = "";
|
|
42450
|
+
for (const c3 of chains) {
|
|
42451
|
+
const sep2 = line ? ", " : "";
|
|
42452
|
+
if (line && line.length + sep2.length + c3.length + chainLabelLen > maxWidth) {
|
|
42453
|
+
chainLines.push(line);
|
|
42454
|
+
line = c3;
|
|
42455
|
+
} else {
|
|
42456
|
+
line += sep2 + c3;
|
|
42457
|
+
}
|
|
42458
|
+
}
|
|
42459
|
+
if (line) chainLines.push(line);
|
|
42460
|
+
const chainsStr = chainLines.map((l4, i2) => (i2 === 0 ? chainLabel : " ".repeat(chainLabelLen)) + import_chalk6.default.bold(l4)).join("\n");
|
|
42461
|
+
const content = `${chainsStr}
|
|
42462
|
+
${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
|
|
42463
|
+
|
|
42464
|
+
${qr3}`;
|
|
42465
|
+
console.log(box(content));
|
|
42466
|
+
}
|
|
42467
|
+
}
|
|
42468
|
+
} catch (err) {
|
|
42469
|
+
handleCommandError(err, opts.json, "Wallet addresses failed");
|
|
42470
|
+
}
|
|
42471
|
+
safeExit();
|
|
42472
|
+
});
|
|
42473
|
+
wallet.command("balance").description("Get wallet balance on a chain (native + token holdings)").option("--chain <key>", "Chain key").option("--all", "Show balances across all chains with funds").option(
|
|
42474
|
+
"--password <password>",
|
|
42475
|
+
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
42476
|
+
).option("--no-tokens", "Skip token balance lookup").option("--json", "JSON output").action(async (opts) => {
|
|
42477
|
+
try {
|
|
42478
|
+
if (opts.all && opts.chain) {
|
|
42479
|
+
throw new WalletError("VALIDATION_ERROR", "--all and --chain are mutually exclusive");
|
|
42480
|
+
}
|
|
42481
|
+
if (!opts.all && !opts.chain) {
|
|
42482
|
+
throw new WalletError("VALIDATION_ERROR", "Provide --chain <key> or --all");
|
|
42483
|
+
}
|
|
42484
|
+
await ensureTrustSDK();
|
|
42485
|
+
const password3 = await resolvePassword(opts);
|
|
42486
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42487
|
+
const httpClient = await getClient();
|
|
42488
|
+
if (!opts.all) {
|
|
42489
|
+
const chain2 = getChainById(opts.chain);
|
|
42490
|
+
if (!chain2) {
|
|
42491
|
+
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
42492
|
+
}
|
|
42493
|
+
}
|
|
42494
|
+
const allAddresses = await provider.getAddresses();
|
|
42495
|
+
const addressMap = /* @__PURE__ */ new Map();
|
|
42496
|
+
for (const a3 of allAddresses) addressMap.set(a3.chainId, a3.address);
|
|
42497
|
+
const requestedChains = opts.all ? Object.keys(CHAINS) : [opts.chain];
|
|
42498
|
+
const skipTokens = opts.tokens === false;
|
|
42499
|
+
const chainEntries = requestedChains.flatMap((chainKey) => {
|
|
42500
|
+
const chain2 = getChainById(chainKey);
|
|
42501
|
+
const address = addressMap.get(chainKey);
|
|
42502
|
+
if (!chain2 || !address) return [];
|
|
42503
|
+
return [{ chainKey, chain: chain2, address }];
|
|
42504
|
+
});
|
|
42505
|
+
if (!opts.all && chainEntries.length === 0) {
|
|
42506
|
+
throw new WalletError(
|
|
42507
|
+
"CHAIN_UNSUPPORTED",
|
|
42508
|
+
`Wallet does not have an address for chain: ${opts.chain}`
|
|
42509
|
+
);
|
|
42510
|
+
}
|
|
42511
|
+
const nativeAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
|
|
42512
|
+
chainKey,
|
|
42513
|
+
chain: chain2,
|
|
42514
|
+
token: void 0,
|
|
42515
|
+
assetId: `c${chain2.coinId}`,
|
|
42516
|
+
userAddress: address
|
|
42517
|
+
}));
|
|
42518
|
+
const tokenAssets = skipTokens ? [] : chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
|
|
42519
|
+
const knownTokens = COMMON_TOKENS[chainKey];
|
|
42520
|
+
if (!knownTokens) return [];
|
|
42521
|
+
return Object.keys(knownTokens).flatMap((sym) => {
|
|
42522
|
+
const resolved = resolveToken(sym, chainKey);
|
|
42523
|
+
if (!resolved) return [];
|
|
42524
|
+
return [
|
|
42525
|
+
{
|
|
42526
|
+
chainKey,
|
|
42527
|
+
chain: chain2,
|
|
42528
|
+
token: { ...resolved, symbol: sym },
|
|
42529
|
+
assetId: `c${chain2.coinId}_t${resolved.address}`,
|
|
42530
|
+
userAddress: address
|
|
42531
|
+
}
|
|
42532
|
+
];
|
|
42533
|
+
});
|
|
42534
|
+
});
|
|
42535
|
+
const allAssets = [...nativeAssets, ...tokenAssets];
|
|
42536
|
+
const balances = await fetchBalances(
|
|
42537
|
+
httpClient,
|
|
42538
|
+
allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
|
|
42539
|
+
);
|
|
42540
|
+
const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
|
|
42541
|
+
const resultsByChain = /* @__PURE__ */ new Map();
|
|
42542
|
+
for (const { chainKey, chain: chain2, address } of chainEntries) {
|
|
42543
|
+
resultsByChain.set(chainKey, {
|
|
42544
|
+
chain: chainKey,
|
|
42545
|
+
address,
|
|
42546
|
+
symbol: chain2.symbol,
|
|
42547
|
+
available: "0",
|
|
42548
|
+
total: "0",
|
|
42549
|
+
totalUsd: null,
|
|
42550
|
+
tokens: []
|
|
42551
|
+
});
|
|
42552
|
+
}
|
|
42553
|
+
for (const balance of balances) {
|
|
42554
|
+
const assetInfo = assetsById.get(balance.assetId);
|
|
42555
|
+
if (!assetInfo) {
|
|
42556
|
+
throw new WalletError(
|
|
42557
|
+
"NETWORK_ERROR",
|
|
42558
|
+
"Could not fetch balances. Please try again later."
|
|
42559
|
+
);
|
|
42560
|
+
}
|
|
42561
|
+
const result = resultsByChain.get(assetInfo.chainKey);
|
|
42562
|
+
if (!result) continue;
|
|
42563
|
+
const { token, chain: chain2 } = assetInfo;
|
|
42564
|
+
const amts = balance.amounts;
|
|
42565
|
+
if (token) {
|
|
42566
|
+
const human = formatAmount(amts.total ?? "0", token.decimals);
|
|
42567
|
+
if (human !== "0") {
|
|
42568
|
+
result.tokens.push({
|
|
42569
|
+
symbol: token.symbol,
|
|
42570
|
+
contract: token.address,
|
|
42571
|
+
balance: human
|
|
42572
|
+
});
|
|
42573
|
+
}
|
|
42574
|
+
} else {
|
|
42575
|
+
result.available = formatAmount(amts.available ?? "0", chain2.decimals);
|
|
42576
|
+
result.total = formatAmount(amts.total ?? "0", chain2.decimals);
|
|
42577
|
+
const lockedHuman = formatAmount(amts.locked ?? "0", chain2.decimals);
|
|
42578
|
+
if (lockedHuman !== "0") result.staked = lockedHuman;
|
|
42579
|
+
const fiat = amts.totalInFiat;
|
|
42580
|
+
result.totalUsd = fiat && fiat !== "" ? parseFloat(fiat) : null;
|
|
42581
|
+
}
|
|
42582
|
+
}
|
|
42583
|
+
const orderedResults = chainEntries.map((e2) => resultsByChain.get(e2.chainKey)).filter((r3) => r3 !== void 0);
|
|
42584
|
+
const visible = opts.all ? orderedResults.filter((r3) => r3.total !== "0" || r3.tokens.length > 0) : orderedResults;
|
|
42585
|
+
const renderBlock = (r3, withSeparator) => {
|
|
42586
|
+
if (withSeparator) console.log("");
|
|
42587
|
+
console.log(import_chalk6.default.bold.underline(`${r3.chain} (${r3.symbol})`));
|
|
42588
|
+
console.log(` ${import_chalk6.default.dim("Address")} ${r3.address}`);
|
|
42589
|
+
console.log(` ${import_chalk6.default.dim("Available")} ${r3.available}`);
|
|
42590
|
+
if (r3.staked) console.log(` ${import_chalk6.default.dim("Staked")} ${r3.staked}`);
|
|
42591
|
+
const usdSuffix = r3.totalUsd !== null ? ` (\u2248 $${r3.totalUsd.toFixed(2)})` : "";
|
|
42592
|
+
console.log(` ${import_chalk6.default.dim("Total")} ${r3.total}${usdSuffix}`);
|
|
42593
|
+
if (r3.tokens.length > 0) {
|
|
42594
|
+
console.log(` ${import_chalk6.default.dim("Tokens:")}`);
|
|
42595
|
+
for (const t of r3.tokens) {
|
|
42596
|
+
console.log(` ${import_chalk6.default.bold(t.symbol.padEnd(10))} ${t.balance}`);
|
|
42597
|
+
}
|
|
42598
|
+
}
|
|
42599
|
+
};
|
|
42600
|
+
if (opts.all) {
|
|
42601
|
+
if (opts.json) {
|
|
42602
|
+
output(visible, true);
|
|
42603
|
+
} else if (visible.length === 0) {
|
|
42604
|
+
info("No chains with non-zero native balance found.");
|
|
42605
|
+
} else {
|
|
42606
|
+
visible.forEach((r3, i2) => renderBlock(r3, i2 > 0));
|
|
42607
|
+
}
|
|
42608
|
+
} else {
|
|
42609
|
+
const single = visible[0];
|
|
42610
|
+
if (opts.json) {
|
|
42611
|
+
output(single, true);
|
|
42612
|
+
} else {
|
|
42613
|
+
renderBlock(single, false);
|
|
42614
|
+
}
|
|
42615
|
+
}
|
|
42616
|
+
} catch (err) {
|
|
42617
|
+
handleCommandError(err, opts.json, "Balance check failed");
|
|
42618
|
+
}
|
|
42619
|
+
safeExit();
|
|
42620
|
+
});
|
|
42621
|
+
const keychain = wallet.command("keychain").description("Manage wallet password in OS keychain");
|
|
42622
|
+
keychain.command("save").description("Save wallet password to OS keychain").requiredOption("--password <password>", "Wallet password to store").option("--json", "JSON output").action(async (opts) => {
|
|
42623
|
+
try {
|
|
42624
|
+
const kc2 = new KeychainManager();
|
|
42625
|
+
if (!kc2.isAvailable()) {
|
|
42626
|
+
throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
|
|
42627
|
+
}
|
|
42628
|
+
await kc2.saveWalletPassword(opts.password);
|
|
42629
|
+
success("Wallet password saved to OS keychain");
|
|
42630
|
+
} catch (err) {
|
|
42631
|
+
handleCommandError(err, opts.json, "Keychain save failed");
|
|
42632
|
+
}
|
|
42633
|
+
safeExit();
|
|
42634
|
+
});
|
|
42635
|
+
keychain.command("delete").description("Remove wallet password from OS keychain").option("--json", "JSON output").action(async (opts) => {
|
|
42636
|
+
try {
|
|
42637
|
+
const kc2 = new KeychainManager();
|
|
42638
|
+
if (!kc2.isAvailable()) {
|
|
42639
|
+
throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
|
|
42640
|
+
}
|
|
42641
|
+
await kc2.deleteWalletPassword();
|
|
42642
|
+
success("Wallet password removed from OS keychain");
|
|
42643
|
+
} catch (err) {
|
|
42644
|
+
handleCommandError(err, opts.json, "Keychain delete failed");
|
|
42645
|
+
}
|
|
42646
|
+
safeExit();
|
|
42647
|
+
});
|
|
42648
|
+
keychain.command("check").description("Check if wallet password is stored in OS keychain").option("--json", "JSON output").action(async (opts) => {
|
|
42649
|
+
try {
|
|
42650
|
+
const kc2 = new KeychainManager();
|
|
42651
|
+
if (!kc2.isAvailable()) {
|
|
42652
|
+
if (opts.json) {
|
|
42653
|
+
output({ available: false, stored: false }, true);
|
|
42654
|
+
} else {
|
|
42655
|
+
warn("keytar not available on this system");
|
|
42656
|
+
}
|
|
42657
|
+
safeExit();
|
|
42658
|
+
return;
|
|
42659
|
+
}
|
|
42660
|
+
const pw = await kc2.getWalletPassword();
|
|
42661
|
+
if (opts.json) {
|
|
42662
|
+
output({ available: true, stored: !!pw }, true);
|
|
42663
|
+
} else if (pw) {
|
|
42664
|
+
success("Wallet password is stored in OS keychain");
|
|
42665
|
+
} else {
|
|
42666
|
+
info("No wallet password found in OS keychain");
|
|
42667
|
+
}
|
|
42668
|
+
} catch (err) {
|
|
42669
|
+
handleCommandError(err, opts.json, "Keychain check failed");
|
|
42670
|
+
}
|
|
42671
|
+
safeExit();
|
|
42672
|
+
});
|
|
42673
|
+
wallet.command("connect").description("Connect external wallet via WalletConnect").option("--project-id <id>", "WalletConnect project ID (or set WALLETCONNECT_PROJECT_ID)").option(
|
|
42674
|
+
"--chains <list>",
|
|
42675
|
+
"Comma-separated CAIP-2 chain IDs",
|
|
42676
|
+
"eip155:1,eip155:56,eip155:137,eip155:8453,eip155:42161"
|
|
42677
|
+
).option("--timeout <seconds>", "Connection timeout in seconds", "300").option("--json", "JSON output").action(async (opts) => {
|
|
42678
|
+
try {
|
|
42679
|
+
const projectId = opts.projectId || process.env.WALLETCONNECT_PROJECT_ID;
|
|
42680
|
+
if (!projectId) {
|
|
42681
|
+
throw new WalletError(
|
|
42682
|
+
"VALIDATION_ERROR",
|
|
42683
|
+
"WalletConnect project ID required. Use --project-id or set WALLETCONNECT_PROJECT_ID"
|
|
42684
|
+
);
|
|
42685
|
+
}
|
|
42686
|
+
const provider = new WalletConnectProvider({ projectId });
|
|
42687
|
+
const chains = opts.chains.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
42688
|
+
info("Connecting via WalletConnect...");
|
|
42689
|
+
const result = await provider.connect(chains);
|
|
42690
|
+
const qr3 = getQRString(result.uri);
|
|
42691
|
+
if (qr3) {
|
|
42692
|
+
console.log(qr3);
|
|
42693
|
+
}
|
|
42694
|
+
info(`Trust Wallet: ${result.deepLinks.native}`);
|
|
42695
|
+
info(`Universal: ${result.deepLinks.universal}`);
|
|
42696
|
+
info("\nWaiting for wallet approval...");
|
|
42697
|
+
const timeoutMs = parseInt(opts.timeout, 10) * 1e3;
|
|
42698
|
+
const session = await provider.waitForSession(timeoutMs);
|
|
42699
|
+
if (opts.json) {
|
|
42700
|
+
output(
|
|
42701
|
+
{
|
|
42702
|
+
connected: true,
|
|
42703
|
+
address: session.address,
|
|
42704
|
+
chainId: session.chainId,
|
|
42705
|
+
peer: session.peerName
|
|
42706
|
+
},
|
|
42707
|
+
true
|
|
42708
|
+
);
|
|
42709
|
+
} else {
|
|
42710
|
+
success(`Connected to ${session.peerName || "wallet"}`);
|
|
42711
|
+
info(` Address: ${session.address}`);
|
|
42712
|
+
info(` Chain: ${session.chainId}`);
|
|
42713
|
+
}
|
|
42714
|
+
} catch (err) {
|
|
42715
|
+
handleCommandError(err, opts.json, "WalletConnect failed");
|
|
42716
|
+
}
|
|
42717
|
+
safeExit();
|
|
42718
|
+
});
|
|
42719
|
+
wallet.command("status").description("Check wallet configuration status").option("--json", "JSON output").action(async (opts) => {
|
|
42720
|
+
try {
|
|
42721
|
+
const store = new WalletConfigStore();
|
|
42722
|
+
const exists = await store.exists();
|
|
42723
|
+
const kc2 = new KeychainManager();
|
|
42724
|
+
const keychainHasPassword = kc2.isAvailable() ? !!await kc2.getWalletPassword() : false;
|
|
42725
|
+
const totalChains = Object.keys(CHAINS).length;
|
|
42726
|
+
let createdAt;
|
|
42727
|
+
let addressCount;
|
|
42728
|
+
if (exists) {
|
|
42729
|
+
const config = await store.getConfig();
|
|
42730
|
+
createdAt = config?.createdAt;
|
|
42731
|
+
addressCount = config?.chains?.length ?? totalChains;
|
|
42732
|
+
}
|
|
42733
|
+
const result = {
|
|
42734
|
+
agentWallet: exists ? "configured" : "not configured",
|
|
42735
|
+
keychainPassword: keychainHasPassword ? "stored" : "not stored",
|
|
42736
|
+
chains: totalChains,
|
|
42737
|
+
supportedChains: totalChains,
|
|
42738
|
+
...createdAt ? { createdAt } : {},
|
|
42739
|
+
...addressCount !== void 0 ? { addressCount } : {}
|
|
42740
|
+
};
|
|
42741
|
+
if (opts.json) {
|
|
42742
|
+
output(result, true);
|
|
42743
|
+
} else {
|
|
42744
|
+
console.log(
|
|
42745
|
+
` ${import_chalk6.default.dim("Wallet")} ${exists ? import_chalk6.default.green("configured") : import_chalk6.default.yellow("not configured")}`
|
|
42746
|
+
);
|
|
42747
|
+
if (createdAt) console.log(` ${import_chalk6.default.dim("Created")} ${createdAt}`);
|
|
42748
|
+
console.log(
|
|
42749
|
+
` ${import_chalk6.default.dim("Keychain")} ${keychainHasPassword ? import_chalk6.default.green("password stored") : import_chalk6.default.yellow("no password")}`
|
|
42750
|
+
);
|
|
42751
|
+
console.log(` ${import_chalk6.default.dim("Chains")} ${totalChains} supported`);
|
|
42752
|
+
if (addressCount !== void 0)
|
|
42753
|
+
console.log(` ${import_chalk6.default.dim("Addresses")} ${addressCount}`);
|
|
42754
|
+
if (!exists) info("\nRun `twak wallet create --password <pw>` to create a wallet.");
|
|
42755
|
+
}
|
|
42756
|
+
} catch (err) {
|
|
42757
|
+
handleCommandError(err, opts.json, "Status failed");
|
|
42758
|
+
}
|
|
42759
|
+
safeExit();
|
|
42760
|
+
});
|
|
42761
|
+
wallet.command("portfolio").description("Show portfolio balances and USD values across chains, including token holdings").option("--chains <list>", "Comma-separated chain keys (default: all supported chains)").option(
|
|
42762
|
+
"--password <password>",
|
|
42763
|
+
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
42764
|
+
).option("--json", "JSON output").action(async (opts) => {
|
|
42765
|
+
try {
|
|
42766
|
+
await ensureTrustSDK();
|
|
42767
|
+
const password3 = await resolvePassword(opts);
|
|
42768
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42769
|
+
const httpClient = await getClient();
|
|
42770
|
+
const allAddresses = await provider.getAddresses();
|
|
42771
|
+
const chainsArg = opts.chains ?? Object.keys(CHAINS).join(",");
|
|
42772
|
+
const requestedChains = chainsArg.split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
42773
|
+
if (requestedChains.length === 0) {
|
|
42774
|
+
throw new WalletError("VALIDATION_ERROR", "--chains must include at least one chain key");
|
|
42775
|
+
}
|
|
42776
|
+
const chainEntries = requestedChains.flatMap((chainKey) => {
|
|
42777
|
+
const chain2 = getChainById(chainKey);
|
|
42778
|
+
const addrEntry = allAddresses.find((a3) => a3.chainId === chainKey);
|
|
42779
|
+
if (!chain2 || !addrEntry) return [];
|
|
42780
|
+
return [{ chainKey, chain: chain2, address: addrEntry.address }];
|
|
42781
|
+
});
|
|
42782
|
+
if (chainEntries.length === 0) {
|
|
42783
|
+
throw new WalletError(
|
|
42784
|
+
"CHAIN_UNSUPPORTED",
|
|
42785
|
+
`No supported chains found in --chains "${opts.chains}"`
|
|
42786
|
+
);
|
|
42787
|
+
}
|
|
42788
|
+
const chainAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
|
|
42789
|
+
chainKey,
|
|
42790
|
+
chain: chain2,
|
|
42791
|
+
token: void 0,
|
|
42792
|
+
assetId: `c${chain2.coinId}`,
|
|
42793
|
+
userAddress: address
|
|
42794
|
+
}));
|
|
42795
|
+
const tokenAssets = chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
|
|
42796
|
+
const knownTokens = COMMON_TOKENS[chainKey];
|
|
42797
|
+
if (!knownTokens) return [];
|
|
42798
|
+
return Object.keys(knownTokens).flatMap((sym) => {
|
|
42799
|
+
const resolved = resolveToken(sym, chainKey);
|
|
42800
|
+
if (!resolved) return [];
|
|
42801
|
+
return [
|
|
42802
|
+
{
|
|
42803
|
+
chainKey,
|
|
42804
|
+
chain: chain2,
|
|
42805
|
+
token: { ...resolved, symbol: sym },
|
|
42806
|
+
assetId: `c${chain2.coinId}_t${resolved.address}`,
|
|
42807
|
+
userAddress: address
|
|
42808
|
+
}
|
|
42809
|
+
];
|
|
42810
|
+
});
|
|
42811
|
+
});
|
|
42812
|
+
const allAssets = [...chainAssets, ...tokenAssets];
|
|
42813
|
+
const balances = await fetchBalances(
|
|
42814
|
+
httpClient,
|
|
42815
|
+
allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
|
|
42816
|
+
);
|
|
42817
|
+
const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
|
|
42818
|
+
const allRows = [];
|
|
42819
|
+
for (const balance of balances) {
|
|
42820
|
+
const assetInfo = assetsById.get(balance.assetId);
|
|
42821
|
+
if (!assetInfo) {
|
|
42822
|
+
throw new WalletError(
|
|
42823
|
+
"NETWORK_ERROR",
|
|
42824
|
+
"Could not fetch balances. Please try again later."
|
|
42825
|
+
);
|
|
42826
|
+
}
|
|
42827
|
+
const { token, chain: chain2, chainKey, userAddress } = assetInfo;
|
|
42828
|
+
const decimals = token ? token.decimals : chain2.decimals;
|
|
42829
|
+
const symbol = token ? token.symbol ?? token.address : chain2.symbol;
|
|
42830
|
+
const isToken = token !== void 0;
|
|
42831
|
+
const humanAmount = formatAmount(balance.amounts.total, decimals);
|
|
42832
|
+
const fiatRaw = balance.amounts.totalInFiat;
|
|
42833
|
+
const usdValue = fiatRaw && fiatRaw !== "" ? parseFloat(fiatRaw) : null;
|
|
42834
|
+
allRows.push({
|
|
42835
|
+
chain: chainKey,
|
|
42836
|
+
type: isToken ? "token" : "native",
|
|
42837
|
+
symbol,
|
|
42838
|
+
address: userAddress,
|
|
42839
|
+
...token ? { contract: token.address } : {},
|
|
42840
|
+
balance: humanAmount,
|
|
42841
|
+
usdValue
|
|
42842
|
+
});
|
|
42843
|
+
}
|
|
42844
|
+
const rows = allRows.filter((r3) => r3.type === "native" || r3.balance !== "0");
|
|
42845
|
+
rows.sort((a3, b3) => {
|
|
42846
|
+
const chainCmp = String(a3.chain).localeCompare(String(b3.chain));
|
|
42847
|
+
if (chainCmp !== 0) return chainCmp;
|
|
42848
|
+
return String(a3.type).localeCompare(String(b3.type));
|
|
42849
|
+
});
|
|
42850
|
+
if (opts.json) {
|
|
42851
|
+
output(rows, true);
|
|
42852
|
+
} else {
|
|
42853
|
+
const totalUsd = rows.reduce(
|
|
42854
|
+
(sum, r3) => sum + (typeof r3.usdValue === "number" ? r3.usdValue : 0),
|
|
42855
|
+
0
|
|
42856
|
+
);
|
|
42857
|
+
console.log("Chain Type Symbol Balance USD");
|
|
42858
|
+
console.log("\u2500".repeat(72));
|
|
42859
|
+
for (const r3 of rows) {
|
|
42860
|
+
const usd = r3.usdValue !== null ? `$${r3.usdValue.toFixed(2)}` : "";
|
|
42861
|
+
console.log(
|
|
42862
|
+
`${String(r3.chain).padEnd(12)} ${String(r3.type).padEnd(7)} ${String(r3.symbol).padEnd(17)} ${String(r3.balance).padEnd(20)} ${usd}`
|
|
42863
|
+
);
|
|
42864
|
+
}
|
|
42865
|
+
console.log("\u2500".repeat(72));
|
|
42866
|
+
console.log(`Total USD: $${totalUsd.toFixed(2)}`);
|
|
42867
|
+
}
|
|
42868
|
+
} catch (err) {
|
|
42869
|
+
handleCommandError(err, opts.json, "Portfolio failed");
|
|
42870
|
+
}
|
|
42871
|
+
safeExit();
|
|
42872
|
+
});
|
|
42873
|
+
wallet.command("sign-message").description("Sign a message with the agent wallet").requiredOption("--chain <key>", "Chain key (e.g., ethereum, solana)").requiredOption("--message <text>", "Message to sign").option(
|
|
42874
|
+
"--password <password>",
|
|
42875
|
+
"Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
|
|
42876
|
+
).option("--json", "JSON output").action(async (opts) => {
|
|
42877
|
+
try {
|
|
42878
|
+
const chain2 = getChainById(opts.chain);
|
|
42879
|
+
if (!chain2) {
|
|
42880
|
+
throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
|
|
42881
|
+
}
|
|
42882
|
+
await ensureTrustSDK();
|
|
42883
|
+
const password3 = await resolvePassword(opts);
|
|
42884
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42885
|
+
const address = await provider.getAddress(opts.chain);
|
|
42886
|
+
const rawSignature = await provider.signMessage(opts.chain, opts.message);
|
|
42887
|
+
const signature = chain2.isEVM && !rawSignature.startsWith("0x") ? `0x${rawSignature}` : rawSignature;
|
|
42888
|
+
output(
|
|
42889
|
+
{
|
|
42890
|
+
chain: opts.chain,
|
|
42891
|
+
address,
|
|
42892
|
+
message: opts.message,
|
|
42893
|
+
signature,
|
|
42894
|
+
...chain2.isEVM ? { digest: eip191Digest(opts.message) } : {}
|
|
42895
|
+
},
|
|
42896
|
+
opts.json
|
|
42897
|
+
);
|
|
42898
|
+
} catch (err) {
|
|
42899
|
+
handleCommandError(err, opts.json, "Sign failed");
|
|
42900
|
+
}
|
|
42901
|
+
safeExit();
|
|
42902
|
+
});
|
|
42903
|
+
wallet.command("register").description("Register wallet addresses with Trust Wallet backend (enables token holdings)").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (opts) => {
|
|
42904
|
+
try {
|
|
42905
|
+
const creds = await ensureTrustSDK();
|
|
42906
|
+
const password3 = await resolvePassword(opts);
|
|
42907
|
+
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
42908
|
+
await registerWalletWithBackend(creds, provider);
|
|
42909
|
+
if (!opts.json) success("Wallet registered with backend");
|
|
42910
|
+
const addresses = await provider.getAddresses();
|
|
42911
|
+
output({ registered: true, chains: addresses.length }, opts.json);
|
|
42912
|
+
} catch (err) {
|
|
42913
|
+
handleCommandError(err, opts.json, "Registration failed");
|
|
42914
|
+
}
|
|
42915
|
+
safeExit();
|
|
42916
|
+
});
|
|
42917
|
+
}
|
|
42918
|
+
|
|
42919
|
+
// src/commands/transfer.ts
|
|
42920
|
+
init_dist();
|
|
42921
|
+
|
|
42836
42922
|
// ../swap/dist/index.mjs
|
|
42837
42923
|
init_dist();
|
|
42924
|
+
init_dist();
|
|
42925
|
+
init_dist();
|
|
42838
42926
|
var SwapClient = class {
|
|
42839
42927
|
constructor(httpClient) {
|
|
42840
42928
|
this.httpClient = httpClient;
|
|
@@ -43116,9 +43204,9 @@ var SwapExecutor = class {
|
|
|
43116
43204
|
);
|
|
43117
43205
|
const chainConfig = getChainById(params.fromChain);
|
|
43118
43206
|
const transactions = await withRetry(() => this.swapClient.getSwapTransactions(route));
|
|
43119
|
-
let
|
|
43207
|
+
let approvalHash;
|
|
43120
43208
|
try {
|
|
43121
|
-
|
|
43209
|
+
approvalHash = await this.ensureStepApproval(
|
|
43122
43210
|
route,
|
|
43123
43211
|
transactions,
|
|
43124
43212
|
chainConfig,
|
|
@@ -43126,10 +43214,10 @@ var SwapExecutor = class {
|
|
|
43126
43214
|
address,
|
|
43127
43215
|
parsedAmount
|
|
43128
43216
|
);
|
|
43129
|
-
if (
|
|
43130
|
-
await this.pollForConfirmation(params.fromChain, address,
|
|
43217
|
+
if (approvalHash) {
|
|
43218
|
+
await this.pollForConfirmation(params.fromChain, address, approvalHash, 6e4);
|
|
43131
43219
|
}
|
|
43132
|
-
let
|
|
43220
|
+
let hash = "";
|
|
43133
43221
|
for (const txData of transactions) {
|
|
43134
43222
|
const txType = txData.transaction.type;
|
|
43135
43223
|
const isApproval = txType === "approval" || txType === "revokeApproval";
|
|
@@ -43138,30 +43226,30 @@ var SwapExecutor = class {
|
|
|
43138
43226
|
txType === "revokeApproval" ? "Revoking prior approval..." : "Sending token approval..."
|
|
43139
43227
|
);
|
|
43140
43228
|
}
|
|
43141
|
-
|
|
43142
|
-
if (isApproval)
|
|
43229
|
+
hash = await this.sendTransaction(txData, chainConfig, params.fromChain);
|
|
43230
|
+
if (isApproval) approvalHash = hash;
|
|
43143
43231
|
this.log(
|
|
43144
|
-
`${isApproval ? "Approval" : "Swap"} tx: ${getExplorerTxUrl(params.fromChain,
|
|
43232
|
+
`${isApproval ? "Approval" : "Swap"} tx: ${getExplorerTxUrl(params.fromChain, hash)}`
|
|
43145
43233
|
);
|
|
43146
43234
|
await this.pollForConfirmation(
|
|
43147
43235
|
params.fromChain,
|
|
43148
43236
|
address,
|
|
43149
|
-
|
|
43237
|
+
hash,
|
|
43150
43238
|
isApproval ? 6e4 : 12e4
|
|
43151
43239
|
);
|
|
43152
43240
|
}
|
|
43153
43241
|
return {
|
|
43154
43242
|
success: true,
|
|
43155
|
-
|
|
43243
|
+
hash,
|
|
43156
43244
|
route,
|
|
43157
|
-
explorerUrl: getExplorerTxUrl(params.fromChain,
|
|
43245
|
+
explorerUrl: getExplorerTxUrl(params.fromChain, hash)
|
|
43158
43246
|
};
|
|
43159
43247
|
} catch (err) {
|
|
43160
43248
|
let msg = err instanceof Error ? err.message : "Unknown error";
|
|
43161
43249
|
let code2 = classifySwapError(msg);
|
|
43162
|
-
if (
|
|
43250
|
+
if (approvalHash) {
|
|
43163
43251
|
code2 = "APPROVAL_SENT_SWAP_FAILED";
|
|
43164
|
-
msg += `. Approval was sent (tx: ${
|
|
43252
|
+
msg += `. Approval was sent (tx: ${approvalHash}). Check allowance before retrying.`;
|
|
43165
43253
|
}
|
|
43166
43254
|
return { success: false, route, error: msg, code: code2 };
|
|
43167
43255
|
}
|
|
@@ -43193,8 +43281,8 @@ var SwapExecutor = class {
|
|
|
43193
43281
|
if (allowance >= required) return void 0;
|
|
43194
43282
|
this.log("Sending token approval...");
|
|
43195
43283
|
const approveResult = await blockchainClient.contract(erc20).withAddress(fromAssetAddr, fromChain).write.approve([stepApproval.operatorAddress, required], this.walletProvider);
|
|
43196
|
-
this.log(`Approval tx: ${getExplorerTxUrl(fromChain, approveResult.
|
|
43197
|
-
return approveResult.
|
|
43284
|
+
this.log(`Approval tx: ${getExplorerTxUrl(fromChain, approveResult.hash)}`);
|
|
43285
|
+
return approveResult.hash;
|
|
43198
43286
|
}
|
|
43199
43287
|
getBlockchainClient() {
|
|
43200
43288
|
const blockchainClient = this.walletProvider.getBlockchainClient?.() ?? this.options.blockchainClient;
|
|
@@ -43419,11 +43507,11 @@ function registerTransferCommand(program3) {
|
|
|
43419
43507
|
} catch (err) {
|
|
43420
43508
|
mapBroadcastError(err);
|
|
43421
43509
|
}
|
|
43422
|
-
const explorerUrl = getExplorerTxUrl(result.chainKey, result.
|
|
43510
|
+
const explorerUrl = getExplorerTxUrl(result.chainKey, result.hash);
|
|
43423
43511
|
success("Transfer sent!");
|
|
43424
43512
|
output(
|
|
43425
43513
|
{
|
|
43426
|
-
hash: result.
|
|
43514
|
+
hash: result.hash,
|
|
43427
43515
|
chain: result.chainKey,
|
|
43428
43516
|
from: address,
|
|
43429
43517
|
to: resolvedTo,
|
|
@@ -43640,7 +43728,7 @@ function registerSwapCommand(program3) {
|
|
|
43640
43728
|
output(
|
|
43641
43729
|
{
|
|
43642
43730
|
...quoteData,
|
|
43643
|
-
hash: result.
|
|
43731
|
+
hash: result.hash,
|
|
43644
43732
|
fromChain,
|
|
43645
43733
|
toChain,
|
|
43646
43734
|
explorer: result.explorerUrl
|
|
@@ -43723,11 +43811,11 @@ function registerErc20Command(program3) {
|
|
|
43723
43811
|
info(`Approving ${opts.spender} to spend from ${address} on ${chainKey}...`);
|
|
43724
43812
|
const client = provider.getBlockchainClient();
|
|
43725
43813
|
const pending = await client.contract(erc20).withAddress(contractAddress, chainKey).write.approve([opts.spender, BigInt(amount)], provider);
|
|
43726
|
-
const explorerUrl = getExplorerTxUrl(chainKey, pending.
|
|
43814
|
+
const explorerUrl = getExplorerTxUrl(chainKey, pending.hash);
|
|
43727
43815
|
success("Approval sent!");
|
|
43728
43816
|
output(
|
|
43729
43817
|
{
|
|
43730
|
-
hash: pending.
|
|
43818
|
+
hash: pending.hash,
|
|
43731
43819
|
chain: chainKey,
|
|
43732
43820
|
owner: address,
|
|
43733
43821
|
spender: opts.spender,
|
|
@@ -43764,11 +43852,11 @@ function registerErc20Command(program3) {
|
|
|
43764
43852
|
info(`Revoking approval for ${opts.spender} on ${chainKey}...`);
|
|
43765
43853
|
const client = provider.getBlockchainClient();
|
|
43766
43854
|
const pending = await client.contract(erc20).withAddress(contractAddress, chainKey).write.approve([opts.spender, 0n], provider);
|
|
43767
|
-
const explorerUrl = getExplorerTxUrl(chainKey, pending.
|
|
43855
|
+
const explorerUrl = getExplorerTxUrl(chainKey, pending.hash);
|
|
43768
43856
|
success("Approval revoked!");
|
|
43769
43857
|
output(
|
|
43770
43858
|
{
|
|
43771
|
-
hash: pending.
|
|
43859
|
+
hash: pending.hash,
|
|
43772
43860
|
chain: chainKey,
|
|
43773
43861
|
owner: address,
|
|
43774
43862
|
spender: opts.spender,
|
|
@@ -43918,7 +44006,7 @@ function registerErc8004Command(program3) {
|
|
|
43918
44006
|
if (!registered) {
|
|
43919
44007
|
throw new WalletError(
|
|
43920
44008
|
"TX_FAILED",
|
|
43921
|
-
`No Registered event emitted (
|
|
44009
|
+
`No Registered event emitted (hash=${confirmed.hash})`
|
|
43922
44010
|
);
|
|
43923
44011
|
}
|
|
43924
44012
|
success("Agent registered!");
|
|
@@ -43928,9 +44016,9 @@ function registerErc8004Command(program3) {
|
|
|
43928
44016
|
owner: registered.owner,
|
|
43929
44017
|
agentURI: registered.agentURI,
|
|
43930
44018
|
...metadata.length > 0 ? { metadata: Object.fromEntries(metadata) } : {},
|
|
43931
|
-
hash: confirmed.
|
|
44019
|
+
hash: confirmed.hash,
|
|
43932
44020
|
chain: chainKey,
|
|
43933
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44021
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
43934
44022
|
},
|
|
43935
44023
|
opts.json
|
|
43936
44024
|
);
|
|
@@ -43964,9 +44052,9 @@ function registerErc8004Command(program3) {
|
|
|
43964
44052
|
{
|
|
43965
44053
|
agentId,
|
|
43966
44054
|
agentURI: opts.uri,
|
|
43967
|
-
hash: confirmed.
|
|
44055
|
+
hash: confirmed.hash,
|
|
43968
44056
|
chain: chainKey,
|
|
43969
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44057
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
43970
44058
|
},
|
|
43971
44059
|
opts.json
|
|
43972
44060
|
);
|
|
@@ -43999,9 +44087,9 @@ function registerErc8004Command(program3) {
|
|
|
43999
44087
|
agentId,
|
|
44000
44088
|
key: opts.key,
|
|
44001
44089
|
value: valueBytes,
|
|
44002
|
-
hash: confirmed.
|
|
44090
|
+
hash: confirmed.hash,
|
|
44003
44091
|
chain: chainKey,
|
|
44004
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44092
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44005
44093
|
},
|
|
44006
44094
|
opts.json
|
|
44007
44095
|
);
|
|
@@ -44061,6 +44149,8 @@ function registerErc8004Command(program3) {
|
|
|
44061
44149
|
init_dist();
|
|
44062
44150
|
init_dist3();
|
|
44063
44151
|
var CHAIN_OPT = "EVM chain key (`bsc` and `bsctestnet` have known deployments)";
|
|
44152
|
+
var OPT_PARAMS_OPT = "Optional opaque optParams bytes passed through raw, as 0x-prefixed hex (defaults to empty)";
|
|
44153
|
+
var SUBMIT_OPT_PARAMS_OPT = `${OPT_PARAMS_OPT}. Evaluators may expect deliverable metadata here, e.g. hex-encoded UTF-8 JSON like {"deliverable_url": "..."}`;
|
|
44064
44154
|
var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
|
|
44065
44155
|
function parseUint(value, label) {
|
|
44066
44156
|
if (!/^\d+$/.test(value)) {
|
|
@@ -44071,6 +44161,16 @@ function parseUint(value, label) {
|
|
|
44071
44161
|
}
|
|
44072
44162
|
return BigInt(value);
|
|
44073
44163
|
}
|
|
44164
|
+
function parseOptParams(value) {
|
|
44165
|
+
if (value === void 0) return "0x";
|
|
44166
|
+
if (!/^0x([0-9a-fA-F]{2})*$/.test(value)) {
|
|
44167
|
+
throw new WalletError(
|
|
44168
|
+
"VALIDATION_ERROR",
|
|
44169
|
+
`--opt-params must be 0x-prefixed bytes (even-length hex): ${value}`
|
|
44170
|
+
);
|
|
44171
|
+
}
|
|
44172
|
+
return value;
|
|
44173
|
+
}
|
|
44074
44174
|
function registerErc8183Command(program3) {
|
|
44075
44175
|
const cmd = program3.command("erc8183").description("ERC-8183 Agentic Commerce \u2014 on-chain job escrows between AI agents");
|
|
44076
44176
|
cmd.command("create-job").description("Create a new job (caller becomes the client)").requiredOption("--provider <address>", "Provider (worker) address").requiredOption("--evaluator <address>", "Evaluator address").requiredOption("--expires-at <unix>", "Expiry as a unix timestamp (seconds)").requiredOption("--description <text>", "Human-readable job description").option("--hook <address>", "Optional hook contract (defaults to none)").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (opts) => {
|
|
@@ -44093,7 +44193,7 @@ function registerErc8183Command(program3) {
|
|
|
44093
44193
|
if (!created) {
|
|
44094
44194
|
throw new WalletError(
|
|
44095
44195
|
"TX_FAILED",
|
|
44096
|
-
`No JobCreated event emitted (
|
|
44196
|
+
`No JobCreated event emitted (hash=${confirmed.hash})`
|
|
44097
44197
|
);
|
|
44098
44198
|
}
|
|
44099
44199
|
success("Job created!");
|
|
@@ -44101,9 +44201,9 @@ function registerErc8183Command(program3) {
|
|
|
44101
44201
|
{
|
|
44102
44202
|
jobId: created.jobId.toString(),
|
|
44103
44203
|
status: "Open",
|
|
44104
|
-
hash: confirmed.
|
|
44204
|
+
hash: confirmed.hash,
|
|
44105
44205
|
chain: chainKey,
|
|
44106
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44206
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44107
44207
|
},
|
|
44108
44208
|
opts.json
|
|
44109
44209
|
);
|
|
@@ -44112,9 +44212,10 @@ function registerErc8183Command(program3) {
|
|
|
44112
44212
|
}
|
|
44113
44213
|
safeExit();
|
|
44114
44214
|
});
|
|
44115
|
-
cmd.command("set-provider <jobId>").description("Set or change the provider (client, while the job is Open)").requiredOption("--provider <address>", "New provider (worker) address").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44215
|
+
cmd.command("set-provider <jobId>").description("Set or change the provider (client, while the job is Open)").requiredOption("--provider <address>", "New provider (worker) address").option("--opt-params <hex>", OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44116
44216
|
try {
|
|
44117
44217
|
const id = parseUint(jobId, "jobId");
|
|
44218
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44118
44219
|
await ensureTrustSDK();
|
|
44119
44220
|
const password3 = await resolvePassword(opts);
|
|
44120
44221
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
@@ -44123,16 +44224,16 @@ function registerErc8183Command(program3) {
|
|
|
44123
44224
|
opts.chain
|
|
44124
44225
|
);
|
|
44125
44226
|
info(`Setting provider for job ${jobId} on ${chainKey}...`);
|
|
44126
|
-
const pending = await commerce.write.setProvider([id, opts.provider,
|
|
44227
|
+
const pending = await commerce.write.setProvider([id, opts.provider, optParams], provider);
|
|
44127
44228
|
const confirmed = await pending.wait();
|
|
44128
44229
|
success("Provider set!");
|
|
44129
44230
|
output(
|
|
44130
44231
|
{
|
|
44131
44232
|
jobId,
|
|
44132
44233
|
provider: opts.provider,
|
|
44133
|
-
hash: confirmed.
|
|
44234
|
+
hash: confirmed.hash,
|
|
44134
44235
|
chain: chainKey,
|
|
44135
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44236
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44136
44237
|
},
|
|
44137
44238
|
opts.json
|
|
44138
44239
|
);
|
|
@@ -44141,10 +44242,11 @@ function registerErc8183Command(program3) {
|
|
|
44141
44242
|
}
|
|
44142
44243
|
safeExit();
|
|
44143
44244
|
});
|
|
44144
|
-
cmd.command("set-budget <jobId>").description("Set the escrow budget (atomic units of the payment token)").requiredOption("--amount <atomic>", "Budget in atomic units").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44245
|
+
cmd.command("set-budget <jobId>").description("Set the escrow budget (atomic units of the payment token)").requiredOption("--amount <atomic>", "Budget in atomic units").option("--opt-params <hex>", OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44145
44246
|
try {
|
|
44146
44247
|
const id = parseUint(jobId, "jobId");
|
|
44147
44248
|
const amount = parseUint(opts.amount, "amount");
|
|
44249
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44148
44250
|
await ensureTrustSDK();
|
|
44149
44251
|
const password3 = await resolvePassword(opts);
|
|
44150
44252
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
@@ -44153,16 +44255,16 @@ function registerErc8183Command(program3) {
|
|
|
44153
44255
|
opts.chain
|
|
44154
44256
|
);
|
|
44155
44257
|
info(`Setting budget for job ${jobId} on ${chainKey}...`);
|
|
44156
|
-
const pending = await commerce.write.setBudget([id, amount,
|
|
44258
|
+
const pending = await commerce.write.setBudget([id, amount, optParams], provider);
|
|
44157
44259
|
const confirmed = await pending.wait();
|
|
44158
44260
|
success("Budget set!");
|
|
44159
44261
|
output(
|
|
44160
44262
|
{
|
|
44161
44263
|
jobId,
|
|
44162
44264
|
amount: opts.amount,
|
|
44163
|
-
hash: confirmed.
|
|
44265
|
+
hash: confirmed.hash,
|
|
44164
44266
|
chain: chainKey,
|
|
44165
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44267
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44166
44268
|
},
|
|
44167
44269
|
opts.json
|
|
44168
44270
|
);
|
|
@@ -44171,37 +44273,53 @@ function registerErc8183Command(program3) {
|
|
|
44171
44273
|
}
|
|
44172
44274
|
safeExit();
|
|
44173
44275
|
});
|
|
44174
|
-
cmd.command("fund <jobId>").description("Fund a job: approve the budget then deposit it into escrow (two txs)").option(
|
|
44276
|
+
cmd.command("fund <jobId>").description("Fund a job: approve the budget then deposit it into escrow (two txs)").option(
|
|
44277
|
+
"--expected-budget <atomic>",
|
|
44278
|
+
"Pin the budget (atomic units): approve and fund exactly this amount instead of reading it on-chain; the contract reverts with BudgetMismatch if the on-chain budget differs"
|
|
44279
|
+
).option("--opt-params <hex>", OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44175
44280
|
try {
|
|
44176
44281
|
const id = parseUint(jobId, "jobId");
|
|
44282
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44177
44283
|
await ensureTrustSDK();
|
|
44178
44284
|
const password3 = await resolvePassword(opts);
|
|
44179
44285
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
44180
44286
|
const client = provider.getBlockchainClient();
|
|
44181
44287
|
const { commerce, chainKey } = resolveErc8183Contracts(client, opts.chain);
|
|
44182
|
-
|
|
44183
|
-
if (
|
|
44184
|
-
|
|
44185
|
-
|
|
44186
|
-
|
|
44187
|
-
|
|
44288
|
+
let budget;
|
|
44289
|
+
if (opts.expectedBudget !== void 0) {
|
|
44290
|
+
budget = parseUint(opts.expectedBudget, "expected-budget");
|
|
44291
|
+
if (budget === 0n) {
|
|
44292
|
+
throw new WalletError(
|
|
44293
|
+
"VALIDATION_ERROR",
|
|
44294
|
+
"--expected-budget must be greater than zero."
|
|
44295
|
+
);
|
|
44296
|
+
}
|
|
44297
|
+
} else {
|
|
44298
|
+
const job = await commerce.read.getJob([id]);
|
|
44299
|
+
if (job.budget === 0n) {
|
|
44300
|
+
throw new WalletError(
|
|
44301
|
+
"VALIDATION_ERROR",
|
|
44302
|
+
`Job ${jobId} has no budget set \u2014 run \`twak erc8183 set-budget\` before funding.`
|
|
44303
|
+
);
|
|
44304
|
+
}
|
|
44305
|
+
budget = job.budget;
|
|
44188
44306
|
}
|
|
44189
44307
|
const token = await commerce.read.paymentToken([]);
|
|
44190
|
-
info(`Approving ${
|
|
44191
|
-
const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address,
|
|
44308
|
+
info(`Approving ${budget.toString()} for the escrow on ${chainKey}...`);
|
|
44309
|
+
const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, budget], provider);
|
|
44192
44310
|
const approveConfirmed = await approvePending.wait();
|
|
44193
44311
|
info(`Funding job ${jobId}...`);
|
|
44194
|
-
const fundPending = await commerce.write.fund([id,
|
|
44312
|
+
const fundPending = await commerce.write.fund([id, budget, optParams], provider);
|
|
44195
44313
|
const fundConfirmed = await fundPending.wait();
|
|
44196
44314
|
success("Job funded!");
|
|
44197
44315
|
output(
|
|
44198
44316
|
{
|
|
44199
44317
|
jobId,
|
|
44200
44318
|
status: "Funded",
|
|
44201
|
-
approveHash: approveConfirmed.
|
|
44202
|
-
hash: fundConfirmed.
|
|
44319
|
+
approveHash: approveConfirmed.hash,
|
|
44320
|
+
hash: fundConfirmed.hash,
|
|
44203
44321
|
chain: chainKey,
|
|
44204
|
-
explorer: getExplorerTxUrl(chainKey, fundConfirmed.
|
|
44322
|
+
explorer: getExplorerTxUrl(chainKey, fundConfirmed.hash)
|
|
44205
44323
|
},
|
|
44206
44324
|
opts.json
|
|
44207
44325
|
);
|
|
@@ -44210,9 +44328,10 @@ function registerErc8183Command(program3) {
|
|
|
44210
44328
|
}
|
|
44211
44329
|
safeExit();
|
|
44212
44330
|
});
|
|
44213
|
-
cmd.command("submit <jobId>").description("Submit a deliverable (bytes32 commitment) for a funded job").requiredOption("--deliverable <bytes32>", "0x-prefixed 32-byte deliverable commitment").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44331
|
+
cmd.command("submit <jobId>").description("Submit a deliverable (bytes32 commitment) for a funded job").requiredOption("--deliverable <bytes32>", "0x-prefixed 32-byte deliverable commitment").option("--opt-params <hex>", SUBMIT_OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44214
44332
|
try {
|
|
44215
44333
|
const id = parseUint(jobId, "jobId");
|
|
44334
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44216
44335
|
await ensureTrustSDK();
|
|
44217
44336
|
const password3 = await resolvePassword(opts);
|
|
44218
44337
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
@@ -44221,16 +44340,16 @@ function registerErc8183Command(program3) {
|
|
|
44221
44340
|
opts.chain
|
|
44222
44341
|
);
|
|
44223
44342
|
info(`Submitting deliverable for job ${jobId} on ${chainKey}...`);
|
|
44224
|
-
const pending = await commerce.write.submit([id, opts.deliverable,
|
|
44343
|
+
const pending = await commerce.write.submit([id, opts.deliverable, optParams], provider);
|
|
44225
44344
|
const confirmed = await pending.wait();
|
|
44226
44345
|
success("Deliverable submitted!");
|
|
44227
44346
|
output(
|
|
44228
44347
|
{
|
|
44229
44348
|
jobId,
|
|
44230
44349
|
status: "Submitted",
|
|
44231
|
-
hash: confirmed.
|
|
44350
|
+
hash: confirmed.hash,
|
|
44232
44351
|
chain: chainKey,
|
|
44233
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44352
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44234
44353
|
},
|
|
44235
44354
|
opts.json
|
|
44236
44355
|
);
|
|
@@ -44239,9 +44358,10 @@ function registerErc8183Command(program3) {
|
|
|
44239
44358
|
}
|
|
44240
44359
|
safeExit();
|
|
44241
44360
|
});
|
|
44242
|
-
cmd.command("complete <jobId>").description("Mark a submitted job complete (evaluator) \u2014 releases escrow").option("--reason <bytes32>", "Optional bytes32 attestation (defaults to zero)").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44361
|
+
cmd.command("complete <jobId>").description("Mark a submitted job complete (evaluator) \u2014 releases escrow").option("--reason <bytes32>", "Optional bytes32 attestation (defaults to zero)").option("--opt-params <hex>", OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44243
44362
|
try {
|
|
44244
44363
|
const id = parseUint(jobId, "jobId");
|
|
44364
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44245
44365
|
await ensureTrustSDK();
|
|
44246
44366
|
const password3 = await resolvePassword(opts);
|
|
44247
44367
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
@@ -44251,7 +44371,7 @@ function registerErc8183Command(program3) {
|
|
|
44251
44371
|
);
|
|
44252
44372
|
info(`Completing job ${jobId} on ${chainKey}...`);
|
|
44253
44373
|
const pending = await commerce.write.complete(
|
|
44254
|
-
[id, opts.reason ?? ZERO_BYTES32,
|
|
44374
|
+
[id, opts.reason ?? ZERO_BYTES32, optParams],
|
|
44255
44375
|
provider
|
|
44256
44376
|
);
|
|
44257
44377
|
const confirmed = await pending.wait();
|
|
@@ -44262,9 +44382,9 @@ function registerErc8183Command(program3) {
|
|
|
44262
44382
|
jobId,
|
|
44263
44383
|
status: "Completed",
|
|
44264
44384
|
released: released ? released.amount.toString() : null,
|
|
44265
|
-
hash: confirmed.
|
|
44385
|
+
hash: confirmed.hash,
|
|
44266
44386
|
chain: chainKey,
|
|
44267
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44387
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44268
44388
|
},
|
|
44269
44389
|
opts.json
|
|
44270
44390
|
);
|
|
@@ -44273,9 +44393,10 @@ function registerErc8183Command(program3) {
|
|
|
44273
44393
|
}
|
|
44274
44394
|
safeExit();
|
|
44275
44395
|
});
|
|
44276
|
-
cmd.command("reject <jobId>").description("Reject a job \u2014 refunds the client if funded").option("--reason <bytes32>", "Optional bytes32 reason (defaults to zero)").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44396
|
+
cmd.command("reject <jobId>").description("Reject a job \u2014 refunds the client if funded").option("--reason <bytes32>", "Optional bytes32 reason (defaults to zero)").option("--opt-params <hex>", OPT_PARAMS_OPT).option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44277
44397
|
try {
|
|
44278
44398
|
const id = parseUint(jobId, "jobId");
|
|
44399
|
+
const optParams = parseOptParams(opts.optParams);
|
|
44279
44400
|
await ensureTrustSDK();
|
|
44280
44401
|
const password3 = await resolvePassword(opts);
|
|
44281
44402
|
const provider = await AgentWalletProvider.fromStorage(password3);
|
|
@@ -44285,7 +44406,7 @@ function registerErc8183Command(program3) {
|
|
|
44285
44406
|
);
|
|
44286
44407
|
info(`Rejecting job ${jobId} on ${chainKey}...`);
|
|
44287
44408
|
const pending = await commerce.write.reject(
|
|
44288
|
-
[id, opts.reason ?? ZERO_BYTES32,
|
|
44409
|
+
[id, opts.reason ?? ZERO_BYTES32, optParams],
|
|
44289
44410
|
provider
|
|
44290
44411
|
);
|
|
44291
44412
|
const confirmed = await pending.wait();
|
|
@@ -44296,9 +44417,9 @@ function registerErc8183Command(program3) {
|
|
|
44296
44417
|
jobId,
|
|
44297
44418
|
status: "Rejected",
|
|
44298
44419
|
refunded: refunded ? refunded.amount.toString() : null,
|
|
44299
|
-
hash: confirmed.
|
|
44420
|
+
hash: confirmed.hash,
|
|
44300
44421
|
chain: chainKey,
|
|
44301
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44422
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44302
44423
|
},
|
|
44303
44424
|
opts.json
|
|
44304
44425
|
);
|
|
@@ -44327,9 +44448,9 @@ function registerErc8183Command(program3) {
|
|
|
44327
44448
|
jobId,
|
|
44328
44449
|
status: "Expired",
|
|
44329
44450
|
refunded: refunded ? refunded.amount.toString() : null,
|
|
44330
|
-
hash: confirmed.
|
|
44451
|
+
hash: confirmed.hash,
|
|
44331
44452
|
chain: chainKey,
|
|
44332
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44453
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44333
44454
|
},
|
|
44334
44455
|
opts.json
|
|
44335
44456
|
);
|
|
@@ -44389,9 +44510,9 @@ function registerErc8183Command(program3) {
|
|
|
44389
44510
|
{
|
|
44390
44511
|
jobId,
|
|
44391
44512
|
policy: policyAddr,
|
|
44392
|
-
hash: confirmed.
|
|
44513
|
+
hash: confirmed.hash,
|
|
44393
44514
|
chain: chainKey,
|
|
44394
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44515
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44395
44516
|
},
|
|
44396
44517
|
opts.json
|
|
44397
44518
|
);
|
|
@@ -44417,9 +44538,9 @@ function registerErc8183Command(program3) {
|
|
|
44417
44538
|
output(
|
|
44418
44539
|
{
|
|
44419
44540
|
jobId,
|
|
44420
|
-
hash: confirmed.
|
|
44541
|
+
hash: confirmed.hash,
|
|
44421
44542
|
chain: chainKey,
|
|
44422
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44543
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44423
44544
|
},
|
|
44424
44545
|
opts.json
|
|
44425
44546
|
);
|
|
@@ -44446,9 +44567,9 @@ function registerErc8183Command(program3) {
|
|
|
44446
44567
|
{
|
|
44447
44568
|
jobId,
|
|
44448
44569
|
status: "Expired",
|
|
44449
|
-
hash: confirmed.
|
|
44570
|
+
hash: confirmed.hash,
|
|
44450
44571
|
chain: chainKey,
|
|
44451
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44572
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44452
44573
|
},
|
|
44453
44574
|
opts.json
|
|
44454
44575
|
);
|
|
@@ -44457,6 +44578,45 @@ function registerErc8183Command(program3) {
|
|
|
44457
44578
|
}
|
|
44458
44579
|
safeExit();
|
|
44459
44580
|
});
|
|
44581
|
+
cmd.command("policy-info <jobId>").description("Show dispute-policy state for a job (read-only)").option("--chain <key>", CHAIN_OPT, "bsc").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44582
|
+
try {
|
|
44583
|
+
const id = parseUint(jobId, "jobId");
|
|
44584
|
+
await ensureTrustSDK();
|
|
44585
|
+
const client = new BlockchainClient();
|
|
44586
|
+
const { router, policy, chainKey } = resolveErc8183Contracts(client, opts.chain);
|
|
44587
|
+
const registeredPolicy = await router.read.jobPolicy([id]);
|
|
44588
|
+
const registered = !isZeroAddress(registeredPolicy);
|
|
44589
|
+
const policyContract = registered && registeredPolicy.toLowerCase() !== policy.address.toLowerCase() ? erc8183Policy.using(client).withAddress(registeredPolicy, chainKey) : policy;
|
|
44590
|
+
const [disputeWindow, submittedAt, disputed, rejectVotes, voteQuorum, quorumSnapshot] = await Promise.all([
|
|
44591
|
+
policyContract.read.disputeWindow([]),
|
|
44592
|
+
policyContract.read.submittedAt([id]),
|
|
44593
|
+
policyContract.read.disputed([id]),
|
|
44594
|
+
policyContract.read.rejectVotes([id]),
|
|
44595
|
+
policyContract.read.voteQuorum([]),
|
|
44596
|
+
policyContract.read.disputeQuorumSnapshot([id])
|
|
44597
|
+
]);
|
|
44598
|
+
const settleableAt = submittedAt > 0n ? submittedAt + disputeWindow : null;
|
|
44599
|
+
output(
|
|
44600
|
+
{
|
|
44601
|
+
jobId,
|
|
44602
|
+
policy: policyContract.address,
|
|
44603
|
+
registered,
|
|
44604
|
+
disputeWindow: disputeWindow.toString(),
|
|
44605
|
+
submittedAt: submittedAt.toString(),
|
|
44606
|
+
disputed,
|
|
44607
|
+
rejectVotes: rejectVotes.toString(),
|
|
44608
|
+
voteQuorum: voteQuorum.toString(),
|
|
44609
|
+
quorumSnapshot: quorumSnapshot.toString(),
|
|
44610
|
+
settleableAt: settleableAt?.toString() ?? null,
|
|
44611
|
+
chain: chainKey
|
|
44612
|
+
},
|
|
44613
|
+
opts.json
|
|
44614
|
+
);
|
|
44615
|
+
} catch (err) {
|
|
44616
|
+
handleCommandError(err, opts.json, "policy-info failed");
|
|
44617
|
+
}
|
|
44618
|
+
safeExit();
|
|
44619
|
+
});
|
|
44460
44620
|
cmd.command("dispute <jobId>").description("Raise a dispute on a job via the OptimisticPolicy (client)").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
|
|
44461
44621
|
try {
|
|
44462
44622
|
const id = parseUint(jobId, "jobId");
|
|
@@ -44474,9 +44634,9 @@ function registerErc8183Command(program3) {
|
|
|
44474
44634
|
output(
|
|
44475
44635
|
{
|
|
44476
44636
|
jobId,
|
|
44477
|
-
hash: confirmed.
|
|
44637
|
+
hash: confirmed.hash,
|
|
44478
44638
|
chain: chainKey,
|
|
44479
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44639
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44480
44640
|
},
|
|
44481
44641
|
opts.json
|
|
44482
44642
|
);
|
|
@@ -44502,9 +44662,9 @@ function registerErc8183Command(program3) {
|
|
|
44502
44662
|
output(
|
|
44503
44663
|
{
|
|
44504
44664
|
jobId,
|
|
44505
|
-
hash: confirmed.
|
|
44665
|
+
hash: confirmed.hash,
|
|
44506
44666
|
chain: chainKey,
|
|
44507
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44667
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44508
44668
|
},
|
|
44509
44669
|
opts.json
|
|
44510
44670
|
);
|
|
@@ -44570,7 +44730,7 @@ function registerCompeteCommand(program3) {
|
|
|
44570
44730
|
if (!confirmed.events.Registered?.[0]) {
|
|
44571
44731
|
throw new WalletError(
|
|
44572
44732
|
"TX_FAILED",
|
|
44573
|
-
`no Registered event emitted (
|
|
44733
|
+
`no Registered event emitted (hash=${confirmed.hash})`
|
|
44574
44734
|
);
|
|
44575
44735
|
}
|
|
44576
44736
|
success("Registered for BNB HACK: AI TRADING AGENT EDITION!");
|
|
@@ -44579,9 +44739,9 @@ function registerCompeteCommand(program3) {
|
|
|
44579
44739
|
registered: true,
|
|
44580
44740
|
participant,
|
|
44581
44741
|
deadline: toIso(deadline),
|
|
44582
|
-
hash: confirmed.
|
|
44742
|
+
hash: confirmed.hash,
|
|
44583
44743
|
chain: chainKey,
|
|
44584
|
-
explorer: getExplorerTxUrl(chainKey, confirmed.
|
|
44744
|
+
explorer: getExplorerTxUrl(chainKey, confirmed.hash)
|
|
44585
44745
|
},
|
|
44586
44746
|
opts.json
|
|
44587
44747
|
);
|
|
@@ -46259,15 +46419,15 @@ async function ensurePermit2Allowance(args) {
|
|
|
46259
46419
|
[PERMIT2_ADDRESS, BigInt(MAX_UINT256_DECIMAL)],
|
|
46260
46420
|
args.walletProvider
|
|
46261
46421
|
);
|
|
46262
|
-
await waitForTxConfirmation(args.blockchainClient, args.chainKey, args.owner, pending.
|
|
46263
|
-
return { token: args.tokenAddress, chain: args.chainKey,
|
|
46422
|
+
await waitForTxConfirmation(args.blockchainClient, args.chainKey, args.owner, pending.hash);
|
|
46423
|
+
return { token: args.tokenAddress, chain: args.chainKey, hash: pending.hash };
|
|
46264
46424
|
}
|
|
46265
46425
|
var APPROVE_TIMEOUT_MS = 6e4;
|
|
46266
46426
|
var APPROVE_POLL_MS = 2e3;
|
|
46267
|
-
async function waitForTxConfirmation(bc2, chainKey, address,
|
|
46427
|
+
async function waitForTxConfirmation(bc2, chainKey, address, hash) {
|
|
46268
46428
|
const start = Date.now();
|
|
46269
46429
|
while (Date.now() - start < APPROVE_TIMEOUT_MS) {
|
|
46270
|
-
const status = await bc2.findTransactionStatus(chainKey, address,
|
|
46430
|
+
const status = await bc2.findTransactionStatus(chainKey, address, hash);
|
|
46271
46431
|
if (status.confirmed) return;
|
|
46272
46432
|
if (status.failed) {
|
|
46273
46433
|
throw new X402Error(
|
|
@@ -46279,7 +46439,7 @@ async function waitForTxConfirmation(bc2, chainKey, address, txHash) {
|
|
|
46279
46439
|
}
|
|
46280
46440
|
throw new X402Error(
|
|
46281
46441
|
"TX_FAILED",
|
|
46282
|
-
`Permit2 approval ${
|
|
46442
|
+
`Permit2 approval ${hash} not confirmed within ${APPROVE_TIMEOUT_MS / 1e3}s`
|
|
46283
46443
|
);
|
|
46284
46444
|
}
|
|
46285
46445
|
function ipv4MappedToDotted(ip) {
|
|
@@ -46796,7 +46956,7 @@ var TransferActionProvider = class extends ActionProvider {
|
|
|
46796
46956
|
const resolvedTo = await resolveAddressOrName(input2.to);
|
|
46797
46957
|
const atomicAmount = parseAmount(input2.amount, decimals);
|
|
46798
46958
|
const isErc20 = Boolean(tokenAddress);
|
|
46799
|
-
let
|
|
46959
|
+
let hash;
|
|
46800
46960
|
if (isErc20) {
|
|
46801
46961
|
if (!this.blockchainClient) {
|
|
46802
46962
|
throw new TransferError(
|
|
@@ -46805,19 +46965,19 @@ var TransferActionProvider = class extends ActionProvider {
|
|
|
46805
46965
|
);
|
|
46806
46966
|
}
|
|
46807
46967
|
const pending = await this.blockchainClient.contract(erc20).withAddress(tokenAddress, chainKey).write.transfer([resolvedTo, BigInt(atomicAmount)], signer);
|
|
46808
|
-
|
|
46968
|
+
hash = pending.hash;
|
|
46809
46969
|
} else {
|
|
46810
|
-
|
|
46970
|
+
hash = await signer.sendTransaction({
|
|
46811
46971
|
chainId: caip2,
|
|
46812
46972
|
to: resolvedTo,
|
|
46813
46973
|
data: "0x",
|
|
46814
46974
|
value: "0x" + BigInt(atomicAmount).toString(16)
|
|
46815
46975
|
});
|
|
46816
46976
|
}
|
|
46817
|
-
const explorerUrl = getExplorerTxUrl(chainKey,
|
|
46977
|
+
const explorerUrl = getExplorerTxUrl(chainKey, hash);
|
|
46818
46978
|
return {
|
|
46819
46979
|
success: true,
|
|
46820
|
-
|
|
46980
|
+
hash,
|
|
46821
46981
|
to: resolvedTo,
|
|
46822
46982
|
resolvedFrom: input2.to !== resolvedTo ? input2.to : void 0,
|
|
46823
46983
|
explorer: explorerUrl || void 0
|
|
@@ -46902,7 +47062,7 @@ var SwapActionProvider = class extends ActionProvider {
|
|
|
46902
47062
|
const outputAmt = formatAmount(lastStep.to.amount, lastStep.to.asset.metadata.decimals);
|
|
46903
47063
|
return {
|
|
46904
47064
|
success: true,
|
|
46905
|
-
|
|
47065
|
+
hash: result.hash,
|
|
46906
47066
|
summary: `${inputAmt} ${firstStep.from.asset.metadata.symbol} -> ${outputAmt} ${lastStep.to.asset.metadata.symbol}`,
|
|
46907
47067
|
provider: result.route.steps.map((s2) => s2.provider.name).join(" -> "),
|
|
46908
47068
|
explorer: result.explorerUrl || void 0
|
|
@@ -47364,7 +47524,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
47364
47524
|
hdWallet,
|
|
47365
47525
|
chainKey
|
|
47366
47526
|
});
|
|
47367
|
-
return { hash: result.
|
|
47527
|
+
return { hash: result.hash, chain: result.chainKey };
|
|
47368
47528
|
}
|
|
47369
47529
|
const chain2 = requireChain(chainKey);
|
|
47370
47530
|
if (chain2.namespace !== "eip155") {
|
|
@@ -47376,24 +47536,24 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
47376
47536
|
if (input2.tokenAddress) assertEvmAddress(input2.tokenAddress, "tokenAddress");
|
|
47377
47537
|
const caipChainId = `${chain2.namespace}:${chain2.chainId}`;
|
|
47378
47538
|
const atomicAmount = parseAmount(input2.amount, decimals);
|
|
47379
|
-
let
|
|
47539
|
+
let hash;
|
|
47380
47540
|
if (input2.tokenAddress) {
|
|
47381
47541
|
if (!this.blockchainClient) {
|
|
47382
47542
|
throw new WalletError("WALLET_NOT_FOUND", "BlockchainClient not available");
|
|
47383
47543
|
}
|
|
47384
47544
|
const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.transfer([input2.to, BigInt(atomicAmount)], wallet);
|
|
47385
|
-
|
|
47545
|
+
hash = pending.hash;
|
|
47386
47546
|
} else {
|
|
47387
47547
|
assertEvmAddress(input2.to, "to");
|
|
47388
47548
|
const valueHex = "0x" + BigInt(atomicAmount).toString(16);
|
|
47389
|
-
|
|
47549
|
+
hash = await wallet.sendTransaction({
|
|
47390
47550
|
chainId: caipChainId,
|
|
47391
47551
|
to: input2.to,
|
|
47392
47552
|
data: "0x",
|
|
47393
47553
|
value: valueHex
|
|
47394
47554
|
});
|
|
47395
47555
|
}
|
|
47396
|
-
return { hash
|
|
47556
|
+
return { hash, chain: chainKey };
|
|
47397
47557
|
}
|
|
47398
47558
|
};
|
|
47399
47559
|
}
|
|
@@ -47424,7 +47584,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
47424
47584
|
}
|
|
47425
47585
|
const amount = input2.amount === "unlimited" ? "115792089237316195423570985008687907853269984665640564039457584007913129639935" : input2.amount;
|
|
47426
47586
|
const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.approve([input2.spender, BigInt(amount)], wallet);
|
|
47427
|
-
return { hash: pending.
|
|
47587
|
+
return { hash: pending.hash, chain: chainKey };
|
|
47428
47588
|
}
|
|
47429
47589
|
};
|
|
47430
47590
|
}
|
|
@@ -47453,7 +47613,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
47453
47613
|
throw new WalletError("WALLET_NOT_FOUND", "BlockchainClient not available");
|
|
47454
47614
|
}
|
|
47455
47615
|
const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.approve([input2.spender, 0n], wallet);
|
|
47456
|
-
return { hash: pending.
|
|
47616
|
+
return { hash: pending.hash, chain: chainKey };
|
|
47457
47617
|
}
|
|
47458
47618
|
};
|
|
47459
47619
|
}
|
|
@@ -47923,7 +48083,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
47923
48083
|
if (cap) return { success: false, ...cap };
|
|
47924
48084
|
}
|
|
47925
48085
|
const atomic = parseAmount(input2.cryptoAmount, decimals);
|
|
47926
|
-
let
|
|
48086
|
+
let hash;
|
|
47927
48087
|
if (input2.tokenAddress) {
|
|
47928
48088
|
if (!this.blockchainClient) {
|
|
47929
48089
|
throw new TransferError(
|
|
@@ -47932,19 +48092,19 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
47932
48092
|
);
|
|
47933
48093
|
}
|
|
47934
48094
|
const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.transfer([input2.depositAddress, BigInt(atomic)], signer);
|
|
47935
|
-
|
|
48095
|
+
hash = pending.hash;
|
|
47936
48096
|
} else {
|
|
47937
|
-
|
|
48097
|
+
hash = await signer.sendTransaction({
|
|
47938
48098
|
chainId: caip2,
|
|
47939
48099
|
to: input2.depositAddress,
|
|
47940
48100
|
data: "0x",
|
|
47941
48101
|
value: "0x" + BigInt(atomic).toString(16)
|
|
47942
48102
|
});
|
|
47943
48103
|
}
|
|
47944
|
-
const explorerUrl = getExplorerTxUrl(chainKey,
|
|
48104
|
+
const explorerUrl = getExplorerTxUrl(chainKey, hash) || void 0;
|
|
47945
48105
|
return {
|
|
47946
48106
|
success: true,
|
|
47947
|
-
|
|
48107
|
+
hash,
|
|
47948
48108
|
chain: chainKey,
|
|
47949
48109
|
tokenAddress: input2.tokenAddress,
|
|
47950
48110
|
to: input2.depositAddress,
|
|
@@ -48114,7 +48274,7 @@ var AutomateActionProvider = class extends ActionProvider {
|
|
|
48114
48274
|
await this.automationStore.update(record2.id, { lastRunAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
48115
48275
|
return {
|
|
48116
48276
|
success: true,
|
|
48117
|
-
|
|
48277
|
+
hash: result.hash,
|
|
48118
48278
|
automationId: record2.id,
|
|
48119
48279
|
swapped: `${record2.amount} ${record2.fromToken} \u2192 ${record2.toToken}`,
|
|
48120
48280
|
explorer: result.explorerUrl || void 0
|
|
@@ -48330,13 +48490,13 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
48330
48490
|
if (!registered) {
|
|
48331
48491
|
throw new WalletError(
|
|
48332
48492
|
"TX_FAILED",
|
|
48333
|
-
`erc8004_register: no Registered event emitted (
|
|
48493
|
+
`erc8004_register: no Registered event emitted (hash=${confirmed.hash})`
|
|
48334
48494
|
);
|
|
48335
48495
|
}
|
|
48336
48496
|
return {
|
|
48337
48497
|
success: true,
|
|
48338
48498
|
agentId: registered.agentId.toString(),
|
|
48339
|
-
|
|
48499
|
+
hash: confirmed.hash,
|
|
48340
48500
|
owner: registered.owner,
|
|
48341
48501
|
agentURI: registered.agentURI,
|
|
48342
48502
|
...entries.length > 0 ? { metadata: Object.fromEntries(entries) } : {},
|
|
@@ -48363,7 +48523,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
48363
48523
|
this.walletContext.activeWallet()
|
|
48364
48524
|
);
|
|
48365
48525
|
const confirmed = await pending.wait();
|
|
48366
|
-
return { success: true,
|
|
48526
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48367
48527
|
}
|
|
48368
48528
|
};
|
|
48369
48529
|
}
|
|
@@ -48387,7 +48547,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
48387
48547
|
this.walletContext.activeWallet()
|
|
48388
48548
|
);
|
|
48389
48549
|
const confirmed = await pending.wait();
|
|
48390
|
-
return { success: true,
|
|
48550
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48391
48551
|
}
|
|
48392
48552
|
};
|
|
48393
48553
|
}
|
|
@@ -48453,6 +48613,7 @@ var jobIdSchema = import_zod17.z.string().regex(/^\d+$/, "jobId must be a decima
|
|
|
48453
48613
|
var amountSchema = import_zod17.z.string().regex(/^\d+$/, "amount must be an atomic (base-unit) integer string.");
|
|
48454
48614
|
var evmAddressSchema = import_zod17.z.string().refine(isEvmAddress, "must be a 0x-prefixed 40-hex EVM address.");
|
|
48455
48615
|
var bytes32Schema = import_zod17.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be 0x-prefixed 32-byte hex.");
|
|
48616
|
+
var optParamsSchema = import_zod17.z.string().regex(/^0x([0-9a-fA-F]{2})*$/, "optParams must be 0x-prefixed bytes.").optional().describe("Optional opaque optParams bytes forwarded raw to the contract (defaults to empty).");
|
|
48456
48617
|
var ZERO_BYTES322 = `0x${"0".repeat(64)}`;
|
|
48457
48618
|
var Erc8183ActionProvider = class extends ActionProvider {
|
|
48458
48619
|
constructor(blockchainClient, walletContext) {
|
|
@@ -48473,6 +48634,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48473
48634
|
this.reject(),
|
|
48474
48635
|
this.claimRefund(),
|
|
48475
48636
|
this.status(),
|
|
48637
|
+
this.policyInfo(),
|
|
48476
48638
|
this.registerJob(),
|
|
48477
48639
|
this.settle(),
|
|
48478
48640
|
this.markExpired(),
|
|
@@ -48514,13 +48676,13 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48514
48676
|
if (!created) {
|
|
48515
48677
|
throw new WalletError(
|
|
48516
48678
|
"TX_FAILED",
|
|
48517
|
-
`erc8183_create_job: no JobCreated event emitted (
|
|
48679
|
+
`erc8183_create_job: no JobCreated event emitted (hash=${confirmed.hash})`
|
|
48518
48680
|
);
|
|
48519
48681
|
}
|
|
48520
48682
|
return {
|
|
48521
48683
|
success: true,
|
|
48522
48684
|
jobId: created.jobId.toString(),
|
|
48523
|
-
|
|
48685
|
+
hash: confirmed.hash,
|
|
48524
48686
|
status: "Open",
|
|
48525
48687
|
chain: chainKey
|
|
48526
48688
|
};
|
|
@@ -48534,16 +48696,17 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48534
48696
|
schema: import_zod17.z.object({
|
|
48535
48697
|
jobId: jobIdSchema,
|
|
48536
48698
|
provider: evmAddressSchema.describe("New provider (worker) address."),
|
|
48699
|
+
optParams: optParamsSchema,
|
|
48537
48700
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48538
48701
|
}),
|
|
48539
48702
|
invoke: async (_ctx, input2) => {
|
|
48540
48703
|
const { commerce, chainKey } = this.bind(input2.chain);
|
|
48541
48704
|
const pending = await commerce.write.setProvider(
|
|
48542
|
-
[BigInt(input2.jobId), input2.provider, "0x"],
|
|
48705
|
+
[BigInt(input2.jobId), input2.provider, input2.optParams ?? "0x"],
|
|
48543
48706
|
this.walletContext.activeWallet()
|
|
48544
48707
|
);
|
|
48545
48708
|
const confirmed = await pending.wait();
|
|
48546
|
-
return { success: true,
|
|
48709
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48547
48710
|
}
|
|
48548
48711
|
};
|
|
48549
48712
|
}
|
|
@@ -48554,47 +48717,64 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48554
48717
|
schema: import_zod17.z.object({
|
|
48555
48718
|
jobId: jobIdSchema,
|
|
48556
48719
|
amount: amountSchema.describe("Budget in atomic units of the payment token."),
|
|
48720
|
+
optParams: optParamsSchema,
|
|
48557
48721
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48558
48722
|
}),
|
|
48559
48723
|
invoke: async (_ctx, input2) => {
|
|
48560
48724
|
const { commerce, chainKey } = this.bind(input2.chain);
|
|
48561
48725
|
const pending = await commerce.write.setBudget(
|
|
48562
|
-
[BigInt(input2.jobId), BigInt(input2.amount), "0x"],
|
|
48726
|
+
[BigInt(input2.jobId), BigInt(input2.amount), input2.optParams ?? "0x"],
|
|
48563
48727
|
this.walletContext.activeWallet()
|
|
48564
48728
|
);
|
|
48565
48729
|
const confirmed = await pending.wait();
|
|
48566
|
-
return { success: true,
|
|
48730
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48567
48731
|
}
|
|
48568
48732
|
};
|
|
48569
48733
|
}
|
|
48570
48734
|
fund() {
|
|
48571
48735
|
return {
|
|
48572
48736
|
name: "erc8183_fund",
|
|
48573
|
-
description: "Fund a job: deposits the on-chain budget into escrow. The escrow pulls the payment token via transferFrom, so this first sends an ERC-20 approval for the exact budget, then calls fund \u2014 two transactions. Moves the job to `Funded`.",
|
|
48737
|
+
description: "Fund a job: deposits the on-chain budget into escrow. The escrow pulls the payment token via transferFrom, so this first sends an ERC-20 approval for the exact budget, then calls fund \u2014 two transactions. Moves the job to `Funded`. Pass `expectedBudget` to pin the amount instead of reading it on-chain.",
|
|
48574
48738
|
schema: import_zod17.z.object({
|
|
48575
48739
|
jobId: jobIdSchema,
|
|
48740
|
+
expectedBudget: amountSchema.optional().describe(
|
|
48741
|
+
"Pin the budget (atomic units): approve and fund exactly this amount instead of reading it on-chain. The contract reverts (BudgetMismatch) if the on-chain budget differs."
|
|
48742
|
+
),
|
|
48743
|
+
optParams: optParamsSchema,
|
|
48576
48744
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48577
48745
|
}),
|
|
48578
48746
|
invoke: async (_ctx, input2) => {
|
|
48579
48747
|
const { client, commerce, chainKey } = this.bind(input2.chain);
|
|
48580
48748
|
const jobId = BigInt(input2.jobId);
|
|
48581
|
-
|
|
48582
|
-
if (
|
|
48583
|
-
|
|
48584
|
-
|
|
48585
|
-
|
|
48586
|
-
|
|
48749
|
+
let budget;
|
|
48750
|
+
if (input2.expectedBudget !== void 0) {
|
|
48751
|
+
budget = BigInt(input2.expectedBudget);
|
|
48752
|
+
if (budget === 0n) {
|
|
48753
|
+
throw new WalletError("VALIDATION_ERROR", "expectedBudget must be greater than zero.");
|
|
48754
|
+
}
|
|
48755
|
+
} else {
|
|
48756
|
+
const job = await commerce.read.getJob([jobId]);
|
|
48757
|
+
if (job.budget === 0n) {
|
|
48758
|
+
throw new WalletError(
|
|
48759
|
+
"VALIDATION_ERROR",
|
|
48760
|
+
`Job ${input2.jobId} has no budget set \u2014 call erc8183_set_budget before funding.`
|
|
48761
|
+
);
|
|
48762
|
+
}
|
|
48763
|
+
budget = job.budget;
|
|
48587
48764
|
}
|
|
48588
48765
|
const token = await commerce.read.paymentToken([]);
|
|
48589
48766
|
const wallet = this.walletContext.activeWallet();
|
|
48590
|
-
const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address,
|
|
48767
|
+
const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, budget], wallet);
|
|
48591
48768
|
const approveConfirmed = await approvePending.wait();
|
|
48592
|
-
const fundPending = await commerce.write.fund(
|
|
48769
|
+
const fundPending = await commerce.write.fund(
|
|
48770
|
+
[jobId, budget, input2.optParams ?? "0x"],
|
|
48771
|
+
wallet
|
|
48772
|
+
);
|
|
48593
48773
|
const fundConfirmed = await fundPending.wait();
|
|
48594
48774
|
return {
|
|
48595
48775
|
success: true,
|
|
48596
|
-
approveHash: approveConfirmed.
|
|
48597
|
-
|
|
48776
|
+
approveHash: approveConfirmed.hash,
|
|
48777
|
+
hash: fundConfirmed.hash,
|
|
48598
48778
|
status: "Funded",
|
|
48599
48779
|
chain: chainKey
|
|
48600
48780
|
};
|
|
@@ -48610,16 +48790,19 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48610
48790
|
deliverable: bytes32Schema.describe(
|
|
48611
48791
|
"bytes32 deliverable commitment (e.g. a content hash)."
|
|
48612
48792
|
),
|
|
48793
|
+
optParams: optParamsSchema.describe(
|
|
48794
|
+
'Optional opaque optParams bytes forwarded raw to the contract (defaults to empty). Evaluators may expect deliverable metadata here, e.g. hex-encoded UTF-8 JSON like {"deliverable_url": "..."}.'
|
|
48795
|
+
),
|
|
48613
48796
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48614
48797
|
}),
|
|
48615
48798
|
invoke: async (_ctx, input2) => {
|
|
48616
48799
|
const { commerce, chainKey } = this.bind(input2.chain);
|
|
48617
48800
|
const pending = await commerce.write.submit(
|
|
48618
|
-
[BigInt(input2.jobId), input2.deliverable, "0x"],
|
|
48801
|
+
[BigInt(input2.jobId), input2.deliverable, input2.optParams ?? "0x"],
|
|
48619
48802
|
this.walletContext.activeWallet()
|
|
48620
48803
|
);
|
|
48621
48804
|
const confirmed = await pending.wait();
|
|
48622
|
-
return { success: true,
|
|
48805
|
+
return { success: true, hash: confirmed.hash, status: "Submitted", chain: chainKey };
|
|
48623
48806
|
}
|
|
48624
48807
|
};
|
|
48625
48808
|
}
|
|
@@ -48630,19 +48813,20 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48630
48813
|
schema: import_zod17.z.object({
|
|
48631
48814
|
jobId: jobIdSchema,
|
|
48632
48815
|
reason: bytes32Schema.optional().describe("Optional bytes32 reason/attestation (defaults to zero)."),
|
|
48816
|
+
optParams: optParamsSchema,
|
|
48633
48817
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48634
48818
|
}),
|
|
48635
48819
|
invoke: async (_ctx, input2) => {
|
|
48636
48820
|
const { commerce, chainKey } = this.bind(input2.chain);
|
|
48637
48821
|
const pending = await commerce.write.complete(
|
|
48638
|
-
[BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, "0x"],
|
|
48822
|
+
[BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, input2.optParams ?? "0x"],
|
|
48639
48823
|
this.walletContext.activeWallet()
|
|
48640
48824
|
);
|
|
48641
48825
|
const confirmed = await pending.wait();
|
|
48642
48826
|
const released = confirmed.events.PaymentReleased?.[0];
|
|
48643
48827
|
return {
|
|
48644
48828
|
success: true,
|
|
48645
|
-
|
|
48829
|
+
hash: confirmed.hash,
|
|
48646
48830
|
status: "Completed",
|
|
48647
48831
|
released: released ? released.amount.toString() : null,
|
|
48648
48832
|
chain: chainKey
|
|
@@ -48657,19 +48841,20 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48657
48841
|
schema: import_zod17.z.object({
|
|
48658
48842
|
jobId: jobIdSchema,
|
|
48659
48843
|
reason: bytes32Schema.optional().describe("Optional bytes32 reason (defaults to zero)."),
|
|
48844
|
+
optParams: optParamsSchema,
|
|
48660
48845
|
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48661
48846
|
}),
|
|
48662
48847
|
invoke: async (_ctx, input2) => {
|
|
48663
48848
|
const { commerce, chainKey } = this.bind(input2.chain);
|
|
48664
48849
|
const pending = await commerce.write.reject(
|
|
48665
|
-
[BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, "0x"],
|
|
48850
|
+
[BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, input2.optParams ?? "0x"],
|
|
48666
48851
|
this.walletContext.activeWallet()
|
|
48667
48852
|
);
|
|
48668
48853
|
const confirmed = await pending.wait();
|
|
48669
48854
|
const refunded = confirmed.events.Refunded?.[0];
|
|
48670
48855
|
return {
|
|
48671
48856
|
success: true,
|
|
48672
|
-
|
|
48857
|
+
hash: confirmed.hash,
|
|
48673
48858
|
status: "Rejected",
|
|
48674
48859
|
refunded: refunded ? refunded.amount.toString() : null,
|
|
48675
48860
|
chain: chainKey
|
|
@@ -48695,7 +48880,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48695
48880
|
const refunded = confirmed.events.Refunded?.[0];
|
|
48696
48881
|
return {
|
|
48697
48882
|
success: true,
|
|
48698
|
-
|
|
48883
|
+
hash: confirmed.hash,
|
|
48699
48884
|
status: "Expired",
|
|
48700
48885
|
refunded: refunded ? refunded.amount.toString() : null,
|
|
48701
48886
|
chain: chainKey
|
|
@@ -48737,6 +48922,46 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48737
48922
|
}
|
|
48738
48923
|
};
|
|
48739
48924
|
}
|
|
48925
|
+
policyInfo() {
|
|
48926
|
+
return {
|
|
48927
|
+
name: "erc8183_policy_info",
|
|
48928
|
+
description: "Read the dispute-policy state of a job: the registered policy address, dispute window, submission time, dispute/vote tallies, and when the job becomes settleable (submittedAt + disputeWindow). Use before `erc8183_settle` to check timing, and before `erc8183_dispute`/`erc8183_vote_reject` to avoid opaque reverts.",
|
|
48929
|
+
schema: import_zod17.z.object({
|
|
48930
|
+
jobId: jobIdSchema,
|
|
48931
|
+
chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
|
|
48932
|
+
}),
|
|
48933
|
+
invoke: async (_ctx, input2) => {
|
|
48934
|
+
const { client, router, policy, chainKey } = this.bind(input2.chain);
|
|
48935
|
+
const jobId = BigInt(input2.jobId);
|
|
48936
|
+
const registeredPolicy = await router.read.jobPolicy([jobId]);
|
|
48937
|
+
const registered = !isZeroAddress(registeredPolicy);
|
|
48938
|
+
const policyContract = registered && registeredPolicy.toLowerCase() !== policy.address.toLowerCase() ? erc8183Policy.using(client).withAddress(registeredPolicy, chainKey) : policy;
|
|
48939
|
+
const [disputeWindow, submittedAt, disputed, rejectVotes, voteQuorum, quorumSnapshot] = await Promise.all([
|
|
48940
|
+
policyContract.read.disputeWindow([]),
|
|
48941
|
+
policyContract.read.submittedAt([jobId]),
|
|
48942
|
+
policyContract.read.disputed([jobId]),
|
|
48943
|
+
policyContract.read.rejectVotes([jobId]),
|
|
48944
|
+
policyContract.read.voteQuorum([]),
|
|
48945
|
+
policyContract.read.disputeQuorumSnapshot([jobId])
|
|
48946
|
+
]);
|
|
48947
|
+
const settleableAt = submittedAt > 0n ? submittedAt + disputeWindow : null;
|
|
48948
|
+
return {
|
|
48949
|
+
success: true,
|
|
48950
|
+
jobId: input2.jobId,
|
|
48951
|
+
policy: policyContract.address,
|
|
48952
|
+
registered,
|
|
48953
|
+
disputeWindow: disputeWindow.toString(),
|
|
48954
|
+
submittedAt: submittedAt.toString(),
|
|
48955
|
+
disputed,
|
|
48956
|
+
rejectVotes: rejectVotes.toString(),
|
|
48957
|
+
voteQuorum: voteQuorum.toString(),
|
|
48958
|
+
quorumSnapshot: quorumSnapshot.toString(),
|
|
48959
|
+
settleableAt: settleableAt?.toString() ?? null,
|
|
48960
|
+
chain: chainKey
|
|
48961
|
+
};
|
|
48962
|
+
}
|
|
48963
|
+
};
|
|
48964
|
+
}
|
|
48740
48965
|
// ----- Router -------------------------------------------------------------
|
|
48741
48966
|
registerJob() {
|
|
48742
48967
|
return {
|
|
@@ -48754,7 +48979,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48754
48979
|
this.walletContext.activeWallet()
|
|
48755
48980
|
);
|
|
48756
48981
|
const confirmed = await pending.wait();
|
|
48757
|
-
return { success: true,
|
|
48982
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48758
48983
|
}
|
|
48759
48984
|
};
|
|
48760
48985
|
}
|
|
@@ -48774,7 +48999,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48774
48999
|
this.walletContext.activeWallet()
|
|
48775
49000
|
);
|
|
48776
49001
|
const confirmed = await pending.wait();
|
|
48777
|
-
return { success: true,
|
|
49002
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48778
49003
|
}
|
|
48779
49004
|
};
|
|
48780
49005
|
}
|
|
@@ -48793,7 +49018,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48793
49018
|
this.walletContext.activeWallet()
|
|
48794
49019
|
);
|
|
48795
49020
|
const confirmed = await pending.wait();
|
|
48796
|
-
return { success: true,
|
|
49021
|
+
return { success: true, hash: confirmed.hash, status: "Expired", chain: chainKey };
|
|
48797
49022
|
}
|
|
48798
49023
|
};
|
|
48799
49024
|
}
|
|
@@ -48813,7 +49038,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48813
49038
|
this.walletContext.activeWallet()
|
|
48814
49039
|
);
|
|
48815
49040
|
const confirmed = await pending.wait();
|
|
48816
|
-
return { success: true,
|
|
49041
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48817
49042
|
}
|
|
48818
49043
|
};
|
|
48819
49044
|
}
|
|
@@ -48832,7 +49057,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
48832
49057
|
this.walletContext.activeWallet()
|
|
48833
49058
|
);
|
|
48834
49059
|
const confirmed = await pending.wait();
|
|
48835
|
-
return { success: true,
|
|
49060
|
+
return { success: true, hash: confirmed.hash, chain: chainKey };
|
|
48836
49061
|
}
|
|
48837
49062
|
};
|
|
48838
49063
|
}
|
|
@@ -48903,14 +49128,14 @@ var CompetitionActionProvider = class extends ActionProvider {
|
|
|
48903
49128
|
if (!confirmed.events.Registered?.[0]) {
|
|
48904
49129
|
throw new WalletError(
|
|
48905
49130
|
"TX_FAILED",
|
|
48906
|
-
`competition_register: no Registered event emitted (
|
|
49131
|
+
`competition_register: no Registered event emitted (hash=${confirmed.hash})`
|
|
48907
49132
|
);
|
|
48908
49133
|
}
|
|
48909
49134
|
return {
|
|
48910
49135
|
success: true,
|
|
48911
49136
|
registered: true,
|
|
48912
49137
|
participant,
|
|
48913
|
-
|
|
49138
|
+
hash: confirmed.hash,
|
|
48914
49139
|
deadline: toIso2(deadline),
|
|
48915
49140
|
chain: CHAIN
|
|
48916
49141
|
};
|
|
@@ -53915,7 +54140,7 @@ async function runAutomationsTick(deps) {
|
|
|
53915
54140
|
runCount: (auto.runCount ?? 0) + 1
|
|
53916
54141
|
});
|
|
53917
54142
|
log("info", `DCA executed: ${res.explorerUrl}`);
|
|
53918
|
-
result.executed.push({ id: auto.id, type: "dca",
|
|
54143
|
+
result.executed.push({ id: auto.id, type: "dca", hash: res.hash });
|
|
53919
54144
|
} else {
|
|
53920
54145
|
log("warn", `DCA ${auto.id} failed: ${res.error}`);
|
|
53921
54146
|
result.errors++;
|
|
@@ -53963,7 +54188,7 @@ async function runAutomationsTick(deps) {
|
|
|
53963
54188
|
lastRunAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
53964
54189
|
});
|
|
53965
54190
|
log("info", `Limit order executed: ${res.explorerUrl}`);
|
|
53966
|
-
result.executed.push({ id: auto.id, type: "limit",
|
|
54191
|
+
result.executed.push({ id: auto.id, type: "limit", hash: res.hash });
|
|
53967
54192
|
} else {
|
|
53968
54193
|
log("warn", `Limit order ${auto.id} failed: ${res.error}`);
|
|
53969
54194
|
result.errors++;
|
|
@@ -54519,7 +54744,7 @@ ${url}`);
|
|
|
54519
54744
|
} catch (err) {
|
|
54520
54745
|
mapBroadcastError(err);
|
|
54521
54746
|
}
|
|
54522
|
-
const explorerUrl = getExplorerTxUrl(result.chainKey, result.
|
|
54747
|
+
const explorerUrl = getExplorerTxUrl(result.chainKey, result.hash);
|
|
54523
54748
|
success("Off-ramp payout broadcast!");
|
|
54524
54749
|
if (!opts.json) {
|
|
54525
54750
|
info(
|
|
@@ -54528,7 +54753,7 @@ ${url}`);
|
|
|
54528
54753
|
}
|
|
54529
54754
|
output(
|
|
54530
54755
|
{
|
|
54531
|
-
hash: result.
|
|
54756
|
+
hash: result.hash,
|
|
54532
54757
|
chain: result.chainKey,
|
|
54533
54758
|
from: address,
|
|
54534
54759
|
to: opts.to,
|
|
@@ -54913,7 +55138,7 @@ function registerX402Command(program3) {
|
|
|
54913
55138
|
confirmApproval: opts.autoApprove ? autoApproveConfirm : makeReadlineApprovalConfirm()
|
|
54914
55139
|
});
|
|
54915
55140
|
if (approval) {
|
|
54916
|
-
info(`x402: Permit2 approved (one-time): tx ${approval.
|
|
55141
|
+
info(`x402: Permit2 approved (one-time): tx ${approval.hash}`);
|
|
54917
55142
|
}
|
|
54918
55143
|
if (payment) {
|
|
54919
55144
|
info(
|
|
@@ -55028,7 +55253,7 @@ var crypto7 = __toESM(require("crypto"));
|
|
|
55028
55253
|
// package.json
|
|
55029
55254
|
var package_default = {
|
|
55030
55255
|
name: "@trustwallet/cli",
|
|
55031
|
-
version: "0.
|
|
55256
|
+
version: "0.19.1",
|
|
55032
55257
|
description: "TWAK CLI \u2014 command-line interface for Trust Wallet Agent Kit",
|
|
55033
55258
|
main: "dist/index.js",
|
|
55034
55259
|
types: "dist/index.d.ts",
|
|
@@ -55404,7 +55629,7 @@ function registerWatchCommand(program3) {
|
|
|
55404
55629
|
tickResults.automations.executed.push({
|
|
55405
55630
|
id: auto.id,
|
|
55406
55631
|
type: "dca",
|
|
55407
|
-
|
|
55632
|
+
hash: result.hash,
|
|
55408
55633
|
explorer: result.explorerUrl
|
|
55409
55634
|
});
|
|
55410
55635
|
} else {
|
|
@@ -55472,7 +55697,7 @@ function registerWatchCommand(program3) {
|
|
|
55472
55697
|
tickResults.automations.executed.push({
|
|
55473
55698
|
id: auto.id,
|
|
55474
55699
|
type: "limit",
|
|
55475
|
-
|
|
55700
|
+
hash: result.hash,
|
|
55476
55701
|
explorer: result.explorerUrl
|
|
55477
55702
|
});
|
|
55478
55703
|
} else {
|