@trustwallet/cli 0.18.0 → 0.19.1

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