@trustwallet/cli 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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, txHash) {
3240
+ function getExplorerTxUrl(chainKey, hash) {
3241
3241
  const chain2 = getChainById(chainKey);
3242
3242
  if (!chain2) return "";
3243
- return `${chain2.explorerUrl}/tx/${txHash}`;
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
- const finalInput = typeof input2 === "string" ? resolvedUrl : input2 instanceof URL ? new URL(resolvedUrl) : new Request(resolvedUrl, input2);
6777
- return originalFetch(finalInput, init3);
6784
+ finalInput = typeof input2 === "string" ? resolvedUrl : input2 instanceof URL ? new URL(resolvedUrl) : new Request(resolvedUrl, input2);
6778
6785
  }
6779
- return originalFetch(input2, init3);
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, txHash) {
7052
+ function createPendingTransaction(client, chainKey, hash) {
7012
7053
  return {
7013
- txHash,
7054
+ hash,
7014
7055
  chainKey,
7015
- wait: (opts) => client.waitForReceipt(chainKey, txHash, opts)
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, txHash, opts) {
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", [txHash], {
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 ${txHash} on ${chainKey}`, {
7470
- txHash,
7510
+ throw new TwakNetworkError(`Timed out waiting for receipt ${hash} on ${chainKey}`, {
7511
+ hash,
7471
7512
  chainKey
7472
7513
  });
7473
7514
  }
@@ -7558,13 +7599,13 @@ var init_dist3 = __esm({
7558
7599
  currency: chainKey
7559
7600
  };
7560
7601
  }
7561
- async findTransactionStatus(chainKey, address, txHash) {
7602
+ async findTransactionStatus(chainKey, address, hash) {
7562
7603
  const coinId = chainKeyToCoinType(chainKey);
7563
7604
  if (coinId === void 0) throw new Error(`Unsupported chain: ${chainKey}`);
7564
7605
  const account = this.createAccountForAddress(coinId, address);
7565
7606
  let result;
7566
7607
  try {
7567
- result = await import_trust_sdk2.BlockchainService.findTransaction(account, txHash);
7608
+ result = await import_trust_sdk2.BlockchainService.findTransaction(account, hash);
7568
7609
  } catch {
7569
7610
  return { confirmed: false, pending: false, failed: false, error: "Transaction not found" };
7570
7611
  }
@@ -7986,7 +8027,9 @@ var init_dist3 = __esm({
7986
8027
  );
7987
8028
  }
7988
8029
  if (json.error) {
7989
- throw new TwakNetworkError(`RPC error on ${method}: ${json.error.message}`, {
8030
+ const { message, data } = json.error;
8031
+ const suffix = revertDataSuffix(message, data);
8032
+ throw new TwakNetworkError(`RPC error on ${method}: ${message}${suffix}`, {
7990
8033
  method,
7991
8034
  rpcUrl,
7992
8035
  rpcError: json.error
@@ -8294,7 +8337,7 @@ var init_dist3 = __esm({
8294
8337
  serializedMessage: params.data,
8295
8338
  hdWallet
8296
8339
  });
8297
- return result2.txHash;
8340
+ return result2.hash;
8298
8341
  }
8299
8342
  if (hasCalldata || hasValue) {
8300
8343
  const result2 = await this.blockchainClient.executeContract({
@@ -8305,7 +8348,7 @@ var init_dist3 = __esm({
8305
8348
  hdWallet,
8306
8349
  chainKey
8307
8350
  });
8308
- return result2.txHash;
8351
+ return result2.hash;
8309
8352
  }
8310
8353
  const result = await this.blockchainClient.transfer({
8311
8354
  assetId,
@@ -8314,7 +8357,7 @@ var init_dist3 = __esm({
8314
8357
  hdWallet,
8315
8358
  chainKey
8316
8359
  });
8317
- return result.txHash;
8360
+ return result.hash;
8318
8361
  }
8319
8362
  supportsChain(chainId) {
8320
8363
  return isChainSupported(chainId);
@@ -40603,762 +40646,139 @@ init_dist2();
40603
40646
  var import_chalk6 = __toESM(require_source());
40604
40647
  init_dist();
40605
40648
 
40606
- // src/branding.ts
40607
- var import_chalk5 = __toESM(require_source());
40608
- var boxen = require_boxen();
40609
- var SHIELD = [
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
- );
40649
+ // ../contracts/dist/index.mjs
40650
+ init_dist();
40651
+ init_dist();
40652
+ init_dist();
40653
+ init_dist();
40654
+ init_dist3();
40655
+ init_dist();
40656
+ init_dist();
40657
+ init_dist();
40658
+ var HEX_PATTERN = /^0x[0-9a-fA-F]*$/;
40659
+ function isHex(value) {
40660
+ return HEX_PATTERN.test(value);
40645
40661
  }
40646
- function box(content) {
40647
- return boxen(content, {
40648
- borderColor: "green",
40649
- borderStyle: "round",
40650
- padding: { top: 0, bottom: 0, left: 1, right: 1 }
40651
- });
40662
+ function hexToBytes3(hex2) {
40663
+ if (!isHex(hex2)) {
40664
+ throw new TwakValidationError(`Invalid hex string: ${hex2}`, { kind: "invalidHex" });
40665
+ }
40666
+ const clean2 = hex2.slice(2);
40667
+ if (clean2.length % 2 !== 0) {
40668
+ throw new TwakValidationError(`Hex string has odd length: ${hex2}`, { kind: "invalidHex" });
40669
+ }
40670
+ const out = new Uint8Array(clean2.length / 2);
40671
+ for (let i2 = 0; i2 < out.length; i2++) {
40672
+ out[i2] = parseInt(clean2.slice(i2 * 2, i2 * 2 + 2), 16);
40673
+ }
40674
+ return out;
40652
40675
  }
40653
-
40654
- // src/commands/wallet.ts
40655
- function getQRString(address) {
40656
- try {
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 "";
40676
+ function bytesToHex3(bytes) {
40677
+ let out = "0x";
40678
+ for (let i2 = 0; i2 < bytes.length; i2++) {
40679
+ out += bytes[i2].toString(16).padStart(2, "0");
40665
40680
  }
40681
+ return out;
40666
40682
  }
40667
- function registerWalletCommand(program3) {
40668
- const wallet = program3.command("wallet").description("Manage agent wallet");
40669
- 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) => {
40670
- try {
40671
- if (!opts.skipPasswordCheck) {
40672
- const weakness = getPasswordWeaknesses(opts.password);
40673
- if (weakness) {
40674
- throw new WalletError("VALIDATION_ERROR", `Password too weak: must ${weakness}.`);
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");
40683
+ function hexOrUtf8ToBytesHex(value) {
40684
+ const looksHex = value.length >= 2 && value[0] === "0" && (value[1] === "x" || value[1] === "X");
40685
+ if (looksHex) {
40686
+ const canonical = "0x" + value.slice(2);
40687
+ if (!isHex(canonical)) {
40688
+ throw new TwakValidationError(
40689
+ `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.`,
40690
+ { kind: "invalidHex" }
40691
+ );
40784
40692
  }
40785
- safeExit();
40786
- });
40787
- 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(
40788
- "--password <password>",
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 }))
40693
+ if ((canonical.length - 2) % 2 !== 0) {
40694
+ throw new TwakValidationError(
40695
+ `Hex value has odd length: ${value}. Solidity bytes must be byte-aligned.`,
40696
+ { kind: "invalidHex" }
40853
40697
  );
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
40698
  }
40933
- safeExit();
40934
- });
40935
- const keychain = wallet.command("keychain").description("Manage wallet password in OS keychain");
40936
- keychain.command("save").description("Save wallet password to OS keychain").requiredOption("--password <password>", "Wallet password to store").option("--json", "JSON output").action(async (opts) => {
40937
- try {
40938
- const kc2 = new KeychainManager();
40939
- if (!kc2.isAvailable()) {
40940
- throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
40941
- }
40942
- await kc2.saveWalletPassword(opts.password);
40943
- success("Wallet password saved to OS keychain");
40944
- } catch (err) {
40945
- handleCommandError(err, opts.json, "Keychain save failed");
40699
+ return canonical;
40700
+ }
40701
+ return bytesToHex3(new TextEncoder().encode(value));
40702
+ }
40703
+ function wc2() {
40704
+ return getWalletCore();
40705
+ }
40706
+ var BRIDGE = {
40707
+ createAbiFunction(name2) {
40708
+ const ctor = wc2().EthereumAbiFunction;
40709
+ if (typeof ctor?.createWithString === "function") {
40710
+ return ctor.createWithString(name2);
40946
40711
  }
40947
- safeExit();
40712
+ return new ctor(name2);
40713
+ },
40714
+ encode(fn2) {
40715
+ return wc2().EthereumAbi.encode(fn2);
40716
+ },
40717
+ decodeOutput(fn2, data) {
40718
+ return wc2().EthereumAbi.decodeOutput(fn2, data);
40719
+ },
40720
+ keccak256(data) {
40721
+ return wc2().Hash.keccak256(data);
40722
+ }
40723
+ };
40724
+ function getAbiBridge() {
40725
+ return BRIDGE;
40726
+ }
40727
+ function findAbiFunction(abi, methodName, argCount) {
40728
+ const matches = abi.filter(
40729
+ (e2) => e2.type === "function" && e2.name === methodName
40730
+ );
40731
+ if (matches.length === 0) {
40732
+ throw new TwakValidationError(`Unknown ABI method: ${methodName}`, {
40733
+ kind: "unknownMethod",
40734
+ methodName
40735
+ });
40736
+ }
40737
+ if (matches.length === 1 || argCount === void 0) {
40738
+ return matches[0];
40739
+ }
40740
+ const byArity = matches.filter((m2) => m2.inputs.length === argCount);
40741
+ if (byArity.length === 1) {
40742
+ return byArity[0];
40743
+ }
40744
+ throw new TwakValidationError(`No unique ${methodName} overload taking ${argCount} argument(s)`, {
40745
+ kind: "unknownMethod",
40746
+ methodName
40948
40747
  });
40949
- keychain.command("delete").description("Remove wallet password from OS keychain").option("--json", "JSON output").action(async (opts) => {
40950
- try {
40951
- const kc2 = new KeychainManager();
40952
- if (!kc2.isAvailable()) {
40953
- throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
40748
+ }
40749
+ function encodeFunctionCall(abi, methodName, args) {
40750
+ const fnDef = findAbiFunction(abi, methodName, args.length);
40751
+ if (args.length !== fnDef.inputs.length) {
40752
+ throw new TwakValidationError(
40753
+ `Wrong arg count for ${methodName}: expected ${fnDef.inputs.length}, got ${args.length}`,
40754
+ {
40755
+ kind: "wrongArgCount",
40756
+ methodName,
40757
+ expected: fnDef.inputs.length,
40758
+ actual: args.length
40954
40759
  }
40955
- await kc2.deleteWalletPassword();
40956
- success("Wallet password removed from OS keychain");
40957
- } catch (err) {
40958
- handleCommandError(err, opts.json, "Keychain delete failed");
40959
- }
40960
- safeExit();
40760
+ );
40761
+ }
40762
+ if (encoderRequiresHandRoll(fnDef.inputs)) {
40763
+ return encodeFunctionCallHandRoll(methodName, fnDef.inputs, args);
40764
+ }
40765
+ const bridge = getAbiBridge();
40766
+ const fn2 = bridge.createAbiFunction(methodName);
40767
+ fnDef.inputs.forEach((param, i2) => {
40768
+ pushParam(fn2, param, args[i2], methodName);
40961
40769
  });
40962
- keychain.command("check").description("Check if wallet password is stored in OS keychain").option("--json", "JSON output").action(async (opts) => {
40963
- try {
40964
- const kc2 = new KeychainManager();
40965
- if (!kc2.isAvailable()) {
40966
- if (opts.json) {
40967
- output({ available: false, stored: false }, true);
40968
- } else {
40969
- warn("keytar not available on this system");
40970
- }
40971
- safeExit();
40972
- return;
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");
40770
+ return bytesToHex3(bridge.encode(fn2));
40771
+ }
40772
+ function pushParam(fn2, param, value, methodName) {
40773
+ const type = param.type;
40774
+ const isOutput = false;
40775
+ if (type === "address") {
40776
+ fn2.addParamAddress(toAddressBytes(value, param, methodName), isOutput);
40777
+ return;
40778
+ }
40779
+ if (type === "bool") {
40780
+ if (typeof value !== "boolean") {
40781
+ throw argTypeMismatch(methodName, param, value, "boolean");
41362
40782
  }
41363
40783
  fn2.addParamBool(value, isOutput);
41364
40784
  return;
@@ -42012,14 +41432,14 @@ function buildWriteProxy(abi, address, chainKey, client) {
42012
41432
  });
42013
41433
  }
42014
41434
  const data = encodeFunctionCall(abi, prop, args);
42015
- const txHash = await signer.sendTransaction({
41435
+ const hash = await signer.sendTransaction({
42016
41436
  chainId: chainKeyToCaip2(chainKey),
42017
41437
  to: address,
42018
41438
  data,
42019
41439
  value: "0x0"
42020
41440
  });
42021
41441
  return makeContractPendingTransaction({
42022
- txHash,
41442
+ hash,
42023
41443
  abi,
42024
41444
  address,
42025
41445
  chainKey,
@@ -42031,22 +41451,22 @@ function buildWriteProxy(abi, address, chainKey, client) {
42031
41451
  });
42032
41452
  }
42033
41453
  function makeContractPendingTransaction(opts) {
42034
- const { txHash, abi, address, chainKey, client, methodName } = opts;
41454
+ const { hash, abi, address, chainKey, client, methodName } = opts;
42035
41455
  return {
42036
- txHash,
41456
+ hash,
42037
41457
  async wait(waitOpts) {
42038
- const receipt = await client.waitForReceipt(chainKey, txHash, {
41458
+ const receipt = await client.waitForReceipt(chainKey, hash, {
42039
41459
  timeoutMs: waitOpts?.timeoutMs
42040
41460
  });
42041
41461
  if (receipt.status === "0x0") {
42042
41462
  throw new TwakError(
42043
41463
  `Transaction reverted on-chain: ${receipt.transactionHash}`,
42044
41464
  "TX_FAILED",
42045
- { txHash: receipt.transactionHash, methodName, receipt }
41465
+ { hash: receipt.transactionHash, methodName, receipt }
42046
41466
  );
42047
41467
  }
42048
41468
  return {
42049
- txHash: receipt.transactionHash,
41469
+ hash: receipt.transactionHash,
42050
41470
  blockNumber: hexToSafeNumber(receipt.blockNumber, "blockNumber"),
42051
41471
  events: extractEvents(abi, receipt.logs, address)
42052
41472
  };
@@ -42143,6 +41563,17 @@ function lookupAddress(id, addresses, chainKey) {
42143
41563
  }
42144
41564
  return address;
42145
41565
  }
41566
+ function eip191Digest(message) {
41567
+ const messageBytes = new TextEncoder().encode(message);
41568
+ const prefixBytes = new TextEncoder().encode(
41569
+ `Ethereum Signed Message:
41570
+ ${messageBytes.length}`
41571
+ );
41572
+ const data = new Uint8Array(prefixBytes.length + messageBytes.length);
41573
+ data.set(prefixBytes);
41574
+ data.set(messageBytes, prefixBytes.length);
41575
+ return bytesToHex3(getAbiBridge().keccak256(data));
41576
+ }
42146
41577
  var ERC20_ABI = [
42147
41578
  {
42148
41579
  type: "function",
@@ -42722,6 +42153,29 @@ var ERC8183_POLICY_ABI = [
42722
42153
  outputs: [],
42723
42154
  stateMutability: "nonpayable"
42724
42155
  },
42156
+ {
42157
+ type: "function",
42158
+ name: "disputeWindow",
42159
+ inputs: [],
42160
+ outputs: [{ name: "", type: "uint64" }],
42161
+ stateMutability: "view"
42162
+ },
42163
+ {
42164
+ // When the policy recorded the job's submission (0 if not submitted).
42165
+ type: "function",
42166
+ name: "submittedAt",
42167
+ inputs: [{ name: "jobId", type: "uint256" }],
42168
+ outputs: [{ name: "", type: "uint64" }],
42169
+ stateMutability: "view"
42170
+ },
42171
+ {
42172
+ // Vote quorum snapshotted for the job when its dispute was raised.
42173
+ type: "function",
42174
+ name: "disputeQuorumSnapshot",
42175
+ inputs: [{ name: "jobId", type: "uint256" }],
42176
+ outputs: [{ name: "", type: "uint16" }],
42177
+ stateMutability: "view"
42178
+ },
42725
42179
  {
42726
42180
  type: "function",
42727
42181
  name: "disputed",
@@ -42833,8 +42287,640 @@ function resolveErc8183Contracts(client, chainInput) {
42833
42287
  };
42834
42288
  }
42835
42289
 
42290
+ // src/branding.ts
42291
+ var import_chalk5 = __toESM(require_source());
42292
+ var boxen = require_boxen();
42293
+ var SHIELD = [
42294
+ " @@=+ ",
42295
+ " @@@@@@@======= ",
42296
+ " @@@@@@@@@@@@@============+ ",
42297
+ " @@@@@@@@@@@@@@@@================ ",
42298
+ " @@@@@@@@@@@@@@@@+=============== ",
42299
+ " @@@@@@@@@@@@@@@@++++============ ",
42300
+ " @@@@@@@@@@@@@@@@++++++++++=====+ ",
42301
+ " @@@@@@@@@@@@@@@@**++++++++++++++ ",
42302
+ " @@@@@@@@@@@@@@@@********++++++++ ",
42303
+ " @@@@@@@@@@@@@@@@**************++ ",
42304
+ " @@@@@@@@@@@@@@@@#####*********** ",
42305
+ " @@@@@@@@@@@@@@@###########**** ",
42306
+ " @@@@@@@@@@@@@@%############## ",
42307
+ " @@@@@@@@@@@@@@%%%%%%%####### ",
42308
+ " @@@@@@@@@@@@@%%%%%%%%%%%%% ",
42309
+ " @@@@@@@@@@@%%%%%%%%%%% ",
42310
+ " @@@@@@@@@@@@@%%%%% ",
42311
+ " @@@@@@@@@@@@@@ ",
42312
+ " @@@@@@@@@@ ",
42313
+ " @@ "
42314
+ ];
42315
+ function printBanner(version3) {
42316
+ const logo = SHIELD.map((l4) => import_chalk5.default.green(l4)).join("\n");
42317
+ const title = import_chalk5.default.green.bold(" Trust Wallet Agent Kit");
42318
+ const ver = import_chalk5.default.dim(` v${version3}`);
42319
+ console.log(
42320
+ boxen(`${logo}
42321
+
42322
+ ${title}
42323
+ ${ver}`, {
42324
+ borderColor: "green",
42325
+ borderStyle: "round",
42326
+ padding: { top: 1, bottom: 1, left: 2, right: 2 }
42327
+ })
42328
+ );
42329
+ }
42330
+ function box(content) {
42331
+ return boxen(content, {
42332
+ borderColor: "green",
42333
+ borderStyle: "round",
42334
+ padding: { top: 0, bottom: 0, left: 1, right: 1 }
42335
+ });
42336
+ }
42337
+
42338
+ // src/commands/wallet.ts
42339
+ function getQRString(address) {
42340
+ try {
42341
+ const qrcode = require("qrcode-terminal");
42342
+ let result = "";
42343
+ qrcode.generate(address, { small: true }, (code2) => {
42344
+ result = code2;
42345
+ });
42346
+ return result;
42347
+ } catch {
42348
+ return "";
42349
+ }
42350
+ }
42351
+ function registerWalletCommand(program3) {
42352
+ const wallet = program3.command("wallet").description("Manage agent wallet");
42353
+ 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) => {
42354
+ try {
42355
+ if (!opts.skipPasswordCheck) {
42356
+ const weakness = getPasswordWeaknesses(opts.password);
42357
+ if (weakness) {
42358
+ throw new WalletError("VALIDATION_ERROR", `Password too weak: must ${weakness}.`);
42359
+ }
42360
+ }
42361
+ await ensureTrustSDK();
42362
+ const store = new WalletConfigStore();
42363
+ if (await store.exists()) {
42364
+ throw new WalletError(
42365
+ "WALLET_EXISTS",
42366
+ "Wallet already exists. Back up ~/.twak/wallet.json, then delete it to create a new one."
42367
+ );
42368
+ }
42369
+ const provider = await AgentWalletProvider.create(opts.password);
42370
+ const addresses = await provider.getAddresses();
42371
+ if (opts.keychain !== false) {
42372
+ const kc2 = new KeychainManager();
42373
+ if (kc2.isAvailable()) {
42374
+ await kc2.saveWalletPassword(opts.password);
42375
+ if (!opts.json) info("Password saved to OS keychain (use --no-keychain to skip)");
42376
+ }
42377
+ }
42378
+ if (!opts.json) success("Agent wallet created successfully");
42379
+ try {
42380
+ const creds = await getCredentials();
42381
+ await registerWalletWithBackend(creds, provider);
42382
+ if (!opts.json) info("Wallet registered with backend");
42383
+ } catch {
42384
+ if (!opts.json) warn("Backend registration failed (holdings may be limited)");
42385
+ }
42386
+ if (opts.json) {
42387
+ output({ addresses }, true);
42388
+ } else {
42389
+ info(`Generated addresses for ${addresses.length} chains`);
42390
+ }
42391
+ } catch (err) {
42392
+ handleCommandError(err, opts.json, "Wallet creation failed");
42393
+ }
42394
+ safeExit();
42395
+ });
42396
+ wallet.command("address").description("Get wallet address for a chain").requiredOption("--chain <key>", "Chain key (e.g., ethereum, solana)").option(
42397
+ "--password <password>",
42398
+ "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
42399
+ ).option("--json", "JSON output").action(async (opts) => {
42400
+ try {
42401
+ if (!getChainById(opts.chain)) {
42402
+ throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
42403
+ }
42404
+ await ensureTrustSDK();
42405
+ const password3 = await resolvePassword(opts);
42406
+ const provider = await AgentWalletProvider.fromStorage(password3);
42407
+ const address = await provider.getAddress(opts.chain);
42408
+ if (opts.json) {
42409
+ output({ chain: opts.chain, address }, true);
42410
+ } else {
42411
+ const qr3 = getQRString(address);
42412
+ const content = `${import_chalk6.default.dim("Chain")} ${import_chalk6.default.bold(opts.chain)}
42413
+ ${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
42414
+
42415
+ ${qr3}`;
42416
+ console.log(box(content));
42417
+ }
42418
+ } catch (err) {
42419
+ handleCommandError(err, opts.json, "Wallet address failed");
42420
+ }
42421
+ safeExit();
42422
+ });
42423
+ wallet.command("addresses").description("List all wallet addresses").option(
42424
+ "--password <password>",
42425
+ "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
42426
+ ).option("--json", "JSON output").action(async (opts) => {
42427
+ try {
42428
+ await ensureTrustSDK();
42429
+ const password3 = await resolvePassword(opts);
42430
+ const provider = await AgentWalletProvider.fromStorage(password3);
42431
+ const addresses = await provider.getAddresses();
42432
+ if (opts.json) {
42433
+ output({ addresses }, true);
42434
+ } else {
42435
+ const grouped = /* @__PURE__ */ new Map();
42436
+ for (const addr of addresses) {
42437
+ const chains = grouped.get(addr.address) ?? [];
42438
+ chains.push(addr.chainId);
42439
+ grouped.set(addr.address, chains);
42440
+ }
42441
+ for (const [address, chains] of grouped) {
42442
+ const qr3 = getQRString(address);
42443
+ const maxWidth = Math.max(address.length + 9, 50);
42444
+ const chainLabel = `${import_chalk6.default.dim("Chains")} `;
42445
+ const chainLabelLen = 9;
42446
+ const chainLines = [];
42447
+ let line = "";
42448
+ for (const c3 of chains) {
42449
+ const sep2 = line ? ", " : "";
42450
+ if (line && line.length + sep2.length + c3.length + chainLabelLen > maxWidth) {
42451
+ chainLines.push(line);
42452
+ line = c3;
42453
+ } else {
42454
+ line += sep2 + c3;
42455
+ }
42456
+ }
42457
+ if (line) chainLines.push(line);
42458
+ const chainsStr = chainLines.map((l4, i2) => (i2 === 0 ? chainLabel : " ".repeat(chainLabelLen)) + import_chalk6.default.bold(l4)).join("\n");
42459
+ const content = `${chainsStr}
42460
+ ${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
42461
+
42462
+ ${qr3}`;
42463
+ console.log(box(content));
42464
+ }
42465
+ }
42466
+ } catch (err) {
42467
+ handleCommandError(err, opts.json, "Wallet addresses failed");
42468
+ }
42469
+ safeExit();
42470
+ });
42471
+ 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(
42472
+ "--password <password>",
42473
+ "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
42474
+ ).option("--no-tokens", "Skip token balance lookup").option("--json", "JSON output").action(async (opts) => {
42475
+ try {
42476
+ if (opts.all && opts.chain) {
42477
+ throw new WalletError("VALIDATION_ERROR", "--all and --chain are mutually exclusive");
42478
+ }
42479
+ if (!opts.all && !opts.chain) {
42480
+ throw new WalletError("VALIDATION_ERROR", "Provide --chain <key> or --all");
42481
+ }
42482
+ await ensureTrustSDK();
42483
+ const password3 = await resolvePassword(opts);
42484
+ const provider = await AgentWalletProvider.fromStorage(password3);
42485
+ const httpClient = await getClient();
42486
+ if (!opts.all) {
42487
+ const chain2 = getChainById(opts.chain);
42488
+ if (!chain2) {
42489
+ throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
42490
+ }
42491
+ }
42492
+ const allAddresses = await provider.getAddresses();
42493
+ const addressMap = /* @__PURE__ */ new Map();
42494
+ for (const a3 of allAddresses) addressMap.set(a3.chainId, a3.address);
42495
+ const requestedChains = opts.all ? Object.keys(CHAINS) : [opts.chain];
42496
+ const skipTokens = opts.tokens === false;
42497
+ const chainEntries = requestedChains.flatMap((chainKey) => {
42498
+ const chain2 = getChainById(chainKey);
42499
+ const address = addressMap.get(chainKey);
42500
+ if (!chain2 || !address) return [];
42501
+ return [{ chainKey, chain: chain2, address }];
42502
+ });
42503
+ if (!opts.all && chainEntries.length === 0) {
42504
+ throw new WalletError(
42505
+ "CHAIN_UNSUPPORTED",
42506
+ `Wallet does not have an address for chain: ${opts.chain}`
42507
+ );
42508
+ }
42509
+ const nativeAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
42510
+ chainKey,
42511
+ chain: chain2,
42512
+ token: void 0,
42513
+ assetId: `c${chain2.coinId}`,
42514
+ userAddress: address
42515
+ }));
42516
+ const tokenAssets = skipTokens ? [] : chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
42517
+ const knownTokens = COMMON_TOKENS[chainKey];
42518
+ if (!knownTokens) return [];
42519
+ return Object.keys(knownTokens).flatMap((sym) => {
42520
+ const resolved = resolveToken(sym, chainKey);
42521
+ if (!resolved) return [];
42522
+ return [
42523
+ {
42524
+ chainKey,
42525
+ chain: chain2,
42526
+ token: { ...resolved, symbol: sym },
42527
+ assetId: `c${chain2.coinId}_t${resolved.address}`,
42528
+ userAddress: address
42529
+ }
42530
+ ];
42531
+ });
42532
+ });
42533
+ const allAssets = [...nativeAssets, ...tokenAssets];
42534
+ const balances = await fetchBalances(
42535
+ httpClient,
42536
+ allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
42537
+ );
42538
+ const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
42539
+ const resultsByChain = /* @__PURE__ */ new Map();
42540
+ for (const { chainKey, chain: chain2, address } of chainEntries) {
42541
+ resultsByChain.set(chainKey, {
42542
+ chain: chainKey,
42543
+ address,
42544
+ symbol: chain2.symbol,
42545
+ available: "0",
42546
+ total: "0",
42547
+ totalUsd: null,
42548
+ tokens: []
42549
+ });
42550
+ }
42551
+ for (const balance of balances) {
42552
+ const assetInfo = assetsById.get(balance.assetId);
42553
+ if (!assetInfo) {
42554
+ throw new WalletError(
42555
+ "NETWORK_ERROR",
42556
+ "Could not fetch balances. Please try again later."
42557
+ );
42558
+ }
42559
+ const result = resultsByChain.get(assetInfo.chainKey);
42560
+ if (!result) continue;
42561
+ const { token, chain: chain2 } = assetInfo;
42562
+ const amts = balance.amounts;
42563
+ if (token) {
42564
+ const human = formatAmount(amts.total ?? "0", token.decimals);
42565
+ if (human !== "0") {
42566
+ result.tokens.push({
42567
+ symbol: token.symbol,
42568
+ contract: token.address,
42569
+ balance: human
42570
+ });
42571
+ }
42572
+ } else {
42573
+ result.available = formatAmount(amts.available ?? "0", chain2.decimals);
42574
+ result.total = formatAmount(amts.total ?? "0", chain2.decimals);
42575
+ const lockedHuman = formatAmount(amts.locked ?? "0", chain2.decimals);
42576
+ if (lockedHuman !== "0") result.staked = lockedHuman;
42577
+ const fiat = amts.totalInFiat;
42578
+ result.totalUsd = fiat && fiat !== "" ? parseFloat(fiat) : null;
42579
+ }
42580
+ }
42581
+ const orderedResults = chainEntries.map((e2) => resultsByChain.get(e2.chainKey)).filter((r3) => r3 !== void 0);
42582
+ const visible = opts.all ? orderedResults.filter((r3) => r3.total !== "0" || r3.tokens.length > 0) : orderedResults;
42583
+ const renderBlock = (r3, withSeparator) => {
42584
+ if (withSeparator) console.log("");
42585
+ console.log(import_chalk6.default.bold.underline(`${r3.chain} (${r3.symbol})`));
42586
+ console.log(` ${import_chalk6.default.dim("Address")} ${r3.address}`);
42587
+ console.log(` ${import_chalk6.default.dim("Available")} ${r3.available}`);
42588
+ if (r3.staked) console.log(` ${import_chalk6.default.dim("Staked")} ${r3.staked}`);
42589
+ const usdSuffix = r3.totalUsd !== null ? ` (\u2248 $${r3.totalUsd.toFixed(2)})` : "";
42590
+ console.log(` ${import_chalk6.default.dim("Total")} ${r3.total}${usdSuffix}`);
42591
+ if (r3.tokens.length > 0) {
42592
+ console.log(` ${import_chalk6.default.dim("Tokens:")}`);
42593
+ for (const t of r3.tokens) {
42594
+ console.log(` ${import_chalk6.default.bold(t.symbol.padEnd(10))} ${t.balance}`);
42595
+ }
42596
+ }
42597
+ };
42598
+ if (opts.all) {
42599
+ if (opts.json) {
42600
+ output(visible, true);
42601
+ } else if (visible.length === 0) {
42602
+ info("No chains with non-zero native balance found.");
42603
+ } else {
42604
+ visible.forEach((r3, i2) => renderBlock(r3, i2 > 0));
42605
+ }
42606
+ } else {
42607
+ const single = visible[0];
42608
+ if (opts.json) {
42609
+ output(single, true);
42610
+ } else {
42611
+ renderBlock(single, false);
42612
+ }
42613
+ }
42614
+ } catch (err) {
42615
+ handleCommandError(err, opts.json, "Balance check failed");
42616
+ }
42617
+ safeExit();
42618
+ });
42619
+ const keychain = wallet.command("keychain").description("Manage wallet password in OS keychain");
42620
+ keychain.command("save").description("Save wallet password to OS keychain").requiredOption("--password <password>", "Wallet password to store").option("--json", "JSON output").action(async (opts) => {
42621
+ try {
42622
+ const kc2 = new KeychainManager();
42623
+ if (!kc2.isAvailable()) {
42624
+ throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
42625
+ }
42626
+ await kc2.saveWalletPassword(opts.password);
42627
+ success("Wallet password saved to OS keychain");
42628
+ } catch (err) {
42629
+ handleCommandError(err, opts.json, "Keychain save failed");
42630
+ }
42631
+ safeExit();
42632
+ });
42633
+ keychain.command("delete").description("Remove wallet password from OS keychain").option("--json", "JSON output").action(async (opts) => {
42634
+ try {
42635
+ const kc2 = new KeychainManager();
42636
+ if (!kc2.isAvailable()) {
42637
+ throw new WalletError("KEYCHAIN_UNAVAILABLE", "OS keychain not available on this system");
42638
+ }
42639
+ await kc2.deleteWalletPassword();
42640
+ success("Wallet password removed from OS keychain");
42641
+ } catch (err) {
42642
+ handleCommandError(err, opts.json, "Keychain delete failed");
42643
+ }
42644
+ safeExit();
42645
+ });
42646
+ keychain.command("check").description("Check if wallet password is stored in OS keychain").option("--json", "JSON output").action(async (opts) => {
42647
+ try {
42648
+ const kc2 = new KeychainManager();
42649
+ if (!kc2.isAvailable()) {
42650
+ if (opts.json) {
42651
+ output({ available: false, stored: false }, true);
42652
+ } else {
42653
+ warn("keytar not available on this system");
42654
+ }
42655
+ safeExit();
42656
+ return;
42657
+ }
42658
+ const pw = await kc2.getWalletPassword();
42659
+ if (opts.json) {
42660
+ output({ available: true, stored: !!pw }, true);
42661
+ } else if (pw) {
42662
+ success("Wallet password is stored in OS keychain");
42663
+ } else {
42664
+ info("No wallet password found in OS keychain");
42665
+ }
42666
+ } catch (err) {
42667
+ handleCommandError(err, opts.json, "Keychain check failed");
42668
+ }
42669
+ safeExit();
42670
+ });
42671
+ wallet.command("connect").description("Connect external wallet via WalletConnect").option("--project-id <id>", "WalletConnect project ID (or set WALLETCONNECT_PROJECT_ID)").option(
42672
+ "--chains <list>",
42673
+ "Comma-separated CAIP-2 chain IDs",
42674
+ "eip155:1,eip155:56,eip155:137,eip155:8453,eip155:42161"
42675
+ ).option("--timeout <seconds>", "Connection timeout in seconds", "300").option("--json", "JSON output").action(async (opts) => {
42676
+ try {
42677
+ const projectId = opts.projectId || process.env.WALLETCONNECT_PROJECT_ID;
42678
+ if (!projectId) {
42679
+ throw new WalletError(
42680
+ "VALIDATION_ERROR",
42681
+ "WalletConnect project ID required. Use --project-id or set WALLETCONNECT_PROJECT_ID"
42682
+ );
42683
+ }
42684
+ const provider = new WalletConnectProvider({ projectId });
42685
+ const chains = opts.chains.split(",").map((s2) => s2.trim()).filter(Boolean);
42686
+ info("Connecting via WalletConnect...");
42687
+ const result = await provider.connect(chains);
42688
+ const qr3 = getQRString(result.uri);
42689
+ if (qr3) {
42690
+ console.log(qr3);
42691
+ }
42692
+ info(`Trust Wallet: ${result.deepLinks.native}`);
42693
+ info(`Universal: ${result.deepLinks.universal}`);
42694
+ info("\nWaiting for wallet approval...");
42695
+ const timeoutMs = parseInt(opts.timeout, 10) * 1e3;
42696
+ const session = await provider.waitForSession(timeoutMs);
42697
+ if (opts.json) {
42698
+ output(
42699
+ {
42700
+ connected: true,
42701
+ address: session.address,
42702
+ chainId: session.chainId,
42703
+ peer: session.peerName
42704
+ },
42705
+ true
42706
+ );
42707
+ } else {
42708
+ success(`Connected to ${session.peerName || "wallet"}`);
42709
+ info(` Address: ${session.address}`);
42710
+ info(` Chain: ${session.chainId}`);
42711
+ }
42712
+ } catch (err) {
42713
+ handleCommandError(err, opts.json, "WalletConnect failed");
42714
+ }
42715
+ safeExit();
42716
+ });
42717
+ wallet.command("status").description("Check wallet configuration status").option("--json", "JSON output").action(async (opts) => {
42718
+ try {
42719
+ const store = new WalletConfigStore();
42720
+ const exists = await store.exists();
42721
+ const kc2 = new KeychainManager();
42722
+ const keychainHasPassword = kc2.isAvailable() ? !!await kc2.getWalletPassword() : false;
42723
+ const totalChains = Object.keys(CHAINS).length;
42724
+ let createdAt;
42725
+ let addressCount;
42726
+ if (exists) {
42727
+ const config = await store.getConfig();
42728
+ createdAt = config?.createdAt;
42729
+ addressCount = config?.chains?.length ?? totalChains;
42730
+ }
42731
+ const result = {
42732
+ agentWallet: exists ? "configured" : "not configured",
42733
+ keychainPassword: keychainHasPassword ? "stored" : "not stored",
42734
+ chains: totalChains,
42735
+ supportedChains: totalChains,
42736
+ ...createdAt ? { createdAt } : {},
42737
+ ...addressCount !== void 0 ? { addressCount } : {}
42738
+ };
42739
+ if (opts.json) {
42740
+ output(result, true);
42741
+ } else {
42742
+ console.log(
42743
+ ` ${import_chalk6.default.dim("Wallet")} ${exists ? import_chalk6.default.green("configured") : import_chalk6.default.yellow("not configured")}`
42744
+ );
42745
+ if (createdAt) console.log(` ${import_chalk6.default.dim("Created")} ${createdAt}`);
42746
+ console.log(
42747
+ ` ${import_chalk6.default.dim("Keychain")} ${keychainHasPassword ? import_chalk6.default.green("password stored") : import_chalk6.default.yellow("no password")}`
42748
+ );
42749
+ console.log(` ${import_chalk6.default.dim("Chains")} ${totalChains} supported`);
42750
+ if (addressCount !== void 0)
42751
+ console.log(` ${import_chalk6.default.dim("Addresses")} ${addressCount}`);
42752
+ if (!exists) info("\nRun `twak wallet create --password <pw>` to create a wallet.");
42753
+ }
42754
+ } catch (err) {
42755
+ handleCommandError(err, opts.json, "Status failed");
42756
+ }
42757
+ safeExit();
42758
+ });
42759
+ 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(
42760
+ "--password <password>",
42761
+ "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
42762
+ ).option("--json", "JSON output").action(async (opts) => {
42763
+ try {
42764
+ await ensureTrustSDK();
42765
+ const password3 = await resolvePassword(opts);
42766
+ const provider = await AgentWalletProvider.fromStorage(password3);
42767
+ const httpClient = await getClient();
42768
+ const allAddresses = await provider.getAddresses();
42769
+ const chainsArg = opts.chains ?? Object.keys(CHAINS).join(",");
42770
+ const requestedChains = chainsArg.split(",").map((s2) => s2.trim()).filter(Boolean);
42771
+ if (requestedChains.length === 0) {
42772
+ throw new WalletError("VALIDATION_ERROR", "--chains must include at least one chain key");
42773
+ }
42774
+ const chainEntries = requestedChains.flatMap((chainKey) => {
42775
+ const chain2 = getChainById(chainKey);
42776
+ const addrEntry = allAddresses.find((a3) => a3.chainId === chainKey);
42777
+ if (!chain2 || !addrEntry) return [];
42778
+ return [{ chainKey, chain: chain2, address: addrEntry.address }];
42779
+ });
42780
+ if (chainEntries.length === 0) {
42781
+ throw new WalletError(
42782
+ "CHAIN_UNSUPPORTED",
42783
+ `No supported chains found in --chains "${opts.chains}"`
42784
+ );
42785
+ }
42786
+ const chainAssets = chainEntries.map(({ chainKey, chain: chain2, address }) => ({
42787
+ chainKey,
42788
+ chain: chain2,
42789
+ token: void 0,
42790
+ assetId: `c${chain2.coinId}`,
42791
+ userAddress: address
42792
+ }));
42793
+ const tokenAssets = chainEntries.flatMap(({ chainKey, chain: chain2, address }) => {
42794
+ const knownTokens = COMMON_TOKENS[chainKey];
42795
+ if (!knownTokens) return [];
42796
+ return Object.keys(knownTokens).flatMap((sym) => {
42797
+ const resolved = resolveToken(sym, chainKey);
42798
+ if (!resolved) return [];
42799
+ return [
42800
+ {
42801
+ chainKey,
42802
+ chain: chain2,
42803
+ token: { ...resolved, symbol: sym },
42804
+ assetId: `c${chain2.coinId}_t${resolved.address}`,
42805
+ userAddress: address
42806
+ }
42807
+ ];
42808
+ });
42809
+ });
42810
+ const allAssets = [...chainAssets, ...tokenAssets];
42811
+ const balances = await fetchBalances(
42812
+ httpClient,
42813
+ allAssets.map(({ assetId, userAddress }) => ({ assetId, address: userAddress }))
42814
+ );
42815
+ const assetsById = new Map(allAssets.map((a3) => [a3.assetId, a3]));
42816
+ const allRows = [];
42817
+ for (const balance of balances) {
42818
+ const assetInfo = assetsById.get(balance.assetId);
42819
+ if (!assetInfo) {
42820
+ throw new WalletError(
42821
+ "NETWORK_ERROR",
42822
+ "Could not fetch balances. Please try again later."
42823
+ );
42824
+ }
42825
+ const { token, chain: chain2, chainKey, userAddress } = assetInfo;
42826
+ const decimals = token ? token.decimals : chain2.decimals;
42827
+ const symbol = token ? token.symbol ?? token.address : chain2.symbol;
42828
+ const isToken = token !== void 0;
42829
+ const humanAmount = formatAmount(balance.amounts.total, decimals);
42830
+ const fiatRaw = balance.amounts.totalInFiat;
42831
+ const usdValue = fiatRaw && fiatRaw !== "" ? parseFloat(fiatRaw) : null;
42832
+ allRows.push({
42833
+ chain: chainKey,
42834
+ type: isToken ? "token" : "native",
42835
+ symbol,
42836
+ address: userAddress,
42837
+ ...token ? { contract: token.address } : {},
42838
+ balance: humanAmount,
42839
+ usdValue
42840
+ });
42841
+ }
42842
+ const rows = allRows.filter((r3) => r3.type === "native" || r3.balance !== "0");
42843
+ rows.sort((a3, b3) => {
42844
+ const chainCmp = String(a3.chain).localeCompare(String(b3.chain));
42845
+ if (chainCmp !== 0) return chainCmp;
42846
+ return String(a3.type).localeCompare(String(b3.type));
42847
+ });
42848
+ if (opts.json) {
42849
+ output(rows, true);
42850
+ } else {
42851
+ const totalUsd = rows.reduce(
42852
+ (sum, r3) => sum + (typeof r3.usdValue === "number" ? r3.usdValue : 0),
42853
+ 0
42854
+ );
42855
+ console.log("Chain Type Symbol Balance USD");
42856
+ console.log("\u2500".repeat(72));
42857
+ for (const r3 of rows) {
42858
+ const usd = r3.usdValue !== null ? `$${r3.usdValue.toFixed(2)}` : "";
42859
+ console.log(
42860
+ `${String(r3.chain).padEnd(12)} ${String(r3.type).padEnd(7)} ${String(r3.symbol).padEnd(17)} ${String(r3.balance).padEnd(20)} ${usd}`
42861
+ );
42862
+ }
42863
+ console.log("\u2500".repeat(72));
42864
+ console.log(`Total USD: $${totalUsd.toFixed(2)}`);
42865
+ }
42866
+ } catch (err) {
42867
+ handleCommandError(err, opts.json, "Portfolio failed");
42868
+ }
42869
+ safeExit();
42870
+ });
42871
+ 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(
42872
+ "--password <password>",
42873
+ "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
42874
+ ).option("--json", "JSON output").action(async (opts) => {
42875
+ try {
42876
+ const chain2 = getChainById(opts.chain);
42877
+ if (!chain2) {
42878
+ throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
42879
+ }
42880
+ await ensureTrustSDK();
42881
+ const password3 = await resolvePassword(opts);
42882
+ const provider = await AgentWalletProvider.fromStorage(password3);
42883
+ const address = await provider.getAddress(opts.chain);
42884
+ const rawSignature = await provider.signMessage(opts.chain, opts.message);
42885
+ const signature = chain2.isEVM && !rawSignature.startsWith("0x") ? `0x${rawSignature}` : rawSignature;
42886
+ output(
42887
+ {
42888
+ chain: opts.chain,
42889
+ address,
42890
+ message: opts.message,
42891
+ signature,
42892
+ ...chain2.isEVM ? { digest: eip191Digest(opts.message) } : {}
42893
+ },
42894
+ opts.json
42895
+ );
42896
+ } catch (err) {
42897
+ handleCommandError(err, opts.json, "Sign failed");
42898
+ }
42899
+ safeExit();
42900
+ });
42901
+ 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) => {
42902
+ try {
42903
+ const creds = await ensureTrustSDK();
42904
+ const password3 = await resolvePassword(opts);
42905
+ const provider = await AgentWalletProvider.fromStorage(password3);
42906
+ await registerWalletWithBackend(creds, provider);
42907
+ if (!opts.json) success("Wallet registered with backend");
42908
+ const addresses = await provider.getAddresses();
42909
+ output({ registered: true, chains: addresses.length }, opts.json);
42910
+ } catch (err) {
42911
+ handleCommandError(err, opts.json, "Registration failed");
42912
+ }
42913
+ safeExit();
42914
+ });
42915
+ }
42916
+
42917
+ // src/commands/transfer.ts
42918
+ init_dist();
42919
+
42836
42920
  // ../swap/dist/index.mjs
42837
42921
  init_dist();
42922
+ init_dist();
42923
+ init_dist();
42838
42924
  var SwapClient = class {
42839
42925
  constructor(httpClient) {
42840
42926
  this.httpClient = httpClient;
@@ -43116,9 +43202,9 @@ var SwapExecutor = class {
43116
43202
  );
43117
43203
  const chainConfig = getChainById(params.fromChain);
43118
43204
  const transactions = await withRetry(() => this.swapClient.getSwapTransactions(route));
43119
- let approvalTxHash;
43205
+ let approvalHash;
43120
43206
  try {
43121
- approvalTxHash = await this.ensureStepApproval(
43207
+ approvalHash = await this.ensureStepApproval(
43122
43208
  route,
43123
43209
  transactions,
43124
43210
  chainConfig,
@@ -43126,10 +43212,10 @@ var SwapExecutor = class {
43126
43212
  address,
43127
43213
  parsedAmount
43128
43214
  );
43129
- if (approvalTxHash) {
43130
- await this.pollForConfirmation(params.fromChain, address, approvalTxHash, 6e4);
43215
+ if (approvalHash) {
43216
+ await this.pollForConfirmation(params.fromChain, address, approvalHash, 6e4);
43131
43217
  }
43132
- let txHash = "";
43218
+ let hash = "";
43133
43219
  for (const txData of transactions) {
43134
43220
  const txType = txData.transaction.type;
43135
43221
  const isApproval = txType === "approval" || txType === "revokeApproval";
@@ -43138,30 +43224,30 @@ var SwapExecutor = class {
43138
43224
  txType === "revokeApproval" ? "Revoking prior approval..." : "Sending token approval..."
43139
43225
  );
43140
43226
  }
43141
- txHash = await this.sendTransaction(txData, chainConfig, params.fromChain);
43142
- if (isApproval) approvalTxHash = txHash;
43227
+ hash = await this.sendTransaction(txData, chainConfig, params.fromChain);
43228
+ if (isApproval) approvalHash = hash;
43143
43229
  this.log(
43144
- `${isApproval ? "Approval" : "Swap"} tx: ${getExplorerTxUrl(params.fromChain, txHash)}`
43230
+ `${isApproval ? "Approval" : "Swap"} tx: ${getExplorerTxUrl(params.fromChain, hash)}`
43145
43231
  );
43146
43232
  await this.pollForConfirmation(
43147
43233
  params.fromChain,
43148
43234
  address,
43149
- txHash,
43235
+ hash,
43150
43236
  isApproval ? 6e4 : 12e4
43151
43237
  );
43152
43238
  }
43153
43239
  return {
43154
43240
  success: true,
43155
- txHash,
43241
+ hash,
43156
43242
  route,
43157
- explorerUrl: getExplorerTxUrl(params.fromChain, txHash)
43243
+ explorerUrl: getExplorerTxUrl(params.fromChain, hash)
43158
43244
  };
43159
43245
  } catch (err) {
43160
43246
  let msg = err instanceof Error ? err.message : "Unknown error";
43161
43247
  let code2 = classifySwapError(msg);
43162
- if (approvalTxHash) {
43248
+ if (approvalHash) {
43163
43249
  code2 = "APPROVAL_SENT_SWAP_FAILED";
43164
- msg += `. Approval was sent (tx: ${approvalTxHash}). Check allowance before retrying.`;
43250
+ msg += `. Approval was sent (tx: ${approvalHash}). Check allowance before retrying.`;
43165
43251
  }
43166
43252
  return { success: false, route, error: msg, code: code2 };
43167
43253
  }
@@ -43193,8 +43279,8 @@ var SwapExecutor = class {
43193
43279
  if (allowance >= required) return void 0;
43194
43280
  this.log("Sending token approval...");
43195
43281
  const approveResult = await blockchainClient.contract(erc20).withAddress(fromAssetAddr, fromChain).write.approve([stepApproval.operatorAddress, required], this.walletProvider);
43196
- this.log(`Approval tx: ${getExplorerTxUrl(fromChain, approveResult.txHash)}`);
43197
- return approveResult.txHash;
43282
+ this.log(`Approval tx: ${getExplorerTxUrl(fromChain, approveResult.hash)}`);
43283
+ return approveResult.hash;
43198
43284
  }
43199
43285
  getBlockchainClient() {
43200
43286
  const blockchainClient = this.walletProvider.getBlockchainClient?.() ?? this.options.blockchainClient;
@@ -43419,11 +43505,11 @@ function registerTransferCommand(program3) {
43419
43505
  } catch (err) {
43420
43506
  mapBroadcastError(err);
43421
43507
  }
43422
- const explorerUrl = getExplorerTxUrl(result.chainKey, result.txHash);
43508
+ const explorerUrl = getExplorerTxUrl(result.chainKey, result.hash);
43423
43509
  success("Transfer sent!");
43424
43510
  output(
43425
43511
  {
43426
- hash: result.txHash,
43512
+ hash: result.hash,
43427
43513
  chain: result.chainKey,
43428
43514
  from: address,
43429
43515
  to: resolvedTo,
@@ -43640,7 +43726,7 @@ function registerSwapCommand(program3) {
43640
43726
  output(
43641
43727
  {
43642
43728
  ...quoteData,
43643
- hash: result.txHash,
43729
+ hash: result.hash,
43644
43730
  fromChain,
43645
43731
  toChain,
43646
43732
  explorer: result.explorerUrl
@@ -43723,11 +43809,11 @@ function registerErc20Command(program3) {
43723
43809
  info(`Approving ${opts.spender} to spend from ${address} on ${chainKey}...`);
43724
43810
  const client = provider.getBlockchainClient();
43725
43811
  const pending = await client.contract(erc20).withAddress(contractAddress, chainKey).write.approve([opts.spender, BigInt(amount)], provider);
43726
- const explorerUrl = getExplorerTxUrl(chainKey, pending.txHash);
43812
+ const explorerUrl = getExplorerTxUrl(chainKey, pending.hash);
43727
43813
  success("Approval sent!");
43728
43814
  output(
43729
43815
  {
43730
- hash: pending.txHash,
43816
+ hash: pending.hash,
43731
43817
  chain: chainKey,
43732
43818
  owner: address,
43733
43819
  spender: opts.spender,
@@ -43764,11 +43850,11 @@ function registerErc20Command(program3) {
43764
43850
  info(`Revoking approval for ${opts.spender} on ${chainKey}...`);
43765
43851
  const client = provider.getBlockchainClient();
43766
43852
  const pending = await client.contract(erc20).withAddress(contractAddress, chainKey).write.approve([opts.spender, 0n], provider);
43767
- const explorerUrl = getExplorerTxUrl(chainKey, pending.txHash);
43853
+ const explorerUrl = getExplorerTxUrl(chainKey, pending.hash);
43768
43854
  success("Approval revoked!");
43769
43855
  output(
43770
43856
  {
43771
- hash: pending.txHash,
43857
+ hash: pending.hash,
43772
43858
  chain: chainKey,
43773
43859
  owner: address,
43774
43860
  spender: opts.spender,
@@ -43918,7 +44004,7 @@ function registerErc8004Command(program3) {
43918
44004
  if (!registered) {
43919
44005
  throw new WalletError(
43920
44006
  "TX_FAILED",
43921
- `No Registered event emitted (txHash=${confirmed.txHash})`
44007
+ `No Registered event emitted (hash=${confirmed.hash})`
43922
44008
  );
43923
44009
  }
43924
44010
  success("Agent registered!");
@@ -43928,9 +44014,9 @@ function registerErc8004Command(program3) {
43928
44014
  owner: registered.owner,
43929
44015
  agentURI: registered.agentURI,
43930
44016
  ...metadata.length > 0 ? { metadata: Object.fromEntries(metadata) } : {},
43931
- hash: confirmed.txHash,
44017
+ hash: confirmed.hash,
43932
44018
  chain: chainKey,
43933
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44019
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
43934
44020
  },
43935
44021
  opts.json
43936
44022
  );
@@ -43964,9 +44050,9 @@ function registerErc8004Command(program3) {
43964
44050
  {
43965
44051
  agentId,
43966
44052
  agentURI: opts.uri,
43967
- hash: confirmed.txHash,
44053
+ hash: confirmed.hash,
43968
44054
  chain: chainKey,
43969
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44055
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
43970
44056
  },
43971
44057
  opts.json
43972
44058
  );
@@ -43999,9 +44085,9 @@ function registerErc8004Command(program3) {
43999
44085
  agentId,
44000
44086
  key: opts.key,
44001
44087
  value: valueBytes,
44002
- hash: confirmed.txHash,
44088
+ hash: confirmed.hash,
44003
44089
  chain: chainKey,
44004
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44090
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44005
44091
  },
44006
44092
  opts.json
44007
44093
  );
@@ -44061,6 +44147,8 @@ function registerErc8004Command(program3) {
44061
44147
  init_dist();
44062
44148
  init_dist3();
44063
44149
  var CHAIN_OPT = "EVM chain key (`bsc` and `bsctestnet` have known deployments)";
44150
+ var OPT_PARAMS_OPT = "Optional opaque optParams bytes passed through raw, as 0x-prefixed hex (defaults to empty)";
44151
+ 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
44152
  var ZERO_BYTES32 = `0x${"0".repeat(64)}`;
44065
44153
  function parseUint(value, label) {
44066
44154
  if (!/^\d+$/.test(value)) {
@@ -44071,6 +44159,16 @@ function parseUint(value, label) {
44071
44159
  }
44072
44160
  return BigInt(value);
44073
44161
  }
44162
+ function parseOptParams(value) {
44163
+ if (value === void 0) return "0x";
44164
+ if (!/^0x([0-9a-fA-F]{2})*$/.test(value)) {
44165
+ throw new WalletError(
44166
+ "VALIDATION_ERROR",
44167
+ `--opt-params must be 0x-prefixed bytes (even-length hex): ${value}`
44168
+ );
44169
+ }
44170
+ return value;
44171
+ }
44074
44172
  function registerErc8183Command(program3) {
44075
44173
  const cmd = program3.command("erc8183").description("ERC-8183 Agentic Commerce \u2014 on-chain job escrows between AI agents");
44076
44174
  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 +44191,7 @@ function registerErc8183Command(program3) {
44093
44191
  if (!created) {
44094
44192
  throw new WalletError(
44095
44193
  "TX_FAILED",
44096
- `No JobCreated event emitted (txHash=${confirmed.txHash})`
44194
+ `No JobCreated event emitted (hash=${confirmed.hash})`
44097
44195
  );
44098
44196
  }
44099
44197
  success("Job created!");
@@ -44101,9 +44199,9 @@ function registerErc8183Command(program3) {
44101
44199
  {
44102
44200
  jobId: created.jobId.toString(),
44103
44201
  status: "Open",
44104
- hash: confirmed.txHash,
44202
+ hash: confirmed.hash,
44105
44203
  chain: chainKey,
44106
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44204
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44107
44205
  },
44108
44206
  opts.json
44109
44207
  );
@@ -44112,9 +44210,10 @@ function registerErc8183Command(program3) {
44112
44210
  }
44113
44211
  safeExit();
44114
44212
  });
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) => {
44213
+ 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
44214
  try {
44117
44215
  const id = parseUint(jobId, "jobId");
44216
+ const optParams = parseOptParams(opts.optParams);
44118
44217
  await ensureTrustSDK();
44119
44218
  const password3 = await resolvePassword(opts);
44120
44219
  const provider = await AgentWalletProvider.fromStorage(password3);
@@ -44123,16 +44222,16 @@ function registerErc8183Command(program3) {
44123
44222
  opts.chain
44124
44223
  );
44125
44224
  info(`Setting provider for job ${jobId} on ${chainKey}...`);
44126
- const pending = await commerce.write.setProvider([id, opts.provider, "0x"], provider);
44225
+ const pending = await commerce.write.setProvider([id, opts.provider, optParams], provider);
44127
44226
  const confirmed = await pending.wait();
44128
44227
  success("Provider set!");
44129
44228
  output(
44130
44229
  {
44131
44230
  jobId,
44132
44231
  provider: opts.provider,
44133
- hash: confirmed.txHash,
44232
+ hash: confirmed.hash,
44134
44233
  chain: chainKey,
44135
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44234
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44136
44235
  },
44137
44236
  opts.json
44138
44237
  );
@@ -44141,10 +44240,11 @@ function registerErc8183Command(program3) {
44141
44240
  }
44142
44241
  safeExit();
44143
44242
  });
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) => {
44243
+ 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
44244
  try {
44146
44245
  const id = parseUint(jobId, "jobId");
44147
44246
  const amount = parseUint(opts.amount, "amount");
44247
+ const optParams = parseOptParams(opts.optParams);
44148
44248
  await ensureTrustSDK();
44149
44249
  const password3 = await resolvePassword(opts);
44150
44250
  const provider = await AgentWalletProvider.fromStorage(password3);
@@ -44153,16 +44253,16 @@ function registerErc8183Command(program3) {
44153
44253
  opts.chain
44154
44254
  );
44155
44255
  info(`Setting budget for job ${jobId} on ${chainKey}...`);
44156
- const pending = await commerce.write.setBudget([id, amount, "0x"], provider);
44256
+ const pending = await commerce.write.setBudget([id, amount, optParams], provider);
44157
44257
  const confirmed = await pending.wait();
44158
44258
  success("Budget set!");
44159
44259
  output(
44160
44260
  {
44161
44261
  jobId,
44162
44262
  amount: opts.amount,
44163
- hash: confirmed.txHash,
44263
+ hash: confirmed.hash,
44164
44264
  chain: chainKey,
44165
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44265
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44166
44266
  },
44167
44267
  opts.json
44168
44268
  );
@@ -44171,37 +44271,53 @@ function registerErc8183Command(program3) {
44171
44271
  }
44172
44272
  safeExit();
44173
44273
  });
44174
- cmd.command("fund <jobId>").description("Fund a job: approve the budget then deposit it into escrow (two txs)").option("--chain <key>", CHAIN_OPT, "bsc").option("--password <password>", "Wallet password").option("--json", "JSON output").action(async (jobId, opts) => {
44274
+ cmd.command("fund <jobId>").description("Fund a job: approve the budget then deposit it into escrow (two txs)").option(
44275
+ "--expected-budget <atomic>",
44276
+ "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"
44277
+ ).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
44278
  try {
44176
44279
  const id = parseUint(jobId, "jobId");
44280
+ const optParams = parseOptParams(opts.optParams);
44177
44281
  await ensureTrustSDK();
44178
44282
  const password3 = await resolvePassword(opts);
44179
44283
  const provider = await AgentWalletProvider.fromStorage(password3);
44180
44284
  const client = provider.getBlockchainClient();
44181
44285
  const { commerce, chainKey } = resolveErc8183Contracts(client, opts.chain);
44182
- const job = await commerce.read.getJob([id]);
44183
- if (job.budget === 0n) {
44184
- throw new WalletError(
44185
- "VALIDATION_ERROR",
44186
- `Job ${jobId} has no budget set \u2014 run \`twak erc8183 set-budget\` before funding.`
44187
- );
44286
+ let budget;
44287
+ if (opts.expectedBudget !== void 0) {
44288
+ budget = parseUint(opts.expectedBudget, "expected-budget");
44289
+ if (budget === 0n) {
44290
+ throw new WalletError(
44291
+ "VALIDATION_ERROR",
44292
+ "--expected-budget must be greater than zero."
44293
+ );
44294
+ }
44295
+ } else {
44296
+ const job = await commerce.read.getJob([id]);
44297
+ if (job.budget === 0n) {
44298
+ throw new WalletError(
44299
+ "VALIDATION_ERROR",
44300
+ `Job ${jobId} has no budget set \u2014 run \`twak erc8183 set-budget\` before funding.`
44301
+ );
44302
+ }
44303
+ budget = job.budget;
44188
44304
  }
44189
44305
  const token = await commerce.read.paymentToken([]);
44190
- info(`Approving ${job.budget.toString()} for the escrow on ${chainKey}...`);
44191
- const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, job.budget], provider);
44306
+ info(`Approving ${budget.toString()} for the escrow on ${chainKey}...`);
44307
+ const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, budget], provider);
44192
44308
  const approveConfirmed = await approvePending.wait();
44193
44309
  info(`Funding job ${jobId}...`);
44194
- const fundPending = await commerce.write.fund([id, job.budget, "0x"], provider);
44310
+ const fundPending = await commerce.write.fund([id, budget, optParams], provider);
44195
44311
  const fundConfirmed = await fundPending.wait();
44196
44312
  success("Job funded!");
44197
44313
  output(
44198
44314
  {
44199
44315
  jobId,
44200
44316
  status: "Funded",
44201
- approveHash: approveConfirmed.txHash,
44202
- hash: fundConfirmed.txHash,
44317
+ approveHash: approveConfirmed.hash,
44318
+ hash: fundConfirmed.hash,
44203
44319
  chain: chainKey,
44204
- explorer: getExplorerTxUrl(chainKey, fundConfirmed.txHash)
44320
+ explorer: getExplorerTxUrl(chainKey, fundConfirmed.hash)
44205
44321
  },
44206
44322
  opts.json
44207
44323
  );
@@ -44210,9 +44326,10 @@ function registerErc8183Command(program3) {
44210
44326
  }
44211
44327
  safeExit();
44212
44328
  });
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) => {
44329
+ 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
44330
  try {
44215
44331
  const id = parseUint(jobId, "jobId");
44332
+ const optParams = parseOptParams(opts.optParams);
44216
44333
  await ensureTrustSDK();
44217
44334
  const password3 = await resolvePassword(opts);
44218
44335
  const provider = await AgentWalletProvider.fromStorage(password3);
@@ -44221,16 +44338,16 @@ function registerErc8183Command(program3) {
44221
44338
  opts.chain
44222
44339
  );
44223
44340
  info(`Submitting deliverable for job ${jobId} on ${chainKey}...`);
44224
- const pending = await commerce.write.submit([id, opts.deliverable, "0x"], provider);
44341
+ const pending = await commerce.write.submit([id, opts.deliverable, optParams], provider);
44225
44342
  const confirmed = await pending.wait();
44226
44343
  success("Deliverable submitted!");
44227
44344
  output(
44228
44345
  {
44229
44346
  jobId,
44230
44347
  status: "Submitted",
44231
- hash: confirmed.txHash,
44348
+ hash: confirmed.hash,
44232
44349
  chain: chainKey,
44233
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44350
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44234
44351
  },
44235
44352
  opts.json
44236
44353
  );
@@ -44239,9 +44356,10 @@ function registerErc8183Command(program3) {
44239
44356
  }
44240
44357
  safeExit();
44241
44358
  });
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) => {
44359
+ 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
44360
  try {
44244
44361
  const id = parseUint(jobId, "jobId");
44362
+ const optParams = parseOptParams(opts.optParams);
44245
44363
  await ensureTrustSDK();
44246
44364
  const password3 = await resolvePassword(opts);
44247
44365
  const provider = await AgentWalletProvider.fromStorage(password3);
@@ -44251,7 +44369,7 @@ function registerErc8183Command(program3) {
44251
44369
  );
44252
44370
  info(`Completing job ${jobId} on ${chainKey}...`);
44253
44371
  const pending = await commerce.write.complete(
44254
- [id, opts.reason ?? ZERO_BYTES32, "0x"],
44372
+ [id, opts.reason ?? ZERO_BYTES32, optParams],
44255
44373
  provider
44256
44374
  );
44257
44375
  const confirmed = await pending.wait();
@@ -44262,9 +44380,9 @@ function registerErc8183Command(program3) {
44262
44380
  jobId,
44263
44381
  status: "Completed",
44264
44382
  released: released ? released.amount.toString() : null,
44265
- hash: confirmed.txHash,
44383
+ hash: confirmed.hash,
44266
44384
  chain: chainKey,
44267
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44385
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44268
44386
  },
44269
44387
  opts.json
44270
44388
  );
@@ -44273,9 +44391,10 @@ function registerErc8183Command(program3) {
44273
44391
  }
44274
44392
  safeExit();
44275
44393
  });
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) => {
44394
+ 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
44395
  try {
44278
44396
  const id = parseUint(jobId, "jobId");
44397
+ const optParams = parseOptParams(opts.optParams);
44279
44398
  await ensureTrustSDK();
44280
44399
  const password3 = await resolvePassword(opts);
44281
44400
  const provider = await AgentWalletProvider.fromStorage(password3);
@@ -44285,7 +44404,7 @@ function registerErc8183Command(program3) {
44285
44404
  );
44286
44405
  info(`Rejecting job ${jobId} on ${chainKey}...`);
44287
44406
  const pending = await commerce.write.reject(
44288
- [id, opts.reason ?? ZERO_BYTES32, "0x"],
44407
+ [id, opts.reason ?? ZERO_BYTES32, optParams],
44289
44408
  provider
44290
44409
  );
44291
44410
  const confirmed = await pending.wait();
@@ -44296,9 +44415,9 @@ function registerErc8183Command(program3) {
44296
44415
  jobId,
44297
44416
  status: "Rejected",
44298
44417
  refunded: refunded ? refunded.amount.toString() : null,
44299
- hash: confirmed.txHash,
44418
+ hash: confirmed.hash,
44300
44419
  chain: chainKey,
44301
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44420
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44302
44421
  },
44303
44422
  opts.json
44304
44423
  );
@@ -44327,9 +44446,9 @@ function registerErc8183Command(program3) {
44327
44446
  jobId,
44328
44447
  status: "Expired",
44329
44448
  refunded: refunded ? refunded.amount.toString() : null,
44330
- hash: confirmed.txHash,
44449
+ hash: confirmed.hash,
44331
44450
  chain: chainKey,
44332
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44451
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44333
44452
  },
44334
44453
  opts.json
44335
44454
  );
@@ -44389,9 +44508,9 @@ function registerErc8183Command(program3) {
44389
44508
  {
44390
44509
  jobId,
44391
44510
  policy: policyAddr,
44392
- hash: confirmed.txHash,
44511
+ hash: confirmed.hash,
44393
44512
  chain: chainKey,
44394
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44513
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44395
44514
  },
44396
44515
  opts.json
44397
44516
  );
@@ -44417,9 +44536,9 @@ function registerErc8183Command(program3) {
44417
44536
  output(
44418
44537
  {
44419
44538
  jobId,
44420
- hash: confirmed.txHash,
44539
+ hash: confirmed.hash,
44421
44540
  chain: chainKey,
44422
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44541
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44423
44542
  },
44424
44543
  opts.json
44425
44544
  );
@@ -44446,9 +44565,9 @@ function registerErc8183Command(program3) {
44446
44565
  {
44447
44566
  jobId,
44448
44567
  status: "Expired",
44449
- hash: confirmed.txHash,
44568
+ hash: confirmed.hash,
44450
44569
  chain: chainKey,
44451
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44570
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44452
44571
  },
44453
44572
  opts.json
44454
44573
  );
@@ -44457,6 +44576,45 @@ function registerErc8183Command(program3) {
44457
44576
  }
44458
44577
  safeExit();
44459
44578
  });
44579
+ 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) => {
44580
+ try {
44581
+ const id = parseUint(jobId, "jobId");
44582
+ await ensureTrustSDK();
44583
+ const client = new BlockchainClient();
44584
+ const { router, policy, chainKey } = resolveErc8183Contracts(client, opts.chain);
44585
+ const registeredPolicy = await router.read.jobPolicy([id]);
44586
+ const registered = !isZeroAddress(registeredPolicy);
44587
+ const policyContract = registered && registeredPolicy.toLowerCase() !== policy.address.toLowerCase() ? erc8183Policy.using(client).withAddress(registeredPolicy, chainKey) : policy;
44588
+ const [disputeWindow, submittedAt, disputed, rejectVotes, voteQuorum, quorumSnapshot] = await Promise.all([
44589
+ policyContract.read.disputeWindow([]),
44590
+ policyContract.read.submittedAt([id]),
44591
+ policyContract.read.disputed([id]),
44592
+ policyContract.read.rejectVotes([id]),
44593
+ policyContract.read.voteQuorum([]),
44594
+ policyContract.read.disputeQuorumSnapshot([id])
44595
+ ]);
44596
+ const settleableAt = submittedAt > 0n ? submittedAt + disputeWindow : null;
44597
+ output(
44598
+ {
44599
+ jobId,
44600
+ policy: policyContract.address,
44601
+ registered,
44602
+ disputeWindow: disputeWindow.toString(),
44603
+ submittedAt: submittedAt.toString(),
44604
+ disputed,
44605
+ rejectVotes: rejectVotes.toString(),
44606
+ voteQuorum: voteQuorum.toString(),
44607
+ quorumSnapshot: quorumSnapshot.toString(),
44608
+ settleableAt: settleableAt?.toString() ?? null,
44609
+ chain: chainKey
44610
+ },
44611
+ opts.json
44612
+ );
44613
+ } catch (err) {
44614
+ handleCommandError(err, opts.json, "policy-info failed");
44615
+ }
44616
+ safeExit();
44617
+ });
44460
44618
  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
44619
  try {
44462
44620
  const id = parseUint(jobId, "jobId");
@@ -44474,9 +44632,9 @@ function registerErc8183Command(program3) {
44474
44632
  output(
44475
44633
  {
44476
44634
  jobId,
44477
- hash: confirmed.txHash,
44635
+ hash: confirmed.hash,
44478
44636
  chain: chainKey,
44479
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44637
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44480
44638
  },
44481
44639
  opts.json
44482
44640
  );
@@ -44502,9 +44660,9 @@ function registerErc8183Command(program3) {
44502
44660
  output(
44503
44661
  {
44504
44662
  jobId,
44505
- hash: confirmed.txHash,
44663
+ hash: confirmed.hash,
44506
44664
  chain: chainKey,
44507
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44665
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44508
44666
  },
44509
44667
  opts.json
44510
44668
  );
@@ -44570,7 +44728,7 @@ function registerCompeteCommand(program3) {
44570
44728
  if (!confirmed.events.Registered?.[0]) {
44571
44729
  throw new WalletError(
44572
44730
  "TX_FAILED",
44573
- `no Registered event emitted (txHash=${confirmed.txHash})`
44731
+ `no Registered event emitted (hash=${confirmed.hash})`
44574
44732
  );
44575
44733
  }
44576
44734
  success("Registered for BNB HACK: AI TRADING AGENT EDITION!");
@@ -44579,9 +44737,9 @@ function registerCompeteCommand(program3) {
44579
44737
  registered: true,
44580
44738
  participant,
44581
44739
  deadline: toIso(deadline),
44582
- hash: confirmed.txHash,
44740
+ hash: confirmed.hash,
44583
44741
  chain: chainKey,
44584
- explorer: getExplorerTxUrl(chainKey, confirmed.txHash)
44742
+ explorer: getExplorerTxUrl(chainKey, confirmed.hash)
44585
44743
  },
44586
44744
  opts.json
44587
44745
  );
@@ -46259,15 +46417,15 @@ async function ensurePermit2Allowance(args) {
46259
46417
  [PERMIT2_ADDRESS, BigInt(MAX_UINT256_DECIMAL)],
46260
46418
  args.walletProvider
46261
46419
  );
46262
- await waitForTxConfirmation(args.blockchainClient, args.chainKey, args.owner, pending.txHash);
46263
- return { token: args.tokenAddress, chain: args.chainKey, txHash: pending.txHash };
46420
+ await waitForTxConfirmation(args.blockchainClient, args.chainKey, args.owner, pending.hash);
46421
+ return { token: args.tokenAddress, chain: args.chainKey, hash: pending.hash };
46264
46422
  }
46265
46423
  var APPROVE_TIMEOUT_MS = 6e4;
46266
46424
  var APPROVE_POLL_MS = 2e3;
46267
- async function waitForTxConfirmation(bc2, chainKey, address, txHash) {
46425
+ async function waitForTxConfirmation(bc2, chainKey, address, hash) {
46268
46426
  const start = Date.now();
46269
46427
  while (Date.now() - start < APPROVE_TIMEOUT_MS) {
46270
- const status = await bc2.findTransactionStatus(chainKey, address, txHash);
46428
+ const status = await bc2.findTransactionStatus(chainKey, address, hash);
46271
46429
  if (status.confirmed) return;
46272
46430
  if (status.failed) {
46273
46431
  throw new X402Error(
@@ -46279,7 +46437,7 @@ async function waitForTxConfirmation(bc2, chainKey, address, txHash) {
46279
46437
  }
46280
46438
  throw new X402Error(
46281
46439
  "TX_FAILED",
46282
- `Permit2 approval ${txHash} not confirmed within ${APPROVE_TIMEOUT_MS / 1e3}s`
46440
+ `Permit2 approval ${hash} not confirmed within ${APPROVE_TIMEOUT_MS / 1e3}s`
46283
46441
  );
46284
46442
  }
46285
46443
  function ipv4MappedToDotted(ip) {
@@ -46796,7 +46954,7 @@ var TransferActionProvider = class extends ActionProvider {
46796
46954
  const resolvedTo = await resolveAddressOrName(input2.to);
46797
46955
  const atomicAmount = parseAmount(input2.amount, decimals);
46798
46956
  const isErc20 = Boolean(tokenAddress);
46799
- let txHash;
46957
+ let hash;
46800
46958
  if (isErc20) {
46801
46959
  if (!this.blockchainClient) {
46802
46960
  throw new TransferError(
@@ -46805,19 +46963,19 @@ var TransferActionProvider = class extends ActionProvider {
46805
46963
  );
46806
46964
  }
46807
46965
  const pending = await this.blockchainClient.contract(erc20).withAddress(tokenAddress, chainKey).write.transfer([resolvedTo, BigInt(atomicAmount)], signer);
46808
- txHash = pending.txHash;
46966
+ hash = pending.hash;
46809
46967
  } else {
46810
- txHash = await signer.sendTransaction({
46968
+ hash = await signer.sendTransaction({
46811
46969
  chainId: caip2,
46812
46970
  to: resolvedTo,
46813
46971
  data: "0x",
46814
46972
  value: "0x" + BigInt(atomicAmount).toString(16)
46815
46973
  });
46816
46974
  }
46817
- const explorerUrl = getExplorerTxUrl(chainKey, txHash);
46975
+ const explorerUrl = getExplorerTxUrl(chainKey, hash);
46818
46976
  return {
46819
46977
  success: true,
46820
- txHash,
46978
+ hash,
46821
46979
  to: resolvedTo,
46822
46980
  resolvedFrom: input2.to !== resolvedTo ? input2.to : void 0,
46823
46981
  explorer: explorerUrl || void 0
@@ -46902,7 +47060,7 @@ var SwapActionProvider = class extends ActionProvider {
46902
47060
  const outputAmt = formatAmount(lastStep.to.amount, lastStep.to.asset.metadata.decimals);
46903
47061
  return {
46904
47062
  success: true,
46905
- txHash: result.txHash,
47063
+ hash: result.hash,
46906
47064
  summary: `${inputAmt} ${firstStep.from.asset.metadata.symbol} -> ${outputAmt} ${lastStep.to.asset.metadata.symbol}`,
46907
47065
  provider: result.route.steps.map((s2) => s2.provider.name).join(" -> "),
46908
47066
  explorer: result.explorerUrl || void 0
@@ -47364,7 +47522,7 @@ var TokenActionProvider = class extends ActionProvider {
47364
47522
  hdWallet,
47365
47523
  chainKey
47366
47524
  });
47367
- return { hash: result.txHash, chain: result.chainKey };
47525
+ return { hash: result.hash, chain: result.chainKey };
47368
47526
  }
47369
47527
  const chain2 = requireChain(chainKey);
47370
47528
  if (chain2.namespace !== "eip155") {
@@ -47376,24 +47534,24 @@ var TokenActionProvider = class extends ActionProvider {
47376
47534
  if (input2.tokenAddress) assertEvmAddress(input2.tokenAddress, "tokenAddress");
47377
47535
  const caipChainId = `${chain2.namespace}:${chain2.chainId}`;
47378
47536
  const atomicAmount = parseAmount(input2.amount, decimals);
47379
- let txHash;
47537
+ let hash;
47380
47538
  if (input2.tokenAddress) {
47381
47539
  if (!this.blockchainClient) {
47382
47540
  throw new WalletError("WALLET_NOT_FOUND", "BlockchainClient not available");
47383
47541
  }
47384
47542
  const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.transfer([input2.to, BigInt(atomicAmount)], wallet);
47385
- txHash = pending.txHash;
47543
+ hash = pending.hash;
47386
47544
  } else {
47387
47545
  assertEvmAddress(input2.to, "to");
47388
47546
  const valueHex = "0x" + BigInt(atomicAmount).toString(16);
47389
- txHash = await wallet.sendTransaction({
47547
+ hash = await wallet.sendTransaction({
47390
47548
  chainId: caipChainId,
47391
47549
  to: input2.to,
47392
47550
  data: "0x",
47393
47551
  value: valueHex
47394
47552
  });
47395
47553
  }
47396
- return { hash: txHash, chain: chainKey };
47554
+ return { hash, chain: chainKey };
47397
47555
  }
47398
47556
  };
47399
47557
  }
@@ -47424,7 +47582,7 @@ var TokenActionProvider = class extends ActionProvider {
47424
47582
  }
47425
47583
  const amount = input2.amount === "unlimited" ? "115792089237316195423570985008687907853269984665640564039457584007913129639935" : input2.amount;
47426
47584
  const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.approve([input2.spender, BigInt(amount)], wallet);
47427
- return { hash: pending.txHash, chain: chainKey };
47585
+ return { hash: pending.hash, chain: chainKey };
47428
47586
  }
47429
47587
  };
47430
47588
  }
@@ -47453,7 +47611,7 @@ var TokenActionProvider = class extends ActionProvider {
47453
47611
  throw new WalletError("WALLET_NOT_FOUND", "BlockchainClient not available");
47454
47612
  }
47455
47613
  const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.approve([input2.spender, 0n], wallet);
47456
- return { hash: pending.txHash, chain: chainKey };
47614
+ return { hash: pending.hash, chain: chainKey };
47457
47615
  }
47458
47616
  };
47459
47617
  }
@@ -47923,7 +48081,7 @@ var OnrampActionProvider = class extends ActionProvider {
47923
48081
  if (cap) return { success: false, ...cap };
47924
48082
  }
47925
48083
  const atomic = parseAmount(input2.cryptoAmount, decimals);
47926
- let txHash;
48084
+ let hash;
47927
48085
  if (input2.tokenAddress) {
47928
48086
  if (!this.blockchainClient) {
47929
48087
  throw new TransferError(
@@ -47932,19 +48090,19 @@ var OnrampActionProvider = class extends ActionProvider {
47932
48090
  );
47933
48091
  }
47934
48092
  const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.transfer([input2.depositAddress, BigInt(atomic)], signer);
47935
- txHash = pending.txHash;
48093
+ hash = pending.hash;
47936
48094
  } else {
47937
- txHash = await signer.sendTransaction({
48095
+ hash = await signer.sendTransaction({
47938
48096
  chainId: caip2,
47939
48097
  to: input2.depositAddress,
47940
48098
  data: "0x",
47941
48099
  value: "0x" + BigInt(atomic).toString(16)
47942
48100
  });
47943
48101
  }
47944
- const explorerUrl = getExplorerTxUrl(chainKey, txHash) || void 0;
48102
+ const explorerUrl = getExplorerTxUrl(chainKey, hash) || void 0;
47945
48103
  return {
47946
48104
  success: true,
47947
- txHash,
48105
+ hash,
47948
48106
  chain: chainKey,
47949
48107
  tokenAddress: input2.tokenAddress,
47950
48108
  to: input2.depositAddress,
@@ -48114,7 +48272,7 @@ var AutomateActionProvider = class extends ActionProvider {
48114
48272
  await this.automationStore.update(record2.id, { lastRunAt: (/* @__PURE__ */ new Date()).toISOString() });
48115
48273
  return {
48116
48274
  success: true,
48117
- txHash: result.txHash,
48275
+ hash: result.hash,
48118
48276
  automationId: record2.id,
48119
48277
  swapped: `${record2.amount} ${record2.fromToken} \u2192 ${record2.toToken}`,
48120
48278
  explorer: result.explorerUrl || void 0
@@ -48330,13 +48488,13 @@ var Erc8004ActionProvider = class extends ActionProvider {
48330
48488
  if (!registered) {
48331
48489
  throw new WalletError(
48332
48490
  "TX_FAILED",
48333
- `erc8004_register: no Registered event emitted (txHash=${confirmed.txHash})`
48491
+ `erc8004_register: no Registered event emitted (hash=${confirmed.hash})`
48334
48492
  );
48335
48493
  }
48336
48494
  return {
48337
48495
  success: true,
48338
48496
  agentId: registered.agentId.toString(),
48339
- txHash: confirmed.txHash,
48497
+ hash: confirmed.hash,
48340
48498
  owner: registered.owner,
48341
48499
  agentURI: registered.agentURI,
48342
48500
  ...entries.length > 0 ? { metadata: Object.fromEntries(entries) } : {},
@@ -48363,7 +48521,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
48363
48521
  this.walletContext.activeWallet()
48364
48522
  );
48365
48523
  const confirmed = await pending.wait();
48366
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
48524
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48367
48525
  }
48368
48526
  };
48369
48527
  }
@@ -48387,7 +48545,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
48387
48545
  this.walletContext.activeWallet()
48388
48546
  );
48389
48547
  const confirmed = await pending.wait();
48390
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
48548
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48391
48549
  }
48392
48550
  };
48393
48551
  }
@@ -48453,6 +48611,7 @@ var jobIdSchema = import_zod17.z.string().regex(/^\d+$/, "jobId must be a decima
48453
48611
  var amountSchema = import_zod17.z.string().regex(/^\d+$/, "amount must be an atomic (base-unit) integer string.");
48454
48612
  var evmAddressSchema = import_zod17.z.string().refine(isEvmAddress, "must be a 0x-prefixed 40-hex EVM address.");
48455
48613
  var bytes32Schema = import_zod17.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be 0x-prefixed 32-byte hex.");
48614
+ 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
48615
  var ZERO_BYTES322 = `0x${"0".repeat(64)}`;
48457
48616
  var Erc8183ActionProvider = class extends ActionProvider {
48458
48617
  constructor(blockchainClient, walletContext) {
@@ -48473,6 +48632,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48473
48632
  this.reject(),
48474
48633
  this.claimRefund(),
48475
48634
  this.status(),
48635
+ this.policyInfo(),
48476
48636
  this.registerJob(),
48477
48637
  this.settle(),
48478
48638
  this.markExpired(),
@@ -48514,13 +48674,13 @@ var Erc8183ActionProvider = class extends ActionProvider {
48514
48674
  if (!created) {
48515
48675
  throw new WalletError(
48516
48676
  "TX_FAILED",
48517
- `erc8183_create_job: no JobCreated event emitted (txHash=${confirmed.txHash})`
48677
+ `erc8183_create_job: no JobCreated event emitted (hash=${confirmed.hash})`
48518
48678
  );
48519
48679
  }
48520
48680
  return {
48521
48681
  success: true,
48522
48682
  jobId: created.jobId.toString(),
48523
- txHash: confirmed.txHash,
48683
+ hash: confirmed.hash,
48524
48684
  status: "Open",
48525
48685
  chain: chainKey
48526
48686
  };
@@ -48534,16 +48694,17 @@ var Erc8183ActionProvider = class extends ActionProvider {
48534
48694
  schema: import_zod17.z.object({
48535
48695
  jobId: jobIdSchema,
48536
48696
  provider: evmAddressSchema.describe("New provider (worker) address."),
48697
+ optParams: optParamsSchema,
48537
48698
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48538
48699
  }),
48539
48700
  invoke: async (_ctx, input2) => {
48540
48701
  const { commerce, chainKey } = this.bind(input2.chain);
48541
48702
  const pending = await commerce.write.setProvider(
48542
- [BigInt(input2.jobId), input2.provider, "0x"],
48703
+ [BigInt(input2.jobId), input2.provider, input2.optParams ?? "0x"],
48543
48704
  this.walletContext.activeWallet()
48544
48705
  );
48545
48706
  const confirmed = await pending.wait();
48546
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
48707
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48547
48708
  }
48548
48709
  };
48549
48710
  }
@@ -48554,47 +48715,64 @@ var Erc8183ActionProvider = class extends ActionProvider {
48554
48715
  schema: import_zod17.z.object({
48555
48716
  jobId: jobIdSchema,
48556
48717
  amount: amountSchema.describe("Budget in atomic units of the payment token."),
48718
+ optParams: optParamsSchema,
48557
48719
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48558
48720
  }),
48559
48721
  invoke: async (_ctx, input2) => {
48560
48722
  const { commerce, chainKey } = this.bind(input2.chain);
48561
48723
  const pending = await commerce.write.setBudget(
48562
- [BigInt(input2.jobId), BigInt(input2.amount), "0x"],
48724
+ [BigInt(input2.jobId), BigInt(input2.amount), input2.optParams ?? "0x"],
48563
48725
  this.walletContext.activeWallet()
48564
48726
  );
48565
48727
  const confirmed = await pending.wait();
48566
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
48728
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48567
48729
  }
48568
48730
  };
48569
48731
  }
48570
48732
  fund() {
48571
48733
  return {
48572
48734
  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`.",
48735
+ 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
48736
  schema: import_zod17.z.object({
48575
48737
  jobId: jobIdSchema,
48738
+ expectedBudget: amountSchema.optional().describe(
48739
+ "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."
48740
+ ),
48741
+ optParams: optParamsSchema,
48576
48742
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48577
48743
  }),
48578
48744
  invoke: async (_ctx, input2) => {
48579
48745
  const { client, commerce, chainKey } = this.bind(input2.chain);
48580
48746
  const jobId = BigInt(input2.jobId);
48581
- const job = await commerce.read.getJob([jobId]);
48582
- if (job.budget === 0n) {
48583
- throw new WalletError(
48584
- "VALIDATION_ERROR",
48585
- `Job ${input2.jobId} has no budget set \u2014 call erc8183_set_budget before funding.`
48586
- );
48747
+ let budget;
48748
+ if (input2.expectedBudget !== void 0) {
48749
+ budget = BigInt(input2.expectedBudget);
48750
+ if (budget === 0n) {
48751
+ throw new WalletError("VALIDATION_ERROR", "expectedBudget must be greater than zero.");
48752
+ }
48753
+ } else {
48754
+ const job = await commerce.read.getJob([jobId]);
48755
+ if (job.budget === 0n) {
48756
+ throw new WalletError(
48757
+ "VALIDATION_ERROR",
48758
+ `Job ${input2.jobId} has no budget set \u2014 call erc8183_set_budget before funding.`
48759
+ );
48760
+ }
48761
+ budget = job.budget;
48587
48762
  }
48588
48763
  const token = await commerce.read.paymentToken([]);
48589
48764
  const wallet = this.walletContext.activeWallet();
48590
- const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, job.budget], wallet);
48765
+ const approvePending = await erc20.using(client).withAddress(token, chainKey).write.approve([commerce.address, budget], wallet);
48591
48766
  const approveConfirmed = await approvePending.wait();
48592
- const fundPending = await commerce.write.fund([jobId, job.budget, "0x"], wallet);
48767
+ const fundPending = await commerce.write.fund(
48768
+ [jobId, budget, input2.optParams ?? "0x"],
48769
+ wallet
48770
+ );
48593
48771
  const fundConfirmed = await fundPending.wait();
48594
48772
  return {
48595
48773
  success: true,
48596
- approveHash: approveConfirmed.txHash,
48597
- txHash: fundConfirmed.txHash,
48774
+ approveHash: approveConfirmed.hash,
48775
+ hash: fundConfirmed.hash,
48598
48776
  status: "Funded",
48599
48777
  chain: chainKey
48600
48778
  };
@@ -48610,16 +48788,19 @@ var Erc8183ActionProvider = class extends ActionProvider {
48610
48788
  deliverable: bytes32Schema.describe(
48611
48789
  "bytes32 deliverable commitment (e.g. a content hash)."
48612
48790
  ),
48791
+ optParams: optParamsSchema.describe(
48792
+ '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": "..."}.'
48793
+ ),
48613
48794
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48614
48795
  }),
48615
48796
  invoke: async (_ctx, input2) => {
48616
48797
  const { commerce, chainKey } = this.bind(input2.chain);
48617
48798
  const pending = await commerce.write.submit(
48618
- [BigInt(input2.jobId), input2.deliverable, "0x"],
48799
+ [BigInt(input2.jobId), input2.deliverable, input2.optParams ?? "0x"],
48619
48800
  this.walletContext.activeWallet()
48620
48801
  );
48621
48802
  const confirmed = await pending.wait();
48622
- return { success: true, txHash: confirmed.txHash, status: "Submitted", chain: chainKey };
48803
+ return { success: true, hash: confirmed.hash, status: "Submitted", chain: chainKey };
48623
48804
  }
48624
48805
  };
48625
48806
  }
@@ -48630,19 +48811,20 @@ var Erc8183ActionProvider = class extends ActionProvider {
48630
48811
  schema: import_zod17.z.object({
48631
48812
  jobId: jobIdSchema,
48632
48813
  reason: bytes32Schema.optional().describe("Optional bytes32 reason/attestation (defaults to zero)."),
48814
+ optParams: optParamsSchema,
48633
48815
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48634
48816
  }),
48635
48817
  invoke: async (_ctx, input2) => {
48636
48818
  const { commerce, chainKey } = this.bind(input2.chain);
48637
48819
  const pending = await commerce.write.complete(
48638
- [BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, "0x"],
48820
+ [BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, input2.optParams ?? "0x"],
48639
48821
  this.walletContext.activeWallet()
48640
48822
  );
48641
48823
  const confirmed = await pending.wait();
48642
48824
  const released = confirmed.events.PaymentReleased?.[0];
48643
48825
  return {
48644
48826
  success: true,
48645
- txHash: confirmed.txHash,
48827
+ hash: confirmed.hash,
48646
48828
  status: "Completed",
48647
48829
  released: released ? released.amount.toString() : null,
48648
48830
  chain: chainKey
@@ -48657,19 +48839,20 @@ var Erc8183ActionProvider = class extends ActionProvider {
48657
48839
  schema: import_zod17.z.object({
48658
48840
  jobId: jobIdSchema,
48659
48841
  reason: bytes32Schema.optional().describe("Optional bytes32 reason (defaults to zero)."),
48842
+ optParams: optParamsSchema,
48660
48843
  chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48661
48844
  }),
48662
48845
  invoke: async (_ctx, input2) => {
48663
48846
  const { commerce, chainKey } = this.bind(input2.chain);
48664
48847
  const pending = await commerce.write.reject(
48665
- [BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, "0x"],
48848
+ [BigInt(input2.jobId), input2.reason ?? ZERO_BYTES322, input2.optParams ?? "0x"],
48666
48849
  this.walletContext.activeWallet()
48667
48850
  );
48668
48851
  const confirmed = await pending.wait();
48669
48852
  const refunded = confirmed.events.Refunded?.[0];
48670
48853
  return {
48671
48854
  success: true,
48672
- txHash: confirmed.txHash,
48855
+ hash: confirmed.hash,
48673
48856
  status: "Rejected",
48674
48857
  refunded: refunded ? refunded.amount.toString() : null,
48675
48858
  chain: chainKey
@@ -48695,7 +48878,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48695
48878
  const refunded = confirmed.events.Refunded?.[0];
48696
48879
  return {
48697
48880
  success: true,
48698
- txHash: confirmed.txHash,
48881
+ hash: confirmed.hash,
48699
48882
  status: "Expired",
48700
48883
  refunded: refunded ? refunded.amount.toString() : null,
48701
48884
  chain: chainKey
@@ -48737,6 +48920,46 @@ var Erc8183ActionProvider = class extends ActionProvider {
48737
48920
  }
48738
48921
  };
48739
48922
  }
48923
+ policyInfo() {
48924
+ return {
48925
+ name: "erc8183_policy_info",
48926
+ 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.",
48927
+ schema: import_zod17.z.object({
48928
+ jobId: jobIdSchema,
48929
+ chain: import_zod17.z.string().default("bsc").describe(CHAIN_DESC)
48930
+ }),
48931
+ invoke: async (_ctx, input2) => {
48932
+ const { client, router, policy, chainKey } = this.bind(input2.chain);
48933
+ const jobId = BigInt(input2.jobId);
48934
+ const registeredPolicy = await router.read.jobPolicy([jobId]);
48935
+ const registered = !isZeroAddress(registeredPolicy);
48936
+ const policyContract = registered && registeredPolicy.toLowerCase() !== policy.address.toLowerCase() ? erc8183Policy.using(client).withAddress(registeredPolicy, chainKey) : policy;
48937
+ const [disputeWindow, submittedAt, disputed, rejectVotes, voteQuorum, quorumSnapshot] = await Promise.all([
48938
+ policyContract.read.disputeWindow([]),
48939
+ policyContract.read.submittedAt([jobId]),
48940
+ policyContract.read.disputed([jobId]),
48941
+ policyContract.read.rejectVotes([jobId]),
48942
+ policyContract.read.voteQuorum([]),
48943
+ policyContract.read.disputeQuorumSnapshot([jobId])
48944
+ ]);
48945
+ const settleableAt = submittedAt > 0n ? submittedAt + disputeWindow : null;
48946
+ return {
48947
+ success: true,
48948
+ jobId: input2.jobId,
48949
+ policy: policyContract.address,
48950
+ registered,
48951
+ disputeWindow: disputeWindow.toString(),
48952
+ submittedAt: submittedAt.toString(),
48953
+ disputed,
48954
+ rejectVotes: rejectVotes.toString(),
48955
+ voteQuorum: voteQuorum.toString(),
48956
+ quorumSnapshot: quorumSnapshot.toString(),
48957
+ settleableAt: settleableAt?.toString() ?? null,
48958
+ chain: chainKey
48959
+ };
48960
+ }
48961
+ };
48962
+ }
48740
48963
  // ----- Router -------------------------------------------------------------
48741
48964
  registerJob() {
48742
48965
  return {
@@ -48754,7 +48977,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48754
48977
  this.walletContext.activeWallet()
48755
48978
  );
48756
48979
  const confirmed = await pending.wait();
48757
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
48980
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48758
48981
  }
48759
48982
  };
48760
48983
  }
@@ -48774,7 +48997,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48774
48997
  this.walletContext.activeWallet()
48775
48998
  );
48776
48999
  const confirmed = await pending.wait();
48777
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
49000
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48778
49001
  }
48779
49002
  };
48780
49003
  }
@@ -48793,7 +49016,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48793
49016
  this.walletContext.activeWallet()
48794
49017
  );
48795
49018
  const confirmed = await pending.wait();
48796
- return { success: true, txHash: confirmed.txHash, status: "Expired", chain: chainKey };
49019
+ return { success: true, hash: confirmed.hash, status: "Expired", chain: chainKey };
48797
49020
  }
48798
49021
  };
48799
49022
  }
@@ -48813,7 +49036,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48813
49036
  this.walletContext.activeWallet()
48814
49037
  );
48815
49038
  const confirmed = await pending.wait();
48816
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
49039
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48817
49040
  }
48818
49041
  };
48819
49042
  }
@@ -48832,7 +49055,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
48832
49055
  this.walletContext.activeWallet()
48833
49056
  );
48834
49057
  const confirmed = await pending.wait();
48835
- return { success: true, txHash: confirmed.txHash, chain: chainKey };
49058
+ return { success: true, hash: confirmed.hash, chain: chainKey };
48836
49059
  }
48837
49060
  };
48838
49061
  }
@@ -48903,14 +49126,14 @@ var CompetitionActionProvider = class extends ActionProvider {
48903
49126
  if (!confirmed.events.Registered?.[0]) {
48904
49127
  throw new WalletError(
48905
49128
  "TX_FAILED",
48906
- `competition_register: no Registered event emitted (txHash=${confirmed.txHash})`
49129
+ `competition_register: no Registered event emitted (hash=${confirmed.hash})`
48907
49130
  );
48908
49131
  }
48909
49132
  return {
48910
49133
  success: true,
48911
49134
  registered: true,
48912
49135
  participant,
48913
- txHash: confirmed.txHash,
49136
+ hash: confirmed.hash,
48914
49137
  deadline: toIso2(deadline),
48915
49138
  chain: CHAIN
48916
49139
  };
@@ -53915,7 +54138,7 @@ async function runAutomationsTick(deps) {
53915
54138
  runCount: (auto.runCount ?? 0) + 1
53916
54139
  });
53917
54140
  log("info", `DCA executed: ${res.explorerUrl}`);
53918
- result.executed.push({ id: auto.id, type: "dca", txHash: res.txHash });
54141
+ result.executed.push({ id: auto.id, type: "dca", hash: res.hash });
53919
54142
  } else {
53920
54143
  log("warn", `DCA ${auto.id} failed: ${res.error}`);
53921
54144
  result.errors++;
@@ -53963,7 +54186,7 @@ async function runAutomationsTick(deps) {
53963
54186
  lastRunAt: (/* @__PURE__ */ new Date()).toISOString()
53964
54187
  });
53965
54188
  log("info", `Limit order executed: ${res.explorerUrl}`);
53966
- result.executed.push({ id: auto.id, type: "limit", txHash: res.txHash });
54189
+ result.executed.push({ id: auto.id, type: "limit", hash: res.hash });
53967
54190
  } else {
53968
54191
  log("warn", `Limit order ${auto.id} failed: ${res.error}`);
53969
54192
  result.errors++;
@@ -54519,7 +54742,7 @@ ${url}`);
54519
54742
  } catch (err) {
54520
54743
  mapBroadcastError(err);
54521
54744
  }
54522
- const explorerUrl = getExplorerTxUrl(result.chainKey, result.txHash);
54745
+ const explorerUrl = getExplorerTxUrl(result.chainKey, result.hash);
54523
54746
  success("Off-ramp payout broadcast!");
54524
54747
  if (!opts.json) {
54525
54748
  info(
@@ -54528,7 +54751,7 @@ ${url}`);
54528
54751
  }
54529
54752
  output(
54530
54753
  {
54531
- hash: result.txHash,
54754
+ hash: result.hash,
54532
54755
  chain: result.chainKey,
54533
54756
  from: address,
54534
54757
  to: opts.to,
@@ -54913,7 +55136,7 @@ function registerX402Command(program3) {
54913
55136
  confirmApproval: opts.autoApprove ? autoApproveConfirm : makeReadlineApprovalConfirm()
54914
55137
  });
54915
55138
  if (approval) {
54916
- info(`x402: Permit2 approved (one-time): tx ${approval.txHash}`);
55139
+ info(`x402: Permit2 approved (one-time): tx ${approval.hash}`);
54917
55140
  }
54918
55141
  if (payment) {
54919
55142
  info(
@@ -55028,7 +55251,7 @@ var crypto7 = __toESM(require("crypto"));
55028
55251
  // package.json
55029
55252
  var package_default = {
55030
55253
  name: "@trustwallet/cli",
55031
- version: "0.18.0",
55254
+ version: "0.19.0",
55032
55255
  description: "TWAK CLI \u2014 command-line interface for Trust Wallet Agent Kit",
55033
55256
  main: "dist/index.js",
55034
55257
  types: "dist/index.d.ts",
@@ -55404,7 +55627,7 @@ function registerWatchCommand(program3) {
55404
55627
  tickResults.automations.executed.push({
55405
55628
  id: auto.id,
55406
55629
  type: "dca",
55407
- txHash: result.txHash,
55630
+ hash: result.hash,
55408
55631
  explorer: result.explorerUrl
55409
55632
  });
55410
55633
  } else {
@@ -55472,7 +55695,7 @@ function registerWatchCommand(program3) {
55472
55695
  tickResults.automations.executed.push({
55473
55696
  id: auto.id,
55474
55697
  type: "limit",
55475
- txHash: result.txHash,
55698
+ hash: result.hash,
55476
55699
  explorer: result.explorerUrl
55477
55700
  });
55478
55701
  } else {