@trustwallet/cli 0.23.0 → 0.24.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
@@ -1046,7 +1046,7 @@ var require_command = __commonJS({
1046
1046
  "use strict";
1047
1047
  var EventEmitter = require("events").EventEmitter;
1048
1048
  var childProcess = require("child_process");
1049
- var path7 = require("path");
1049
+ var path13 = require("path");
1050
1050
  var fs10 = require("fs");
1051
1051
  var process3 = require("process");
1052
1052
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -1979,9 +1979,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
1979
1979
  let launchWithNode = false;
1980
1980
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1981
1981
  function findFile(baseDir, baseName) {
1982
- const localBin = path7.resolve(baseDir, baseName);
1982
+ const localBin = path13.resolve(baseDir, baseName);
1983
1983
  if (fs10.existsSync(localBin)) return localBin;
1984
- if (sourceExt.includes(path7.extname(baseName))) return void 0;
1984
+ if (sourceExt.includes(path13.extname(baseName))) return void 0;
1985
1985
  const foundExt = sourceExt.find(
1986
1986
  (ext) => fs10.existsSync(`${localBin}${ext}`)
1987
1987
  );
@@ -1999,17 +1999,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
1999
1999
  } catch (err) {
2000
2000
  resolvedScriptPath = this._scriptPath;
2001
2001
  }
2002
- executableDir = path7.resolve(
2003
- path7.dirname(resolvedScriptPath),
2002
+ executableDir = path13.resolve(
2003
+ path13.dirname(resolvedScriptPath),
2004
2004
  executableDir
2005
2005
  );
2006
2006
  }
2007
2007
  if (executableDir) {
2008
2008
  let localFile = findFile(executableDir, executableFile);
2009
2009
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2010
- const legacyName = path7.basename(
2010
+ const legacyName = path13.basename(
2011
2011
  this._scriptPath,
2012
- path7.extname(this._scriptPath)
2012
+ path13.extname(this._scriptPath)
2013
2013
  );
2014
2014
  if (legacyName !== this._name) {
2015
2015
  localFile = findFile(
@@ -2020,7 +2020,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2020
2020
  }
2021
2021
  executableFile = localFile || executableFile;
2022
2022
  }
2023
- launchWithNode = sourceExt.includes(path7.extname(executableFile));
2023
+ launchWithNode = sourceExt.includes(path13.extname(executableFile));
2024
2024
  let proc;
2025
2025
  if (process3.platform !== "win32") {
2026
2026
  if (launchWithNode) {
@@ -2860,7 +2860,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2860
2860
  * @return {Command}
2861
2861
  */
2862
2862
  nameFromFilename(filename) {
2863
- this._name = path7.basename(filename, path7.extname(filename));
2863
+ this._name = path13.basename(filename, path13.extname(filename));
2864
2864
  return this;
2865
2865
  }
2866
2866
  /**
@@ -2874,9 +2874,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2874
2874
  * @param {string} [path]
2875
2875
  * @return {(string|null|Command)}
2876
2876
  */
2877
- executableDir(path8) {
2878
- if (path8 === void 0) return this._executableDir;
2879
- this._executableDir = path8;
2877
+ executableDir(path14) {
2878
+ if (path14 === void 0) return this._executableDir;
2879
+ this._executableDir = path14;
2880
2880
  return this;
2881
2881
  }
2882
2882
  /**
@@ -3108,213 +3108,13 @@ var require_commander = __commonJS({
3108
3108
  });
3109
3109
 
3110
3110
  // ../core/dist/index.mjs
3111
- var dist_exports = {};
3112
- __export(dist_exports, {
3113
- ALERT_ERROR_CODES: () => ALERT_ERROR_CODES,
3114
- ALLOWED_OFFRAMP_PROVIDERS: () => ALLOWED_OFFRAMP_PROVIDERS,
3115
- AUTOMATION_ERROR_CODES: () => AUTOMATION_ERROR_CODES,
3116
- AlertError: () => AlertError,
3117
- AutomationError: () => AutomationError,
3118
- BALANCE_ERROR_CODES: () => BALANCE_ERROR_CODES,
3119
- BalanceError: () => BalanceError,
3120
- CELO_NATIVE_ADDRESS: () => CELO_NATIVE_ADDRESS,
3121
- CHAINS: () => CHAINS,
3122
- COMMON_ERROR_CODES: () => COMMON_ERROR_CODES,
3123
- COMMON_TOKENS: () => COMMON_TOKENS,
3124
- CommandError: () => CommandError,
3125
- DEFAULT_USER_AGENT: () => DEFAULT_USER_AGENT,
3126
- ERC20_ERROR_CODES: () => ERC20_ERROR_CODES,
3127
- ERC20_TRANSFER_SIG: () => ERC20_TRANSFER_SIG,
3128
- EVM_ADDRESS_RE: () => EVM_ADDRESS_RE,
3129
- Erc20Error: () => Erc20Error,
3130
- McpResponse: () => McpResponse,
3131
- NATIVE_TOKEN_ADDRESS: () => NATIVE_TOKEN_ADDRESS,
3132
- QUERY_ERROR_CODES: () => QUERY_ERROR_CODES,
3133
- QueryError: () => QueryError,
3134
- SOLANA_NATIVE_ADDRESS: () => SOLANA_NATIVE_ADDRESS,
3135
- SWAP_ERROR_CODES: () => SWAP_ERROR_CODES,
3136
- SwapError: () => SwapError,
3137
- TESTNET_CHAINS: () => TESTNET_CHAINS,
3138
- TRANSFER_ERROR_CODES: () => TRANSFER_ERROR_CODES,
3139
- TransferError: () => TransferError,
3140
- TwakApiError: () => TwakApiError,
3141
- TwakError: () => TwakError,
3142
- TwakHttpClient: () => TwakHttpClient,
3143
- TwakNetworkError: () => TwakNetworkError,
3144
- TwakValidationError: () => TwakValidationError,
3145
- WALLET_ERROR_CODES: () => WALLET_ERROR_CODES,
3146
- WATCH_ERROR_CODES: () => WATCH_ERROR_CODES,
3147
- WalletError: () => WalletError,
3148
- WatchError: () => WatchError,
3149
- X402Error: () => X402Error,
3150
- X402_ERROR_CODES: () => X402_ERROR_CODES,
3151
- ZERO_ADDRESS: () => ZERO_ADDRESS,
3152
- assertEvmAddress: () => assertEvmAddress,
3153
- assertStrictPositiveAmount: () => assertStrictPositiveAmount,
3154
- chainKeyToCoinType: () => chainKeyToCoinType,
3155
- classifyApiError: () => classifyApiError,
3156
- classifyStorageError: () => classifyStorageError,
3157
- classifyWalletLoadError: () => classifyWalletLoadError,
3158
- coinTypeToChainKey: () => coinTypeToChainKey,
3159
- createTwakClient: () => createTwakClient,
3160
- encodeErc20Transfer: () => encodeErc20Transfer,
3161
- errorMessage: () => errorMessage,
3162
- fetchBalance: () => fetchBalance,
3163
- fetchBalances: () => fetchBalances,
3164
- formatAmount: () => formatAmount,
3165
- formatTokenId: () => formatTokenId,
3166
- getChainByCoinId: () => getChainByCoinId,
3167
- getChainByEvmId: () => getChainByEvmId,
3168
- getChainById: () => getChainById,
3169
- getChainDomainId: () => getChainDomainId,
3170
- getChainMapKey: () => getChainMapKey,
3171
- getEVMChains: () => getEVMChains,
3172
- getExplorerTxUrl: () => getExplorerTxUrl,
3173
- getNativeAddressPlaceholder: () => getNativeAddressPlaceholder,
3174
- getSampleAccount: () => getSampleAccount,
3175
- getSupportedChains: () => getSupportedChains,
3176
- getSupportedCoinTypes: () => getSupportedCoinTypes,
3177
- isChainSupported: () => isChainSupported,
3178
- isCoinTypeSupported: () => isCoinTypeSupported,
3179
- isEvmAddress: () => isEvmAddress,
3180
- isNativeTokenId: () => isNativeTokenId,
3181
- isRateLimited: () => isRateLimited,
3182
- isTestnetChain: () => isTestnetChain,
3183
- isZeroAddress: () => isZeroAddress,
3184
- lookupKnownTokenDecimals: () => lookupKnownTokenDecimals,
3185
- parseAmount: () => parseAmount,
3186
- parseTokenId: () => parseTokenId,
3187
- rankQuotesByBest: () => rankQuotesByBest,
3188
- requireChain: () => requireChain,
3189
- resolveAddress: () => resolveAddress,
3190
- resolveAddressOrName: () => resolveAddressOrName,
3191
- resolveAsset: () => resolveAsset,
3192
- resolveChain: () => resolveChain,
3193
- resolveDecimals: () => resolveDecimals,
3194
- resolveName: () => resolveName,
3195
- resolveToken: () => resolveToken,
3196
- signRequest: () => signRequest,
3197
- sortQueryParams: () => sortQueryParams,
3198
- sortQueryParamsGoCompat: () => sortQueryParamsGoCompat,
3199
- toCamelCase: () => toCamelCase,
3200
- tokenIdToChain: () => tokenIdToChain,
3201
- tryClassifyError: () => tryClassifyError,
3202
- withRetry: () => withRetry
3203
- });
3204
- function getChainById(chainKey) {
3205
- const lower = chainKey.toLowerCase();
3206
- return CHAINS[lower] ?? TESTNET_CHAINS[lower] ?? Object.values(CHAINS).find((c3) => c3.id === lower) ?? Object.values(TESTNET_CHAINS).find((c3) => c3.id === lower);
3207
- }
3208
- function getChainByCoinId(coinId) {
3209
- return Object.values(CHAINS).find((chain2) => chain2.coinId === coinId);
3210
- }
3211
- function getChainByEvmId(evmChainId) {
3212
- return Object.values(CHAINS).find((chain2) => chain2.chainId === evmChainId) ?? Object.values(TESTNET_CHAINS).find((chain2) => chain2.chainId === evmChainId);
3213
- }
3214
- function isTestnetChain(chainKey) {
3215
- if (!chainKey) return false;
3216
- return Object.hasOwn(TESTNET_CHAINS, chainKey.toLowerCase());
3217
- }
3218
- function getSupportedChains() {
3219
- return Object.values(CHAINS);
3220
- }
3221
- function getEVMChains() {
3222
- return Object.values(CHAINS).filter((chain2) => chain2.isEVM);
3223
- }
3224
- function isChainSupported(chainKey) {
3225
- return chainKey.toLowerCase() in CHAINS;
3226
- }
3227
- function getChainMapKey(chainKey) {
3228
- const lower = chainKey.toLowerCase();
3229
- if (CHAINS[lower]) return lower;
3230
- const entry = Object.entries(CHAINS).find(([, c3]) => c3.id === lower);
3231
- return entry?.[0];
3232
- }
3233
- function getChainDomainId(chainKey) {
3234
- const lower = chainKey.toLowerCase();
3235
- const chain2 = CHAINS[lower];
3236
- if (chain2) return chain2.id;
3237
- const entry = Object.entries(CHAINS).find(([, c3]) => c3.id === lower);
3238
- if (!entry) throw new Error(`Unsupported chain: ${chainKey}`);
3239
- return entry[1].id;
3240
- }
3241
- function getExplorerTxUrl(chainKey, hash) {
3242
- const chain2 = getChainById(chainKey);
3243
- if (!chain2) return "";
3244
- return `${chain2.explorerUrl}/tx/${hash}`;
3245
- }
3246
- function getSampleAccount(chainKey) {
3247
- return getChainById(chainKey)?.sampleAccount || "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
3248
- }
3249
- function getNativeAddressPlaceholder(chainKey) {
3250
- const chain2 = getChainById(chainKey);
3251
- if (!chain2) return NATIVE_TOKEN_ADDRESS;
3252
- if (chain2.namespace === "solana") return SOLANA_NATIVE_ADDRESS;
3253
- if (chain2.id === "celo") return CELO_NATIVE_ADDRESS;
3254
- return NATIVE_TOKEN_ADDRESS;
3255
- }
3256
- function lookupKnownTokenDecimals(chainKey, tokenAddress) {
3257
- const chain2 = getChainById(chainKey);
3258
- if (!chain2) return void 0;
3259
- if (!tokenAddress) return chain2.decimals;
3260
- const mapKey = getChainMapKey(chainKey) ?? chainKey.toLowerCase();
3261
- const registry = COMMON_TOKENS[mapKey] ?? {};
3262
- const entry = Object.values(registry).find(
3263
- (e2) => e2.address.toLowerCase() === tokenAddress.toLowerCase()
3111
+ function toRegistry(definitions) {
3112
+ return Object.fromEntries(
3113
+ Object.entries(definitions).map(([key, d3]) => [
3114
+ key,
3115
+ { ...d3, id: d3.id, coinId: d3.coinId }
3116
+ ])
3264
3117
  );
3265
- return entry?.decimals;
3266
- }
3267
- function resolveToken(token, chainKey) {
3268
- const assetIdMatch = token.match(/^c(\d+)(?:_t(.+))?$/);
3269
- if (assetIdMatch) {
3270
- const coinId = parseInt(assetIdMatch[1]);
3271
- const contractAddress = assetIdMatch[2];
3272
- const found = Object.entries(CHAINS).find(([, c3]) => c3.coinId === coinId);
3273
- if (found) {
3274
- const [, chain2] = found;
3275
- if (contractAddress) {
3276
- return { address: contractAddress };
3277
- }
3278
- return { address: getNativeAddressPlaceholder(chain2.id) };
3279
- }
3280
- }
3281
- const upperToken = token.toUpperCase();
3282
- const chainConfig = getChainById(chainKey);
3283
- const mapKey = getChainMapKey(chainKey) ?? chainKey.toLowerCase();
3284
- const chainTokens = COMMON_TOKENS[mapKey];
3285
- if (chainTokens?.[upperToken]) {
3286
- return { address: chainTokens[upperToken].address };
3287
- }
3288
- if (NATIVE_SYMBOLS.has(upperToken) || chainConfig && upperToken === chainConfig.symbol.toUpperCase()) {
3289
- return { address: getNativeAddressPlaceholder(chainKey) };
3290
- }
3291
- if (upperToken.startsWith("USDC")) {
3292
- const entry = chainTokens?.["USDC.e"] || chainTokens?.["USDC"];
3293
- if (!entry) return null;
3294
- return { address: entry.address };
3295
- }
3296
- if (upperToken.startsWith("USDT")) {
3297
- const entry = chainTokens?.["USDT"];
3298
- if (!entry) return null;
3299
- return { address: entry.address };
3300
- }
3301
- if (token.startsWith("0x") || token.length > 20) {
3302
- return { address: token };
3303
- }
3304
- return null;
3305
- }
3306
- function chainKeyToCoinType(chainKey) {
3307
- const key = chainKey.toLowerCase();
3308
- return (CHAINS[key] ?? Object.values(CHAINS).find((c3) => c3.id.toLowerCase() === key))?.coinId;
3309
- }
3310
- function coinTypeToChainKey(coinType) {
3311
- return Object.entries(CHAINS).find(([, chain2]) => chain2.coinId === coinType)?.[0];
3312
- }
3313
- function getSupportedCoinTypes() {
3314
- return Object.values(CHAINS).map((chain2) => chain2.coinId);
3315
- }
3316
- function isCoinTypeSupported(coinType) {
3317
- return Object.values(CHAINS).some((chain2) => chain2.coinId === coinType);
3318
3118
  }
3319
3119
  function errorMessage(err) {
3320
3120
  if (err instanceof Error) return err.message;
@@ -3441,14 +3241,121 @@ function parseTokenId(id) {
3441
3241
  const contractAddress = match[2] || void 0;
3442
3242
  return { coinId, contractAddress };
3443
3243
  }
3444
- function isNativeTokenId(id) {
3445
- return /^c\d+$/.test(id);
3244
+ function chainOf(chainKey) {
3245
+ return REGISTRY[chainKey];
3246
+ }
3247
+ function isTestnet(chainKey) {
3248
+ return Object.hasOwn(TESTNET_CHAINS, chainKey);
3249
+ }
3250
+ function coinIdOf(chainKey) {
3251
+ return chainOf(chainKey).coinId;
3252
+ }
3253
+ function evmChainIdOf(chainKey) {
3254
+ const chain2 = chainOf(chainKey);
3255
+ if (chain2.namespace !== "eip155") {
3256
+ throw new WalletError("CHAIN_UNSUPPORTED", `${chainKey} is not an EVM chain`);
3257
+ }
3258
+ return Number(chain2.chainId);
3259
+ }
3260
+ function caip2Of(chainKey) {
3261
+ const chain2 = chainOf(chainKey);
3262
+ return `${chain2.namespace}:${chain2.chainId}`;
3263
+ }
3264
+ function backendIdOf(chainKey) {
3265
+ return chainOf(chainKey).id;
3266
+ }
3267
+ function assetIdOf(chainKey, tokenAddress) {
3268
+ return formatTokenId(coinIdOf(chainKey), tokenAddress);
3269
+ }
3270
+ function allChainKeys() {
3271
+ return Object.keys(REGISTRY);
3272
+ }
3273
+ function knownChainKey(key) {
3274
+ if (!Object.hasOwn(REGISTRY, key)) throw new Error(`Not a chain key: "${key}"`);
3275
+ return key;
3276
+ }
3277
+ function byChainKey(entries) {
3278
+ for (const key of Object.keys(entries)) knownChainKey(key);
3279
+ return entries;
3280
+ }
3281
+ function mainnetChainKeys() {
3282
+ return Object.keys(CHAINS);
3283
+ }
3284
+ function mainnetChainKeysWhere(predicate) {
3285
+ return mainnetChainKeys().filter((key) => predicate(chainOf(key)));
3286
+ }
3287
+ function chainKeysWithKnownTokens() {
3288
+ return Object.keys(COMMON_TOKENS);
3289
+ }
3290
+ function testnetChainKeys() {
3291
+ return Object.keys(TESTNET_CHAINS);
3292
+ }
3293
+ function mainnetChainKeyForCoinId(coinId) {
3294
+ return mainnetChainKeys().find((key) => chainOf(key).coinId === coinId);
3295
+ }
3296
+ function chainKeyForCaip2(caip2) {
3297
+ return allChainKeys().find((key) => caip2Of(key) === caip2) ?? null;
3298
+ }
3299
+ function chainKeyForBackendId(backendId) {
3300
+ return allChainKeys().find((key) => backendIdOf(key) === backendId);
3301
+ }
3302
+ function getExplorerTxUrl(chainKey, hash) {
3303
+ return `${chainOf(chainKey).explorerUrl}/tx/${hash}`;
3304
+ }
3305
+ function getSampleAccount(chainKey) {
3306
+ return chainOf(chainKey).sampleAccount;
3307
+ }
3308
+ function getNativeAddressPlaceholder(chainKey) {
3309
+ const chain2 = chainOf(chainKey);
3310
+ if (chain2.namespace === "solana") return SOLANA_NATIVE_ADDRESS;
3311
+ if (chain2.id === "celo") return CELO_NATIVE_ADDRESS;
3312
+ return NATIVE_TOKEN_ADDRESS;
3313
+ }
3314
+ function lookupKnownTokenDecimals(chainKey, tokenAddress) {
3315
+ if (!tokenAddress) return chainOf(chainKey).decimals;
3316
+ const registry = COMMON_TOKENS[chainKey] ?? {};
3317
+ const entry = Object.values(registry).find(
3318
+ (e2) => e2.address.toLowerCase() === tokenAddress.toLowerCase()
3319
+ );
3320
+ return entry?.decimals;
3321
+ }
3322
+ function resolveToken(token, chainKey) {
3323
+ if (/^c\d+(?:_t.+)?$/.test(token)) {
3324
+ const { coinId, contractAddress } = parseTokenId(token);
3325
+ const assetChain = mainnetChainKeyForCoinId(coinId);
3326
+ if (assetChain) {
3327
+ if (contractAddress) {
3328
+ return { address: contractAddress };
3329
+ }
3330
+ return { address: getNativeAddressPlaceholder(assetChain) };
3331
+ }
3332
+ }
3333
+ const upperToken = token.toUpperCase();
3334
+ const chainConfig = chainOf(chainKey);
3335
+ const chainTokens = COMMON_TOKENS[chainKey];
3336
+ if (chainTokens?.[upperToken]) {
3337
+ return { address: chainTokens[upperToken].address };
3338
+ }
3339
+ if (NATIVE_SYMBOLS.has(upperToken) || upperToken === chainConfig.symbol.toUpperCase()) {
3340
+ return { address: getNativeAddressPlaceholder(chainKey) };
3341
+ }
3342
+ if (upperToken.startsWith("USDC")) {
3343
+ const entry = chainTokens?.["USDC.e"] || chainTokens?.["USDC"];
3344
+ if (!entry) return null;
3345
+ return { address: entry.address };
3346
+ }
3347
+ if (upperToken.startsWith("USDT")) {
3348
+ const entry = chainTokens?.["USDT"];
3349
+ if (!entry) return null;
3350
+ return { address: entry.address };
3351
+ }
3352
+ if (token.startsWith("0x") || token.length > 20) {
3353
+ return { address: token };
3354
+ }
3355
+ return null;
3446
3356
  }
3447
3357
  function tokenIdToChain(id) {
3448
- const { coinId } = parseTokenId(id);
3449
- const chain2 = getChainByCoinId(coinId);
3450
- if (!chain2) return void 0;
3451
- return Object.entries(CHAINS).find(([, c3]) => c3.coinId === coinId)?.[0];
3358
+ return mainnetChainKeyForCoinId(parseTokenId(id).coinId);
3452
3359
  }
3453
3360
  function resolveChain(input2) {
3454
3361
  if (typeof input2 !== "string" || input2.trim().length === 0) {
@@ -3462,7 +3369,8 @@ function resolveChain(input2) {
3462
3369
  if (colonIdx > 0 && colonIdx < lower.length - 1) {
3463
3370
  const namespace = lower.slice(0, colonIdx);
3464
3371
  const reference = lower.slice(colonIdx + 1);
3465
- for (const [key, chain2] of Object.entries(RESOLVABLE_CHAINS)) {
3372
+ for (const key of RESOLVABLE_KEYS) {
3373
+ const chain2 = REGISTRY[key];
3466
3374
  if (chain2.namespace === namespace && chain2.chainId.toLowerCase() === reference) {
3467
3375
  return key;
3468
3376
  }
@@ -3474,17 +3382,17 @@ function resolveChain(input2) {
3474
3382
  const underscoreIdx = rest.indexOf("_");
3475
3383
  const coinStr = underscoreIdx === -1 ? rest : rest.slice(0, underscoreIdx);
3476
3384
  if (/^\d+$/.test(coinStr)) {
3477
- const key = coinTypeToChainKey(Number(coinStr));
3385
+ const key = mainnetChainKeyForCoinId(Number(coinStr));
3478
3386
  if (key) return key;
3479
3387
  throw chainUnsupported(input2);
3480
3388
  }
3481
3389
  }
3482
- if (RESOLVABLE_CHAINS[lower]) return lower;
3390
+ const direct = RESOLVABLE_KEYS.find((key) => key === lower);
3391
+ if (direct) return direct;
3483
3392
  const aliased = ALIASES[lower];
3484
3393
  if (aliased) return aliased;
3485
- for (const [key, chain2] of Object.entries(RESOLVABLE_CHAINS)) {
3486
- if (chain2.id === lower) return key;
3487
- }
3394
+ const byId = RESOLVABLE_KEYS.find((key) => REGISTRY[key].id === lower);
3395
+ if (byId) return byId;
3488
3396
  if (/^0x[0-9a-f]+$/.test(lower)) {
3489
3397
  const key = lookupEvm(parseInt(lower, 16).toString());
3490
3398
  if (key) return key;
@@ -3495,15 +3403,13 @@ function resolveChain(input2) {
3495
3403
  throw chainUnsupported(input2);
3496
3404
  }
3497
3405
  function lookupEvm(chainId) {
3498
- for (const [key, chain2] of Object.entries(RESOLVABLE_CHAINS)) {
3499
- if (chain2.namespace === "eip155" && chain2.chainId === chainId) return key;
3500
- }
3501
- return void 0;
3406
+ return RESOLVABLE_KEYS.find(
3407
+ (key) => REGISTRY[key].namespace === "eip155" && REGISTRY[key].chainId === chainId
3408
+ );
3502
3409
  }
3503
3410
  function resolveAsset(chain2, tokenAddress) {
3504
3411
  const chainKey = resolveChain(chain2);
3505
- const coinId = RESOLVABLE_CHAINS[chainKey].coinId;
3506
- return { chainKey, coinId, assetId: formatTokenId(coinId, tokenAddress) };
3412
+ return { chainKey, coinId: coinIdOf(chainKey), assetId: assetIdOf(chainKey, tokenAddress) };
3507
3413
  }
3508
3414
  function chainUnsupported(input2) {
3509
3415
  const suggestions = suggest(input2);
@@ -3558,39 +3464,6 @@ async function resolveAddress(search, chain2, params) {
3558
3464
  const match = matches.find((m2) => m2.address.toLowerCase() === address.toLowerCase());
3559
3465
  return match?.address || address;
3560
3466
  }
3561
- function sortQueryParams(query) {
3562
- if (!query) return query;
3563
- const queryParams = new URLSearchParams(query);
3564
- const keys2 = Array.from(queryParams.keys());
3565
- keys2.sort();
3566
- const uniqueKeys = Array.from(new Set(keys2));
3567
- const sortedParams = new URLSearchParams();
3568
- for (const key of uniqueKeys) {
3569
- const values = queryParams.getAll(key);
3570
- for (const value of values) {
3571
- sortedParams.append(key, value);
3572
- }
3573
- }
3574
- return sortedParams.toString();
3575
- }
3576
- function goQueryEscape(str) {
3577
- return encodeURIComponent(str).replace(/%20/g, "+").replace(/\*/g, "%2A").replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
3578
- }
3579
- function sortQueryParamsGoCompat(query) {
3580
- if (!query) return query;
3581
- const queryParams = new URLSearchParams(query);
3582
- const keys2 = Array.from(queryParams.keys());
3583
- keys2.sort();
3584
- const uniqueKeys = Array.from(new Set(keys2));
3585
- const parts = [];
3586
- for (const key of uniqueKeys) {
3587
- const values = queryParams.getAll(key);
3588
- for (const value of values) {
3589
- parts.push(`${goQueryEscape(key)}=${goQueryEscape(value)}`);
3590
- }
3591
- }
3592
- return parts.join("&");
3593
- }
3594
3467
  function formatAmount(amount, decimals) {
3595
3468
  const value = BigInt(amount);
3596
3469
  const divisor = 10n ** BigInt(decimals);
@@ -3656,6 +3529,10 @@ async function resolveAddressOrName(value) {
3656
3529
  if (!resolved) throw new Error(`Could not resolve name: ${value}`);
3657
3530
  return resolved;
3658
3531
  }
3532
+ function twakHome(env = process.env) {
3533
+ const configured = env.TWAK_HOME?.trim();
3534
+ return configured ? path.resolve(configured) : path.join(os.homedir(), ".twak");
3535
+ }
3659
3536
  function isEvmAddress(value) {
3660
3537
  return EVM_ADDRESS_RE.test(value);
3661
3538
  }
@@ -3670,19 +3547,6 @@ function assertEvmAddress(value, label) {
3670
3547
  );
3671
3548
  }
3672
3549
  }
3673
- function encodeErc20Transfer(to3, amount) {
3674
- assertEvmAddress(to3, "to");
3675
- const paddedTo = to3.slice(2).toLowerCase().padStart(64, "0");
3676
- const paddedAmount = amount.toString(16).padStart(64, "0");
3677
- return `${ERC20_TRANSFER_SIG}${paddedTo}${paddedAmount}`;
3678
- }
3679
- function requireChain(chainKey) {
3680
- const chain2 = getChainById(chainKey);
3681
- if (!chain2) {
3682
- throw new TwakValidationError(`Unknown chain: ${chainKey}`, { chainKey });
3683
- }
3684
- return chain2;
3685
- }
3686
3550
  function sortQueryRaw(query) {
3687
3551
  if (!query) return query;
3688
3552
  const parts = query.split("&").filter(Boolean);
@@ -3693,11 +3557,11 @@ function sortQueryRaw(query) {
3693
3557
  });
3694
3558
  return parts.join("&");
3695
3559
  }
3696
- function signRequest(method, path7, query, accessId, hmacSecret) {
3560
+ function signRequest(method, path23, query, accessId, hmacSecret) {
3697
3561
  const date = (/* @__PURE__ */ new Date()).toUTCString();
3698
3562
  const nonce = (0, import_crypto.randomUUID)();
3699
3563
  const sortedQuery = sortQueryRaw(query);
3700
- const plaintext = [method.toUpperCase(), path7, sortedQuery, accessId, nonce, date].join(";");
3564
+ const plaintext = [method.toUpperCase(), path23, sortedQuery, accessId, nonce, date].join(";");
3701
3565
  const signature = (0, import_crypto.createHmac)("sha256", hmacSecret).update(plaintext).digest("base64");
3702
3566
  return {
3703
3567
  "X-TW-CREDENTIAL": accessId,
@@ -3783,14 +3647,16 @@ async function fetchBalance(httpClient, assetId, address, currency = "USD") {
3783
3647
  throw new BalanceError("NETWORK_ERROR", "Could not fetch balance. Please try again later.");
3784
3648
  }
3785
3649
  }
3786
- 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, commandErrorCodeSet, 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, BARE_EVM_ADDRESS, ASSET_ID_EVM_ADDRESS, 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;
3650
+ var os, path, import_crypto, NATIVE_TOKEN_ADDRESS, SOLANA_NATIVE_ADDRESS, MAINNET_DEFINITIONS, TESTNET_DEFINITIONS, CHAINS, TESTNET_CHAINS, REGISTRY, COMMON_TOKEN_DEFINITIONS, COMMON_TOKENS, TwakError, TwakApiError, TwakNetworkError, TwakValidationError, CommandError, COMMON_ERROR_CODES, EXECUTION_REVERTED_RE, FS_ERRNO_CODES, commandErrorCodeSet, 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, NATIVE_SYMBOLS, CELO_NATIVE_ADDRESS, RESOLVABLE_KEYS, ALIASES, BARE_EVM_ADDRESS, ASSET_ID_EVM_ADDRESS, DECIMAL_AMOUNT_RE, UNSAFE_KEYS, NAMING_API, EVM_ADDRESS_RE, ZERO_ADDRESS, DEFAULT_GATEWAY_URL, DEFAULT_MARKET_URL, DEFAULT_TIMEOUT, DEFAULT_USER_AGENT, DEFAULT_X_ORIGIN, TwakHttpClient, ALLOWED_OFFRAMP_PROVIDERS, McpResponse;
3787
3651
  var init_dist = __esm({
3788
3652
  "../core/dist/index.mjs"() {
3789
3653
  "use strict";
3654
+ os = __toESM(require("os"), 1);
3655
+ path = __toESM(require("path"), 1);
3790
3656
  import_crypto = require("crypto");
3791
3657
  NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
3792
3658
  SOLANA_NATIVE_ADDRESS = "So11111111111111111111111111111111111111112";
3793
- CHAINS = {
3659
+ MAINNET_DEFINITIONS = {
3794
3660
  ethereum: {
3795
3661
  id: "ethereum",
3796
3662
  name: "Ethereum",
@@ -4124,7 +3990,7 @@ var init_dist = __esm({
4124
3990
  sampleAccount: "0x8d1f3c7b5e9a2047c6b3d80f1e4a9258c7d6b3e5f8a0c2d4e6f8a0b2c4d6e8f"
4125
3991
  }
4126
3992
  };
4127
- TESTNET_CHAINS = {
3993
+ TESTNET_DEFINITIONS = {
4128
3994
  bsctestnet: {
4129
3995
  id: "smartchain-testnet",
4130
3996
  name: "BNB Smart Chain Testnet",
@@ -4139,7 +4005,10 @@ var init_dist = __esm({
4139
4005
  sampleAccount: "0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"
4140
4006
  }
4141
4007
  };
4142
- COMMON_TOKENS = {
4008
+ CHAINS = toRegistry(MAINNET_DEFINITIONS);
4009
+ TESTNET_CHAINS = toRegistry(TESTNET_DEFINITIONS);
4010
+ REGISTRY = { ...CHAINS, ...TESTNET_CHAINS };
4011
+ COMMON_TOKEN_DEFINITIONS = {
4143
4012
  ethereum: {
4144
4013
  USDT: { address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", decimals: 6 },
4145
4014
  USDC: { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", decimals: 6 },
@@ -4207,36 +4076,7 @@ var init_dist = __esm({
4207
4076
  WSOL: { address: "So11111111111111111111111111111111111111112", decimals: 9 }
4208
4077
  }
4209
4078
  };
4210
- NATIVE_SYMBOLS = /* @__PURE__ */ new Set([
4211
- "NATIVE",
4212
- "ETH",
4213
- "MATIC",
4214
- "BNB",
4215
- "AVAX",
4216
- "FTM",
4217
- "S",
4218
- "CELO",
4219
- // EVM
4220
- "SOL",
4221
- // Solana
4222
- "TRX",
4223
- // Tron
4224
- "APT",
4225
- // Aptos
4226
- "TON",
4227
- // TON
4228
- "SUI",
4229
- // Sui
4230
- "NEAR",
4231
- // NEAR
4232
- "ATOM",
4233
- // Cosmos
4234
- "BTC",
4235
- "LTC",
4236
- "DOGE"
4237
- // Bitcoin family
4238
- ]);
4239
- CELO_NATIVE_ADDRESS = "0x471EcE3750Da237f93B8E339c536989b8978a438";
4079
+ COMMON_TOKENS = COMMON_TOKEN_DEFINITIONS;
4240
4080
  TwakError = class extends Error {
4241
4081
  constructor(message, code2, details) {
4242
4082
  super(message);
@@ -4431,7 +4271,37 @@ var init_dist = __esm({
4431
4271
  this.name = "X402Error";
4432
4272
  }
4433
4273
  };
4434
- RESOLVABLE_CHAINS = { ...CHAINS, ...TESTNET_CHAINS };
4274
+ NATIVE_SYMBOLS = /* @__PURE__ */ new Set([
4275
+ "NATIVE",
4276
+ "ETH",
4277
+ "MATIC",
4278
+ "BNB",
4279
+ "AVAX",
4280
+ "FTM",
4281
+ "S",
4282
+ "CELO",
4283
+ // EVM
4284
+ "SOL",
4285
+ // Solana
4286
+ "TRX",
4287
+ // Tron
4288
+ "APT",
4289
+ // Aptos
4290
+ "TON",
4291
+ // TON
4292
+ "SUI",
4293
+ // Sui
4294
+ "NEAR",
4295
+ // NEAR
4296
+ "ATOM",
4297
+ // Cosmos
4298
+ "BTC",
4299
+ "LTC",
4300
+ "DOGE"
4301
+ // Bitcoin family
4302
+ ]);
4303
+ CELO_NATIVE_ADDRESS = "0x471EcE3750Da237f93B8E339c536989b8978a438";
4304
+ RESOLVABLE_KEYS = Object.keys(REGISTRY);
4435
4305
  ALIASES = {
4436
4306
  "binance-smart-chain": "bsc",
4437
4307
  matic: "polygon",
@@ -4444,7 +4314,6 @@ var init_dist = __esm({
4444
4314
  UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
4445
4315
  NAMING_API = "https://naming.trustwallet.com/v1/lookup";
4446
4316
  EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
4447
- ERC20_TRANSFER_SIG = "0xa9059cbb";
4448
4317
  ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
4449
4318
  DEFAULT_GATEWAY_URL = "https://tws.trustwallet.com";
4450
4319
  DEFAULT_MARKET_URL = "https://market.trustwallet.com";
@@ -4470,11 +4339,11 @@ var init_dist = __esm({
4470
4339
  this.resolveCredentials = () => fixed;
4471
4340
  }
4472
4341
  }
4473
- async gateway(method, path7, body, query) {
4474
- const url = new URL(path7, this.config.gatewayBaseUrl);
4342
+ async gateway(method, path23, body, query) {
4343
+ const url = new URL(path23, this.config.gatewayBaseUrl);
4475
4344
  if (query) url.search = query;
4476
4345
  const { accessId, hmacSecret } = this.resolveCredentials();
4477
- const headers = signRequest(method, path7, query || "", accessId, hmacSecret);
4346
+ const headers = signRequest(method, path23, query || "", accessId, hmacSecret);
4478
4347
  return this.fetch(url.toString(), {
4479
4348
  method,
4480
4349
  headers: {
@@ -4485,14 +4354,14 @@ var init_dist = __esm({
4485
4354
  body: body ? JSON.stringify(body) : void 0
4486
4355
  });
4487
4356
  }
4488
- async amber(method, path7, body) {
4489
- if (!path7.startsWith("/amber-api/")) {
4357
+ async amber(method, path23, body) {
4358
+ if (!path23.startsWith("/amber-api/")) {
4490
4359
  throw new Error("Amber API path must start with '/amber-api/'.");
4491
4360
  }
4492
- return this.gateway(method, path7, body);
4361
+ return this.gateway(method, path23, body);
4493
4362
  }
4494
- async market(method, path7, body) {
4495
- const url = new URL(path7, this.config.marketBaseUrl);
4363
+ async market(method, path23, body) {
4364
+ const url = new URL(path23, this.config.marketBaseUrl);
4496
4365
  const raw = await this.fetch(url.toString(), {
4497
4366
  method,
4498
4367
  headers: { "Content-Type": "application/json" },
@@ -4612,28 +4481,43 @@ function getPassword(service, account) {
4612
4481
  throw err;
4613
4482
  }
4614
4483
  }
4615
- var fs, path, os, crypto2, crypto22, import_keyring, crypto3, crypto4, FileStore, ALGORITHM, KEY_LENGTH, IV_LENGTH, SALT_LENGTH, ITERATIONS, SERVICE, WALLET_ACCOUNT, API_SECRET_ACCOUNT, PROBE_ACCOUNT, KeychainManager, CREDENTIALS_FILE, CredentialManager, WALLET_FILE, WalletConfigStore, ALERTS_FILE, AlertStore, AUTOMATIONS_FILE, AutomationStore, ASSET_CACHE_FILE, AssetCache;
4484
+ function typeStoredChains(stored, chainOf2, withChain) {
4485
+ const records = [];
4486
+ const invalid = [];
4487
+ for (const record2 of stored) {
4488
+ try {
4489
+ records.push(withChain(record2, resolveChain(chainOf2(record2))));
4490
+ } catch (err) {
4491
+ invalid.push({ id: record2.id, chain: chainOf2(record2), error: errorMessage(err) });
4492
+ }
4493
+ }
4494
+ return { records, invalid };
4495
+ }
4496
+ var fs, path2, crypto2, crypto22, path22, import_keyring, crypto3, crypto4, FileStore, ALGORITHM, KEY_LENGTH, IV_LENGTH, SALT_LENGTH, ITERATIONS, SERVICE, WALLET_ACCOUNT, API_SECRET_ACCOUNT, PROBE_ACCOUNT, KeychainManager, CREDENTIALS_FILE, CredentialManager, WALLET_FILE, WalletConfigStore, ALERTS_FILE, AlertStore, AUTOMATIONS_FILE, AutomationStore, ASSET_CACHE_FILE, AssetCache;
4616
4497
  var init_dist2 = __esm({
4617
4498
  "../storage/dist/index.mjs"() {
4618
4499
  "use strict";
4619
4500
  fs = __toESM(require("fs"), 1);
4620
- path = __toESM(require("path"), 1);
4621
- os = __toESM(require("os"), 1);
4501
+ path2 = __toESM(require("path"), 1);
4622
4502
  crypto2 = __toESM(require("crypto"), 1);
4503
+ init_dist();
4623
4504
  crypto22 = __toESM(require("crypto"), 1);
4505
+ path22 = __toESM(require("path"), 1);
4624
4506
  import_keyring = require("@napi-rs/keyring");
4507
+ init_dist();
4625
4508
  crypto3 = __toESM(require("crypto"), 1);
4509
+ init_dist();
4626
4510
  crypto4 = __toESM(require("crypto"), 1);
4627
4511
  FileStore = class {
4628
4512
  dataDir;
4629
4513
  constructor(config) {
4630
- this.dataDir = config?.dataDir || path.join(os.homedir(), ".twak");
4514
+ this.dataDir = config?.dataDir || twakHome();
4631
4515
  }
4632
4516
  getDataDir() {
4633
4517
  return this.dataDir;
4634
4518
  }
4635
4519
  async read(filename) {
4636
- const filePath = path.join(this.dataDir, filename);
4520
+ const filePath = path2.join(this.dataDir, filename);
4637
4521
  try {
4638
4522
  const data = await fs.promises.readFile(filePath, "utf-8");
4639
4523
  return JSON.parse(data);
@@ -4646,7 +4530,7 @@ var init_dist2 = __esm({
4646
4530
  }
4647
4531
  async write(filename, data) {
4648
4532
  await fs.promises.mkdir(this.dataDir, { recursive: true, mode: 448 });
4649
- const filePath = path.join(this.dataDir, filename);
4533
+ const filePath = path2.join(this.dataDir, filename);
4650
4534
  const tmpPath = `${filePath}.tmp.${crypto2.randomBytes(8).toString("hex")}`;
4651
4535
  await fs.promises.writeFile(tmpPath, JSON.stringify(data, null, 2), {
4652
4536
  encoding: "utf-8",
@@ -4663,7 +4547,7 @@ var init_dist2 = __esm({
4663
4547
  }
4664
4548
  }
4665
4549
  async exists(filename) {
4666
- const filePath = path.join(this.dataDir, filename);
4550
+ const filePath = path2.join(this.dataDir, filename);
4667
4551
  try {
4668
4552
  await fs.promises.access(filePath);
4669
4553
  return true;
@@ -4672,7 +4556,7 @@ var init_dist2 = __esm({
4672
4556
  }
4673
4557
  }
4674
4558
  async remove(filename) {
4675
- const filePath = path.join(this.dataDir, filename);
4559
+ const filePath = path2.join(this.dataDir, filename);
4676
4560
  try {
4677
4561
  await fs.promises.unlink(filePath);
4678
4562
  } catch {
@@ -4689,24 +4573,33 @@ var init_dist2 = __esm({
4689
4573
  API_SECRET_ACCOUNT = "api-secret";
4690
4574
  PROBE_ACCOUNT = "probe";
4691
4575
  KeychainManager = class {
4576
+ walletAccount;
4577
+ apiSecretAccount;
4578
+ /** `dataDir`: the twak folder these secrets belong to (default: twakHome()). */
4579
+ constructor(dataDir = twakHome()) {
4580
+ const folder = path22.resolve(dataDir);
4581
+ const suffix = folder === twakHome({}) ? "" : `@${folder}`;
4582
+ this.walletAccount = WALLET_ACCOUNT + suffix;
4583
+ this.apiSecretAccount = API_SECRET_ACCOUNT + suffix;
4584
+ }
4692
4585
  async getWalletPassword() {
4693
- return getPassword(SERVICE, WALLET_ACCOUNT);
4586
+ return getPassword(SERVICE, this.walletAccount);
4694
4587
  }
4695
4588
  async saveWalletPassword(password3) {
4696
- new import_keyring.Entry(SERVICE, WALLET_ACCOUNT).setPassword(password3);
4589
+ new import_keyring.Entry(SERVICE, this.walletAccount).setPassword(password3);
4697
4590
  }
4698
4591
  async deleteWalletPassword() {
4699
- new import_keyring.Entry(SERVICE, WALLET_ACCOUNT).deletePassword();
4592
+ new import_keyring.Entry(SERVICE, this.walletAccount).deletePassword();
4700
4593
  }
4701
4594
  async getApiSecret() {
4702
- return getPassword(SERVICE, API_SECRET_ACCOUNT);
4595
+ return getPassword(SERVICE, this.apiSecretAccount);
4703
4596
  }
4704
4597
  async saveApiSecret(secret) {
4705
- new import_keyring.Entry(SERVICE, API_SECRET_ACCOUNT).setPassword(secret);
4598
+ new import_keyring.Entry(SERVICE, this.apiSecretAccount).setPassword(secret);
4706
4599
  }
4707
4600
  async deleteApiSecret() {
4708
4601
  try {
4709
- new import_keyring.Entry(SERVICE, API_SECRET_ACCOUNT).deletePassword();
4602
+ new import_keyring.Entry(SERVICE, this.apiSecretAccount).deletePassword();
4710
4603
  } catch {
4711
4604
  }
4712
4605
  }
@@ -4742,7 +4635,7 @@ var init_dist2 = __esm({
4742
4635
  kc;
4743
4636
  constructor(config) {
4744
4637
  this.store = new FileStore(config);
4745
- this.kc = new KeychainManager();
4638
+ this.kc = new KeychainManager(this.store.getDataDir());
4746
4639
  }
4747
4640
  async load() {
4748
4641
  const stored = await this.store.read(CREDENTIALS_FILE);
@@ -4826,8 +4719,18 @@ var init_dist2 = __esm({
4826
4719
  constructor(config) {
4827
4720
  this.store = new FileStore(config);
4828
4721
  }
4722
+ async readStored() {
4723
+ return await this.store.read(ALERTS_FILE) || [];
4724
+ }
4725
+ typed(stored) {
4726
+ return typeStoredChains(
4727
+ stored,
4728
+ (a3) => a3.chainKey,
4729
+ (a3, chainKey) => ({ ...a3, chainKey })
4730
+ );
4731
+ }
4829
4732
  async create(alert) {
4830
- const alerts = await this.list();
4733
+ const alerts = await this.readStored();
4831
4734
  const record2 = {
4832
4735
  ...alert,
4833
4736
  id: crypto3.randomUUID(),
@@ -4838,23 +4741,28 @@ var init_dist2 = __esm({
4838
4741
  await this.store.write(ALERTS_FILE, alerts);
4839
4742
  return record2;
4840
4743
  }
4744
+ /** Alerts whose chain resolves; see listInvalid for the others. */
4841
4745
  async list() {
4842
- return await this.store.read(ALERTS_FILE) || [];
4746
+ return this.typed(await this.readStored()).records;
4747
+ }
4748
+ /** Stored alerts whose chain no longer resolves. */
4749
+ async listInvalid() {
4750
+ return this.typed(await this.readStored()).invalid;
4843
4751
  }
4844
4752
  async getById(id) {
4845
4753
  const alerts = await this.list();
4846
4754
  return alerts.find((a3) => a3.id === id);
4847
4755
  }
4848
4756
  async update(id, updates) {
4849
- const alerts = await this.list();
4757
+ const alerts = await this.readStored();
4850
4758
  const index = alerts.findIndex((a3) => a3.id === id);
4851
4759
  if (index === -1) return void 0;
4852
4760
  alerts[index] = { ...alerts[index], ...updates };
4853
4761
  await this.store.write(ALERTS_FILE, alerts);
4854
- return alerts[index];
4762
+ return this.typed([alerts[index]]).records[0];
4855
4763
  }
4856
4764
  async delete(id) {
4857
- const alerts = await this.list();
4765
+ const alerts = await this.readStored();
4858
4766
  const filtered = alerts.filter((a3) => a3.id !== id);
4859
4767
  if (filtered.length === alerts.length) return false;
4860
4768
  await this.store.write(ALERTS_FILE, filtered);
@@ -4874,8 +4782,18 @@ var init_dist2 = __esm({
4874
4782
  constructor(config) {
4875
4783
  this.store = new FileStore(config);
4876
4784
  }
4785
+ async readStored() {
4786
+ return await this.store.read(AUTOMATIONS_FILE) || [];
4787
+ }
4788
+ typed(stored) {
4789
+ return typeStoredChains(
4790
+ stored,
4791
+ (a3) => a3.chain,
4792
+ (a3, chain2) => ({ ...a3, chain: chain2 })
4793
+ );
4794
+ }
4877
4795
  async create(record2) {
4878
- const automations = await this.list();
4796
+ const automations = await this.readStored();
4879
4797
  const entry = {
4880
4798
  ...record2,
4881
4799
  id: crypto4.randomUUID(),
@@ -4886,23 +4804,28 @@ var init_dist2 = __esm({
4886
4804
  await this.store.write(AUTOMATIONS_FILE, automations);
4887
4805
  return entry;
4888
4806
  }
4807
+ /** Automations whose chain resolves; see listInvalid for the others. */
4889
4808
  async list() {
4890
- return await this.store.read(AUTOMATIONS_FILE) || [];
4809
+ return this.typed(await this.readStored()).records;
4810
+ }
4811
+ /** Stored automations whose chain no longer resolves. */
4812
+ async listInvalid() {
4813
+ return this.typed(await this.readStored()).invalid;
4891
4814
  }
4892
4815
  async getById(id) {
4893
4816
  const automations = await this.list();
4894
4817
  return automations.find((a3) => a3.id === id);
4895
4818
  }
4896
4819
  async update(id, updates) {
4897
- const automations = await this.list();
4820
+ const automations = await this.readStored();
4898
4821
  const index = automations.findIndex((a3) => a3.id === id);
4899
4822
  if (index === -1) return void 0;
4900
4823
  automations[index] = { ...automations[index], ...updates };
4901
4824
  await this.store.write(AUTOMATIONS_FILE, automations);
4902
- return automations[index];
4825
+ return this.typed([automations[index]]).records[0];
4903
4826
  }
4904
4827
  async delete(id) {
4905
- const automations = await this.list();
4828
+ const automations = await this.readStored();
4906
4829
  const filtered = automations.filter((a3) => a3.id !== id);
4907
4830
  if (filtered.length === automations.length) return false;
4908
4831
  await this.store.write(AUTOMATIONS_FILE, filtered);
@@ -5827,15 +5750,15 @@ var require_route = __commonJS({
5827
5750
  };
5828
5751
  }
5829
5752
  function wrapConversion(toModel, graph) {
5830
- const path7 = [graph[toModel].parent, toModel];
5753
+ const path13 = [graph[toModel].parent, toModel];
5831
5754
  let fn2 = conversions[graph[toModel].parent][toModel];
5832
5755
  let cur = graph[toModel].parent;
5833
5756
  while (graph[cur].parent) {
5834
- path7.unshift(graph[cur].parent);
5757
+ path13.unshift(graph[cur].parent);
5835
5758
  fn2 = link(conversions[graph[cur].parent][cur], fn2);
5836
5759
  cur = graph[cur].parent;
5837
5760
  }
5838
- fn2.conversion = path7;
5761
+ fn2.conversion = path13;
5839
5762
  return fn2;
5840
5763
  }
5841
5764
  module2.exports = function(fromModel) {
@@ -6076,7 +5999,7 @@ var require_has_flag = __commonJS({
6076
5999
  var require_supports_color = __commonJS({
6077
6000
  "../../node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports2, module2) {
6078
6001
  "use strict";
6079
- var os5 = require("os");
6002
+ var os4 = require("os");
6080
6003
  var tty = require("tty");
6081
6004
  var hasFlag = require_has_flag();
6082
6005
  var { env } = process;
@@ -6124,7 +6047,7 @@ var require_supports_color = __commonJS({
6124
6047
  return min;
6125
6048
  }
6126
6049
  if (process.platform === "win32") {
6127
- const osRelease = os5.release().split(".");
6050
+ const osRelease = os4.release().split(".");
6128
6051
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
6129
6052
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
6130
6053
  }
@@ -6506,8 +6429,8 @@ var require_source = __commonJS({
6506
6429
  });
6507
6430
 
6508
6431
  // ../wallet-core/dist/index.mjs
6509
- var dist_exports2 = {};
6510
- __export(dist_exports2, {
6432
+ var dist_exports = {};
6433
+ __export(dist_exports, {
6511
6434
  AgentWalletProvider: () => AgentWalletProvider,
6512
6435
  ChainClient: () => ChainClient,
6513
6436
  TeeWalletProvider: () => TeeWalletProvider,
@@ -6545,13 +6468,13 @@ function getPolyfillNaasSessionId() {
6545
6468
  }
6546
6469
  function resolveSdkDir() {
6547
6470
  try {
6548
- return path2.dirname(__require.resolve("@trustwallet-trust-sdk/trust-sdk"));
6471
+ return path3.dirname(__require.resolve("@trustwallet-trust-sdk/trust-sdk"));
6549
6472
  } catch {
6550
6473
  let dir = __dirname;
6551
6474
  for (let i2 = 0; i2 < 10; i2++) {
6552
- const candidate = path2.join(dir, "trust-sdk", "trust-sdk.js");
6553
- if (fs2.existsSync(candidate)) return path2.dirname(candidate);
6554
- const parent = path2.dirname(dir);
6475
+ const candidate = path3.join(dir, "trust-sdk", "trust-sdk.js");
6476
+ if (fs2.existsSync(candidate)) return path3.dirname(candidate);
6477
+ const parent = path3.dirname(dir);
6555
6478
  if (parent === dir) break;
6556
6479
  dir = parent;
6557
6480
  }
@@ -6677,15 +6600,15 @@ function applyPolyfills() {
6677
6600
  }
6678
6601
  }
6679
6602
  if (!fs2.existsSync(filePath)) {
6680
- const basename2 = path2.basename(filePath);
6681
- const candidate = path2.join(sdkDir, basename2);
6603
+ const basename2 = path3.basename(filePath);
6604
+ const candidate = path3.join(sdkDir, basename2);
6682
6605
  if (fs2.existsSync(candidate)) {
6683
6606
  filePath = candidate;
6684
6607
  }
6685
6608
  }
6686
- const resolvedPath = path2.resolve(filePath);
6687
- const resolvedSdkDir = path2.resolve(sdkDir);
6688
- if (!resolvedPath.startsWith(resolvedSdkDir + path2.sep) && resolvedPath !== resolvedSdkDir) {
6609
+ const resolvedPath = path3.resolve(filePath);
6610
+ const resolvedSdkDir = path3.resolve(sdkDir);
6611
+ if (!resolvedPath.startsWith(resolvedSdkDir + path3.sep) && resolvedPath !== resolvedSdkDir) {
6689
6612
  this.status = 403;
6690
6613
  if (this._async && this.onerror) this.onerror();
6691
6614
  return;
@@ -6710,8 +6633,7 @@ function applyPolyfills() {
6710
6633
  };
6711
6634
  }
6712
6635
  if (typeof globalThis.localStorage === "undefined") {
6713
- const os5 = __require("os");
6714
- const storePath = path2.join(os5.homedir(), ".twak", "local-storage.json");
6636
+ const storePath = path3.join(twakHome(), "local-storage.json");
6715
6637
  const load = () => {
6716
6638
  try {
6717
6639
  return JSON.parse(fs2.readFileSync(storePath, "utf-8"));
@@ -6720,7 +6642,7 @@ function applyPolyfills() {
6720
6642
  }
6721
6643
  };
6722
6644
  const save = (data) => {
6723
- const dir = path2.dirname(storePath);
6645
+ const dir = path3.dirname(storePath);
6724
6646
  if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true, mode: 448 });
6725
6647
  const tmp = `${storePath}.tmp`;
6726
6648
  fs2.writeFileSync(tmp, JSON.stringify(data), { encoding: "utf-8", mode: 384 });
@@ -6993,7 +6915,7 @@ async function initTrustSDK(config) {
6993
6915
  await import_trust_sdk.AmberService.setEnvironment(import_trust_sdk.TwEnvironmentProduction);
6994
6916
  await import_trust_sdk.BlockchainService.useBitcoinV2();
6995
6917
  buildCoinTypeMap();
6996
- for (const cfg of Object.values(TESTNET_CHAINS)) {
6918
+ for (const cfg of testnetChainKeys().map(chainOf)) {
6997
6919
  try {
6998
6920
  await import_trust_sdk.BlockchainService.setNode(
6999
6921
  new import_trust_sdk.CustomChain(getCoinType(cfg.coinId), cfg.chainId),
@@ -7120,25 +7042,15 @@ function decodeEvmTxFields(rawTxHex) {
7120
7042
  };
7121
7043
  }
7122
7044
  function chainKeyToDefinedChain(chainKey) {
7123
- let coinId;
7124
- let canonicalKey;
7125
- try {
7126
- ({ coinId, chainKey: canonicalKey } = resolveAsset(chainKey));
7127
- } catch (err) {
7128
- if (err instanceof WalletError) {
7129
- throw new TwakValidationError(err.message, { chainKey });
7130
- }
7131
- throw err;
7132
- }
7133
- const ct5 = getCoinType(coinId);
7045
+ const chainConfig = chainOf(chainKey);
7046
+ const ct5 = getCoinType(chainConfig.coinId);
7134
7047
  if (!ct5) {
7135
- throw new TwakValidationError(`No CoinType mapping for coinId ${coinId}`, { chainKey, coinId });
7136
- }
7137
- const chainConfig = getChainById(canonicalKey);
7138
- if (!chainConfig) {
7139
- throw new TwakValidationError(`No chain config for ${canonicalKey}`, { chainKey });
7048
+ throw new TwakValidationError(`No CoinType mapping for coinId ${chainConfig.coinId}`, {
7049
+ chainKey,
7050
+ coinId: chainConfig.coinId
7051
+ });
7140
7052
  }
7141
- const chain2 = isTestnetChain(canonicalKey) ? new import_trust_sdk3.CustomChain(ct5, chainConfig.chainId) : new import_trust_sdk3.DefinedChain(ct5);
7053
+ const chain2 = isTestnet(chainKey) ? new import_trust_sdk3.CustomChain(ct5, chainConfig.chainId) : new import_trust_sdk3.DefinedChain(ct5);
7142
7054
  return { chain: chain2, chainConfig };
7143
7055
  }
7144
7056
  function humanAmountToWei(amount, decimals = 18) {
@@ -7196,8 +7108,8 @@ function getCoinDecimals(coinId) {
7196
7108
  const ct5 = requireCoinType(coinId);
7197
7109
  return wc3.CoinTypeConfiguration.getDecimals(ct5);
7198
7110
  } catch {
7199
- const chain2 = getChainByCoinId(coinId);
7200
- return chain2?.decimals ?? 18;
7111
+ const chainKey = mainnetChainKeyForCoinId(coinId);
7112
+ return chainKey ? chainOf(chainKey).decimals : 18;
7201
7113
  }
7202
7114
  }
7203
7115
  function tokenTypeForCoinId(coinId) {
@@ -7278,9 +7190,9 @@ async function getAmberDomainsByCoinId() {
7278
7190
  }
7279
7191
  return domainsByCoinId;
7280
7192
  }
7281
- async function gatewayFetch(method, path22, config, body) {
7282
- const headers = signRequest(method, path22, "", config.accessId, config.hmacSecret);
7283
- return fetch(`${GATEWAY_URL}${path22}`, {
7193
+ async function gatewayFetch(method, path23, config, body) {
7194
+ const headers = signRequest(method, path23, "", config.accessId, config.hmacSecret);
7195
+ return fetch(`${GATEWAY_URL}${path23}`, {
7284
7196
  method,
7285
7197
  headers: {
7286
7198
  ...headers,
@@ -7369,12 +7281,13 @@ function registerShutdownHandlers(providers, onBeforeExit) {
7369
7281
  process.removeListener("SIGTERM", handler);
7370
7282
  };
7371
7283
  }
7372
- var fs2, path2, import_trust_sdk, import_trust_sdk2, import_trust_sdk3, import_trust_sdk4, import_trust_sdk5, import_crypto2, __require, polyfillsApplied, _credentials, _naasSessionId, nodeStubsPatched, sponsorNonceByAddress, NAAS_SESSION_RE, naasSessionPatched, coinTypeByValue, walletCore, initialized, BSC_COIN_ID, DEFAULT_BSC_SPONSORED_RPC, SPONSOR_PRECHECK_TIMEOUT_MS, SPONSOR_USER_AGENT, RPC_TIMEOUT_MS, RECEIPT_POLL_INTERVAL_MS, RECEIPT_DEFAULT_TIMEOUT_MS, ChainClient, SigningChainClient, WalletCoreSigner, domainsByCoinId, GATEWAY_URL, DEVICE_INFO_BODY, VerifyCredentialsError, WALLET_ID_SUFFIX, WALLET_ID_LENGTH, EVM_COIN_IDS, MAINTAINED_COIN_IDS, WalletProvider, AgentWalletProvider, TeeWalletProvider, WalletContext, SHUTDOWN_TIMEOUT_MS;
7284
+ var fs2, path3, import_trust_sdk, import_trust_sdk2, import_trust_sdk3, import_trust_sdk4, import_trust_sdk5, import_crypto2, __require, polyfillsApplied, _credentials, _naasSessionId, nodeStubsPatched, sponsorNonceByAddress, NAAS_SESSION_RE, naasSessionPatched, coinTypeByValue, walletCore, initialized, BSC_COIN_ID, DEFAULT_BSC_SPONSORED_RPC, SPONSOR_PRECHECK_TIMEOUT_MS, SPONSOR_USER_AGENT, RPC_TIMEOUT_MS, RECEIPT_POLL_INTERVAL_MS, RECEIPT_DEFAULT_TIMEOUT_MS, ChainClient, SigningChainClient, WalletCoreSigner, domainsByCoinId, GATEWAY_URL, DEVICE_INFO_BODY, VerifyCredentialsError, WALLET_ID_SUFFIX, WALLET_ID_LENGTH, EVM_COIN_IDS, MAINTAINED_COIN_IDS, WalletProvider, AgentWalletProvider, ETHEREUM, TeeWalletProvider, WalletContext, SHUTDOWN_TIMEOUT_MS;
7373
7285
  var init_dist3 = __esm({
7374
7286
  "../wallet-core/dist/index.mjs"() {
7375
7287
  "use strict";
7376
7288
  fs2 = __toESM(require("fs"), 1);
7377
- path2 = __toESM(require("path"), 1);
7289
+ path3 = __toESM(require("path"), 1);
7290
+ init_dist();
7378
7291
  import_trust_sdk = require("@trustwallet-trust-sdk/trust-sdk");
7379
7292
  init_dist();
7380
7293
  import_trust_sdk2 = require("@trustwallet-trust-sdk/trust-sdk");
@@ -7389,6 +7302,7 @@ var init_dist3 = __esm({
7389
7302
  init_dist();
7390
7303
  init_dist2();
7391
7304
  init_dist();
7305
+ init_dist();
7392
7306
  __require = /* @__PURE__ */ ((x6) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x6, {
7393
7307
  get: (a3, b3) => (typeof require !== "undefined" ? require : a3)[b3]
7394
7308
  }) : x6)(function(x6) {
@@ -7571,7 +7485,7 @@ var init_dist3 = __esm({
7571
7485
  if (!isTransientRateLimit(err) || Date.now() + pollMs >= deadline) throw err;
7572
7486
  }
7573
7487
  const sleepMs = Math.min(pollMs, Math.max(0, deadline - Date.now()));
7574
- await new Promise((resolve2) => setTimeout(resolve2, sleepMs));
7488
+ await new Promise((resolve22) => setTimeout(resolve22, sleepMs));
7575
7489
  }
7576
7490
  throw new TwakNetworkError(`Timed out waiting for receipt ${hash} on ${chainKey}`, {
7577
7491
  hash,
@@ -7582,9 +7496,7 @@ var init_dist3 = __esm({
7582
7496
  return def.using(this);
7583
7497
  }
7584
7498
  async findTransactionStatus(chainKey, address, hash) {
7585
- const coinId = chainKeyToCoinType(chainKey);
7586
- if (coinId === void 0) throw new Error(`Unsupported chain: ${chainKey}`);
7587
- const account = this.createAccountForAddress(coinId, address);
7499
+ const account = this.createAccountForAddress(coinIdOf(chainKey), address, chainKey);
7588
7500
  let result;
7589
7501
  try {
7590
7502
  result = await import_trust_sdk2.BlockchainService.findTransaction(account, hash);
@@ -7604,27 +7516,17 @@ var init_dist3 = __esm({
7604
7516
  };
7605
7517
  }
7606
7518
  async getNodes(chainKey) {
7607
- const coinId = chainKeyToCoinType(chainKey);
7608
- if (coinId === void 0) {
7609
- throw new Error(`Unsupported chain: ${chainKey}`);
7610
- }
7611
- const ct5 = requireCoinType(coinId);
7612
- const chain2 = new import_trust_sdk2.DefinedChain(ct5);
7519
+ const { chain: chain2 } = chainKeyToDefinedChain(chainKey);
7613
7520
  const nodes = await import_trust_sdk2.BlockchainService.getNodes(chain2);
7614
7521
  return nodes.map((n4) => ({ url: n4.url }));
7615
7522
  }
7616
7523
  async setNode(chainKey, rpcUrl) {
7617
- const coinId = chainKeyToCoinType(chainKey);
7618
- if (coinId === void 0) {
7619
- throw new Error(`Unsupported chain: ${chainKey}`);
7620
- }
7621
- const ct5 = requireCoinType(coinId);
7622
- const chain2 = new import_trust_sdk2.DefinedChain(ct5);
7524
+ const { chain: chain2 } = chainKeyToDefinedChain(chainKey);
7623
7525
  await import_trust_sdk2.BlockchainService.setNode(chain2, new import_trust_sdk2.Node(rpcUrl));
7624
7526
  }
7625
7527
  createAccountForAddress(coinId, address, chainKey) {
7626
7528
  const ct5 = requireCoinType(coinId);
7627
- const chain2 = chainKey !== void 0 && isTestnetChain(chainKey) ? chainKeyToDefinedChain(chainKey).chain : new import_trust_sdk2.DefinedChain(ct5);
7529
+ const chain2 = chainKey !== void 0 && isTestnet(chainKey) ? chainKeyToDefinedChain(chainKey).chain : new import_trust_sdk2.DefinedChain(ct5);
7628
7530
  const wc3 = getWalletCore();
7629
7531
  const derivation = coinId === 0 && address.startsWith("bc1p") ? wc3.Derivation.bitcoinTaproot : coinId === 0 && address.startsWith("bc1") ? wc3.Derivation.bitcoinSegwit : wc3.Derivation.default;
7630
7532
  return new import_trust_sdk2.Account(address, derivation, "", "", "", chain2);
@@ -7753,9 +7655,9 @@ var init_dist3 = __esm({
7753
7655
  return this.signAndBroadcast(transaction, account, coinId, chainKey, ct5, params.hdWallet);
7754
7656
  }
7755
7657
  async transferRawSolana(params) {
7756
- const ct5 = requireCoinType(501);
7757
- const chain2 = new import_trust_sdk2.DefinedChain(ct5);
7758
- const account = this.getAccountFromSigner("solana");
7658
+ const { chain: chain2 } = chainKeyToDefinedChain(params.chainKey);
7659
+ const ct5 = requireCoinType(coinIdOf(params.chainKey));
7660
+ const account = this.getAccountFromSigner(params.chainKey);
7759
7661
  const asset = new import_trust_sdk2.Asset.Coin(account);
7760
7662
  const trade = new import_trust_sdk2.TransactionTrade(
7761
7663
  asset,
@@ -7774,24 +7676,16 @@ var init_dist3 = __esm({
7774
7676
  const nonce = await import_trust_sdk2.BlockchainService.fetchNonce(account);
7775
7677
  const encodedTx = await signTransactionBytes(trade, fee, nonce, params.hdWallet, ct5);
7776
7678
  const hash = await import_trust_sdk2.BlockchainService.sendTransactionV2(chain2, encodedTx);
7777
- return createPendingTransaction(this, "solana", hash);
7679
+ return createPendingTransaction(this, params.chainKey, hash);
7778
7680
  }
7779
7681
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7780
7682
  async signMessage(chainKey, message, privateKey) {
7781
- const coinId = chainKeyToCoinType(chainKey);
7782
- if (coinId === void 0) {
7783
- throw new Error(`Unsupported chain: ${chainKey}`);
7784
- }
7785
- const ct5 = requireCoinType(coinId);
7786
- const payload = getChainById(chainKey)?.isEVM ? `0x${Buffer.from(message, "utf8").toString("hex")}` : message;
7683
+ const ct5 = requireCoinType(coinIdOf(chainKey));
7684
+ const payload = chainOf(chainKey).isEVM ? `0x${Buffer.from(message, "utf8").toString("hex")}` : message;
7787
7685
  return import_trust_sdk2.BlockchainService.signMessage(ct5, payload, import_trust_sdk2.MessageType.Message, privateKey);
7788
7686
  }
7789
7687
  async signTypedData(params) {
7790
- const coinId = chainKeyToCoinType(params.chainKey);
7791
- if (coinId === void 0) {
7792
- throw new Error(`Unsupported chain: ${params.chainKey}`);
7793
- }
7794
- const ct5 = requireCoinType(coinId);
7688
+ const ct5 = requireCoinType(coinIdOf(params.chainKey));
7795
7689
  const privateKey = params.hdWallet.getKeyForCoin(ct5);
7796
7690
  if (!privateKey) {
7797
7691
  throw new Error(`Could not derive private key for chain ${params.chainKey}`);
@@ -7802,7 +7696,7 @@ var init_dist3 = __esm({
7802
7696
  params.typedDataJson,
7803
7697
  import_trust_sdk2.MessageType.TypedMessageEip155,
7804
7698
  privateKey,
7805
- params.chainId
7699
+ evmChainIdOf(params.chainKey)
7806
7700
  );
7807
7701
  } finally {
7808
7702
  try {
@@ -7813,12 +7707,9 @@ var init_dist3 = __esm({
7813
7707
  }
7814
7708
  async estimateFee(assetId, params) {
7815
7709
  const { coinId, contractAddress } = parseTokenId(assetId);
7816
- const chainKey = coinTypeToChainKey(coinId);
7817
- if (!chainKey) {
7818
- throw new Error(`Unsupported coin type: ${coinId}`);
7819
- }
7820
- const ct5 = requireCoinType(coinId);
7821
- const chain2 = new import_trust_sdk2.DefinedChain(ct5);
7710
+ const { chainKey } = params;
7711
+ requireCoinType(coinId);
7712
+ const { chain: chain2 } = chainKeyToDefinedChain(chainKey);
7822
7713
  const account = this.getAccountFromSigner(chainKey);
7823
7714
  const asset = contractAddress ? new import_trust_sdk2.Asset.Token(account, contractAddress, tokenTypeForCoinId(coinId)) : new import_trust_sdk2.Asset.Coin(account);
7824
7715
  const transaction = new import_trust_sdk2.TransactionTransfer(
@@ -7916,7 +7807,7 @@ var init_dist3 = __esm({
7916
7807
  * EIP-7702 token-as-gas sponsorship.
7917
7808
  */
7918
7809
  async signAndBroadcast(transaction, account, coinId, chainKey, ct5, hdWallet) {
7919
- const testnet = isTestnetChain(chainKey);
7810
+ const testnet = isTestnet(chainKey);
7920
7811
  const chain2 = testnet ? chainKeyToDefinedChain(chainKey).chain : new import_trust_sdk2.DefinedChain(ct5);
7921
7812
  const sponsoredUrl = this.getSponsoredRpcUrl(coinId, testnet);
7922
7813
  if (sponsoredUrl) {
@@ -8023,7 +7914,7 @@ var init_dist3 = __esm({
8023
7914
  * Trust SDK routes through the Smart Wallet fee service internally.
8024
7915
  */
8025
7916
  async calculateFeeWithSponsorship(transaction, account, coinId, chainKey) {
8026
- if (!_SigningChainClient.SPONSORABLE_COINS.includes(coinId) || chainKey !== void 0 && isTestnetChain(chainKey)) {
7917
+ if (!_SigningChainClient.SPONSORABLE_COINS.includes(coinId) || chainKey !== void 0 && isTestnet(chainKey)) {
8027
7918
  return { fee: await import_trust_sdk2.BlockchainService.calculateFee(transaction) };
8028
7919
  }
8029
7920
  let supports7702 = false;
@@ -8181,10 +8072,7 @@ var init_dist3 = __esm({
8181
8072
  getAddress(chainKey) {
8182
8073
  const cached = this.addressCache.get(chainKey);
8183
8074
  if (cached) return cached;
8184
- const coinId = chainKeyToCoinType(chainKey) ?? getChainById(chainKey)?.coinId;
8185
- if (coinId === void 0) {
8186
- throw new Error(`Unsupported chain: ${chainKey}`);
8187
- }
8075
+ const coinId = coinIdOf(chainKey);
8188
8076
  const ct5 = getCoinType(coinId);
8189
8077
  if (!ct5) {
8190
8078
  throw new Error(`No CoinType mapping for chain: ${chainKey} (coinId: ${coinId})`);
@@ -8201,16 +8089,13 @@ var init_dist3 = __esm({
8201
8089
  }
8202
8090
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8203
8091
  getAccount(chainKey) {
8204
- const testnet = isTestnetChain(chainKey);
8205
- const coinId = chainKeyToCoinType(chainKey) ?? getChainById(chainKey)?.coinId;
8206
- if (coinId === void 0) {
8207
- throw new Error(`Unsupported chain: ${chainKey}`);
8208
- }
8092
+ const testnet = isTestnet(chainKey);
8093
+ const coinId = coinIdOf(chainKey);
8209
8094
  const ct5 = getCoinType(coinId);
8210
8095
  if (!ct5) {
8211
8096
  throw new Error(`No CoinType mapping for chain: ${chainKey} (coinId: ${coinId})`);
8212
8097
  }
8213
- const chain2 = testnet ? new import_trust_sdk4.CustomChain(ct5, getChainById(chainKey).chainId) : new import_trust_sdk4.DefinedChain(ct5);
8098
+ const chain2 = testnet ? new import_trust_sdk4.CustomChain(ct5, chainOf(chainKey).chainId) : new import_trust_sdk4.DefinedChain(ct5);
8214
8099
  const accounts = import_trust_sdk4.AccountManagementService.createDefaultAccountsHdWallet(chain2, this.hdWallet);
8215
8100
  if (accounts.length === 0) {
8216
8101
  throw new Error(`No accounts for chain: ${chainKey}`);
@@ -8228,26 +8113,23 @@ var init_dist3 = __esm({
8228
8113
  }
8229
8114
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8230
8115
  getPrivateKey(chainKey) {
8231
- const coinId = chainKeyToCoinType(chainKey);
8232
- if (coinId === void 0) {
8233
- throw new Error(`Unsupported chain: ${chainKey}`);
8234
- }
8116
+ const coinId = coinIdOf(chainKey);
8235
8117
  const ct5 = getCoinType(coinId);
8236
8118
  if (!ct5) {
8237
8119
  throw new Error(`No CoinType mapping for chain: ${chainKey} (coinId: ${coinId})`);
8238
8120
  }
8239
8121
  return this.hdWallet.getKeyForCoin(ct5);
8240
8122
  }
8123
+ /** The wallet's address on every mainnet chain it supports, in registry order. */
8241
8124
  getAllAddresses() {
8242
- for (const chainKey of Object.keys(CHAINS)) {
8243
- if (!this.addressCache.has(chainKey)) {
8244
- try {
8245
- this.getAddress(chainKey);
8246
- } catch {
8247
- }
8125
+ const addresses = /* @__PURE__ */ new Map();
8126
+ for (const chainKey of mainnetChainKeys()) {
8127
+ try {
8128
+ addresses.set(chainKey, this.getAddress(chainKey));
8129
+ } catch {
8248
8130
  }
8249
8131
  }
8250
- return new Map(this.addressCache);
8132
+ return addresses;
8251
8133
  }
8252
8134
  destroy() {
8253
8135
  this.addressCache.clear();
@@ -8375,7 +8257,7 @@ var init_dist3 = __esm({
8375
8257
  const hdWallet = walletCore2.HDWallet.create(128, "");
8376
8258
  const mnemonic = hdWallet.mnemonic();
8377
8259
  const store = new WalletConfigStore();
8378
- await store.saveMnemonic(mnemonic, password3, Object.keys(CHAINS));
8260
+ await store.saveMnemonic(mnemonic, password3, mainnetChainKeys());
8379
8261
  const signer = WalletCoreSigner.fromHDWallet(hdWallet);
8380
8262
  const client = new SigningChainClient(signer);
8381
8263
  return new _AgentWalletProvider(signer, client);
@@ -8389,32 +8271,32 @@ var init_dist3 = __esm({
8389
8271
  }
8390
8272
  static async fromMnemonic(mnemonic, password3) {
8391
8273
  const store = new WalletConfigStore();
8392
- await store.saveMnemonic(mnemonic, password3, Object.keys(CHAINS));
8274
+ await store.saveMnemonic(mnemonic, password3, mainnetChainKeys());
8393
8275
  const signer = await WalletCoreSigner.fromMnemonic(mnemonic);
8394
8276
  const client = new SigningChainClient(signer);
8395
8277
  return new _AgentWalletProvider(signer, client);
8396
8278
  }
8397
- async getAddress(chainId) {
8279
+ async getAddress(chainKey) {
8398
8280
  await this.ensureConnected();
8399
8281
  this.resetAutoLockTimer();
8400
- return this.signer.getAddress(chainId);
8282
+ return this.signer.getAddress(chainKey);
8401
8283
  }
8402
8284
  async getAddresses() {
8403
8285
  await this.ensureConnected();
8404
8286
  this.resetAutoLockTimer();
8405
8287
  const addresses = this.signer.getAllAddresses();
8406
8288
  const result = [];
8407
- for (const [chainId, address] of addresses) {
8408
- result.push({ address, chainId });
8289
+ for (const [chainKey, address] of addresses) {
8290
+ result.push({ address, chainKey });
8409
8291
  }
8410
8292
  return result;
8411
8293
  }
8412
- async signMessage(chainId, message) {
8294
+ async signMessage(chainKey, message) {
8413
8295
  await this.ensureConnected();
8414
8296
  this.resetAutoLockTimer();
8415
- const privateKey = this.signer.getPrivateKey(chainId);
8297
+ const privateKey = this.signer.getPrivateKey(chainKey);
8416
8298
  try {
8417
- return await this.blockchainClient.signMessage(chainId, message, privateKey);
8299
+ return await this.blockchainClient.signMessage(chainKey, message, privateKey);
8418
8300
  } finally {
8419
8301
  try {
8420
8302
  privateKey.data().fill(0);
@@ -8422,12 +8304,11 @@ var init_dist3 = __esm({
8422
8304
  }
8423
8305
  }
8424
8306
  }
8425
- async signTypedData(chainKey, chainId, typedDataJson) {
8307
+ async signTypedData(chainKey, typedDataJson) {
8426
8308
  await this.ensureConnected();
8427
8309
  this.resetAutoLockTimer();
8428
8310
  return this.blockchainClient.signTypedData({
8429
8311
  chainKey,
8430
- chainId,
8431
8312
  typedDataJson,
8432
8313
  hdWallet: this.signer.getHDWallet()
8433
8314
  });
@@ -8435,25 +8316,16 @@ var init_dist3 = __esm({
8435
8316
  async sendTransaction(params) {
8436
8317
  await this.ensureConnected();
8437
8318
  this.resetAutoLockTimer();
8438
- const { getChainByEvmId: getChainByEvmId2, chainKeyToCoinType: chainKeyToCoinType3, resolveChain: resolveChain2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
8439
- let assetId;
8440
- if (params.chainId.startsWith("eip155:")) {
8441
- const chain2 = getChainByEvmId2(params.chainId.replace("eip155:", ""));
8442
- if (!chain2) throw new Error(`Unsupported chain: ${params.chainId}`);
8443
- assetId = `c${chain2.coinId}`;
8444
- } else if (params.chainId.startsWith("solana:")) {
8445
- assetId = "c501";
8446
- } else {
8447
- const coinId = chainKeyToCoinType3(params.chainId);
8448
- if (coinId === void 0) throw new Error(`Unsupported chain: ${params.chainId}`);
8449
- assetId = `c${coinId}`;
8450
- }
8451
- const chainKey = resolveChain2(params.chainId);
8319
+ const { chainKey } = params;
8320
+ const chain2 = chainOf(chainKey);
8321
+ const assetId = assetIdOf(chainKey);
8322
+ const isSolana = chain2.namespace === "solana";
8452
8323
  const hdWallet = this.signer.getHDWallet();
8453
8324
  const hasCalldata = params.data && params.data !== "0x" && params.data !== "0x0";
8454
8325
  const hasValue = params.value && params.value !== "0x0" && params.value !== "0x" && params.value !== "0";
8455
- if (params.chainId.startsWith("solana:") && hasCalldata) {
8326
+ if (isSolana && hasCalldata) {
8456
8327
  const result2 = await this.blockchainClient.transferRawSolana({
8328
+ chainKey,
8457
8329
  serializedMessage: params.data,
8458
8330
  hdWallet
8459
8331
  });
@@ -8493,9 +8365,6 @@ var init_dist3 = __esm({
8493
8365
  this.resetAutoLockTimer();
8494
8366
  return this.blockchainClient.getOwnBalance(assetId, chainKey);
8495
8367
  }
8496
- supportsChain(chainId) {
8497
- return isChainSupported(chainId);
8498
- }
8499
8368
  /**
8500
8369
  * No-op for agent wallets — they are always connected via local HD wallet.
8501
8370
  * WalletConnect-style connection URIs/QR codes do not apply.
@@ -8521,22 +8390,23 @@ var init_dist3 = __esm({
8521
8390
  return this.connected;
8522
8391
  }
8523
8392
  };
8393
+ ETHEREUM = knownChainKey("ethereum");
8524
8394
  TeeWalletProvider = class extends WalletProvider {
8525
8395
  name = "tee";
8526
8396
  kind = "remote";
8527
8397
  address = null;
8528
- async getAddress(_chainId) {
8398
+ async getAddress(_chainKey) {
8529
8399
  if (!this.address) throw new Error("TEE wallet not initialized");
8530
8400
  return this.address;
8531
8401
  }
8532
8402
  async getAddresses() {
8533
8403
  if (!this.address) return [];
8534
- return [{ address: this.address, chainId: "eip155:1" }];
8404
+ return [{ address: this.address, chainKey: ETHEREUM }];
8535
8405
  }
8536
- async signMessage(_chainId, _message) {
8406
+ async signMessage(_chainKey, _message) {
8537
8407
  throw new Error("TEE signing not yet implemented");
8538
8408
  }
8539
- async signTypedData(_chainKey, _chainId, _typedDataJson) {
8409
+ async signTypedData(_chainKey, _typedDataJson) {
8540
8410
  throw new Error("TEE signing not yet implemented");
8541
8411
  }
8542
8412
  async sendTransaction(_params) {
@@ -8548,10 +8418,7 @@ var init_dist3 = __esm({
8548
8418
  async getBalance() {
8549
8419
  throw new Error("TEE balances not yet implemented");
8550
8420
  }
8551
- supportsChain(_chainId) {
8552
- return false;
8553
- }
8554
- async connect(_chains) {
8421
+ async connect(_chainKeys) {
8555
8422
  throw new Error("TEE wallet connect not yet implemented");
8556
8423
  }
8557
8424
  async disconnect() {
@@ -8719,15 +8586,15 @@ var init_dist3 = __esm({
8719
8586
  * V1 does not restrict the peer wallet: any WC v2 client can pair. The
8720
8587
  * user's choice to scan the QR is the consent moment.
8721
8588
  */
8722
- async beginWalletConnect(chains) {
8723
- return this.enqueue(() => this.beginWalletConnectImpl(chains));
8589
+ async beginWalletConnect(chainKeys) {
8590
+ return this.enqueue(() => this.beginWalletConnectImpl(chainKeys));
8724
8591
  }
8725
- async beginWalletConnectImpl(chains) {
8592
+ async beginWalletConnectImpl(chainKeys) {
8726
8593
  const wc3 = this.walletConnect();
8727
8594
  this._generation++;
8728
8595
  await this.disconnectWcIfAny();
8729
8596
  try {
8730
- this._pairing = await wc3.connect(chains);
8597
+ this._pairing = await wc3.connect(chainKeys);
8731
8598
  } catch (err) {
8732
8599
  this._wallet = void 0;
8733
8600
  this._pairing = void 0;
@@ -8848,11 +8715,11 @@ function __metadata(metadataKey, metadataValue) {
8848
8715
  }
8849
8716
  function __awaiter(thisArg, _arguments, P5, generator) {
8850
8717
  function adopt(value) {
8851
- return value instanceof P5 ? value : new P5(function(resolve2) {
8852
- resolve2(value);
8718
+ return value instanceof P5 ? value : new P5(function(resolve4) {
8719
+ resolve4(value);
8853
8720
  });
8854
8721
  }
8855
- return new (P5 || (P5 = Promise))(function(resolve2, reject) {
8722
+ return new (P5 || (P5 = Promise))(function(resolve4, reject) {
8856
8723
  function fulfilled(value) {
8857
8724
  try {
8858
8725
  step(generator.next(value));
@@ -8868,7 +8735,7 @@ function __awaiter(thisArg, _arguments, P5, generator) {
8868
8735
  }
8869
8736
  }
8870
8737
  function step(result) {
8871
- result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
8738
+ result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
8872
8739
  }
8873
8740
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8874
8741
  });
@@ -9046,14 +8913,14 @@ function __asyncValues(o4) {
9046
8913
  }, i2);
9047
8914
  function verb(n4) {
9048
8915
  i2[n4] = o4[n4] && function(v5) {
9049
- return new Promise(function(resolve2, reject) {
9050
- v5 = o4[n4](v5), settle(resolve2, reject, v5.done, v5.value);
8916
+ return new Promise(function(resolve4, reject) {
8917
+ v5 = o4[n4](v5), settle(resolve4, reject, v5.done, v5.value);
9051
8918
  });
9052
8919
  };
9053
8920
  }
9054
- function settle(resolve2, reject, d3, v5) {
8921
+ function settle(resolve4, reject, d3, v5) {
9055
8922
  Promise.resolve(v5).then(function(v6) {
9056
- resolve2({ value: v6, done: d3 });
8923
+ resolve4({ value: v6, done: d3 });
9057
8924
  }, reject);
9058
8925
  }
9059
8926
  }
@@ -9122,9 +8989,9 @@ var require_delay = __commonJS({
9122
8989
  Object.defineProperty(exports2, "__esModule", { value: true });
9123
8990
  exports2.delay = void 0;
9124
8991
  function delay(timeout) {
9125
- return new Promise((resolve2) => {
8992
+ return new Promise((resolve4) => {
9126
8993
  setTimeout(() => {
9127
- resolve2(true);
8994
+ resolve4(true);
9128
8995
  }, timeout);
9129
8996
  });
9130
8997
  }
@@ -9390,9 +9257,9 @@ var require_cjs3 = __commonJS({
9390
9257
  if (href.indexOf("/") === 0) {
9391
9258
  absoluteHref += href;
9392
9259
  } else {
9393
- const path7 = loc.pathname.split("/");
9394
- path7.pop();
9395
- const finalPath = path7.join("/");
9260
+ const path13 = loc.pathname.split("/");
9261
+ path13.pop();
9262
+ const finalPath = path13.join("/");
9396
9263
  absoluteHref += finalPath + "/" + href;
9397
9264
  }
9398
9265
  icons2.push(absoluteHref);
@@ -13448,8 +13315,8 @@ var require_ws = __commonJS({
13448
13315
  });
13449
13316
 
13450
13317
  // ../contracts/dist/index.mjs
13451
- var dist_exports3 = {};
13452
- __export(dist_exports3, {
13318
+ var dist_exports2 = {};
13319
+ __export(dist_exports2, {
13453
13320
  COMPETITION_ABI: () => COMPETITION_ABI,
13454
13321
  COMPETITION_ADDRESSES: () => COMPETITION_ADDRESSES,
13455
13322
  ERC20_ABI: () => ERC20_ABI,
@@ -14234,7 +14101,7 @@ function createContractInstance(opts) {
14234
14101
  address
14235
14102
  });
14236
14103
  }
14237
- const chainDef = requireChain(chainKey);
14104
+ const chainDef = chainOf(chainKey);
14238
14105
  if (chainDef.namespace !== "eip155") {
14239
14106
  throw new TwakValidationError(
14240
14107
  `Contract calls are EVM-only; ${chainKey} is namespace ${chainDef.namespace}`,
@@ -14290,7 +14157,7 @@ function buildWriteProxy(abi, address, chainKey, client) {
14290
14157
  }
14291
14158
  const data = encodeFunctionCall(abi, prop, args);
14292
14159
  const hash = await signer.sendTransaction({
14293
- chainId: chainKeyToCaip2(chainKey),
14160
+ chainKey,
14294
14161
  to: address,
14295
14162
  data,
14296
14163
  value: "0x0"
@@ -14365,10 +14232,6 @@ function hexToSafeNumber(hex2, fieldName) {
14365
14232
  }
14366
14233
  return Number(big);
14367
14234
  }
14368
- function chainKeyToCaip2(chainKey) {
14369
- const def = requireChain(chainKey);
14370
- return `${def.namespace}:${def.chainId}`;
14371
- }
14372
14235
  function isJsInternal(prop) {
14373
14236
  return JS_INTERNAL_PROPS.has(prop);
14374
14237
  }
@@ -14448,9 +14311,8 @@ function parseOptParams(value) {
14448
14311
  function jobStatusName(status) {
14449
14312
  return JOB_STATUS[Number(status)] ?? "Unknown";
14450
14313
  }
14451
- function resolveErc8183Contracts(client, chainInput) {
14452
- const chainKey = resolveChain(chainInput);
14453
- const chain2 = requireChain(chainKey);
14314
+ function resolveErc8183Contracts(client, chainKey) {
14315
+ const chain2 = chainOf(chainKey);
14454
14316
  if (chain2.namespace !== "eip155") {
14455
14317
  throw new WalletError(
14456
14318
  "CHAIN_UNSUPPORTED",
@@ -14470,9 +14332,8 @@ function resolveErc8183Contracts(client, chainInput) {
14470
14332
  chainKey
14471
14333
  };
14472
14334
  }
14473
- function resolveErc8004Contract(client, chainInput) {
14474
- const chainKey = resolveChain(chainInput);
14475
- const chain2 = requireChain(chainKey);
14335
+ function resolveErc8004Contract(client, chainKey) {
14336
+ const chain2 = chainOf(chainKey);
14476
14337
  if (chain2.namespace !== "eip155") {
14477
14338
  throw new WalletError(
14478
14339
  "CHAIN_UNSUPPORTED",
@@ -14490,7 +14351,7 @@ function resolveErc8004Contract(client, chainInput) {
14490
14351
  return { contract, chainKey };
14491
14352
  }
14492
14353
  function resolveCompetitionContract(client) {
14493
- const chainKey = "bsc";
14354
+ const chainKey = knownChainKey("bsc");
14494
14355
  const addressOverride = process.env.COMPETITION_REGISTRY_ADDRESS;
14495
14356
  const contract = competition.using(client).resolve({ chainKey, addressOverride });
14496
14357
  return { contract, chainKey };
@@ -14510,6 +14371,7 @@ var init_dist4 = __esm({
14510
14371
  init_dist();
14511
14372
  init_dist();
14512
14373
  init_dist();
14374
+ init_dist();
14513
14375
  HEX_PATTERN = /^0x[0-9a-fA-F]*$/;
14514
14376
  BRIDGE = {
14515
14377
  createAbiFunction(name2) {
@@ -15108,18 +14970,18 @@ var init_dist4 = __esm({
15108
14970
  anonymous: false
15109
14971
  }
15110
14972
  ];
15111
- ERC8183_COMMERCE_ADDRESSES = {
14973
+ ERC8183_COMMERCE_ADDRESSES = byChainKey({
15112
14974
  bsc: "0xea4daa3100a767e86fded867729ae7446476eba6",
15113
14975
  bsctestnet: "0xa206c0517b6371c6638cd9e4a42cc9f02a33b0de"
15114
- };
15115
- ERC8183_ROUTER_ADDRESSES = {
14976
+ });
14977
+ ERC8183_ROUTER_ADDRESSES = byChainKey({
15116
14978
  bsc: "0x51895229e12f9876011789b04f8698af06ccd6da",
15117
14979
  bsctestnet: "0xd7d36d66d2f1b608a0f943f722d27e3744f66f25"
15118
- };
15119
- ERC8183_POLICY_ADDRESSES = {
14980
+ });
14981
+ ERC8183_POLICY_ADDRESSES = byChainKey({
15120
14982
  bsc: "0x9c01845705b3078aa2e8cff7520a6376fd766de5",
15121
14983
  bsctestnet: "0x4f4678d4439fec812ac7674bb3efb4c8f5fb78a6"
15122
- };
14984
+ });
15123
14985
  erc8183Commerce = defineContract({
15124
14986
  id: "erc8183-commerce",
15125
14987
  abi: ERC8183_COMMERCE_ABI,
@@ -15561,10 +15423,10 @@ var init_dist4 = __esm({
15561
15423
  anonymous: false
15562
15424
  }
15563
15425
  ];
15564
- ERC8004_ADDRESSES = {
15426
+ ERC8004_ADDRESSES = byChainKey({
15565
15427
  bsc: "0x8004a169fb4a3325136eb29fa0ceb6d2e539a432",
15566
15428
  bsctestnet: "0x8004a818bfb912233c491871b3d84c89a494bd9e"
15567
- };
15429
+ });
15568
15430
  erc8004 = defineContract({
15569
15431
  id: "erc8004",
15570
15432
  abi: ERC8004_ABI,
@@ -15606,9 +15468,9 @@ var init_dist4 = __esm({
15606
15468
  anonymous: false
15607
15469
  }
15608
15470
  ];
15609
- COMPETITION_ADDRESSES = {
15471
+ COMPETITION_ADDRESSES = byChainKey({
15610
15472
  bsc: "0x212c61B9B72C95d95BF29CF032F5E5635629Aed5"
15611
- };
15473
+ });
15612
15474
  competition = defineContract({
15613
15475
  id: "competition",
15614
15476
  abi: COMPETITION_ABI,
@@ -16334,24 +16196,73 @@ var dapps_service_exports = {};
16334
16196
  __export(dapps_service_exports, {
16335
16197
  DappsService: () => DappsService
16336
16198
  });
16337
- var fs7, path5, os3, CACHE_FILE, CACHE_TTL_MS, DappsService;
16199
+ function toProtocol(p3) {
16200
+ const llamaChains = Array.isArray(p3.chains) ? p3.chains : [];
16201
+ return {
16202
+ id: p3.id || p3.slug || "",
16203
+ name: p3.name || "",
16204
+ symbol: p3.symbol || "",
16205
+ url: p3.url || "",
16206
+ description: p3.description || "",
16207
+ category: p3.category || "",
16208
+ chains: llamaChains.flatMap(
16209
+ (c3) => typeof c3 === "string" && LLAMA_CHAIN_KEYS[c3] ? [LLAMA_CHAIN_KEYS[c3]] : []
16210
+ ),
16211
+ tvl: p3.tvl ?? 0,
16212
+ logo: p3.logo || "",
16213
+ audits: p3.audits || "0",
16214
+ change1d: p3.change_1d ?? null,
16215
+ change7d: p3.change_7d ?? null,
16216
+ mcap: p3.mcap ?? null
16217
+ };
16218
+ }
16219
+ var fs7, path11, cacheFile, CACHE_TTL_MS, CACHE_VERSION, LLAMA_CHAIN_KEYS, DappsService;
16338
16220
  var init_dapps_service = __esm({
16339
16221
  "../security/dist/services/dapps-service.mjs"() {
16340
16222
  "use strict";
16341
16223
  fs7 = __toESM(require("fs"), 1);
16342
- path5 = __toESM(require("path"), 1);
16343
- os3 = __toESM(require("os"), 1);
16224
+ path11 = __toESM(require("path"), 1);
16344
16225
  init_dist();
16345
- CACHE_FILE = path5.join(os3.homedir(), ".twak", "dapps-cache.json");
16226
+ cacheFile = () => path11.join(twakHome(), "dapps-cache.json");
16346
16227
  CACHE_TTL_MS = 6 * 36e5;
16228
+ CACHE_VERSION = 2;
16229
+ LLAMA_CHAIN_KEYS = Object.fromEntries(
16230
+ Object.entries({
16231
+ Ethereum: "ethereum",
16232
+ Binance: "bsc",
16233
+ Arbitrum: "arbitrum",
16234
+ Base: "base",
16235
+ Polygon: "polygon",
16236
+ Avalanche: "avalanche",
16237
+ Solana: "solana",
16238
+ Optimism: "optimism",
16239
+ Fantom: "fantom",
16240
+ Sonic: "sonic",
16241
+ Linea: "linea",
16242
+ Bitcoin: "bitcoin",
16243
+ Blast: "blast",
16244
+ "zkSync Era": "zksync",
16245
+ Scroll: "scroll",
16246
+ Sui: "sui",
16247
+ Tron: "tron",
16248
+ TON: "ton",
16249
+ Aptos: "aptos",
16250
+ Celo: "celo",
16251
+ Near: "near",
16252
+ Litecoin: "litecoin",
16253
+ Cosmos: "cosmos",
16254
+ Aurora: "aurora",
16255
+ Doge: "dogecoin"
16256
+ }).map(([name2, key]) => [name2, knownChainKey(key)])
16257
+ );
16347
16258
  DappsService = class {
16348
16259
  protocols = null;
16349
16260
  async getProtocols() {
16350
16261
  if (this.protocols) return this.protocols;
16351
16262
  const cached = this.readCache();
16352
16263
  if (cached) {
16353
- this.protocols = cached;
16354
- return cached;
16264
+ this.protocols = cached.map(toProtocol);
16265
+ return this.protocols;
16355
16266
  }
16356
16267
  let resp;
16357
16268
  try {
@@ -16364,23 +16275,9 @@ var init_dapps_service = __esm({
16364
16275
  if (!resp.ok) {
16365
16276
  throw new TwakApiError(`DeFi Llama API error: ${resp.status}`, resp.status);
16366
16277
  }
16367
- const raw = await resp.json();
16368
- this.protocols = raw.filter((p3) => p3.tvl > 0).map((p3) => ({
16369
- id: p3.id || p3.slug || "",
16370
- name: p3.name || "",
16371
- symbol: p3.symbol || "",
16372
- url: p3.url || "",
16373
- description: p3.description || "",
16374
- category: p3.category || "",
16375
- chains: Array.isArray(p3.chains) ? p3.chains : [],
16376
- tvl: p3.tvl ?? 0,
16377
- logo: p3.logo || "",
16378
- audits: p3.audits || "0",
16379
- change1d: p3.change_1d ?? null,
16380
- change7d: p3.change_7d ?? null,
16381
- mcap: p3.mcap ?? null
16382
- }));
16383
- this.writeCache(this.protocols);
16278
+ const raw = (await resp.json()).filter((p3) => (p3.tvl ?? 0) > 0);
16279
+ this.protocols = raw.map(toProtocol);
16280
+ this.writeCache(raw);
16384
16281
  return this.protocols;
16385
16282
  }
16386
16283
  async getTop(limit = 20, category) {
@@ -16408,9 +16305,9 @@ var init_dapps_service = __esm({
16408
16305
  }
16409
16306
  readCache() {
16410
16307
  try {
16411
- const raw = fs7.readFileSync(CACHE_FILE, "utf-8");
16308
+ const raw = fs7.readFileSync(cacheFile(), "utf-8");
16412
16309
  const data = JSON.parse(raw);
16413
- if (Date.now() - data.fetchedAt < CACHE_TTL_MS) {
16310
+ if (data.version === CACHE_VERSION && Date.now() - data.fetchedAt < CACHE_TTL_MS) {
16414
16311
  return data.protocols;
16415
16312
  }
16416
16313
  } catch {
@@ -16419,10 +16316,10 @@ var init_dapps_service = __esm({
16419
16316
  }
16420
16317
  writeCache(protocols) {
16421
16318
  try {
16422
- const dir = path5.dirname(CACHE_FILE);
16319
+ const dir = path11.dirname(cacheFile());
16423
16320
  fs7.mkdirSync(dir, { recursive: true });
16424
- const data = { fetchedAt: Date.now(), protocols };
16425
- fs7.writeFileSync(CACHE_FILE, JSON.stringify(data));
16321
+ const data = { version: CACHE_VERSION, fetchedAt: Date.now(), protocols };
16322
+ fs7.writeFileSync(cacheFile(), JSON.stringify(data));
16426
16323
  } catch {
16427
16324
  }
16428
16325
  }
@@ -19381,7 +19278,7 @@ var require_compile = __commonJS({
19381
19278
  const schOrFunc = root.refs[ref];
19382
19279
  if (schOrFunc)
19383
19280
  return schOrFunc;
19384
- let _sch = resolve2.call(this, root, ref);
19281
+ let _sch = resolve4.call(this, root, ref);
19385
19282
  if (_sch === void 0) {
19386
19283
  const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
19387
19284
  const { schemaId } = this.opts;
@@ -19408,7 +19305,7 @@ var require_compile = __commonJS({
19408
19305
  function sameSchemaEnv(s1, s2) {
19409
19306
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
19410
19307
  }
19411
- function resolve2(root, ref) {
19308
+ function resolve4(root, ref) {
19412
19309
  let sch;
19413
19310
  while (typeof (sch = this.refs[ref]) == "string")
19414
19311
  ref = sch;
@@ -19623,8 +19520,8 @@ var require_utils2 = __commonJS({
19623
19520
  }
19624
19521
  return ind;
19625
19522
  }
19626
- function removeDotSegments(path7) {
19627
- let input2 = path7;
19523
+ function removeDotSegments(path13) {
19524
+ let input2 = path13;
19628
19525
  const output2 = [];
19629
19526
  let nextSlash = -1;
19630
19527
  let len = 0;
@@ -19823,8 +19720,8 @@ var require_schemes = __commonJS({
19823
19720
  wsComponent.secure = void 0;
19824
19721
  }
19825
19722
  if (wsComponent.resourceName) {
19826
- const [path7, query] = wsComponent.resourceName.split("?");
19827
- wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
19723
+ const [path13, query] = wsComponent.resourceName.split("?");
19724
+ wsComponent.path = path13 && path13 !== "/" ? path13 : void 0;
19828
19725
  wsComponent.query = query;
19829
19726
  wsComponent.resourceName = void 0;
19830
19727
  }
@@ -19983,7 +19880,7 @@ var require_fast_uri = __commonJS({
19983
19880
  }
19984
19881
  return uri;
19985
19882
  }
19986
- function resolve2(baseURI, relativeURI, options) {
19883
+ function resolve4(baseURI, relativeURI, options) {
19987
19884
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
19988
19885
  const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
19989
19886
  schemelessOptions.skipEscape = true;
@@ -20210,7 +20107,7 @@ var require_fast_uri = __commonJS({
20210
20107
  var fastUri = {
20211
20108
  SCHEMES,
20212
20109
  normalize,
20213
- resolve: resolve2,
20110
+ resolve: resolve4,
20214
20111
  resolveComponent,
20215
20112
  equal,
20216
20113
  serialize,
@@ -23222,11 +23119,11 @@ function __rest2(s2, e2) {
23222
23119
  }
23223
23120
  function __awaiter2(thisArg, _arguments, P5, generator) {
23224
23121
  function adopt(value) {
23225
- return value instanceof P5 ? value : new P5(function(resolve2) {
23226
- resolve2(value);
23122
+ return value instanceof P5 ? value : new P5(function(resolve4) {
23123
+ resolve4(value);
23227
23124
  });
23228
23125
  }
23229
- return new (P5 || (P5 = Promise))(function(resolve2, reject) {
23126
+ return new (P5 || (P5 = Promise))(function(resolve4, reject) {
23230
23127
  function fulfilled(value) {
23231
23128
  try {
23232
23129
  step(generator.next(value));
@@ -23242,7 +23139,7 @@ function __awaiter2(thisArg, _arguments, P5, generator) {
23242
23139
  }
23243
23140
  }
23244
23141
  function step(result) {
23245
- result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
23142
+ result.done ? resolve4(result.value) : adopt(result.value).then(fulfilled, rejected);
23246
23143
  }
23247
23144
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23248
23145
  });
@@ -23812,8 +23709,8 @@ var init_timeline = __esm({
23812
23709
  };
23813
23710
  Timeline2.prototype.push = function(event) {
23814
23711
  var _this = this;
23815
- return new Promise(function(resolve2) {
23816
- _this.queue.push([event, resolve2]);
23712
+ return new Promise(function(resolve4) {
23713
+ _this.queue.push([event, resolve4]);
23817
23714
  _this.scheduleApply(0);
23818
23715
  });
23819
23716
  };
@@ -23833,7 +23730,7 @@ var init_timeline = __esm({
23833
23730
  };
23834
23731
  Timeline2.prototype.apply = function(item) {
23835
23732
  return __awaiter2(this, void 0, void 0, function() {
23836
- var _a2, event, _b, resolve2, before, before_1, before_1_1, plugin, e2, e_1_1, enrichment, enrichment_1, enrichment_1_1, plugin, e2, e_2_1, destination, executeDestinations;
23733
+ var _a2, event, _b, resolve4, before, before_1, before_1_1, plugin, e2, e_1_1, enrichment, enrichment_1, enrichment_1_1, plugin, e2, e_2_1, destination, executeDestinations;
23837
23734
  var e_1, _c2, e_2, _d;
23838
23735
  return __generator2(this, function(_e6) {
23839
23736
  switch (_e6.label) {
@@ -23845,7 +23742,7 @@ var init_timeline = __esm({
23845
23742
  ];
23846
23743
  }
23847
23744
  _a2 = __read2(item, 1), event = _a2[0];
23848
- _b = __read2(item, 2), resolve2 = _b[1];
23745
+ _b = __read2(item, 2), resolve4 = _b[1];
23849
23746
  this.loggerProvider.log("Timeline.apply: Initial event", event);
23850
23747
  before = this.plugins.filter(function(plugin2) {
23851
23748
  return plugin2.type === "before";
@@ -23866,7 +23763,7 @@ var init_timeline = __esm({
23866
23763
  e2 = _e6.sent();
23867
23764
  if (e2 === null) {
23868
23765
  this.loggerProvider.log("Timeline.apply: Event filtered out by before plugin '".concat(String(plugin.name), "', event: ").concat(JSON.stringify(event)));
23869
- resolve2({ event, code: 0, message: "" });
23766
+ resolve4({ event, code: 0, message: "" });
23870
23767
  return [
23871
23768
  2
23872
23769
  /*return*/
@@ -23915,7 +23812,7 @@ var init_timeline = __esm({
23915
23812
  e2 = _e6.sent();
23916
23813
  if (e2 === null) {
23917
23814
  this.loggerProvider.log("Timeline.apply: Event filtered out by enrichment plugin '".concat(String(plugin.name), "', event: ").concat(JSON.stringify(event)));
23918
- resolve2({ event, code: 0, message: "" });
23815
+ resolve4({ event, code: 0, message: "" });
23919
23816
  return [
23920
23817
  2
23921
23818
  /*return*/
@@ -23958,7 +23855,7 @@ var init_timeline = __esm({
23958
23855
  void Promise.all(executeDestinations).then(function(_a3) {
23959
23856
  var _b2 = __read2(_a3, 1), result = _b2[0];
23960
23857
  var resolveResult = result || buildResult(event, 100, "Event not tracked, no destination plugins on the instance");
23961
- resolve2(resolveResult);
23858
+ resolve4(resolveResult);
23962
23859
  });
23963
23860
  return [
23964
23861
  2
@@ -24297,8 +24194,8 @@ var init_core_client = __esm({
24297
24194
  var _this = this;
24298
24195
  return __generator2(this, function(_a2) {
24299
24196
  if (!this.isReady) {
24300
- return [2, new Promise(function(resolve2) {
24301
- _this.dispatchQ.push(_this.dispatchWithCallback.bind(_this, event, resolve2));
24197
+ return [2, new Promise(function(resolve4) {
24198
+ _this.dispatchQ.push(_this.dispatchWithCallback.bind(_this, event, resolve4));
24302
24199
  })];
24303
24200
  }
24304
24201
  return [2, this.process(event)];
@@ -24731,12 +24628,12 @@ var init_debug = __esm({
24731
24628
  };
24732
24629
  };
24733
24630
  };
24734
- getValueByStringPath = function(obj, path7) {
24631
+ getValueByStringPath = function(obj, path13) {
24735
24632
  var e_1, _a2;
24736
- path7 = path7.replace(/\[(\w+)\]/g, ".$1");
24737
- path7 = path7.replace(/^\./, "");
24633
+ path13 = path13.replace(/\[(\w+)\]/g, ".$1");
24634
+ path13 = path13.replace(/^\./, "");
24738
24635
  try {
24739
- for (var _b = __values2(path7.split(".")), _c2 = _b.next(); !_c2.done; _c2 = _b.next()) {
24636
+ for (var _b = __values2(path13.split(".")), _c2 = _b.next(); !_c2.done; _c2 = _b.next()) {
24740
24637
  var attr = _c2.value;
24741
24638
  if (attr in obj) {
24742
24639
  obj = obj[attr];
@@ -24761,8 +24658,8 @@ var init_debug = __esm({
24761
24658
  var res = {};
24762
24659
  try {
24763
24660
  for (var paths_1 = __values2(paths), paths_1_1 = paths_1.next(); !paths_1_1.done; paths_1_1 = paths_1.next()) {
24764
- var path7 = paths_1_1.value;
24765
- res[path7] = getValueByStringPath(client, path7);
24661
+ var path13 = paths_1_1.value;
24662
+ res[path13] = getValueByStringPath(client, path13);
24766
24663
  }
24767
24664
  } catch (e_2_1) {
24768
24665
  e_2 = { error: e_2_1 };
@@ -24900,12 +24797,12 @@ var init_destination = __esm({
24900
24797
  if (!event.insert_id) {
24901
24798
  event.insert_id = UUID();
24902
24799
  }
24903
- return new Promise(function(resolve2) {
24800
+ return new Promise(function(resolve4) {
24904
24801
  var context = {
24905
24802
  event,
24906
24803
  attempts: 0,
24907
24804
  callback: function(result) {
24908
- return resolve2(result);
24805
+ return resolve4(result);
24909
24806
  },
24910
24807
  timeout: 0
24911
24808
  };
@@ -25417,7 +25314,7 @@ var init_context = __esm({
25417
25314
  };
25418
25315
  Context2.prototype.execute = function(context) {
25419
25316
  var _this = this;
25420
- return new Promise(function(resolve2) {
25317
+ return new Promise(function(resolve4) {
25421
25318
  var time = (/* @__PURE__ */ new Date()).getTime();
25422
25319
  var contextEvent = __assign2(__assign2(__assign2({ time, insert_id: UUID(), plan: _this.config.plan }, _this.config.ingestionMetadata && {
25423
25320
  ingestion_metadata: {
@@ -25425,7 +25322,7 @@ var init_context = __esm({
25425
25322
  source_version: _this.config.ingestionMetadata.sourceVersion
25426
25323
  }
25427
25324
  }), context), { event_id: _this.eventId++, library: _this.library });
25428
- return resolve2(contextEvent);
25325
+ return resolve4(contextEvent);
25429
25326
  });
25430
25327
  };
25431
25328
  return Context2;
@@ -25471,7 +25368,7 @@ var init_http = __esm({
25471
25368
  port: url.port,
25472
25369
  protocol: url.protocol
25473
25370
  };
25474
- return new Promise(function(resolve2) {
25371
+ return new Promise(function(resolve4) {
25475
25372
  var req = protocol.request(options, function(res) {
25476
25373
  res.setEncoding("utf8");
25477
25374
  var responsePayload = "";
@@ -25483,15 +25380,15 @@ var init_http = __esm({
25483
25380
  try {
25484
25381
  var parsedResponsePayload = JSON.parse(responsePayload);
25485
25382
  var result = _this.buildResponse(parsedResponsePayload);
25486
- resolve2(result);
25383
+ resolve4(result);
25487
25384
  } catch (_a2) {
25488
- resolve2(_this.buildResponse({ code: res.statusCode }));
25385
+ resolve4(_this.buildResponse({ code: res.statusCode }));
25489
25386
  }
25490
25387
  }
25491
25388
  });
25492
25389
  });
25493
25390
  req.on("error", function() {
25494
- return resolve2(null);
25391
+ return resolve4(null);
25495
25392
  });
25496
25393
  req.end(requestPayload);
25497
25394
  });
@@ -25677,6 +25574,7 @@ var {
25677
25574
  } = import_index.default;
25678
25575
 
25679
25576
  // src/commands/init.ts
25577
+ var path5 = __toESM(require("path"));
25680
25578
  init_dist();
25681
25579
  init_dist2();
25682
25580
 
@@ -25798,12 +25696,10 @@ async function ensureTrustSDK() {
25798
25696
  }
25799
25697
  async function registerWalletWithBackend(creds, provider) {
25800
25698
  const accounts = [];
25801
- for (const key of Object.keys(CHAINS)) {
25802
- const chain2 = getChainById(key);
25803
- if (!chain2) continue;
25699
+ for (const key of mainnetChainKeys()) {
25804
25700
  try {
25805
25701
  const address = await provider.getAddress(key);
25806
- if (address) accounts.push({ coin: chain2.coinId, address });
25702
+ if (address) accounts.push({ coin: coinIdOf(key), address });
25807
25703
  } catch {
25808
25704
  }
25809
25705
  }
@@ -25811,6 +25707,11 @@ async function registerWalletWithBackend(creds, provider) {
25811
25707
  await registerDeviceAndWallet(creds, accounts);
25812
25708
  }
25813
25709
  }
25710
+ async function findWalletPassword(opts) {
25711
+ if (opts?.password) return opts.password;
25712
+ if (process.env.TWAK_WALLET_PASSWORD) return process.env.TWAK_WALLET_PASSWORD;
25713
+ return new KeychainManager().getWalletPassword();
25714
+ }
25814
25715
  async function resolvePassword(opts) {
25815
25716
  if (opts?.password) {
25816
25717
  process.stderr.write(
@@ -25818,12 +25719,9 @@ async function resolvePassword(opts) {
25818
25719
  "Note: --password is visible in shell history. Use `twak wallet keychain save` or TWAK_WALLET_PASSWORD instead.\n"
25819
25720
  )
25820
25721
  );
25821
- return opts.password;
25822
25722
  }
25823
- if (process.env.TWAK_WALLET_PASSWORD) return process.env.TWAK_WALLET_PASSWORD;
25824
- const kc2 = new KeychainManager();
25825
- const stored = await kc2.getWalletPassword();
25826
- if (stored) return stored;
25723
+ const password3 = await findWalletPassword(opts);
25724
+ if (password3) return password3;
25827
25725
  throw new Error(
25828
25726
  "No wallet password found. Provide --password, set TWAK_WALLET_PASSWORD, or run `twak wallet keychain save --password <pw>`"
25829
25727
  );
@@ -26496,8 +26394,8 @@ async function dispose(driver) {
26496
26394
 
26497
26395
  // ../../node_modules/.pnpm/idb-keyval@6.2.2/node_modules/idb-keyval/dist/index.js
26498
26396
  function promisifyRequest(request) {
26499
- return new Promise((resolve2, reject) => {
26500
- request.oncomplete = request.onsuccess = () => resolve2(request.result);
26397
+ return new Promise((resolve4, reject) => {
26398
+ request.oncomplete = request.onsuccess = () => resolve4(request.result);
26501
26399
  request.onabort = request.onerror = () => reject(request.error);
26502
26400
  });
26503
26401
  }
@@ -28351,10 +28249,10 @@ var __spreadArray = function(to3, from8, pack) {
28351
28249
  var BrowserInfo = (
28352
28250
  /** @class */
28353
28251
  /* @__PURE__ */ (function() {
28354
- function BrowserInfo2(name2, version3, os5) {
28252
+ function BrowserInfo2(name2, version3, os4) {
28355
28253
  this.name = name2;
28356
28254
  this.version = version3;
28357
- this.os = os5;
28255
+ this.os = os4;
28358
28256
  this.type = "browser";
28359
28257
  }
28360
28258
  return BrowserInfo2;
@@ -28375,10 +28273,10 @@ var NodeInfo = (
28375
28273
  var SearchBotDeviceInfo = (
28376
28274
  /** @class */
28377
28275
  /* @__PURE__ */ (function() {
28378
- function SearchBotDeviceInfo2(name2, version3, os5, bot) {
28276
+ function SearchBotDeviceInfo2(name2, version3, os4, bot) {
28379
28277
  this.name = name2;
28380
28278
  this.version = version3;
28381
- this.os = os5;
28279
+ this.os = os4;
28382
28280
  this.bot = bot;
28383
28281
  this.type = "bot-device";
28384
28282
  }
@@ -28521,19 +28419,19 @@ function parseUserAgent(ua) {
28521
28419
  versionParts = [];
28522
28420
  }
28523
28421
  var version3 = versionParts.join(".");
28524
- var os5 = detectOS(ua);
28422
+ var os4 = detectOS(ua);
28525
28423
  var searchBotMatch = SEARCHBOT_OS_REGEX.exec(ua);
28526
28424
  if (searchBotMatch && searchBotMatch[1]) {
28527
- return new SearchBotDeviceInfo(name2, version3, os5, searchBotMatch[1]);
28425
+ return new SearchBotDeviceInfo(name2, version3, os4, searchBotMatch[1]);
28528
28426
  }
28529
- return new BrowserInfo(name2, version3, os5);
28427
+ return new BrowserInfo(name2, version3, os4);
28530
28428
  }
28531
28429
  function detectOS(ua) {
28532
28430
  for (var ii2 = 0, count = operatingSystemRules.length; ii2 < count; ii2++) {
28533
- var _a2 = operatingSystemRules[ii2], os5 = _a2[0], regex = _a2[1];
28431
+ var _a2 = operatingSystemRules[ii2], os4 = _a2[0], regex = _a2[1];
28534
28432
  var match = regex.exec(ua);
28535
28433
  if (match) {
28536
- return os5;
28434
+ return os4;
28537
28435
  }
28538
28436
  }
28539
28437
  return null;
@@ -32115,7 +32013,7 @@ function alphabet(letters) {
32115
32013
  };
32116
32014
  }
32117
32015
  // @__NO_SIDE_EFFECTS__
32118
- function join3(separator = "") {
32016
+ function join4(separator = "") {
32119
32017
  astr("join", separator);
32120
32018
  return {
32121
32019
  encode: (from8) => {
@@ -32283,8 +32181,8 @@ function radix2(bits, revPadding = false) {
32283
32181
  }
32284
32182
  };
32285
32183
  }
32286
- var base32 = /* @__PURE__ */ chain(/* @__PURE__ */ radix2(5), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), /* @__PURE__ */ padding(5), /* @__PURE__ */ join3(""));
32287
- var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join3(""));
32184
+ var base32 = /* @__PURE__ */ chain(/* @__PURE__ */ radix2(5), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), /* @__PURE__ */ padding(5), /* @__PURE__ */ join4(""));
32185
+ var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join4(""));
32288
32186
  var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
32289
32187
 
32290
32188
  // ../../node_modules/.pnpm/ox@0.9.3_typescript@5.7.3_zod@3.25.76/node_modules/ox/_esm/core/Secp256k1.js
@@ -41647,7 +41545,7 @@ var Os3 = ut4;
41647
41545
  init_dist3();
41648
41546
  init_dist();
41649
41547
  var fs5 = __toESM(require("fs"), 1);
41650
- var path3 = __toESM(require("path"), 1);
41548
+ var path4 = __toESM(require("path"), 1);
41651
41549
  var crypto7 = __toESM(require("crypto"), 1);
41652
41550
  init_dist();
41653
41551
  var __require2 = /* @__PURE__ */ ((x6) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x6, {
@@ -41710,7 +41608,7 @@ var FileKeyValueStorage = class {
41710
41608
  const snapshot = JSON.stringify(Object.fromEntries(this.load()));
41711
41609
  const tmpPath = `${this.filePath}.tmp.${crypto7.randomBytes(8).toString("hex")}`;
41712
41610
  try {
41713
- fs5.mkdirSync(path3.dirname(this.filePath), { recursive: true, mode: 448 });
41611
+ fs5.mkdirSync(path4.dirname(this.filePath), { recursive: true, mode: 448 });
41714
41612
  fs5.writeFileSync(tmpPath, snapshot, { encoding: "utf-8", mode: 384 });
41715
41613
  fs5.renameSync(tmpPath, this.filePath);
41716
41614
  } catch (err) {
@@ -41764,8 +41662,8 @@ function toRequestError(err) {
41764
41662
  }
41765
41663
  async function settleWithin(promise, ms3) {
41766
41664
  let timer;
41767
- const elapsed = new Promise((resolve2) => {
41768
- timer = setTimeout(resolve2, ms3);
41665
+ const elapsed = new Promise((resolve4) => {
41666
+ timer = setTimeout(resolve4, ms3);
41769
41667
  });
41770
41668
  try {
41771
41669
  await Promise.race([promise.catch(() => void 0), elapsed]);
@@ -41861,9 +41759,9 @@ var WalletConnectProvider = class extends WalletProvider {
41861
41759
  }
41862
41760
  /**
41863
41761
  * Returns the WC account to use as the `from` field for a signing request
41864
- * on `chainId`. EVM-only: throws `CHAIN_UNSUPPORTED` if `chainId` isn't in
41865
- * the `eip155` namespace. Accepts both CAIP-2 (`eip155:56`) and chain keys
41866
- * (`bsc`, `arbitrum`) — chain keys are normalised to CAIP-2 internally.
41762
+ * on CAIP-2 chain `caip2`. EVM-only: throws `CHAIN_UNSUPPORTED` if it isn't
41763
+ * in the `eip155` namespace. Callers convert chain keys first
41764
+ * (caip2ForChainKey); CAIP-2 never leaves this class.
41867
41765
  *
41868
41766
  * Prefers an exact CAIP-2 match; falls back to any other `eip155:*` account
41869
41767
  * in the session. The fallback is safe because all EVM chains derive from
@@ -41872,59 +41770,61 @@ var WalletConnectProvider = class extends WalletProvider {
41872
41770
  * same-address property (see the April 2026 design notes on Bitcoin vs.
41873
41771
  * Bitcoin Cash derivations).
41874
41772
  */
41875
- resolveFromAddress(chainIdOrKey) {
41876
- const chainId = chainIdOrKey.includes(":") ? chainIdOrKey : (() => {
41877
- const def = getChainById(chainIdOrKey);
41878
- return def ? `${def.namespace}:${def.chainId}` : chainIdOrKey;
41879
- })();
41880
- const namespace = chainId.split(":")[0];
41773
+ resolveFromAddress(caip2) {
41774
+ const namespace = caip2.split(":")[0];
41881
41775
  if (namespace !== "eip155") {
41882
41776
  throw new WalletError(
41883
41777
  "CHAIN_UNSUPPORTED",
41884
- `WalletConnect signing is only supported for EVM chains (eip155:*). Got: ${chainIdOrKey}`
41778
+ `WalletConnect signing is only supported for EVM chains (eip155:*). Got: ${caip2}`
41885
41779
  );
41886
41780
  }
41887
41781
  const accounts = this.getAllSessionAccounts();
41888
- const exact = accounts.find((a3) => a3.chainId === chainId);
41782
+ const exact = accounts.find((a3) => a3.caip2 === caip2);
41889
41783
  if (exact) return exact.address;
41890
- const sameNs = accounts.find((a3) => a3.chainId.startsWith("eip155:"));
41784
+ const sameNs = accounts.find((a3) => a3.caip2.startsWith("eip155:"));
41891
41785
  if (sameNs) return sameNs.address;
41892
41786
  throw new WalletError(
41893
41787
  "WC_NOT_CONNECTED",
41894
- `No account in WalletConnect session for chain ${chainIdOrKey}. Complete pairing and include this chain, then retry.`
41788
+ `No account in WalletConnect session for chain ${caip2}. Complete pairing and include this chain, then retry.`
41895
41789
  );
41896
41790
  }
41897
- async getAddress(chainId) {
41898
- return this.resolveFromAddress(chainId);
41791
+ async getAddress(chainKey) {
41792
+ return this.resolveFromAddress(caip2Of(chainKey));
41899
41793
  }
41794
+ /** The session's accounts, keyed by twak chain key (the WalletAddress
41795
+ * contract); accounts on chains twak does not support are left out. */
41900
41796
  async getAddresses() {
41901
- return this.getAllSessionAccounts();
41797
+ return this.getAllSessionAccounts().flatMap(({ address, caip2 }) => {
41798
+ const chainKey = chainKeyForCaip2(caip2);
41799
+ return chainKey ? [{ address, chainKey }] : [];
41800
+ });
41902
41801
  }
41903
- async signMessage(chainId, message) {
41802
+ async signMessage(chainKey, message) {
41904
41803
  const session = this.getActiveSession();
41905
41804
  if (!session) throw new WalletError("WC_NOT_CONNECTED", WC_NOT_CONNECTED_MSG);
41906
41805
  const client = await this.ensureClient();
41806
+ const caip2 = caip2Of(chainKey);
41907
41807
  const hexMessage = `0x${Buffer.from(message, "utf8").toString("hex")}`;
41908
41808
  return this.request(client, {
41909
41809
  topic: session.topic,
41910
- chainId,
41810
+ chainId: caip2,
41911
41811
  request: {
41912
41812
  method: "personal_sign",
41913
- params: [hexMessage, this.resolveFromAddress(chainId)]
41813
+ params: [hexMessage, this.resolveFromAddress(caip2)]
41914
41814
  }
41915
41815
  });
41916
41816
  }
41917
- async signTypedData(chainKey, chainId, typedDataJson) {
41817
+ async signTypedData(chainKey, typedDataJson) {
41918
41818
  const session = this.getActiveSession();
41919
41819
  if (!session) throw new WalletError("WC_NOT_CONNECTED", WC_NOT_CONNECTED_MSG);
41920
41820
  const client = await this.ensureClient();
41921
- const caipChainId = chainKey.includes(":") ? chainKey : `eip155:${chainId}`;
41821
+ const caip2 = caip2Of(chainKey);
41922
41822
  return this.request(client, {
41923
41823
  topic: session.topic,
41924
- chainId: caipChainId,
41824
+ chainId: caip2,
41925
41825
  request: {
41926
41826
  method: "eth_signTypedData_v4",
41927
- params: [this.resolveFromAddress(caipChainId), typedDataJson]
41827
+ params: [this.resolveFromAddress(caip2), typedDataJson]
41928
41828
  }
41929
41829
  });
41930
41830
  }
@@ -41934,7 +41834,7 @@ var WalletConnectProvider = class extends WalletProvider {
41934
41834
  */
41935
41835
  async transfer(request) {
41936
41836
  const { chainKey } = request;
41937
- const chain2 = requireChain(chainKey);
41837
+ const chain2 = chainOf(chainKey);
41938
41838
  if (chain2.namespace !== "eip155") {
41939
41839
  throw new TransferError(
41940
41840
  "CHAIN_UNSUPPORTED",
@@ -41948,13 +41848,13 @@ var WalletConnectProvider = class extends WalletProvider {
41948
41848
  const { contractAddress } = parseTokenId(request.assetId);
41949
41849
  if (contractAddress) {
41950
41850
  assertEvmAddress(contractAddress, "tokenAddress");
41951
- const { erc20: erc202 } = await Promise.resolve().then(() => (init_dist4(), dist_exports3));
41851
+ const { erc20: erc202 } = await Promise.resolve().then(() => (init_dist4(), dist_exports2));
41952
41852
  const pending = await this.config.chainClient.contract(erc202).withAddress(contractAddress, chainKey).write.transfer([request.to, atomicAmount], this);
41953
41853
  return { hash: pending.hash, chainKey };
41954
41854
  }
41955
41855
  assertEvmAddress(request.to, "to");
41956
41856
  const hash = await this.sendTransaction({
41957
- chainId: `${chain2.namespace}:${chain2.chainId}`,
41857
+ chainKey,
41958
41858
  to: request.to,
41959
41859
  data: "0x",
41960
41860
  value: "0x" + atomicAmount.toString(16)
@@ -41969,11 +41869,12 @@ var WalletConnectProvider = class extends WalletProvider {
41969
41869
  const session = this.getActiveSession();
41970
41870
  if (!session) throw new WalletError("WC_NOT_CONNECTED", WC_NOT_CONNECTED_MSG);
41971
41871
  const client = await this.ensureClient();
41972
- const namespace = params.chainId.split(":")[0];
41872
+ const caip2 = caip2Of(params.chainKey);
41873
+ const namespace = caip2.split(":")[0];
41973
41874
  if (namespace !== "eip155") {
41974
41875
  throw new WalletError(
41975
41876
  "CHAIN_UNSUPPORTED",
41976
- `WalletConnect signing is only supported for EVM chains (eip155:*). Got: ${params.chainId}`
41877
+ `WalletConnect signing is only supported for EVM chains (eip155:*). Got: ${params.chainKey}`
41977
41878
  );
41978
41879
  }
41979
41880
  let value = params.value || "0x0";
@@ -41982,12 +41883,12 @@ var WalletConnectProvider = class extends WalletProvider {
41982
41883
  }
41983
41884
  return this.request(client, {
41984
41885
  topic: session.topic,
41985
- chainId: params.chainId,
41886
+ chainId: caip2,
41986
41887
  request: {
41987
41888
  method: "eth_sendTransaction",
41988
41889
  params: [
41989
41890
  {
41990
- from: this.resolveFromAddress(params.chainId),
41891
+ from: this.resolveFromAddress(caip2),
41991
41892
  to: params.to,
41992
41893
  data: params.data,
41993
41894
  value,
@@ -41998,9 +41899,6 @@ var WalletConnectProvider = class extends WalletProvider {
41998
41899
  }
41999
41900
  });
42000
41901
  }
42001
- supportsChain(chainId) {
42002
- return chainId.startsWith("eip155:");
42003
- }
42004
41902
  /**
42005
41903
  * Ends a session in two phases:
42006
41904
  * 1. Tell the peer wallet (best-effort, bounded by PEER_NOTIFY_TIMEOUT_MS:
@@ -42026,7 +41924,8 @@ var WalletConnectProvider = class extends WalletProvider {
42026
41924
  * existing session is revoked first: asking to pair again expresses the
42027
41925
  * intent to invalidate the previous one.
42028
41926
  */
42029
- async connect(chains = getDefaultWcChains()) {
41927
+ async connect(chainKeys = getDefaultWcChainKeys()) {
41928
+ const chains = chainKeys.map(caip2Of);
42030
41929
  const client = await this.ensureClient();
42031
41930
  const generation = ++this.pairingGeneration;
42032
41931
  for (const session of client.session.getAll()) {
@@ -42166,8 +42065,8 @@ var WalletConnectProvider = class extends WalletProvider {
42166
42065
  for (const account of accounts) {
42167
42066
  const parts = account.split(":");
42168
42067
  const address = parts[parts.length - 1];
42169
- const chainId = parts.slice(0, -1).join(":");
42170
- result.push({ address, chainId });
42068
+ const caip2 = parts.slice(0, -1).join(":");
42069
+ result.push({ address, caip2 });
42171
42070
  }
42172
42071
  }
42173
42072
  }
@@ -42179,11 +42078,11 @@ var WalletConnectProvider = class extends WalletProvider {
42179
42078
  if (accounts.length > 0) {
42180
42079
  const parts = accounts[0].split(":");
42181
42080
  const address = parts[parts.length - 1];
42182
- const chainId = parts.slice(0, -1).join(":");
42081
+ const chainKey = chainKeyForCaip2(parts.slice(0, -1).join(":")) ?? void 0;
42183
42082
  return {
42184
42083
  topic: session.topic,
42185
42084
  address,
42186
- chainId,
42085
+ chainKey,
42187
42086
  expiry: session.expiry,
42188
42087
  peerName: session.peer?.metadata?.name,
42189
42088
  peerIcon: session.peer?.metadata?.icons?.[0]
@@ -42193,7 +42092,6 @@ var WalletConnectProvider = class extends WalletProvider {
42193
42092
  return {
42194
42093
  topic: session.topic,
42195
42094
  address: "",
42196
- chainId: "",
42197
42095
  expiry: session.expiry,
42198
42096
  peerName: session.peer?.metadata?.name,
42199
42097
  peerIcon: session.peer?.metadata?.icons?.[0]
@@ -42201,8 +42099,8 @@ var WalletConnectProvider = class extends WalletProvider {
42201
42099
  }
42202
42100
  };
42203
42101
  var WC_SUPPORTED_NAMESPACES = /* @__PURE__ */ new Set(["eip155"]);
42204
- function getDefaultWcChains() {
42205
- return Object.values(CHAINS).filter((c3) => WC_SUPPORTED_NAMESPACES.has(c3.namespace)).map((c3) => `${c3.namespace}:${c3.chainId}`);
42102
+ function getDefaultWcChainKeys() {
42103
+ return mainnetChainKeysWhere((chain2) => WC_SUPPORTED_NAMESPACES.has(chain2.namespace));
42206
42104
  }
42207
42105
  function getNamespaceMethods(namespace) {
42208
42106
  switch (namespace) {
@@ -42275,7 +42173,7 @@ function registerInitCommand(program3) {
42275
42173
  if (opts.json) {
42276
42174
  output({ configured: true, source: "cli" }, true);
42277
42175
  } else {
42278
- success("Credentials saved to ~/.twak/credentials.json");
42176
+ success(`Credentials saved to ${path5.join(twakHome(), "credentials.json")}`);
42279
42177
  }
42280
42178
  await tryRegisterWallet();
42281
42179
  if (!opts.json) {
@@ -42295,7 +42193,9 @@ function registerInitCommand(program3) {
42295
42193
  if (opts.json) {
42296
42194
  output({ configured: true, source: "env" }, true);
42297
42195
  } else {
42298
- success("Credentials saved from environment variables to ~/.twak/credentials.json");
42196
+ success(
42197
+ `Credentials saved from environment variables to ${path5.join(twakHome(), "credentials.json")}`
42198
+ );
42299
42199
  }
42300
42200
  await tryRegisterWallet();
42301
42201
  if (!opts.json) {
@@ -42316,7 +42216,7 @@ function registerInitCommand(program3) {
42316
42216
  true
42317
42217
  );
42318
42218
  } else {
42319
- info("Configuration already exists at ~/.twak/");
42219
+ info(`Configuration already exists at ${twakHome()}`);
42320
42220
  info(` Access ID: ${existing.accessId.slice(0, 8)}...`);
42321
42221
  info(` WC Project ID: ${existing.walletConnectProjectId || "not set"}`);
42322
42222
  }
@@ -42355,18 +42255,18 @@ var import_promises2 = require("fs/promises");
42355
42255
  var import_node_crypto = require("crypto");
42356
42256
  var import_promises = require("fs/promises");
42357
42257
  var import_node_path = require("path");
42358
- async function writeAtomic(path7, contents, mode = 420) {
42359
- await (0, import_promises.mkdir)((0, import_node_path.dirname)(path7), { recursive: true });
42258
+ async function writeAtomic(path13, contents, mode = 420) {
42259
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(path13), { recursive: true });
42360
42260
  let effectiveMode = mode;
42361
42261
  try {
42362
- const st4 = await (0, import_promises.stat)(path7);
42262
+ const st4 = await (0, import_promises.stat)(path13);
42363
42263
  effectiveMode = st4.mode & 511;
42364
42264
  } catch {
42365
42265
  }
42366
- const tmpPath = `${path7}.tmp.${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
42266
+ const tmpPath = `${path13}.tmp.${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
42367
42267
  await (0, import_promises.writeFile)(tmpPath, contents, { mode: effectiveMode });
42368
42268
  try {
42369
- await (0, import_promises.rename)(tmpPath, path7);
42269
+ await (0, import_promises.rename)(tmpPath, path13);
42370
42270
  } catch (err) {
42371
42271
  try {
42372
42272
  await (0, import_promises.rm)(tmpPath, { force: true });
@@ -42376,6 +42276,52 @@ async function writeAtomic(path7, contents, mode = 420) {
42376
42276
  }
42377
42277
  }
42378
42278
 
42279
+ // src/setup/harnesses/types.ts
42280
+ init_dist();
42281
+ var TARGET_ENTRY = {
42282
+ command: "twak",
42283
+ args: ["serve"]
42284
+ };
42285
+ var TARGET_ENTRY_WATCH = {
42286
+ command: "twak",
42287
+ args: ["serve", "--watch"]
42288
+ };
42289
+ function targetEntry(watch2, env) {
42290
+ const entry = watch2 ? TARGET_ENTRY_WATCH : TARGET_ENTRY;
42291
+ return env.TWAK_HOME?.trim() ? { ...entry, env: { TWAK_HOME: twakHome(env) } } : entry;
42292
+ }
42293
+ function isTwakHomeOnlyEnv(env) {
42294
+ if (!env || typeof env !== "object" || Array.isArray(env)) return false;
42295
+ const keys2 = Object.keys(env);
42296
+ return keys2.length === 1 && keys2[0] === "TWAK_HOME" && typeof env.TWAK_HOME === "string";
42297
+ }
42298
+ function parseEntry(raw) {
42299
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
42300
+ const entry = raw;
42301
+ if (typeof entry.command !== "string") return null;
42302
+ if (!Array.isArray(entry.args) || !entry.args.every((a3) => typeof a3 === "string")) return null;
42303
+ const parsed = { command: entry.command, args: entry.args };
42304
+ if (isTwakHomeOnlyEnv(entry.env)) parsed.env = { ...entry.env };
42305
+ return parsed;
42306
+ }
42307
+ function isCanonicalEntry(entry) {
42308
+ if (entry === null) return false;
42309
+ if (entry.env !== void 0 && !isTwakHomeOnlyEnv(entry.env)) return false;
42310
+ const shape = { command: entry.command, args: entry.args };
42311
+ return entriesEqual(shape, TARGET_ENTRY) || entriesEqual(shape, TARGET_ENTRY_WATCH);
42312
+ }
42313
+ function envsEqual(a3 = {}, b3 = {}) {
42314
+ const keys2 = Object.keys(a3);
42315
+ return keys2.length === Object.keys(b3).length && keys2.every((k4) => a3[k4] === b3[k4]);
42316
+ }
42317
+ function entriesEqual(a3, b3) {
42318
+ if (a3 === null || b3 === null) return a3 === b3;
42319
+ if (a3.command !== b3.command) return false;
42320
+ if (a3.args.length !== b3.args.length) return false;
42321
+ if (!envsEqual(a3.env, b3.env)) return false;
42322
+ return a3.args.every((arg, i2) => arg === b3.args[i2]);
42323
+ }
42324
+
42379
42325
  // src/setup/harnesses/json-base.ts
42380
42326
  function createJsonMcpHarness(opts) {
42381
42327
  const { name: name2, displayName, configPath: configPath2 } = opts;
@@ -42401,12 +42347,7 @@ function createJsonMcpHarness(opts) {
42401
42347
  configPath: configPath2,
42402
42348
  async getCurrentEntry() {
42403
42349
  const config = await readConfig2();
42404
- const entry = config.mcpServers?.twak;
42405
- if (!entry || typeof entry !== "object") return null;
42406
- if (typeof entry.command !== "string") return null;
42407
- if (!Array.isArray(entry.args) || !entry.args.every((a3) => typeof a3 === "string"))
42408
- return null;
42409
- return { command: entry.command, args: entry.args };
42350
+ return parseEntry(config.mcpServers?.twak);
42410
42351
  },
42411
42352
  async getRawEntry() {
42412
42353
  const config = await readConfig2();
@@ -42506,11 +42447,7 @@ var codex = {
42506
42447
  configPath,
42507
42448
  async getCurrentEntry() {
42508
42449
  const config = await readConfig();
42509
- const entry = config.mcp_servers?.twak;
42510
- if (!entry || typeof entry !== "object") return null;
42511
- if (typeof entry.command !== "string") return null;
42512
- if (!Array.isArray(entry.args) || !entry.args.every((a3) => typeof a3 === "string")) return null;
42513
- return { command: entry.command, args: entry.args };
42450
+ return parseEntry(config.mcp_servers?.twak);
42514
42451
  },
42515
42452
  async getRawEntry() {
42516
42453
  const config = await readConfig();
@@ -42534,34 +42471,13 @@ var codex = {
42534
42471
  };
42535
42472
  var codex_default = codex;
42536
42473
 
42537
- // src/setup/harnesses/types.ts
42538
- var TARGET_ENTRY = {
42539
- command: "twak",
42540
- args: ["serve"]
42541
- };
42542
- var TARGET_ENTRY_WATCH = {
42543
- command: "twak",
42544
- args: ["serve", "--watch"]
42545
- };
42546
- function targetEntry(watch2) {
42547
- return watch2 ? TARGET_ENTRY_WATCH : TARGET_ENTRY;
42548
- }
42549
- function isCanonicalEntry(entry) {
42550
- return entriesEqual(entry, TARGET_ENTRY) || entriesEqual(entry, TARGET_ENTRY_WATCH);
42551
- }
42552
- function entriesEqual(a3, b3) {
42553
- if (a3 === null || b3 === null) return a3 === b3;
42554
- if (a3.command !== b3.command) return false;
42555
- if (a3.args.length !== b3.args.length) return false;
42556
- return a3.args.every((arg, i2) => arg === b3.args[i2]);
42557
- }
42558
-
42559
42474
  // src/setup/harnesses/index.ts
42560
42475
  var ALL_HARNESSES = [claude_code_default, claude_desktop_default, cursor_default, codex_default];
42561
42476
 
42562
42477
  // src/setup/phase-credentials.ts
42563
42478
  var import_prompts = require("@inquirer/prompts");
42564
42479
  init_dist2();
42480
+ var path6 = __toESM(require("path"));
42565
42481
  init_dist();
42566
42482
  var PORTAL_URL = "https://portal.trustwallet.com/dashboard/apps";
42567
42483
  var WC_DASHBOARD_URL = "https://dashboard.walletconnect.com/";
@@ -42632,11 +42548,13 @@ Set one only to use your own project. Get one at: ${WC_DASHBOARD_URL}
42632
42548
  success(`Saved access ID ${accessId.slice(0, 8)} to ${storageLocation(result.keychain)}`);
42633
42549
  }
42634
42550
  function storageLocation(keychain) {
42635
- return keychain ? "~/.twak/credentials.json (0600) + OS keychain (HMAC secret mirror)" : "~/.twak/credentials.json (0600); OS keychain unavailable, secret only on disk";
42551
+ const file = path6.join(twakHome(), "credentials.json");
42552
+ return keychain ? `${file} (0600) + OS keychain (HMAC secret mirror)` : `${file} (0600); OS keychain unavailable, secret only on disk`;
42636
42553
  }
42637
42554
 
42638
42555
  // src/setup/phase-harnesses.ts
42639
42556
  var import_prompts2 = require("@inquirer/prompts");
42557
+ var path7 = __toESM(require("path"));
42640
42558
  init_dist();
42641
42559
 
42642
42560
  // src/setup/skills.ts
@@ -42657,7 +42575,7 @@ function skillsAgentFor(harness) {
42657
42575
  }
42658
42576
  var SKILLS_TIMEOUT_MS = 12e4;
42659
42577
  var defaultSkillsInstaller = {
42660
- install: (agent) => new Promise((resolve2, reject) => {
42578
+ install: (agent) => new Promise((resolve4, reject) => {
42661
42579
  const child = (0, import_node_child_process.spawn)(
42662
42580
  "npx",
42663
42581
  ["-y", "skills", "add", "trustwallet/tw-agent-skills", "-a", agent],
@@ -42681,7 +42599,7 @@ var defaultSkillsInstaller = {
42681
42599
  child.on(
42682
42600
  "exit",
42683
42601
  (code2) => settle(
42684
- () => code2 === 0 ? resolve2() : reject(new Error(`npx skills exited with code ${code2}`))
42602
+ () => code2 === 0 ? resolve4() : reject(new Error(`npx skills exited with code ${code2}`))
42685
42603
  )
42686
42604
  );
42687
42605
  })
@@ -42692,12 +42610,17 @@ function indent(s2, spaces) {
42692
42610
  const prefix = " ".repeat(spaces);
42693
42611
  return s2.split("\n").map((line) => prefix + line).join("\n");
42694
42612
  }
42613
+ function entryHasForeignEnv(raw) {
42614
+ return !!raw && typeof raw === "object" && !Array.isArray(raw) && "env" in raw && !isTwakHomeOnlyEnv(raw.env);
42615
+ }
42695
42616
  function entryHasExtras(raw) {
42696
42617
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
42697
- return Object.keys(raw).some((k4) => k4 !== "command" && k4 !== "args");
42618
+ return entryHasForeignEnv(raw) || Object.keys(raw).some(
42619
+ (k4) => k4 !== "command" && k4 !== "args" && k4 !== "env"
42620
+ );
42698
42621
  }
42699
- function entryHasEnv(raw) {
42700
- return !!raw && typeof raw === "object" && !Array.isArray(raw) && "env" in raw;
42622
+ function entryFolder(entry) {
42623
+ return entry.env?.TWAK_HOME ?? twakHome({});
42701
42624
  }
42702
42625
  var defaultPrompter2 = {
42703
42626
  selectHarnesses: (choices) => (0, import_prompts2.checkbox)({
@@ -42741,7 +42664,7 @@ async function runHarnessesPhase(opts, deps = makeDefaultDeps2()) {
42741
42664
  }
42742
42665
  if (opts.harness) {
42743
42666
  const writer = findHarness(deps.harnesses, opts.harness);
42744
- const entry = targetEntry(await deps.prompter.confirmWatch());
42667
+ const entry = targetEntry(await deps.prompter.confirmWatch(), deps.env);
42745
42668
  await processHarness(writer, deps, true, entry);
42746
42669
  return;
42747
42670
  }
@@ -42754,7 +42677,7 @@ async function runMultiSelect(deps) {
42754
42677
  info("No harnesses selected. Re-run `twak setup --harness <name>` later to wire one.");
42755
42678
  return;
42756
42679
  }
42757
- const entry = targetEntry(await deps.prompter.confirmWatch());
42680
+ const entry = targetEntry(await deps.prompter.confirmWatch(), deps.env);
42758
42681
  let wrote = 0;
42759
42682
  let removed = 0;
42760
42683
  for (const name2 of selected) {
@@ -42797,13 +42720,18 @@ async function processHarness(writer, deps, verbose, entry) {
42797
42720
  }
42798
42721
  if (current !== null && isCanonicalEntry(current) && !entryHasExtras(raw)) {
42799
42722
  info(`Updating ${writer.displayName} \u2192 ${writer.configPath()}`);
42723
+ if (entryFolder(current) !== entryFolder(entry)) {
42724
+ warn(
42725
+ `${writer.displayName}: its twak server will use ${entryFolder(entry)} instead of ${entryFolder(current)}; a wallet or credentials in the old folder are not moved.`
42726
+ );
42727
+ }
42800
42728
  await writer.writeEntry(entry);
42801
42729
  await runSkillsInstall(writer.name, deps);
42802
42730
  return "wrote";
42803
42731
  }
42804
- if (entryHasEnv(raw)) {
42732
+ if (entryHasForeignEnv(raw)) {
42805
42733
  warn(
42806
- `${writer.displayName} has an existing twak entry with an \`env\` block. Choosing Update will drop it; if it contained credentials, the harness will fall back to ~/.twak/credentials.json (run \`twak setup --reconfigure-creds\` to refresh) before restarting.`
42734
+ `${writer.displayName} has an existing twak entry with an \`env\` block. Choosing Update will drop it; if it contained credentials, the harness will fall back to ${path7.join(twakHome(), "credentials.json")} (run \`twak setup --reconfigure-creds\` to refresh) before restarting.`
42807
42735
  );
42808
42736
  }
42809
42737
  const action = await deps.prompter.resolveConflict(writer.displayName, raw, entry);
@@ -42857,7 +42785,7 @@ async function runNonInteractive2(opts, deps) {
42857
42785
  );
42858
42786
  }
42859
42787
  const forceOverwrite = deps.env.TWAK_SETUP_FORCE_HARNESS_OVERWRITE === "1";
42860
- const entry = targetEntry(deps.env.TWAK_SETUP_WATCH === "1");
42788
+ const entry = targetEntry(deps.env.TWAK_SETUP_WATCH === "1", deps.env);
42861
42789
  for (const name2 of names) {
42862
42790
  const writer = findHarness(deps.harnesses, name2);
42863
42791
  let current;
@@ -42882,9 +42810,9 @@ async function runNonInteractive2(opts, deps) {
42882
42810
  continue;
42883
42811
  }
42884
42812
  if (forceOverwrite) {
42885
- if (entryHasEnv(raw)) {
42813
+ if (entryHasForeignEnv(raw)) {
42886
42814
  warn(
42887
- `${writer.displayName}: existing twak entry has an \`env\` block \u2014 dropping it because TWAK_SETUP_FORCE_HARNESS_OVERWRITE=1. If it held credentials, run \`twak setup --reconfigure-creds\` so they live in ~/.twak/credentials.json.`
42815
+ `${writer.displayName}: existing twak entry has an \`env\` block \u2014 dropping it because TWAK_SETUP_FORCE_HARNESS_OVERWRITE=1. If it held credentials, run \`twak setup --reconfigure-creds\` so they live in ${path7.join(twakHome(), "credentials.json")}.`
42888
42816
  );
42889
42817
  } else {
42890
42818
  warn(
@@ -42915,6 +42843,7 @@ function findHarness(harnesses, name2) {
42915
42843
  var import_node_crypto2 = require("crypto");
42916
42844
  var import_prompts3 = require("@inquirer/prompts");
42917
42845
  init_dist2();
42846
+ var path8 = __toESM(require("path"));
42918
42847
  init_dist();
42919
42848
 
42920
42849
  // src/password.ts
@@ -42986,7 +42915,7 @@ function makeDefaultDeps3() {
42986
42915
  async create(pw) {
42987
42916
  await ensureTrustSDK();
42988
42917
  const provider = await AgentWalletProvider.create(pw);
42989
- const primaryAddress = await provider.getAddress("ethereum") ?? "<unknown>";
42918
+ const primaryAddress = await provider.getAddress(knownChainKey("ethereum")) ?? "<unknown>";
42990
42919
  return { primaryAddress };
42991
42920
  }
42992
42921
  },
@@ -43041,7 +42970,7 @@ async function preflightWalletCreate(deps) {
43041
42970
  if (await deps.storage.exists()) {
43042
42971
  throw new WalletError(
43043
42972
  "WALLET_EXISTS",
43044
- "Wallet already exists. Back up ~/.twak/wallet.json, then delete it to create a new one."
42973
+ `Wallet already exists. Back up ${path8.join(twakHome(), "wallet.json")}, then delete it to create a new one.`
43045
42974
  );
43046
42975
  }
43047
42976
  if (!deps.keychain.isAvailable()) {
@@ -43206,8 +43135,17 @@ function registerAuthCommand(program3) {
43206
43135
 
43207
43136
  // src/commands/wallet.ts
43208
43137
  var fs6 = __toESM(require("fs"));
43138
+ var path10 = __toESM(require("path"));
43209
43139
  init_dist2();
43210
43140
  var import_chalk6 = __toESM(require_source());
43141
+
43142
+ // src/chain-options.ts
43143
+ init_dist();
43144
+ function parseChainList(value) {
43145
+ return value.split(",").map((s2) => s2.trim()).filter(Boolean).map((s2) => resolveChain(s2));
43146
+ }
43147
+
43148
+ // src/commands/wallet.ts
43211
43149
  init_dist();
43212
43150
 
43213
43151
  // ../operations/dist/index.mjs
@@ -43267,9 +43205,9 @@ var TransferExecutor = class {
43267
43205
  }
43268
43206
  async run(params) {
43269
43207
  const { wallet, swapClient, onInfo, onWarn } = this.deps;
43270
- const chainKey = resolveChain(params.chain);
43208
+ const chainKey = params.chain;
43271
43209
  const contractAddress = params.tokenAddress && params.tokenAddress.toLowerCase() !== NATIVE_TOKEN_ADDRESS.toLowerCase() ? params.tokenAddress : void 0;
43272
- const { assetId } = resolveAsset(chainKey, contractAddress);
43210
+ const assetId = assetIdOf(chainKey, contractAddress);
43273
43211
  const tokenInfo = resolveToken(assetId, chainKey);
43274
43212
  if (!tokenInfo) {
43275
43213
  throw new TransferError(
@@ -43455,10 +43393,9 @@ function getMemState(state, auto) {
43455
43393
  }
43456
43394
  function limitOrderAssetId(auto) {
43457
43395
  const tokenInfo = resolveToken(auto.toToken, auto.chain);
43458
- const chain2 = getChainById(auto.chain);
43459
- if (!tokenInfo || !chain2) return null;
43396
+ if (!tokenInfo) return null;
43460
43397
  const isNative = tokenInfo.address === NATIVE_TOKEN_ADDRESS || tokenInfo.address === SOLANA_NATIVE_ADDRESS || !tokenInfo.address;
43461
- return formatTokenId(chain2.coinId, isNative ? void 0 : tokenInfo.address);
43398
+ return formatTokenId(coinIdOf(auto.chain), isNative ? void 0 : tokenInfo.address);
43462
43399
  }
43463
43400
  function automationLabel(type) {
43464
43401
  return type === "dca" ? "DCA" : "Limit order";
@@ -43503,11 +43440,6 @@ async function processAutomation(auto, ctx) {
43503
43440
  ctx.result.automations.skipped++;
43504
43441
  return;
43505
43442
  }
43506
- if (!getChainById(auto.chain)) {
43507
- ctx.log("warn", `Automation ${auto.id.slice(0, 8)} skipped \u2014 unknown chain "${auto.chain}"`);
43508
- ctx.result.automations.skipped++;
43509
- return;
43510
- }
43511
43443
  if (auto.type === "dca") {
43512
43444
  const effectiveLastRunAt = memState ? memState.lastRunAt : auto.lastRunAt ?? null;
43513
43445
  const lastRun = effectiveLastRunAt ? new Date(effectiveLastRunAt).getTime() : 0;
@@ -43593,6 +43525,13 @@ async function runWatchTick(deps) {
43593
43525
  const activeAlerts = deps.alertStore ? await deps.alertStore.getActive() : [];
43594
43526
  const automations = await deps.automationStore.getActive();
43595
43527
  result.alerts.checked = activeAlerts.length;
43528
+ for (const invalid of deps.alertStore ? await deps.alertStore.listInvalid() : []) {
43529
+ log("warn", `Alert ${invalid.id.slice(0, 8)} not monitored: ${invalid.error}`);
43530
+ }
43531
+ for (const invalid of await deps.automationStore.listInvalid()) {
43532
+ log("warn", `Automation ${invalid.id.slice(0, 8)} skipped: ${invalid.error}`);
43533
+ result.automations.skipped++;
43534
+ }
43596
43535
  const assetIds = new Set(activeAlerts.map((a3) => a3.tokenId));
43597
43536
  for (const auto of automations) {
43598
43537
  if (auto.type !== "limit") continue;
@@ -43676,16 +43615,15 @@ var Watcher = class {
43676
43615
  };
43677
43616
  function resolveAssets(addresses, chainKeys, { includeTokens = true } = {}) {
43678
43617
  const entries = chainKeys.flatMap((chainKey) => {
43679
- const chain2 = getChainById(chainKey);
43680
- const addrEntry = addresses.find((a3) => a3.chainId === chainKey);
43681
- if (!chain2 || !addrEntry) return [];
43682
- return [{ chainKey, chain: chain2, address: addrEntry.address }];
43618
+ const addrEntry = addresses.find((a3) => a3.chainKey === chainKey);
43619
+ if (!addrEntry) return [];
43620
+ return [{ chainKey, chain: chainOf(chainKey), address: addrEntry.address }];
43683
43621
  });
43684
43622
  const natives = entries.map(({ chainKey, chain: chain2, address }) => ({
43685
43623
  chainKey,
43686
43624
  chain: chain2,
43687
43625
  token: void 0,
43688
- assetId: `c${chain2.coinId}`,
43626
+ assetId: assetIdOf(chainKey),
43689
43627
  address
43690
43628
  }));
43691
43629
  if (!includeTokens) return natives;
@@ -43700,7 +43638,7 @@ function resolveAssets(addresses, chainKeys, { includeTokens = true } = {}) {
43700
43638
  chainKey,
43701
43639
  chain: chain2,
43702
43640
  token: { ...resolved, symbol: sym, decimals: knownTokens[sym].decimals },
43703
- assetId: `c${chain2.coinId}_t${resolved.address}`,
43641
+ assetId: assetIdOf(chainKey, resolved.address),
43704
43642
  address
43705
43643
  }
43706
43644
  ];
@@ -43732,9 +43670,9 @@ function decodeAmount(amounts, decimals) {
43732
43670
  async function buildPortfolio(httpClient, { addresses, chains }) {
43733
43671
  let chainKeys;
43734
43672
  if (chains === void 0) {
43735
- chainKeys = Object.keys(CHAINS);
43673
+ chainKeys = mainnetChainKeys();
43736
43674
  } else {
43737
- chainKeys = [...new Set(chains.map((s2) => s2.trim()).filter(Boolean))];
43675
+ chainKeys = [...new Set(chains)];
43738
43676
  if (chainKeys.length === 0) {
43739
43677
  throw new WalletError("VALIDATION_ERROR", "chains must include at least one chain key");
43740
43678
  }
@@ -43823,12 +43761,12 @@ function box(content) {
43823
43761
  }
43824
43762
 
43825
43763
  // src/walletconnect-config.ts
43826
- var path4 = __toESM(require("path"));
43764
+ var path9 = __toESM(require("path"));
43827
43765
  init_dist();
43828
43766
  init_dist2();
43829
43767
  var RESTORE_TIMEOUT_MS = 1e4;
43830
43768
  function wcStoragePath() {
43831
- return path4.join(new FileStore().getDataDir(), "walletconnect.json");
43769
+ return path9.join(new FileStore().getDataDir(), "walletconnect.json");
43832
43770
  }
43833
43771
  var DEFAULT_WC_PROJECT_ID = "a863b78b54c4222603c8db4d6d880172";
43834
43772
  async function resolveWcProjectId(flag) {
@@ -43902,10 +43840,17 @@ async function getWalletConnectStatus(projectIdFlag) {
43902
43840
  }
43903
43841
  function registerWalletCommand(program3) {
43904
43842
  const wallet = program3.command("wallet").description("Manage agent wallet");
43905
- 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) => {
43843
+ wallet.command("create").description("Create a new agent wallet").option("--password <password>", "Password to encrypt the wallet (or set TWAK_WALLET_PASSWORD)").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) => {
43906
43844
  try {
43845
+ const password3 = opts.password || process.env.TWAK_WALLET_PASSWORD;
43846
+ if (!password3) {
43847
+ throw new WalletError(
43848
+ "VALIDATION_ERROR",
43849
+ "No wallet password: provide --password or set TWAK_WALLET_PASSWORD."
43850
+ );
43851
+ }
43907
43852
  if (!opts.skipPasswordCheck) {
43908
- const weakness = getPasswordWeaknesses(opts.password);
43853
+ const weakness = getPasswordWeaknesses(password3);
43909
43854
  if (weakness) {
43910
43855
  throw new WalletError("VALIDATION_ERROR", `Password too weak: must ${weakness}.`);
43911
43856
  }
@@ -43915,15 +43860,15 @@ function registerWalletCommand(program3) {
43915
43860
  if (await store.exists()) {
43916
43861
  throw new WalletError(
43917
43862
  "WALLET_EXISTS",
43918
- "Wallet already exists. Back up ~/.twak/wallet.json, then delete it to create a new one."
43863
+ `Wallet already exists. Back up ${path10.join(twakHome(), "wallet.json")}, then delete it to create a new one.`
43919
43864
  );
43920
43865
  }
43921
- const provider = await AgentWalletProvider.create(opts.password);
43866
+ const provider = await AgentWalletProvider.create(password3);
43922
43867
  const addresses = await provider.getAddresses();
43923
43868
  if (opts.keychain !== false) {
43924
43869
  const kc2 = new KeychainManager();
43925
43870
  if (kc2.isAvailable()) {
43926
- await kc2.saveWalletPassword(opts.password);
43871
+ await kc2.saveWalletPassword(password3);
43927
43872
  if (!opts.json) info("Password saved to OS keychain (use --no-keychain to skip)");
43928
43873
  }
43929
43874
  }
@@ -43936,7 +43881,10 @@ function registerWalletCommand(program3) {
43936
43881
  if (!opts.json) warn("Backend registration failed (holdings may be limited)");
43937
43882
  }
43938
43883
  if (opts.json) {
43939
- output({ addresses }, true);
43884
+ output(
43885
+ { addresses: addresses.map((a3) => ({ address: a3.address, chain: a3.chainKey })) },
43886
+ true
43887
+ );
43940
43888
  } else {
43941
43889
  info(`Generated addresses for ${addresses.length} chains`);
43942
43890
  }
@@ -43950,18 +43898,16 @@ function registerWalletCommand(program3) {
43950
43898
  "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
43951
43899
  ).option("--json", "JSON output").action(async (opts) => {
43952
43900
  try {
43953
- if (!getChainById(opts.chain)) {
43954
- throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
43955
- }
43901
+ const chainKey = resolveChain(opts.chain);
43956
43902
  await ensureTrustSDK();
43957
43903
  const password3 = await resolvePassword(opts);
43958
43904
  const provider = await AgentWalletProvider.fromStorage(password3);
43959
- const address = await provider.getAddress(opts.chain);
43905
+ const address = await provider.getAddress(chainKey);
43960
43906
  if (opts.json) {
43961
- output({ chain: opts.chain, address }, true);
43907
+ output({ chain: chainKey, address }, true);
43962
43908
  } else {
43963
43909
  const qr3 = getQRString(address);
43964
- const content = `${import_chalk6.default.dim("Chain")} ${import_chalk6.default.bold(opts.chain)}
43910
+ const content = `${import_chalk6.default.dim("Chain")} ${import_chalk6.default.bold(chainKey)}
43965
43911
  ${import_chalk6.default.dim("Address")} ${import_chalk6.default.green(address)}
43966
43912
 
43967
43913
  ${qr3}`;
@@ -43982,12 +43928,15 @@ ${qr3}`;
43982
43928
  const provider = await AgentWalletProvider.fromStorage(password3);
43983
43929
  const addresses = await provider.getAddresses();
43984
43930
  if (opts.json) {
43985
- output({ addresses }, true);
43931
+ output(
43932
+ { addresses: addresses.map((a3) => ({ address: a3.address, chain: a3.chainKey })) },
43933
+ true
43934
+ );
43986
43935
  } else {
43987
43936
  const grouped = /* @__PURE__ */ new Map();
43988
43937
  for (const addr of addresses) {
43989
43938
  const chains = grouped.get(addr.address) ?? [];
43990
- chains.push(addr.chainId);
43939
+ chains.push(addr.chainKey);
43991
43940
  grouped.set(addr.address, chains);
43992
43941
  }
43993
43942
  for (const [address, chains] of grouped) {
@@ -44035,21 +43984,15 @@ ${qr3}`;
44035
43984
  const password3 = await resolvePassword(opts);
44036
43985
  const provider = await AgentWalletProvider.fromStorage(password3);
44037
43986
  const httpClient = await getClient();
44038
- if (!opts.all) {
44039
- const chain2 = getChainById(opts.chain);
44040
- if (!chain2) {
44041
- throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
44042
- }
44043
- }
43987
+ const requestedChains = opts.all ? mainnetChainKeys() : [resolveChain(opts.chain)];
44044
43988
  const allAddresses = await provider.getAddresses();
44045
- const requestedChains = opts.all ? Object.keys(CHAINS) : [opts.chain];
44046
43989
  const assets = resolveAssets(allAddresses, requestedChains, {
44047
43990
  includeTokens: opts.tokens !== false
44048
43991
  });
44049
43992
  if (!opts.all && assets.length === 0) {
44050
43993
  throw new WalletError(
44051
43994
  "CHAIN_UNSUPPORTED",
44052
- `Wallet does not have an address for chain: ${opts.chain}`
43995
+ `Wallet does not have an address for chain: ${requestedChains[0]}`
44053
43996
  );
44054
43997
  }
44055
43998
  const joined = await fetchAssetBalances(httpClient, assets);
@@ -44184,14 +44127,14 @@ ${qr3}`;
44184
44127
  "WalletConnect project ID override (default: Trust Wallet project; or WALLETCONNECT_PROJECT_ID / twak init --wc-project-id)"
44185
44128
  ).option(
44186
44129
  "--chains <list>",
44187
- "Comma-separated CAIP-2 chain IDs (default: all supported EVM chains)"
44130
+ "Comma-separated chains: keys, aliases or CAIP-2 IDs (default: all supported EVM chains)"
44188
44131
  ).option("--timeout <seconds>", "Connection timeout in seconds", "300").option("--json", "JSON output").action(async (opts) => {
44189
44132
  try {
44190
44133
  const projectId = await resolveWcProjectId(opts.projectId);
44191
44134
  const provider = createWalletConnectProvider(projectId, new ChainClient());
44192
- const chains = opts.chains ? opts.chains.split(",").map((s2) => s2.trim()).filter(Boolean) : getDefaultWcChains();
44135
+ const chainKeys = opts.chains ? parseChainList(opts.chains) : void 0;
44193
44136
  info("Connecting via WalletConnect...");
44194
- const result = await provider.connect(chains);
44137
+ const result = await provider.connect(chainKeys);
44195
44138
  const qr3 = getQRString(result.uri);
44196
44139
  if (qr3) {
44197
44140
  console.log(qr3);
@@ -44206,7 +44149,7 @@ ${qr3}`;
44206
44149
  {
44207
44150
  connected: true,
44208
44151
  address: session.address,
44209
- chainId: session.chainId,
44152
+ chain: session.chainKey,
44210
44153
  peer: session.peerName
44211
44154
  },
44212
44155
  true
@@ -44214,7 +44157,7 @@ ${qr3}`;
44214
44157
  } else {
44215
44158
  success(`Connected to ${session.peerName || "wallet"}`);
44216
44159
  info(` Address: ${session.address}`);
44217
- info(` Chain: ${session.chainId}`);
44160
+ if (session.chainKey) info(` Chain: ${session.chainKey}`);
44218
44161
  }
44219
44162
  } catch (err) {
44220
44163
  handleCommandError(err, opts.json, "WalletConnect failed");
@@ -44252,7 +44195,7 @@ ${qr3}`;
44252
44195
  const exists = await store.exists();
44253
44196
  const kc2 = new KeychainManager();
44254
44197
  const keychainHasPassword = kc2.isAvailable() ? !!await kc2.getWalletPassword() : false;
44255
- const totalChains = Object.keys(CHAINS).length;
44198
+ const totalChains = mainnetChainKeys().length;
44256
44199
  let createdAt;
44257
44200
  let addressCount;
44258
44201
  if (exists) {
@@ -44305,7 +44248,7 @@ ${qr3}`;
44305
44248
  const provider = await AgentWalletProvider.fromStorage(password3);
44306
44249
  const httpClient = await getClient();
44307
44250
  const addresses = await provider.getAddresses();
44308
- const chains = opts.chains !== void 0 ? opts.chains.split(",") : void 0;
44251
+ const chains = opts.chains !== void 0 ? parseChainList(opts.chains) : void 0;
44309
44252
  const { rows, totalUsd } = await buildPortfolio(httpClient, { addresses, chains });
44310
44253
  if (opts.json) {
44311
44254
  output(rows, true);
@@ -44331,19 +44274,17 @@ ${qr3}`;
44331
44274
  "Wallet password (falls back to keychain / TWAK_WALLET_PASSWORD)"
44332
44275
  ).option("--json", "JSON output").action(async (opts) => {
44333
44276
  try {
44334
- const chain2 = getChainById(opts.chain);
44335
- if (!chain2) {
44336
- throw new WalletError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
44337
- }
44277
+ const chainKey = resolveChain(opts.chain);
44278
+ const chain2 = chainOf(chainKey);
44338
44279
  await ensureTrustSDK();
44339
44280
  const password3 = await resolvePassword(opts);
44340
44281
  const provider = await AgentWalletProvider.fromStorage(password3);
44341
- const address = await provider.getAddress(opts.chain);
44342
- const rawSignature = await provider.signMessage(opts.chain, opts.message);
44282
+ const address = await provider.getAddress(chainKey);
44283
+ const rawSignature = await provider.signMessage(chainKey, opts.message);
44343
44284
  const signature = chain2.isEVM && !rawSignature.startsWith("0x") ? `0x${rawSignature}` : rawSignature;
44344
44285
  output(
44345
44286
  {
44346
- chain: opts.chain,
44287
+ chain: chainKey,
44347
44288
  address,
44348
44289
  message: opts.message,
44349
44290
  signature,
@@ -44380,20 +44321,23 @@ init_dist();
44380
44321
  init_dist3();
44381
44322
  init_dist();
44382
44323
  init_dist4();
44324
+ init_dist();
44383
44325
  var SwapClient = class {
44384
44326
  constructor(httpClient) {
44385
44327
  this.httpClient = httpClient;
44386
44328
  }
44387
44329
  async getQuote(params) {
44388
- const fromChain = getChainById(params.fromChain);
44389
- const toChain = getChainById(params.toChain);
44390
- if (!fromChain)
44391
- throw new TwakError(`Unsupported source chain: ${params.fromChain}`, "CHAIN_UNSUPPORTED");
44392
- if (!toChain)
44393
- throw new TwakError(`Unsupported destination chain: ${params.toChain}`, "CHAIN_UNSUPPORTED");
44330
+ for (const chainKey of [params.fromChain, params.toChain]) {
44331
+ if (isTestnet(chainKey)) {
44332
+ throw new TwakError(
44333
+ `Swaps are not supported on testnet chains (${chainKey})`,
44334
+ "CHAIN_UNSUPPORTED"
44335
+ );
44336
+ }
44337
+ }
44394
44338
  const domains = await getAmberDomainsByCoinId();
44395
- const fromDomain = domains.get(fromChain.coinId) ?? getChainDomainId(params.fromChain);
44396
- const toDomain = domains.get(toChain.coinId) ?? getChainDomainId(params.toChain);
44339
+ const fromDomain = domains.get(coinIdOf(params.fromChain)) ?? backendIdOf(params.fromChain);
44340
+ const toDomain = domains.get(coinIdOf(params.toChain)) ?? backendIdOf(params.toChain);
44397
44341
  const payload = {
44398
44342
  fromAsset: params.fromToken,
44399
44343
  fromAddress: params.walletAddress,
@@ -44440,7 +44384,7 @@ var SwapClient = class {
44440
44384
  return transactions;
44441
44385
  }
44442
44386
  async searchTokens(params) {
44443
- const coinIds = params.networks ? params.networks : (params.chains || Object.keys(CHAINS)).map((c3) => getChainById(c3)?.coinId).filter((id) => id != null).join(",");
44387
+ const coinIds = params.networks ? params.networks : (params.chains ?? mainnetChainKeys()).map(coinIdOf).join(",");
44444
44388
  const queryParams = new URLSearchParams({
44445
44389
  networks: coinIds,
44446
44390
  exactQuery: params.query,
@@ -44460,18 +44404,16 @@ var SwapClient = class {
44460
44404
  name: doc.name,
44461
44405
  symbol: doc.symbol,
44462
44406
  address: this.extractAddressFromAssetId(doc.asset_id),
44463
- chain: this.getChainFromAssetId(doc.asset_id),
44407
+ chain: this.chainOfAssetId(doc.asset_id),
44464
44408
  decimals: doc.decimals,
44465
44409
  logoUrl: doc.icon_url,
44466
44410
  priceUsd: doc.price?.price,
44467
44411
  priceChange24h: doc.price?.percent_change_24h
44468
44412
  }));
44469
44413
  }
44470
- async getTokenPrice(chainId, tokenAddress) {
44471
- const chain2 = getChainById(chainId);
44472
- if (!chain2) return null;
44414
+ async getTokenPrice(chainKey, tokenAddress) {
44473
44415
  const isNative = tokenAddress === NATIVE_TOKEN_ADDRESS || tokenAddress === SOLANA_NATIVE_ADDRESS || !tokenAddress;
44474
- const assetId = formatTokenId(chain2.coinId, isNative ? void 0 : tokenAddress);
44416
+ const assetId = formatTokenId(coinIdOf(chainKey), isNative ? void 0 : tokenAddress);
44475
44417
  try {
44476
44418
  const response = await this.httpClient.market("POST", "/v2/market/tickers", {
44477
44419
  currency: "USD",
@@ -44533,15 +44475,25 @@ var SwapClient = class {
44533
44475
  return "";
44534
44476
  }
44535
44477
  }
44536
- getChainFromAssetId(assetId) {
44478
+ chainOfAssetId(assetId) {
44537
44479
  try {
44538
- const { coinId } = parseTokenId(assetId);
44539
- return coinTypeToChainKey(coinId) || "unknown";
44480
+ return tokenIdToChain(assetId);
44540
44481
  } catch {
44541
- return "unknown";
44482
+ return void 0;
44542
44483
  }
44543
44484
  }
44544
44485
  };
44486
+ var SIGNABLE_SOURCE_NAMESPACES = ["eip155", "solana"];
44487
+ function swapSourceUnsupportedReason(chainKey) {
44488
+ if (isTestnet(chainKey)) {
44489
+ return `Swaps are not supported on testnet chains (${chainKey}).`;
44490
+ }
44491
+ const chain2 = chainOf(chainKey);
44492
+ if (!SIGNABLE_SOURCE_NAMESPACES.includes(chain2.namespace)) {
44493
+ return `Swaps cannot start on ${chain2.name}: twak signs swap transactions on EVM chains and Solana only.`;
44494
+ }
44495
+ return void 0;
44496
+ }
44545
44497
  function classifySwapError(message) {
44546
44498
  const m2 = message.toLowerCase();
44547
44499
  if (m2.includes("insufficient funds") || m2.includes("exceeds balance"))
@@ -44558,6 +44510,8 @@ var SwapExecutor = class {
44558
44510
  this.options.onStatus?.(msg);
44559
44511
  }
44560
44512
  async execute(params) {
44513
+ const unsupported = swapSourceUnsupportedReason(params.fromChain);
44514
+ if (unsupported) throw new TwakError(unsupported, "CHAIN_UNSUPPORTED");
44561
44515
  const address = await this.walletProvider.getAddress(params.fromChain);
44562
44516
  const fromTokenInfo = resolveToken(params.fromToken, params.fromChain);
44563
44517
  if (!fromTokenInfo)
@@ -44612,7 +44566,7 @@ var SwapExecutor = class {
44612
44566
  this.log(
44613
44567
  `Swapping ${inputAmt} ${firstStep.from.asset.metadata.symbol} -> ${outputAmt} ${lastStep.to.asset.metadata.symbol} via ${route.steps.map((s2) => s2.provider.name).join(" -> ")}`
44614
44568
  );
44615
- const chainConfig = getChainById(params.fromChain);
44569
+ const chainConfig = chainOf(params.fromChain);
44616
44570
  const transactions = await withRetry(() => this.swapClient.getSwapTransactions(route));
44617
44571
  let approvalHash;
44618
44572
  try {
@@ -44681,7 +44635,7 @@ var SwapExecutor = class {
44681
44635
  (t) => t.transaction.type === "approval" || t.transaction.type === "revokeApproval"
44682
44636
  );
44683
44637
  const stepApproval = route.steps[0].approval;
44684
- if (hasApprovalTx || !chainConfig?.isEVM || !stepApproval?.operatorAddress) return void 0;
44638
+ if (hasApprovalTx || !chainConfig.isEVM || !stepApproval?.operatorAddress) return void 0;
44685
44639
  const fromAssetAddr = route.steps[0].from.asset.address;
44686
44640
  if (!fromAssetAddr || fromAssetAddr.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase())
44687
44641
  return void 0;
@@ -44695,15 +44649,15 @@ var SwapExecutor = class {
44695
44649
  return approveResult.hash;
44696
44650
  }
44697
44651
  async sendTransaction(txData, chainConfig, fromChain) {
44698
- if (chainConfig?.namespace === "solana" && txData.transaction.solanaTx) {
44652
+ if (chainConfig.namespace === "solana" && txData.transaction.solanaTx) {
44699
44653
  return this.walletProvider.sendTransaction({
44700
- chainId: `solana:${chainConfig.chainId}`,
44654
+ chainKey: fromChain,
44701
44655
  to: "",
44702
44656
  data: txData.transaction.solanaTx.serializedMessage
44703
44657
  });
44704
44658
  } else if (txData.transaction.evmTx) {
44705
44659
  return this.walletProvider.sendTransaction({
44706
- chainId: `eip155:${chainConfig?.chainId || "1"}`,
44660
+ chainKey: fromChain,
44707
44661
  to: txData.transaction.evmTx.to,
44708
44662
  data: txData.transaction.evmTx.data,
44709
44663
  value: txData.transaction.evmTx.value || "0x0"
@@ -44822,7 +44776,7 @@ function registerTransferCommand(program3) {
44822
44776
  } catch {
44823
44777
  throw new TransferError("VALIDATION_ERROR", `Invalid token ID: ${opts.token}`);
44824
44778
  }
44825
- const resolvedKey = coinTypeToChainKey(coinId);
44779
+ const resolvedKey = mainnetChainKeyForCoinId(coinId);
44826
44780
  if (!resolvedKey) {
44827
44781
  throw new TransferError(
44828
44782
  "CHAIN_UNSUPPORTED",
@@ -44938,7 +44892,7 @@ function registerSwapCommand(program3) {
44938
44892
  const detectChain = (token, fallback) => {
44939
44893
  const m2 = token.match(/^c(\d+)/i);
44940
44894
  if (m2) {
44941
- const key = coinTypeToChainKey(parseInt(m2[1]));
44895
+ const key = mainnetChainKeyForCoinId(parseInt(m2[1], 10));
44942
44896
  if (!key)
44943
44897
  throw new SwapError(
44944
44898
  "CHAIN_UNSUPPORTED",
@@ -44946,15 +44900,13 @@ function registerSwapCommand(program3) {
44946
44900
  );
44947
44901
  return key;
44948
44902
  }
44949
- return fallback;
44903
+ return resolveChain(fallback);
44950
44904
  };
44951
44905
  const fromChain = detectChain(from8, opts.chain);
44952
44906
  const toChain = opts.toChain ? detectChain(to3, opts.toChain) : fromChain;
44953
- if (!getChainById(fromChain)) {
44954
- throw new SwapError("CHAIN_UNSUPPORTED", `Unknown chain: ${fromChain}`);
44955
- }
44956
- if (!getChainById(toChain)) {
44957
- throw new SwapError("CHAIN_UNSUPPORTED", `Unknown chain: ${toChain}`);
44907
+ const unsupported = swapSourceUnsupportedReason(fromChain);
44908
+ if (unsupported && !opts.quoteOnly) {
44909
+ throw new SwapError("CHAIN_UNSUPPORTED", unsupported);
44958
44910
  }
44959
44911
  const fromInfo = resolveToken(from8, fromChain);
44960
44912
  if (!fromInfo) {
@@ -45001,7 +44953,7 @@ function registerSwapCommand(program3) {
45001
44953
  }
45002
44954
  const parsedAmount = parseAmount(resolvedAmount, fromDecimals);
45003
44955
  const needsWallet = !opts.quoteOnly;
45004
- let walletAddress = getChainById(fromChain)?.sampleAccount || "0x0000000000000000000000000000000000000000";
44956
+ let walletAddress = chainOf(fromChain).sampleAccount;
45005
44957
  let provider = null;
45006
44958
  let destinationAddress;
45007
44959
  if (needsWallet) {
@@ -45115,7 +45067,7 @@ function resolveErc20WriteTarget(opts, nativeMsg) {
45115
45067
  if (!contractAddress) {
45116
45068
  throw new Erc20Error("NOT_ERC20", nativeMsg);
45117
45069
  }
45118
- const chainKey = coinTypeToChainKey(coinId);
45070
+ const chainKey = mainnetChainKeyForCoinId(coinId);
45119
45071
  if (!chainKey) {
45120
45072
  throw new Erc20Error("CHAIN_UNSUPPORTED", `Unsupported coin type in asset ID: ${opts.token}`);
45121
45073
  }
@@ -45255,7 +45207,7 @@ function registerErc20Command(program3) {
45255
45207
  );
45256
45208
  }
45257
45209
  try {
45258
- const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
45210
+ const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports));
45259
45211
  const wc3 = getWalletCore2();
45260
45212
  const ct5 = getCoinType2(coinId);
45261
45213
  if (ct5 && !wc3.CoinTypeExt.validate(ct5, parsed)) {
@@ -45267,7 +45219,7 @@ function registerErc20Command(program3) {
45267
45219
  } catch (err) {
45268
45220
  if (err instanceof CommandError) throw err;
45269
45221
  }
45270
- const k4 = coinTypeToChainKey(coinId);
45222
+ const k4 = mainnetChainKeyForCoinId(coinId);
45271
45223
  if (!k4) {
45272
45224
  throw new Erc20Error(
45273
45225
  "CHAIN_UNSUPPORTED",
@@ -45331,10 +45283,13 @@ function registerErc8004Command(program3) {
45331
45283
  await ensureTrustSDK();
45332
45284
  const password3 = await resolvePassword(opts);
45333
45285
  const provider = await AgentWalletProvider.fromStorage(password3);
45334
- const ops = new Erc8004Operations(resolveErc8004Contract(new ChainClient(), opts.chain), {
45335
- signer: provider,
45336
- onInfo: info
45337
- });
45286
+ const ops = new Erc8004Operations(
45287
+ resolveErc8004Contract(new ChainClient(), resolveChain(opts.chain)),
45288
+ {
45289
+ signer: provider,
45290
+ onInfo: info
45291
+ }
45292
+ );
45338
45293
  const result = await ops.register({
45339
45294
  agentURI: opts.uri,
45340
45295
  metadata: parseMetadataPairs(opts.metadata)
@@ -45370,10 +45325,13 @@ function registerErc8004Command(program3) {
45370
45325
  await ensureTrustSDK();
45371
45326
  const password3 = await resolvePassword(opts);
45372
45327
  const provider = await AgentWalletProvider.fromStorage(password3);
45373
- const ops = new Erc8004Operations(resolveErc8004Contract(new ChainClient(), opts.chain), {
45374
- signer: provider,
45375
- onInfo: info
45376
- });
45328
+ const ops = new Erc8004Operations(
45329
+ resolveErc8004Contract(new ChainClient(), resolveChain(opts.chain)),
45330
+ {
45331
+ signer: provider,
45332
+ onInfo: info
45333
+ }
45334
+ );
45377
45335
  const result = await ops.setUri({ agentId, agentURI: opts.uri });
45378
45336
  success("agentURI updated!");
45379
45337
  output(
@@ -45401,10 +45359,13 @@ function registerErc8004Command(program3) {
45401
45359
  await ensureTrustSDK();
45402
45360
  const password3 = await resolvePassword(opts);
45403
45361
  const provider = await AgentWalletProvider.fromStorage(password3);
45404
- const ops = new Erc8004Operations(resolveErc8004Contract(new ChainClient(), opts.chain), {
45405
- signer: provider,
45406
- onInfo: info
45407
- });
45362
+ const ops = new Erc8004Operations(
45363
+ resolveErc8004Contract(new ChainClient(), resolveChain(opts.chain)),
45364
+ {
45365
+ signer: provider,
45366
+ onInfo: info
45367
+ }
45368
+ );
45408
45369
  const result = await ops.setMetadata({ agentId, key: opts.key, value: opts.value });
45409
45370
  success("Metadata set!");
45410
45371
  output(
@@ -45431,7 +45392,9 @@ function registerErc8004Command(program3) {
45431
45392
  try {
45432
45393
  parseAgentId(agentId);
45433
45394
  await ensureTrustSDK();
45434
- const ops = new Erc8004Operations(resolveErc8004Contract(new ChainClient(), opts.chain));
45395
+ const ops = new Erc8004Operations(
45396
+ resolveErc8004Contract(new ChainClient(), resolveChain(opts.chain))
45397
+ );
45435
45398
  const result = await ops.getMetadata({ agentId, key: opts.key });
45436
45399
  output(
45437
45400
  { agentId, key: result.key, value: result.value, chain: result.chainKey },
@@ -45450,7 +45413,9 @@ function registerErc8004Command(program3) {
45450
45413
  try {
45451
45414
  parseAgentId(agentId);
45452
45415
  await ensureTrustSDK();
45453
- const ops = new Erc8004Operations(resolveErc8004Contract(new ChainClient(), opts.chain));
45416
+ const ops = new Erc8004Operations(
45417
+ resolveErc8004Contract(new ChainClient(), resolveChain(opts.chain))
45418
+ );
45454
45419
  const result = await ops.show({ agentId });
45455
45420
  output(
45456
45421
  {
@@ -45477,7 +45442,7 @@ var CHAIN_OPT = "EVM chain key (`bsc` and `bsctestnet` have known deployments)";
45477
45442
  var OPT_PARAMS_OPT = "Optional opaque optParams bytes passed through raw, as 0x-prefixed hex (defaults to empty)";
45478
45443
  var SUBMIT_OPT_PARAMS_OPT = `${OPT_PARAMS_OPT}. Evaluators may expect deliverable metadata here, e.g. hex-encoded UTF-8 JSON like {"deliverable_url": "..."}`;
45479
45444
  function buildOps(client, chainInput, signer) {
45480
- return new Erc8183Operations(resolveErc8183Contracts(client, chainInput), {
45445
+ return new Erc8183Operations(resolveErc8183Contracts(client, resolveChain(chainInput)), {
45481
45446
  signer,
45482
45447
  onInfo: info,
45483
45448
  erc20At: (token, chainKey) => erc20.using(client).withAddress(token, chainKey),
@@ -46017,6 +45982,13 @@ init_dist();
46017
45982
 
46018
45983
  // ../security/dist/index.mjs
46019
45984
  init_dist();
45985
+ function chainOfAssetId(assetId) {
45986
+ try {
45987
+ return tokenIdToChain(assetId);
45988
+ } catch {
45989
+ return void 0;
45990
+ }
45991
+ }
46020
45992
  var SecurityService = class {
46021
45993
  constructor(client) {
46022
45994
  this.client = client;
@@ -46055,10 +46027,14 @@ var SecurityService = class {
46055
46027
  }
46056
46028
  }
46057
46029
  async getAssetInfo(assetId) {
46058
- const info2 = await this.client.gateway(
46030
+ const response = await this.client.gateway(
46059
46031
  "GET",
46060
46032
  `/v1/assets/${encodeURIComponent(assetId)}`
46061
46033
  );
46034
+ delete response.network;
46035
+ const raw = response;
46036
+ const chain2 = chainOfAssetId(assetId);
46037
+ const info2 = chain2 ? { ...raw, chain: chain2 } : raw;
46062
46038
  try {
46063
46039
  const priceResp = await this.client.market("POST", "/v2/market/tickers", { currency: "USD", assets: [assetId] });
46064
46040
  const ticker = priceResp.tickers?.[0];
@@ -46116,13 +46092,12 @@ var SecurityService = class {
46116
46092
  const price = doc.price || {};
46117
46093
  const market = doc.market || {};
46118
46094
  const assetIdRaw = asset.asset_id || doc.asset_id || "";
46119
- const coinId = assetIdRaw ? parseInt(assetIdRaw.replace(/^c/, "").split("_")[0], 10) : NaN;
46120
- const chain2 = !isNaN(coinId) ? coinTypeToChainKey(coinId) || "" : "";
46095
+ const chain2 = chainOfAssetId(assetIdRaw);
46121
46096
  return {
46122
46097
  assetId: assetIdRaw,
46123
46098
  name: asset.name || doc.name || "",
46124
46099
  symbol: asset.symbol || doc.symbol || "",
46125
- chain: chain2,
46100
+ ...chain2 ? { chain: chain2 } : {},
46126
46101
  logoUrl: asset.icon_url || doc.icon_url,
46127
46102
  priceUsd: price.price ?? doc.price_usd,
46128
46103
  priceChange24h: price.percent_change_24h ?? doc.price_change_24h,
@@ -46171,13 +46146,12 @@ var SecurityService = class {
46171
46146
  const tickers = response.tickers || [];
46172
46147
  const sortKey = sort === "market_cap" ? "market_cap" : sort === "volume_24h" ? "volume_24h" : "change_24h";
46173
46148
  return tickers.sort((a3, b3) => (b3[sortKey] ?? 0) - (a3[sortKey] ?? 0)).slice(0, limit).map((t) => {
46174
- const coinId = t.id ? parseInt(t.id.replace(/^c/, ""), 10) : NaN;
46175
- const chain2 = !isNaN(coinId) ? coinTypeToChainKey(coinId) || "" : "";
46149
+ const chain2 = chainOfAssetId(t.id || "");
46176
46150
  return {
46177
46151
  assetId: t.id || "",
46178
46152
  name: t.slug || t.id || "",
46179
46153
  symbol: t.slug?.toUpperCase() || "",
46180
- chain: chain2,
46154
+ ...chain2 ? { chain: chain2 } : {},
46181
46155
  logoUrl: void 0,
46182
46156
  priceUsd: t.price,
46183
46157
  priceChange24h: t.change_24h,
@@ -46247,22 +46221,19 @@ async function resolveTokenLabel(tokenId, service) {
46247
46221
  const cached = await assetCache.get(tokenId);
46248
46222
  if (cached !== void 0) return cached;
46249
46223
  try {
46250
- const { coinId, contractAddress } = parseTokenId(tokenId);
46251
- const chain2 = getChainByCoinId(coinId);
46252
- if (!chain2) return tokenId;
46224
+ const { contractAddress } = parseTokenId(tokenId);
46225
+ const chainKey = tokenIdToChain(tokenId);
46226
+ if (!chainKey) return tokenId;
46253
46227
  if (!contractAddress) {
46254
- return chain2.symbol;
46228
+ return chainOf(chainKey).symbol;
46255
46229
  }
46256
- const chainKey = tokenIdToChain(tokenId);
46257
- if (chainKey) {
46258
- const chainTokens = COMMON_TOKENS[chainKey];
46259
- if (chainTokens) {
46260
- const normalizedAddr = contractAddress.toLowerCase();
46261
- for (const [sym, entry] of Object.entries(chainTokens)) {
46262
- if (entry.address.toLowerCase() === normalizedAddr) {
46263
- await assetCache.set(tokenId, sym);
46264
- return sym;
46265
- }
46230
+ const chainTokens = COMMON_TOKENS[chainKey];
46231
+ if (chainTokens) {
46232
+ const normalizedAddr = contractAddress.toLowerCase();
46233
+ for (const [sym, entry] of Object.entries(chainTokens)) {
46234
+ if (entry.address.toLowerCase() === normalizedAddr) {
46235
+ await assetCache.set(tokenId, sym);
46236
+ return sym;
46266
46237
  }
46267
46238
  }
46268
46239
  }
@@ -46277,7 +46248,7 @@ async function resolveTokenLabel(tokenId, service) {
46277
46248
  }
46278
46249
  }
46279
46250
  const short = contractAddress.length > 10 ? `${contractAddress.slice(0, 6)}\u2026${contractAddress.slice(-4)}` : contractAddress;
46280
- return `${chain2.symbol}/${short}`;
46251
+ return `${chainOf(chainKey).symbol}/${short}`;
46281
46252
  } catch {
46282
46253
  return tokenId;
46283
46254
  }
@@ -46301,7 +46272,7 @@ function registerAlertCommand(program3) {
46301
46272
  throw new AlertError("VALIDATION_ERROR", "Price must be a positive number");
46302
46273
  }
46303
46274
  let resolvedTokenId = opts.token;
46304
- let resolvedChain = opts.chain;
46275
+ let resolvedChain = opts.chain ? resolveChain(opts.chain) : void 0;
46305
46276
  try {
46306
46277
  parseTokenId(opts.token);
46307
46278
  if (!resolvedChain) {
@@ -46325,7 +46296,6 @@ function registerAlertCommand(program3) {
46325
46296
  AVAX: "avalanche",
46326
46297
  FTM: "fantom",
46327
46298
  TRX: "tron",
46328
- DOT: "polkadot",
46329
46299
  ATOM: "cosmos",
46330
46300
  NEAR: "near",
46331
46301
  APT: "aptos",
@@ -46337,7 +46307,7 @@ function registerAlertCommand(program3) {
46337
46307
  S: "sonic"
46338
46308
  };
46339
46309
  if (!resolvedChain && NATIVE_SYMBOLS2[sym]) {
46340
- resolvedChain = NATIVE_SYMBOLS2[sym];
46310
+ resolvedChain = knownChainKey(NATIVE_SYMBOLS2[sym]);
46341
46311
  }
46342
46312
  if (!resolvedChain) {
46343
46313
  throw new AlertError(
@@ -46345,13 +46315,7 @@ function registerAlertCommand(program3) {
46345
46315
  `Cannot resolve "${opts.token}" without --chain. Provide --chain or use asset ID format (c60).`
46346
46316
  );
46347
46317
  }
46348
- const chain2 = getChainById(resolvedChain);
46349
- if (!chain2) {
46350
- throw new AlertError(
46351
- "CHAIN_UNSUPPORTED",
46352
- `Unknown chain: ${resolvedChain}. Run \`twak chains\` to see supported chains.`
46353
- );
46354
- }
46318
+ const chain2 = chainOf(resolvedChain);
46355
46319
  const resolved = resolveToken(sym, resolvedChain);
46356
46320
  if (!resolved) {
46357
46321
  throw new AlertError(
@@ -46365,12 +46329,6 @@ function registerAlertCommand(program3) {
46365
46329
  resolvedTokenId = formatTokenId(chain2.coinId, resolved.address);
46366
46330
  }
46367
46331
  }
46368
- if (!isChainSupported(resolvedChain)) {
46369
- throw new AlertError(
46370
- "CHAIN_UNSUPPORTED",
46371
- `Unknown chain: ${resolvedChain}. Run \`twak chains\` to see supported chains.`
46372
- );
46373
- }
46374
46332
  const record2 = await alertStore.create({
46375
46333
  tokenId: resolvedTokenId,
46376
46334
  chainKey: resolvedChain,
@@ -46388,16 +46346,15 @@ function registerAlertCommand(program3) {
46388
46346
  const alerts = opts.active ? await alertStore.getActive() : await alertStore.list();
46389
46347
  const client = await tryGetClient();
46390
46348
  const service = client ? new SecurityService(client) : void 0;
46349
+ for (const r3 of await alertStore.listInvalid()) {
46350
+ warn(`Alert ${r3.id} is invalid: ${r3.error} (stored chain "${r3.chain}")`);
46351
+ }
46391
46352
  if (opts.json) {
46392
46353
  const enriched = await Promise.all(
46393
- alerts.map(async (a3) => {
46394
- let chainLabel = a3.chainKey;
46395
- try {
46396
- chainLabel = tokenIdToChain(a3.tokenId) ?? a3.chainKey;
46397
- } catch {
46398
- }
46399
- return { ...a3, tokenLabel: await resolveTokenLabel(a3.tokenId, service), chainLabel };
46400
- })
46354
+ alerts.map(async (a3) => ({
46355
+ ...a3,
46356
+ tokenLabel: await resolveTokenLabel(a3.tokenId, service)
46357
+ }))
46401
46358
  );
46402
46359
  output(enriched, true);
46403
46360
  } else {
@@ -46407,15 +46364,8 @@ function registerAlertCommand(program3) {
46407
46364
  }
46408
46365
  for (const a3 of alerts) {
46409
46366
  const label = await resolveTokenLabel(a3.tokenId, service);
46410
- let chainHint = "";
46411
- try {
46412
- const chain2 = tokenIdToChain(a3.tokenId);
46413
- chainHint = chain2 ? ` (${chain2})` : "";
46414
- } catch {
46415
- chainHint = "";
46416
- }
46417
46367
  info(
46418
- `${a3.id} | ${label}${chainHint} | ${a3.condition} $${a3.targetPrice} | ${a3.active ? "active" : "triggered"}`
46368
+ `${a3.id} | ${label} (${a3.chainKey}) | ${a3.condition} $${a3.targetPrice} | ${a3.active ? "active" : "triggered"}`
46419
46369
  );
46420
46370
  }
46421
46371
  }
@@ -46469,6 +46419,11 @@ function toRFC3339(value) {
46469
46419
  if (!isNaN(d3.getTime())) return d3.toISOString();
46470
46420
  return value;
46471
46421
  }
46422
+ function toRecord(raw, requested) {
46423
+ const { chain: chain2, ...rest } = raw;
46424
+ const chainKey = chain2 ? chainKeyForBackendId(chain2) : requested;
46425
+ return chainKey ? { ...rest, chain: chainKey } : rest;
46426
+ }
46472
46427
  var TransactionService = class {
46473
46428
  constructor(client) {
46474
46429
  this.client = client;
@@ -46476,7 +46431,7 @@ var TransactionService = class {
46476
46431
  async getHistory(params) {
46477
46432
  const from8 = params.from ?? new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString();
46478
46433
  const to3 = params.to ?? (/* @__PURE__ */ new Date()).toISOString();
46479
- const chainId = params.chain ? getChainById(params.chain)?.id ?? params.chain : void 0;
46434
+ const chainId = params.chain ? backendIdOf(params.chain) : void 0;
46480
46435
  const query = new URLSearchParams();
46481
46436
  query.set("address", params.address);
46482
46437
  if (params.asset) query.set("asset", params.asset);
@@ -46491,31 +46446,28 @@ var TransactionService = class {
46491
46446
  void 0,
46492
46447
  query.toString()
46493
46448
  );
46494
- return response.data || [];
46449
+ return (response.data || []).map((r3) => toRecord(r3, params.chain));
46495
46450
  }
46496
46451
  async getBulkHistory(params) {
46497
46452
  const from8 = params.from ?? new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString();
46498
46453
  const to3 = params.to ?? (/* @__PURE__ */ new Date()).toISOString();
46499
- const addresses = params.addresses.map((a3) => ({
46500
- ...a3,
46501
- chain: getChainById(a3.chain)?.id ?? a3.chain
46502
- }));
46454
+ const addresses = params.addresses.map((a3) => ({ ...a3, chain: backendIdOf(a3.chain) }));
46503
46455
  const response = await this.client.gateway("POST", "/v1/txhub/bulk_history", {
46504
46456
  addresses,
46505
46457
  from: toRFC3339(from8),
46506
46458
  to: toRFC3339(to3),
46507
46459
  ...params.nextToken ? { next_token: params.nextToken } : {}
46508
46460
  });
46509
- return response.data || [];
46461
+ return (response.data || []).map((r3) => toRecord(r3));
46510
46462
  }
46511
46463
  async getByHash(hash, chain2) {
46512
- const chainId = getChainById(chain2)?.id ?? chain2;
46513
- return this.client.gateway(
46464
+ const record2 = await this.client.gateway(
46514
46465
  "GET",
46515
46466
  `/v1/txhub/txs/${hash}`,
46516
46467
  void 0,
46517
- `chain=${chainId}`
46468
+ `chain=${backendIdOf(chain2)}`
46518
46469
  );
46470
+ return toRecord(record2, chain2);
46519
46471
  }
46520
46472
  async getSwapHistory(params) {
46521
46473
  return this.getHistory({ ...params, txType: "swap" });
@@ -46537,39 +46489,34 @@ function registerQueryCommand(program3) {
46537
46489
  const client = await getClient();
46538
46490
  const swapClient = new SwapClient(client);
46539
46491
  const tokens = token.split(",").map((t) => t.trim()).filter(Boolean);
46540
- const resolveChain2 = (t) => {
46541
- if (opts.chain) return opts.chain;
46542
- if (Object.prototype.hasOwnProperty.call(CHAINS, t.toLowerCase())) return t.toLowerCase();
46543
- const bySymbol = Object.entries(CHAINS).find(
46544
- ([, c3]) => c3.symbol.toUpperCase() === t.toUpperCase()
46545
- )?.[0];
46546
- if (bySymbol) return bySymbol;
46492
+ const explicitChain = opts.chain ? resolveChain(opts.chain) : void 0;
46493
+ const homeChainOf = (t) => {
46494
+ if (explicitChain) return explicitChain;
46495
+ const lower = t.toLowerCase();
46547
46496
  const upper = t.toUpperCase();
46548
- for (const [chainKey, chainTokens] of Object.entries(COMMON_TOKENS)) {
46549
- if (Object.prototype.hasOwnProperty.call(chainTokens, upper)) return chainKey;
46550
- }
46551
- return "ethereum";
46552
- };
46553
- if (opts.chain && !getChainById(opts.chain)) {
46554
- throw new QueryError(
46555
- "CHAIN_UNSUPPORTED",
46556
- `Unknown chain: ${opts.chain}. Run 'twak chains' to list supported chains.`
46497
+ const byName = mainnetChainKeys().find((k4) => k4 === lower);
46498
+ if (byName) return byName;
46499
+ const bySymbol = mainnetChainKeys().find(
46500
+ (k4) => chainOf(k4).symbol.toUpperCase() === upper
46557
46501
  );
46558
- }
46502
+ if (bySymbol) return bySymbol;
46503
+ const byToken = chainKeysWithKnownTokens().find(
46504
+ (k4) => Object.prototype.hasOwnProperty.call(COMMON_TOKENS[k4], upper)
46505
+ );
46506
+ return byToken ?? knownChainKey("ethereum");
46507
+ };
46559
46508
  if (tokens.length > 1) {
46560
46509
  const assetIds = [];
46561
46510
  const tokenMeta = [];
46562
46511
  for (const t of tokens) {
46563
- const chain3 = resolveChain2(t);
46512
+ const chain3 = homeChainOf(t);
46564
46513
  const info2 = resolveToken(t, chain3);
46565
46514
  if (!info2) {
46566
46515
  warn(`Unknown token: ${t.toUpperCase()}`);
46567
46516
  continue;
46568
46517
  }
46569
- const chainInfo = getChainById(chain3);
46570
- if (!chainInfo) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown chain: ${chain3}`);
46571
46518
  const isNative = !info2.address || info2.address === NATIVE_TOKEN_ADDRESS || info2.address === SOLANA_NATIVE_ADDRESS;
46572
- const assetId = isNative ? `c${chainInfo.coinId}` : `c${chainInfo.coinId}_t${info2.address}`;
46519
+ const assetId = isNative ? assetIdOf(chain3) : assetIdOf(chain3, info2.address);
46573
46520
  assetIds.push(assetId);
46574
46521
  tokenMeta.push({ token: t.toUpperCase(), chain: chain3 });
46575
46522
  }
@@ -46605,7 +46552,7 @@ function registerQueryCommand(program3) {
46605
46552
  }
46606
46553
  return;
46607
46554
  }
46608
- const chain2 = resolveChain2(token);
46555
+ const chain2 = homeChainOf(token);
46609
46556
  const tokenInfo = resolveToken(token, chain2);
46610
46557
  let price = null;
46611
46558
  if (tokenInfo) {
@@ -46635,10 +46582,8 @@ function registerQueryCommand(program3) {
46635
46582
  );
46636
46583
  }
46637
46584
  const period = typeof opts.history === "string" ? opts.history : "week";
46638
- const chainInfo = getChainById(chain2);
46639
- if (!chainInfo) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown chain: ${chain2}`);
46640
46585
  const isNative = !tokenInfo.address || tokenInfo.address === NATIVE_TOKEN_ADDRESS || tokenInfo.address === SOLANA_NATIVE_ADDRESS;
46641
- const assetId = isNative ? `c${chainInfo.coinId}` : `c${chainInfo.coinId}_t${tokenInfo.address}`;
46586
+ const assetId = isNative ? assetIdOf(chain2) : assetIdOf(chain2, tokenInfo.address);
46642
46587
  const chartData = await client.gateway("GET", `/v1/market/charts/${assetId}`, void 0, `currency=USD&period=${period}`);
46643
46588
  output(
46644
46589
  { token: token.toUpperCase(), chain: chain2, priceUsd: price, history: chartData.prices },
@@ -46665,12 +46610,7 @@ function registerQueryCommand(program3) {
46665
46610
  networks = opts.networks.split(",").map((n4) => {
46666
46611
  const trimmed = n4.trim();
46667
46612
  if (/^\d+$/.test(trimmed)) return trimmed;
46668
- const chain2 = getChainById(trimmed);
46669
- if (chain2) return String(chain2.coinId);
46670
- throw new QueryError(
46671
- "CHAIN_UNSUPPORTED",
46672
- `Unknown network "${trimmed}". Use a supported chain name or numeric coin ID.`
46673
- );
46613
+ return String(coinIdOf(resolveChain(trimmed)));
46674
46614
  }).join(",");
46675
46615
  }
46676
46616
  const result = await swapClient.searchTokens({
@@ -46687,22 +46627,17 @@ function registerQueryCommand(program3) {
46687
46627
  try {
46688
46628
  const client = await getClient();
46689
46629
  const service = new TransactionService(client);
46690
- if (opts.chain && !getChainById(opts.chain)) {
46691
- throw new QueryError(
46692
- "CHAIN_UNSUPPORTED",
46693
- `Unknown chain: ${opts.chain}. Run 'twak chains' to list supported chains.`
46694
- );
46695
- }
46696
- if (opts.address && opts.chain && !/^(0x[0-9a-fA-F]{40}|[1-9A-HJ-NP-Za-km-z]{20,}|[A-Za-z0-9]{20,})$/.test(opts.address)) {
46630
+ const chainKey = opts.chain ? resolveChain(opts.chain) : void 0;
46631
+ if (opts.address && chainKey && !/^(0x[0-9a-fA-F]{40}|[1-9A-HJ-NP-Za-km-z]{20,}|[A-Za-z0-9]{20,})$/.test(opts.address)) {
46697
46632
  throw new QueryError("VALIDATION_ERROR", `Invalid address: "${opts.address}"`);
46698
46633
  }
46699
- if (!opts.chain) {
46634
+ if (!chainKey) {
46700
46635
  await ensureTrustSDK();
46701
46636
  const password3 = await resolvePassword(opts);
46702
46637
  const provider = await AgentWalletProvider.fromStorage(password3);
46703
46638
  const allAddresses = await provider.getAddresses();
46704
46639
  const addresses = allAddresses.map((wa2) => ({
46705
- chain: wa2.chainId,
46640
+ chain: wa2.chainKey,
46706
46641
  address: wa2.address
46707
46642
  }));
46708
46643
  const result2 = await service.getBulkHistory({
@@ -46725,46 +46660,42 @@ function registerQueryCommand(program3) {
46725
46660
  await ensureTrustSDK();
46726
46661
  const password3 = await resolvePassword(opts);
46727
46662
  const provider = await AgentWalletProvider.fromStorage(password3);
46728
- address = await provider.getAddress(opts.chain);
46663
+ address = await provider.getAddress(chainKey);
46729
46664
  }
46730
46665
  const result = await service.getHistory({
46731
46666
  address,
46732
- chain: opts.chain,
46667
+ chain: chainKey,
46733
46668
  from: opts.from,
46734
46669
  to: opts.to,
46735
46670
  limit: parseInt(opts.limit, 10)
46736
46671
  });
46737
46672
  if (result.length > 0) {
46738
- const chain2 = getChainById(opts.chain);
46739
- if (chain2) {
46740
- const swapClient = new SwapClient(client);
46741
- const price = await swapClient.getTokenPrice(opts.chain, "");
46742
- const enriched = result.map((tx) => {
46743
- if (!tx.amount || tx.amount === "0") return tx;
46744
- try {
46745
- const big = BigInt(tx.amount);
46746
- const divisor = 10n ** BigInt(chain2.decimals);
46747
- const intPart = big / divisor;
46748
- const scale = 10000n;
46749
- const fracScaled = big % divisor * scale / divisor;
46750
- const usdValue = price !== null && (intPart > 0n || fracScaled > 0n) && intPart <= BigInt(Number.MAX_SAFE_INTEGER) ? parseFloat(
46751
- ((Number(intPart) + Number(fracScaled) / 1e4) * price).toFixed(4)
46752
- ) : void 0;
46753
- return { ...tx, usdValue };
46754
- } catch {
46755
- return tx;
46756
- }
46757
- });
46758
- output(enriched, opts.json);
46759
- return;
46760
- }
46673
+ const chain2 = chainOf(chainKey);
46674
+ const swapClient = new SwapClient(client);
46675
+ const price = await swapClient.getTokenPrice(chainKey, "");
46676
+ const enriched = result.map((tx) => {
46677
+ if (!tx.amount || tx.amount === "0") return tx;
46678
+ try {
46679
+ const big = BigInt(tx.amount);
46680
+ const divisor = 10n ** BigInt(chain2.decimals);
46681
+ const intPart = big / divisor;
46682
+ const scale = 10000n;
46683
+ const fracScaled = big % divisor * scale / divisor;
46684
+ const usdValue = price !== null && (intPart > 0n || fracScaled > 0n) && intPart <= BigInt(Number.MAX_SAFE_INTEGER) ? parseFloat(((Number(intPart) + Number(fracScaled) / 1e4) * price).toFixed(4)) : void 0;
46685
+ return { ...tx, usdValue };
46686
+ } catch {
46687
+ return tx;
46688
+ }
46689
+ });
46690
+ output(enriched, opts.json);
46691
+ return;
46761
46692
  }
46762
46693
  if (opts.json) {
46763
46694
  output(result, true);
46764
46695
  } else if (result.length === 0) {
46765
- const explorer = opts.chain === "ethereum" ? "etherscan.io" : opts.chain === "bsc" ? "bscscan.com" : void 0;
46766
- const hint = explorer ? ` Check ${explorer} for full history.` : "";
46767
- info(`No transactions found via API.${hint}`);
46696
+ info(
46697
+ `No transactions found via API. Check ${chainOf(chainKey).explorerUrl} for full history.`
46698
+ );
46768
46699
  } else {
46769
46700
  output(result, false);
46770
46701
  }
@@ -46775,30 +46706,25 @@ function registerQueryCommand(program3) {
46775
46706
  });
46776
46707
  program3.command("tx <hash>").description("Get transaction details by hash (on-chain RPC lookup)").requiredOption("--chain <name>", "Chain name").option("--address <address>", "Wallet address (auto-detected from wallet if omitted)").option("--password <pw>", "Wallet password (for auto-detecting address)").option("--json", "JSON output").action(async (hash, opts) => {
46777
46708
  try {
46778
- if (!getChainById(opts.chain)) {
46779
- throw new QueryError(
46780
- "CHAIN_UNSUPPORTED",
46781
- `Unknown chain: ${opts.chain}. Run 'twak chains' to list supported chains.`
46782
- );
46783
- }
46709
+ const chainKey = resolveChain(opts.chain);
46784
46710
  let address = opts.address;
46785
46711
  if (!address) {
46786
46712
  try {
46787
46713
  await ensureTrustSDK();
46788
46714
  const password3 = await resolvePassword(opts);
46789
46715
  const provider = await AgentWalletProvider.fromStorage(password3);
46790
- address = await provider.getAddress(opts.chain);
46716
+ address = await provider.getAddress(chainKey);
46791
46717
  } catch {
46792
46718
  }
46793
46719
  }
46794
46720
  if (address) {
46795
46721
  await ensureTrustSDK();
46796
46722
  const chainClient = new ChainClient();
46797
- const status = await chainClient.findTransactionStatus(opts.chain, address, hash);
46723
+ const status = await chainClient.findTransactionStatus(chainKey, address, hash);
46798
46724
  output(
46799
46725
  {
46800
46726
  hash,
46801
- chain: opts.chain,
46727
+ chain: chainKey,
46802
46728
  ...status
46803
46729
  },
46804
46730
  opts.json
@@ -46806,7 +46732,7 @@ function registerQueryCommand(program3) {
46806
46732
  } else {
46807
46733
  const client = await getClient();
46808
46734
  const service = new TransactionService(client);
46809
- const result = await service.getByHash(hash, opts.chain);
46735
+ const result = await service.getByHash(hash, chainKey);
46810
46736
  output(result, opts.json);
46811
46737
  }
46812
46738
  } catch (err) {
@@ -46814,15 +46740,14 @@ function registerQueryCommand(program3) {
46814
46740
  }
46815
46741
  });
46816
46742
  program3.command("chains").description("List supported chains").option("--json", "JSON output").action(async (opts) => {
46817
- const chainEntries = Object.entries(CHAINS);
46743
+ const chainEntries = mainnetChainKeys().map((key) => [key, chainOf(key)]);
46818
46744
  if (opts.json) {
46819
46745
  output(
46820
46746
  chainEntries.map(([key, chain2]) => ({
46821
- key,
46747
+ chain: key,
46822
46748
  name: chain2.name,
46823
46749
  symbol: chain2.symbol,
46824
46750
  namespace: chain2.namespace,
46825
- chainId: chain2.id,
46826
46751
  coinId: chain2.coinId
46827
46752
  })),
46828
46753
  true
@@ -46852,23 +46777,23 @@ function registerQueryCommand(program3) {
46852
46777
  });
46853
46778
  program3.command("balance").description("Get token balance for an address (native or ERC-20)").requiredOption("--address <address>", "Wallet address").option("--coin <coinId>", "SLIP44 coin ID (for native token)").option("--chain <key>", "Chain key (e.g., ethereum, bsc)").option("--token <address>", "Token contract address (for ERC-20)").option("--json", "JSON output").action(async (opts) => {
46854
46779
  try {
46855
- let coinId;
46856
- if (opts.coin) {
46857
- coinId = Number(opts.coin);
46858
- if (!Number.isInteger(coinId))
46780
+ let chainKey;
46781
+ if (opts.chain) {
46782
+ chainKey = resolveChain(opts.chain);
46783
+ } else if (opts.coin) {
46784
+ if (!/^\d+$/.test(String(opts.coin)))
46859
46785
  throw new QueryError("VALIDATION_ERROR", `Invalid coin ID: ${opts.coin}`);
46860
- } else if (opts.chain) {
46861
- const chainInfo = getChainById(opts.chain);
46862
- if (!chainInfo) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
46863
- coinId = chainInfo.coinId;
46786
+ const byCoin = mainnetChainKeyForCoinId(parseTokenId(`c${opts.coin}`).coinId);
46787
+ if (!byCoin) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown coin ID: ${opts.coin}`);
46788
+ chainKey = byCoin;
46864
46789
  } else {
46865
46790
  throw new QueryError("VALIDATION_ERROR", "Provide --coin or --chain");
46866
46791
  }
46867
- const chain2 = getChainByCoinId(coinId);
46868
- if (!chain2) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown coin ID: ${coinId}`);
46792
+ const chain2 = chainOf(chainKey);
46793
+ const coinId = chain2.coinId;
46869
46794
  try {
46870
46795
  await ensureTrustSDK();
46871
- const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
46796
+ const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports));
46872
46797
  const wc3 = getWalletCore2();
46873
46798
  const ct5 = getCoinType2(coinId);
46874
46799
  if (ct5 && !wc3.CoinTypeExt.validate(ct5, opts.address)) {
@@ -46877,13 +46802,12 @@ function registerQueryCommand(program3) {
46877
46802
  } catch (err) {
46878
46803
  if (err instanceof CommandError) throw err;
46879
46804
  }
46880
- const assetId = opts.token ? `c${coinId}_t${opts.token}` : `c${coinId}`;
46805
+ const assetId = assetIdOf(chainKey, opts.token);
46881
46806
  const httpClient = await getClient();
46882
46807
  let decimals = chain2.decimals;
46883
46808
  let symbol = chain2.symbol;
46884
46809
  if (opts.token) {
46885
46810
  const swapClient = new SwapClient(httpClient);
46886
- const chainKey = opts.chain || Object.entries(CHAINS).find(([, c3]) => c3.coinId === coinId)?.[0] || "";
46887
46811
  const tokens = await swapClient.searchTokens({
46888
46812
  query: opts.token,
46889
46813
  chains: [chainKey],
@@ -46901,7 +46825,7 @@ function registerQueryCommand(program3) {
46901
46825
  output(
46902
46826
  {
46903
46827
  address: opts.address,
46904
- chain: chain2.id,
46828
+ chain: chainKey,
46905
46829
  symbol,
46906
46830
  ...opts.token ? { token: opts.token } : {},
46907
46831
  decimalsKnown: false,
@@ -46920,7 +46844,7 @@ function registerQueryCommand(program3) {
46920
46844
  output(
46921
46845
  {
46922
46846
  address: opts.address,
46923
- chain: chain2.id,
46847
+ chain: chainKey,
46924
46848
  symbol,
46925
46849
  ...opts.token ? { token: opts.token } : {},
46926
46850
  available: formatAmount(amts.available ?? "0", decimals),
@@ -46954,29 +46878,33 @@ function registerQueryCommand(program3) {
46954
46878
  "Provide --chain <key> or --asset-id <id> to validate an address"
46955
46879
  );
46956
46880
  }
46957
- let assetId = opts.assetId;
46958
- if (!assetId && opts.chain) {
46959
- const chain2 = getChainById(opts.chain);
46960
- if (!chain2) throw new QueryError("CHAIN_UNSUPPORTED", `Unknown chain: ${opts.chain}`);
46961
- assetId = `c${chain2.coinId}`;
46881
+ let chainKey;
46882
+ if (opts.chain) {
46883
+ chainKey = resolveChain(opts.chain);
46884
+ } else {
46885
+ try {
46886
+ chainKey = tokenIdToChain(opts.assetId);
46887
+ } catch {
46888
+ chainKey = void 0;
46889
+ }
46962
46890
  }
46891
+ const assetId = opts.assetId ?? (chainKey ? assetIdOf(chainKey) : void 0);
46963
46892
  if (assetId) {
46964
46893
  const coinIdStr = assetId.replace(/^c/, "").split("_")[0];
46965
46894
  const coinId = parseInt(coinIdStr, 10);
46966
46895
  try {
46967
46896
  await ensureTrustSDK();
46968
- const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
46897
+ const { getWalletCore: getWalletCore2, getCoinType: getCoinType2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports));
46969
46898
  const wc3 = getWalletCore2();
46970
46899
  const ct5 = getCoinType2(coinId);
46971
46900
  if (ct5) {
46972
46901
  const isValid = wc3.CoinTypeExt.validate(ct5, opts.address);
46973
46902
  if (!isValid) {
46974
- const chainInfo = getChainByCoinId(coinId);
46975
- const label = chainInfo?.name ?? `coin ${coinId}`;
46903
+ const label = chainKey ? chainOf(chainKey).name : `coin ${coinId}`;
46976
46904
  const result = {
46977
46905
  status: "error",
46978
46906
  valid: false,
46979
- chain: chainInfo?.id,
46907
+ ...chainKey ? { chain: chainKey } : {},
46980
46908
  message: `Invalid address format for ${label}`
46981
46909
  };
46982
46910
  output(result, opts.json);
@@ -46989,11 +46917,6 @@ function registerQueryCommand(program3) {
46989
46917
  const client = await getClient();
46990
46918
  const service = new SecurityService(client);
46991
46919
  const backendResult = await service.validate({ address: opts.address, assetId });
46992
- const chainKey = opts.chain || (assetId ? (() => {
46993
- const coinIdStr = assetId.replace(/^c/, "").split("_")[0];
46994
- const coinId = parseInt(coinIdStr, 10);
46995
- return getChainByCoinId(coinId)?.id;
46996
- })() : void 0);
46997
46920
  const enriched = { ...backendResult, ...chainKey ? { chain: chainKey } : {} };
46998
46921
  output(enriched, opts.json);
46999
46922
  } catch (err) {
@@ -47127,6 +47050,7 @@ init_dist();
47127
47050
  var import_zod3 = require("zod");
47128
47051
  init_dist();
47129
47052
  var import_zod4 = require("zod");
47053
+ init_dist();
47130
47054
  var import_zod5 = require("zod");
47131
47055
  init_dist();
47132
47056
  var import_zod6 = require("zod");
@@ -47373,11 +47297,7 @@ async function signTransferWithAuthorization(p3) {
47373
47297
  domain: p3.token,
47374
47298
  message: authorization
47375
47299
  });
47376
- const rawSignature = await p3.walletProvider.signTypedData(
47377
- p3.chainKey,
47378
- p3.token.chainId,
47379
- JSON.stringify(typedData)
47380
- );
47300
+ const rawSignature = await p3.walletProvider.signTypedData(p3.chainKey, JSON.stringify(typedData));
47381
47301
  const signature = normalizeEip712Signature(rawSignature);
47382
47302
  return { signature, authorization };
47383
47303
  }
@@ -47442,11 +47362,7 @@ async function signPermit2Authorization(p3) {
47442
47362
  witnessTo: p3.payTo,
47443
47363
  validAfter
47444
47364
  });
47445
- const rawSignature = await p3.walletProvider.signTypedData(
47446
- p3.chainKey,
47447
- p3.chainId,
47448
- JSON.stringify(typedData)
47449
- );
47365
+ const rawSignature = await p3.walletProvider.signTypedData(p3.chainKey, JSON.stringify(typedData));
47450
47366
  const signature = normalizeEip712Signature(rawSignature);
47451
47367
  return {
47452
47368
  signature,
@@ -47535,7 +47451,6 @@ async function payAndFetch(args) {
47535
47451
  amount: getAmount(kind),
47536
47452
  tokenName,
47537
47453
  asset: getAsset(kind),
47538
- network: getNetwork(kind),
47539
47454
  chainKey,
47540
47455
  payTo: getPayTo(kind)
47541
47456
  });
@@ -47605,7 +47520,7 @@ async function payAndFetch(args) {
47605
47520
  payment = {
47606
47521
  amount,
47607
47522
  tokenName,
47608
- network: getNetwork(kind),
47523
+ chain: chainKey,
47609
47524
  payTo: getPayTo(kind),
47610
47525
  nonce
47611
47526
  };
@@ -47638,7 +47553,7 @@ async function ensurePermit2Allowance(args) {
47638
47553
  };
47639
47554
  const approved = await args.confirmApproval?.(ctx) === true;
47640
47555
  if (!approved) {
47641
- const assetId = formatTokenId(CHAINS[args.chainKey].coinId, args.tokenAddress);
47556
+ const assetId = formatTokenId(coinIdOf(args.chainKey), args.tokenAddress);
47642
47557
  throw new X402Error(
47643
47558
  "PERMIT2_APPROVAL_REQUIRED",
47644
47559
  `Permit2 needs a one-time approval for ${args.tokenAddress} on ${args.chainKey}. Run: twak erc20 approve --token ${assetId} --spender ${PERMIT2_ADDRESS} --amount unlimited`
@@ -47735,29 +47650,16 @@ async function validateX402Url(urlStr) {
47735
47650
  }
47736
47651
  }
47737
47652
  function parseNetwork(network) {
47738
- const caip = /^eip155:(\d+)$/.exec(network);
47739
- if (caip) {
47740
- const evmChainId = parseInt(caip[1], 10);
47741
- const entry2 = Object.entries(CHAINS).find(([, c3]) => c3.chainId === String(evmChainId));
47742
- if (!entry2) {
47743
- throw new X402Error("CHAIN_UNSUPPORTED", `x402: unsupported chain eip155:${evmChainId}`);
47744
- }
47745
- return { evmChainId, chainKey: entry2[0] };
47746
- }
47747
47653
  const lower = network.toLowerCase();
47748
- const entry = Object.entries(CHAINS).find(
47749
- ([key, c3]) => key === lower || c3.id.toLowerCase() === lower
47750
- );
47751
- if (!entry) {
47654
+ const chainKey = /^eip155:\d+$/.test(network) ? chainKeyForCaip2(network) ?? void 0 : mainnetChainKeys().find((key) => key === lower) ?? chainKeyForBackendId(lower);
47655
+ if (!chainKey || isTestnet(chainKey) || chainOf(chainKey).namespace !== "eip155") {
47752
47656
  throw new X402Error("CHAIN_UNSUPPORTED", `x402: unsupported network "${network}"`);
47753
47657
  }
47754
- return { evmChainId: parseInt(entry[1].chainId, 10), chainKey: entry[0] };
47658
+ return { evmChainId: evmChainIdOf(chainKey), chainKey };
47755
47659
  }
47756
47660
  function networkMatches(kind, prefer) {
47757
- const lower = prefer.toLowerCase();
47758
- if (getNetwork(kind).toLowerCase() === lower) return true;
47759
47661
  try {
47760
- return parseNetwork(getNetwork(kind)).chainKey.toLowerCase() === lower;
47662
+ return parseNetwork(getNetwork(kind)).chainKey === prefer;
47761
47663
  } catch {
47762
47664
  return false;
47763
47665
  }
@@ -47930,7 +47832,7 @@ async function quoteX402(args) {
47930
47832
  }
47931
47833
  const accepts = payableAccepts.map((kind) => {
47932
47834
  const transferMethod = effectiveTransferMethod(kind);
47933
- const network = getNetwork(kind);
47835
+ const { chainKey: chain2 } = parseNetwork(getNetwork(kind));
47934
47836
  const asset = getAsset(kind);
47935
47837
  const amount = getAmount(kind);
47936
47838
  const extra = getExtra(kind);
@@ -47939,7 +47841,7 @@ async function quoteX402(args) {
47939
47841
  const tokenLabel = tokenName || asset;
47940
47842
  const approvalTag = requiresApproval ? " (Permit2, requires one-time on-chain approval the first time you pay this token on this chain)" : " (gasless)";
47941
47843
  return {
47942
- network,
47844
+ chain: chain2,
47943
47845
  scheme: getScheme(kind),
47944
47846
  asset,
47945
47847
  tokenName,
@@ -47955,7 +47857,7 @@ async function quoteX402(args) {
47955
47857
  // strip control chars to defend against terminal-escape injection.
47956
47858
  // Raw values stay on the structured `tokenName` / `transferMethod`
47957
47859
  // fields so consumers can apply their own escaping policy.
47958
- description: `${amount} of ${safeText(tokenLabel)} on ${network} via ${safeText(transferMethod)}${approvalTag}`
47860
+ description: `${amount} of ${safeText(tokenLabel)} on ${chain2} via ${safeText(transferMethod)}${approvalTag}`
47959
47861
  };
47960
47862
  });
47961
47863
  const chosen = accepts.find((a3) => a3.preferred);
@@ -47965,7 +47867,7 @@ async function quoteX402(args) {
47965
47867
  if (chosen) {
47966
47868
  const safeTokenLabel = safeText(chosen.tokenName) || chosen.asset;
47967
47869
  const safeMethod = safeText(chosen.transferMethod);
47968
- summary = `Endpoint offers ${accepts.length} payment option(s). Default route: ${chosen.amount} of ${safeTokenLabel} on ${chosen.network} via ${safeMethod}${chosen.requiresApproval ? " (requires one-time Permit2 approval)" : " (gasless)"}.`;
47870
+ summary = `Endpoint offers ${accepts.length} payment option(s). Default route: ${chosen.amount} of ${safeTokenLabel} on ${chosen.chain} via ${safeMethod}${chosen.requiresApproval ? " (requires one-time Permit2 approval)" : " (gasless)"}.`;
47969
47871
  nextAction = `Show these payment options to the user and let them pick one. Then call x402_request with this url${requestShapeHint}, maxPaymentAtomic set to the picked option's amount, and preferAsset set to its asset contract.`;
47970
47872
  } else if (accepts.length > 0) {
47971
47873
  summary = `Endpoint offers ${accepts.length} payment option(s), but none are supported by this client.`;
@@ -47996,9 +47898,6 @@ var import_zod18 = require("zod");
47996
47898
  init_dist();
47997
47899
  init_dist4();
47998
47900
  var ActionProvider = class {
47999
- supportsChain(_chainId) {
48000
- return true;
48001
- }
48002
47901
  };
48003
47902
  var ActionRegistry = class {
48004
47903
  providers = [];
@@ -48149,13 +48048,21 @@ var TransferActionProvider = class extends ActionProvider {
48149
48048
  )
48150
48049
  }),
48151
48050
  invoke: async (_ctx, input2) => {
48051
+ let chain2;
48052
+ try {
48053
+ chain2 = resolveChain(input2.chain);
48054
+ } catch (err) {
48055
+ const classified = tryClassifyError(err);
48056
+ if (!classified) throw err;
48057
+ return { success: false, code: classified.code, message: classified.message };
48058
+ }
48152
48059
  const wallet = this.walletContext.activeWallet();
48153
48060
  const executor = new TransferExecutor({
48154
48061
  wallet,
48155
48062
  swapClient: this.swapClient
48156
48063
  });
48157
48064
  const result = await executor.execute({
48158
- chain: input2.chain,
48065
+ chain: chain2,
48159
48066
  to: input2.to,
48160
48067
  amount: input2.amount,
48161
48068
  tokenAddress: input2.tokenAddress,
@@ -48517,7 +48424,7 @@ var AlertActionProvider = class extends ActionProvider {
48517
48424
  condition: input2.condition,
48518
48425
  targetPrice: input2.targetPrice
48519
48426
  });
48520
- const label = input2.tokenAddress ? `${input2.tokenAddress} on ${chainKey}` : `${requireChain(chainKey).symbol} on ${chainKey}`;
48427
+ const label = input2.tokenAddress ? `${input2.tokenAddress} on ${chainKey}` : `${chainOf(chainKey).symbol} on ${chainKey}`;
48521
48428
  return {
48522
48429
  id: alert.id,
48523
48430
  message: `Alert created: notify when ${label} goes ${input2.condition} $${input2.targetPrice}`
@@ -48534,7 +48441,8 @@ var AlertActionProvider = class extends ActionProvider {
48534
48441
  }),
48535
48442
  invoke: async (_ctx, input2) => {
48536
48443
  const alerts = input2.activeOnly ? await this.alertStore.getActive() : await this.alertStore.list();
48537
- return { alerts, count: alerts.length };
48444
+ const invalid = await this.alertStore.listInvalid();
48445
+ return { alerts, count: alerts.length, invalid };
48538
48446
  }
48539
48447
  };
48540
48448
  }
@@ -48619,7 +48527,10 @@ var AgentWalletActionProvider = class extends ActionProvider {
48619
48527
  schema: import_zod9.z.object({}),
48620
48528
  invoke: async () => {
48621
48529
  const wallet = this.requireWallet();
48622
- const addresses = await wallet.getAddresses();
48530
+ const addresses = (await wallet.getAddresses()).map((a3) => ({
48531
+ address: a3.address,
48532
+ chain: a3.chainKey
48533
+ }));
48623
48534
  return { addresses, count: addresses.length };
48624
48535
  }
48625
48536
  };
@@ -48707,7 +48618,7 @@ var TokenActionProvider = class extends ActionProvider {
48707
48618
  invoke: async (_ctx, input2) => {
48708
48619
  const wallet = this.walletContext.activeWallet();
48709
48620
  const chainKey = resolveChain(input2.chain);
48710
- const chain2 = requireChain(chainKey);
48621
+ const chain2 = chainOf(chainKey);
48711
48622
  if (chain2.namespace !== "eip155") {
48712
48623
  throw new WalletError(
48713
48624
  "CHAIN_UNSUPPORTED",
@@ -48737,7 +48648,7 @@ var TokenActionProvider = class extends ActionProvider {
48737
48648
  invoke: async (_ctx, input2) => {
48738
48649
  const wallet = this.walletContext.activeWallet();
48739
48650
  const chainKey = resolveChain(input2.chain);
48740
- const chain2 = requireChain(chainKey);
48651
+ const chain2 = chainOf(chainKey);
48741
48652
  if (chain2.namespace !== "eip155") {
48742
48653
  throw new WalletError(
48743
48654
  "CHAIN_UNSUPPORTED",
@@ -49200,14 +49111,13 @@ var OnrampActionProvider = class extends ActionProvider {
49200
49111
  invoke: async (_ctx, input2) => {
49201
49112
  const signer = this.walletContext.activeWallet();
49202
49113
  const { chainKey } = resolveAsset(input2.chain);
49203
- const chainDef = requireChain(chainKey);
49114
+ const chainDef = chainOf(chainKey);
49204
49115
  if (chainDef.namespace !== "eip155") {
49205
49116
  throw new TransferError(
49206
49117
  "CHAIN_UNSUPPORTED",
49207
49118
  `confirm_offramp_transfer is EVM-only. ${chainKey} is not supported.`
49208
49119
  );
49209
49120
  }
49210
- const caip2 = `eip155:${chainDef.chainId}`;
49211
49121
  const decimals = validateOfframpInput(input2, chainKey, chainDef.decimals);
49212
49122
  if (this.priceLookup) {
49213
49123
  const cap = await checkOfframpUsdCap(
@@ -49232,7 +49142,7 @@ var OnrampActionProvider = class extends ActionProvider {
49232
49142
  hash = pending.hash;
49233
49143
  } else {
49234
49144
  hash = await signer.sendTransaction({
49235
- chainId: caip2,
49145
+ chainKey,
49236
49146
  to: input2.depositAddress,
49237
49147
  data: "0x",
49238
49148
  value: "0x" + BigInt(atomic).toString(16)
@@ -49304,6 +49214,10 @@ var AutomateActionProvider = class extends ActionProvider {
49304
49214
  };
49305
49215
  }
49306
49216
  const chainKey = resolveChain(input2.chain);
49217
+ const unsupported = swapSourceUnsupportedReason(chainKey);
49218
+ if (unsupported) {
49219
+ return { success: false, code: "CHAIN_UNSUPPORTED", message: unsupported };
49220
+ }
49307
49221
  const record2 = await this.automationStore.create({
49308
49222
  type: input2.type,
49309
49223
  fromToken: input2.fromToken,
@@ -49329,7 +49243,8 @@ var AutomateActionProvider = class extends ActionProvider {
49329
49243
  invoke: async (_ctx, input2) => {
49330
49244
  const all = await this.automationStore.list();
49331
49245
  const automations = input2.activeOnly ? all.filter((a3) => a3.active) : all;
49332
- return { success: true, count: automations.length, automations };
49246
+ const invalid = await this.automationStore.listInvalid();
49247
+ return { success: true, count: automations.length, automations, invalid };
49333
49248
  }
49334
49249
  };
49335
49250
  }
@@ -49478,7 +49393,7 @@ var X402ActionProvider = class extends ActionProvider {
49478
49393
  "When true (default), silently grants an UNLIMITED Permit2 allowance if the endpoint requires it \u2014 DANGEROUS, see SAFETY in the action description. Defaults true because MCP agents cannot interact with a prompt, but you MUST consult the user before relying on this on any endpoint you have not paid before. Set to false to surface code: 'PERMIT2_APPROVAL_REQUIRED' instead and route approval out-of-band."
49479
49394
  ),
49480
49395
  preferNetwork: import_zod14.z.string().optional().describe(
49481
- `Optional override: restrict payment to this network when the endpoint offers multiple. Accepts either CAIP-2 ("eip155:8453") or a chain key ("base"). Case-insensitive. Use this when the user has a balance on a specific chain \u2014 without it, the picker chooses based on transfer-method preference (EIP-3009 over Permit2), which can land on a chain where the wallet has no funds. If no offered entry matches, the call returns code: 'NO_MATCHING_ROUTE' with the list of offered networks so you can re-ask the user.`
49396
+ 'Optional override: restrict payment to this chain when the endpoint offers multiple. Pass the `chain` of a quoted option ("base"); other chain forms ("eip155:8453", "8453") are resolved too. Use this when the user has a balance on a specific chain \u2014 without it, the picker chooses based on transfer-method preference (EIP-3009 over Permit2), which can land on a chain where the wallet has no funds. If no offered entry matches, the call returns code: \'NO_MATCHING_ROUTE\' with the list of offered networks so you can re-ask the user.'
49482
49397
  ),
49483
49398
  preferMethod: import_zod14.z.string().optional().describe(
49484
49399
  `Optional override: restrict payment to this transfer method ("eip3009", "permit2", or "permit2-exact"). Case-insensitive. Use this to force the gasless route (eip3009) or to insist on a specific Permit2 variant. If no offered entry matches, the call returns code: 'NO_MATCHING_ROUTE'.`
@@ -49495,7 +49410,7 @@ var X402ActionProvider = class extends ActionProvider {
49495
49410
  method: input2.method,
49496
49411
  body: input2.body,
49497
49412
  maxPaymentAtomic: input2.maxPaymentAtomic,
49498
- preferNetwork: input2.preferNetwork,
49413
+ preferNetwork: input2.preferNetwork !== void 0 ? resolveChain(input2.preferNetwork) : void 0,
49499
49414
  preferMethod: input2.preferMethod,
49500
49415
  preferAsset: input2.preferAsset,
49501
49416
  provider,
@@ -49515,7 +49430,7 @@ var X402ActionProvider = class extends ActionProvider {
49515
49430
  content: result.content,
49516
49431
  payment: result.payment,
49517
49432
  approval: result.approval,
49518
- summary: result.payment ? `Paid ${result.payment.amount} ${result.payment.tokenName} on ${result.payment.network} \u2192 ${preview}` : "Request succeeded without payment."
49433
+ summary: result.payment ? `Paid ${result.payment.amount} ${result.payment.tokenName} on ${result.payment.chain} \u2192 ${preview}` : "Request succeeded without payment."
49519
49434
  };
49520
49435
  } catch (err) {
49521
49436
  if (err instanceof X402Error) {
@@ -49558,7 +49473,10 @@ var WalletModeActionProvider = class extends ActionProvider {
49558
49473
  * emits a single text block with the JSON snapshot.
49559
49474
  */
49560
49475
  snapshotResponse(snapshot) {
49561
- const textPayload = snapshot.pairing ? { ...snapshot, pairing: { ...snapshot.pairing, qrCodeImageUrl: void 0 } } : snapshot;
49476
+ const textPayload = {
49477
+ ...snapshot.pairing ? { ...snapshot, pairing: { ...snapshot.pairing, qrCodeImageUrl: void 0 } } : snapshot,
49478
+ twakHome: twakHome()
49479
+ };
49562
49480
  const content = [{ type: "text", text: JSON.stringify(textPayload, null, 2) }];
49563
49481
  if (snapshot.pairing?.qrCodeImageUrl) {
49564
49482
  const match = snapshot.pairing.qrCodeImageUrl.match(/^data:(image\/[^;]+);base64,(.+)$/);
@@ -49598,7 +49516,7 @@ var WalletModeActionProvider = class extends ActionProvider {
49598
49516
  getWalletStatus() {
49599
49517
  return {
49600
49518
  name: "get_wallet_status",
49601
- description: 'Returns the current wallet binding for this MCP server session: state ("unbound" | "local" | "wc-pairing" | "wc-connected"), wallet type (when bound), peer name (when wc-connected), and pairing data (URI / deep link / QR code, when state="wc-pairing"). When state="wc-pairing", the response includes an inline QR-code image (MCP image content), a mobile deep link (`pairing.deepLink`) for users on their phone, and the raw `pairing.uri` as a copyable string for advanced users. Poll this after switch_wallet_mode({mode: "walletconnect"}) until state transitions to "wc-connected"; that\'s when signing actions become usable. If the user asks to see the QR code again (e.g. "show me the QR", "I can\'t see it"), call this action again \u2014 every call while state="wc-pairing" re-emits the inline QR image. Do NOT try to render the QR yourself from the URI or the response JSON.',
49519
+ description: 'Returns the current wallet binding for this MCP server session: state ("unbound" | "local" | "wc-pairing" | "wc-connected"), wallet type (when bound), peer name (when wc-connected), pairing data (URI / deep link / QR code, when state="wc-pairing"), and `twakHome`: the folder this server keeps its files in (wallet, WalletConnect session, credentials), set from TWAK_HOME when the server started (default ~/.twak). When state="wc-pairing", the response includes an inline QR-code image (MCP image content), a mobile deep link (`pairing.deepLink`) for users on their phone, and the raw `pairing.uri` as a copyable string for advanced users. Poll this after switch_wallet_mode({mode: "walletconnect"}) until state transitions to "wc-connected"; that\'s when signing actions become usable. If the user asks to see the QR code again (e.g. "show me the QR", "I can\'t see it"), call this action again \u2014 every call while state="wc-pairing" re-emits the inline QR image. Do NOT try to render the QR yourself from the URI or the response JSON.',
49602
49520
  schema: import_zod15.z.object({}),
49603
49521
  invoke: async () => this.snapshotResponse(this.walletContext.snapshot())
49604
49522
  };
@@ -49735,9 +49653,12 @@ var Erc8004ActionProvider = class extends ActionProvider {
49735
49653
  if (!this.blockchainClient) {
49736
49654
  throw new WalletError("WALLET_NOT_FOUND", "Chain client not available");
49737
49655
  }
49738
- return new Erc8004Operations(resolveErc8004Contract(this.blockchainClient, chainInput), {
49739
- signer
49740
- });
49656
+ return new Erc8004Operations(
49657
+ resolveErc8004Contract(this.blockchainClient, resolveChain(chainInput)),
49658
+ {
49659
+ signer
49660
+ }
49661
+ );
49741
49662
  }
49742
49663
  };
49743
49664
  var jobIdSchema = import_zod17.z.string().regex(/^\d+$/, "jobId must be a decimal integer string.").describe("Numeric jobId as a decimal string.");
@@ -50121,14 +50042,14 @@ var Erc8183ActionProvider = class extends ActionProvider {
50121
50042
  throw new WalletError("WALLET_NOT_FOUND", "Chain client not available");
50122
50043
  }
50123
50044
  const client = this.blockchainClient;
50124
- return new Erc8183Operations(resolveErc8183Contracts(client, chainInput), {
50045
+ return new Erc8183Operations(resolveErc8183Contracts(client, resolveChain(chainInput)), {
50125
50046
  signer,
50126
50047
  erc20At: (token, chainKey) => erc20.using(client).withAddress(token, chainKey),
50127
50048
  policyAt: (address, chainKey) => erc8183Policy.using(client).withAddress(address, chainKey)
50128
50049
  });
50129
50050
  }
50130
50051
  };
50131
- var CHAIN = "bsc";
50052
+ var CHAIN = knownChainKey("bsc");
50132
50053
  function toIso2(deadline) {
50133
50054
  return new Date(Number(deadline) * 1e3).toISOString();
50134
50055
  }
@@ -53626,7 +53547,7 @@ var Protocol = class {
53626
53547
  return;
53627
53548
  }
53628
53549
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
53629
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
53550
+ await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
53630
53551
  options?.signal?.throwIfAborted();
53631
53552
  }
53632
53553
  } catch (error2) {
@@ -53643,7 +53564,7 @@ var Protocol = class {
53643
53564
  */
53644
53565
  request(request, resultSchema, options) {
53645
53566
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
53646
- return new Promise((resolve2, reject) => {
53567
+ return new Promise((resolve4, reject) => {
53647
53568
  const earlyReject = (error2) => {
53648
53569
  reject(error2);
53649
53570
  };
@@ -53721,7 +53642,7 @@ var Protocol = class {
53721
53642
  if (!parseResult.success) {
53722
53643
  reject(parseResult.error);
53723
53644
  } else {
53724
- resolve2(parseResult.data);
53645
+ resolve4(parseResult.data);
53725
53646
  }
53726
53647
  } catch (error2) {
53727
53648
  reject(error2);
@@ -53982,12 +53903,12 @@ var Protocol = class {
53982
53903
  }
53983
53904
  } catch {
53984
53905
  }
53985
- return new Promise((resolve2, reject) => {
53906
+ return new Promise((resolve4, reject) => {
53986
53907
  if (signal.aborted) {
53987
53908
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
53988
53909
  return;
53989
53910
  }
53990
- const timeoutId = setTimeout(resolve2, interval);
53911
+ const timeoutId = setTimeout(resolve4, interval);
53991
53912
  signal.addEventListener("abort", () => {
53992
53913
  clearTimeout(timeoutId);
53993
53914
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -54857,12 +54778,12 @@ var StdioServerTransport = class {
54857
54778
  this.onclose?.();
54858
54779
  }
54859
54780
  send(message) {
54860
- return new Promise((resolve2) => {
54781
+ return new Promise((resolve4) => {
54861
54782
  const json = serializeMessage(message);
54862
54783
  if (this._stdout.write(json)) {
54863
- resolve2();
54784
+ resolve4();
54864
54785
  } else {
54865
- this._stdout.once("drain", resolve2);
54786
+ this._stdout.once("drain", resolve4);
54866
54787
  }
54867
54788
  });
54868
54789
  }
@@ -55009,7 +54930,7 @@ var TwakRestServer = class {
55009
54930
  };
55010
54931
  }
55011
54932
  start() {
55012
- return new Promise((resolve2, reject) => {
54933
+ return new Promise((resolve4, reject) => {
55013
54934
  const server = (0, import_http.createServer)((req, res) => this.handleRequest(req, res));
55014
54935
  this.httpServer = server;
55015
54936
  server.on("error", (err) => {
@@ -55029,20 +54950,20 @@ var TwakRestServer = class {
55029
54950
  } else {
55030
54951
  console.error("WARNING: No API key configured \u2014 REST server is unauthenticated");
55031
54952
  }
55032
- resolve2();
54953
+ resolve4();
55033
54954
  });
55034
54955
  });
55035
54956
  }
55036
54957
  stop() {
55037
- return new Promise((resolve2) => {
54958
+ return new Promise((resolve4) => {
55038
54959
  if (this.httpServer?.listening) {
55039
54960
  this.httpServer.close(() => {
55040
54961
  this.httpServer = null;
55041
- resolve2();
54962
+ resolve4();
55042
54963
  });
55043
54964
  } else {
55044
54965
  this.httpServer = null;
55045
- resolve2();
54966
+ resolve4();
55046
54967
  }
55047
54968
  });
55048
54969
  }
@@ -55271,7 +55192,7 @@ function registerServeCommand(program3) {
55271
55192
  }
55272
55193
  const walletLoader = new AgentWalletLoader({
55273
55194
  walletExists: () => new WalletConfigStore().exists(),
55274
- resolvePassword: async () => opts.password || process.env.TWAK_WALLET_PASSWORD || await new KeychainManager().getWalletPassword() || void 0,
55195
+ resolvePassword: async () => await findWalletPassword(opts) ?? void 0,
55275
55196
  open: (password3) => AgentWalletProvider.fromStorage(password3),
55276
55197
  onLoaded: (agentWallet) => {
55277
55198
  if (autoLockMinutes) {
@@ -55731,7 +55652,7 @@ ${url}`);
55731
55652
  } catch {
55732
55653
  throw new TransferError("VALIDATION_ERROR", `Invalid asset ID: ${opts.asset}`);
55733
55654
  }
55734
- const chainKey = coinTypeToChainKey(coinId);
55655
+ const chainKey = mainnetChainKeyForCoinId(coinId);
55735
55656
  if (!chainKey) {
55736
55657
  throw new TransferError(
55737
55658
  "CHAIN_UNSUPPORTED",
@@ -55797,7 +55718,7 @@ ${url}`);
55797
55718
  decimals,
55798
55719
  memo: opts.memo,
55799
55720
  // Mainnet by construction — onramp has no --chain input and derives
55800
- // chainKey from the asset's coinId via the CHAINS-only resolver.
55721
+ // chainKey from the asset's coinId via mainnetChainKeyForCoinId.
55801
55722
  chainKey
55802
55723
  });
55803
55724
  } catch (err) {
@@ -55894,20 +55815,9 @@ function registerAutomateCommand(program3) {
55894
55815
  if (isNaN(amount) || amount <= 0) {
55895
55816
  throw new AutomationError("VALIDATION_ERROR", "Amount must be a positive number");
55896
55817
  }
55897
- if (!isChainSupported(opts.chain)) {
55898
- throw new AutomationError(
55899
- "CHAIN_UNSUPPORTED",
55900
- `Unsupported chain: ${opts.chain}. Run 'twak chains' to list supported chains.`
55901
- );
55902
- }
55903
- const SWAP_SUPPORTED_NAMESPACES = ["eip155", "solana"];
55904
- const chainInfo = getChainById(opts.chain);
55905
- if (chainInfo && !SWAP_SUPPORTED_NAMESPACES.includes(chainInfo.namespace)) {
55906
- throw new AutomationError(
55907
- "CHAIN_UNSUPPORTED",
55908
- `${chainInfo.name} automations are not supported. Use an EVM chain or Solana.`
55909
- );
55910
- }
55818
+ const chain2 = resolveChain(opts.chain);
55819
+ const unsupported = swapSourceUnsupportedReason(chain2);
55820
+ if (unsupported) throw new AutomationError("CHAIN_UNSUPPORTED", unsupported);
55911
55821
  let intervalMs;
55912
55822
  if (opts.interval) {
55913
55823
  const parsed = parseInterval2(opts.interval);
@@ -55939,7 +55849,7 @@ function registerAutomateCommand(program3) {
55939
55849
  type: opts.interval ? "dca" : "limit",
55940
55850
  fromToken: opts.from,
55941
55851
  toToken: opts.to,
55942
- chain: opts.chain,
55852
+ chain: chain2,
55943
55853
  amount: opts.amount,
55944
55854
  intervalMs,
55945
55855
  targetPrice: opts.price ? parseFloat(opts.price) : void 0,
@@ -55951,11 +55861,11 @@ function registerAutomateCommand(program3) {
55951
55861
  success("Automation created!");
55952
55862
  if (opts.interval && intervalMs) {
55953
55863
  info(
55954
- `DCA: ${opts.amount} ${opts.from} \u2192 ${opts.to} every ${formatInterval(intervalMs)} on ${opts.chain}`
55864
+ `DCA: ${opts.amount} ${opts.from} \u2192 ${opts.to} every ${formatInterval(intervalMs)} on ${chain2}`
55955
55865
  );
55956
55866
  } else {
55957
55867
  info(
55958
- `Limit: swap ${opts.amount} ${opts.from} \u2192 ${opts.to} when price ${opts.condition} $${opts.price} on ${opts.chain}`
55868
+ `Limit: swap ${opts.amount} ${opts.from} \u2192 ${opts.to} when price ${opts.condition} $${opts.price} on ${chain2}`
55959
55869
  );
55960
55870
  }
55961
55871
  output(record2, opts.json);
@@ -55967,6 +55877,9 @@ function registerAutomateCommand(program3) {
55967
55877
  try {
55968
55878
  const store = new AutomationStore();
55969
55879
  const records = await store.list();
55880
+ for (const r3 of await store.listInvalid()) {
55881
+ warn(`Automation ${r3.id} is invalid: ${r3.error} (stored chain "${r3.chain}")`);
55882
+ }
55970
55883
  if (opts.json) {
55971
55884
  const enriched = records.map((r3) => {
55972
55885
  const nextRunAt = r3.type === "dca" && r3.intervalMs ? r3.lastRunAt ? new Date(new Date(r3.lastRunAt).getTime() + r3.intervalMs).toISOString() : (/* @__PURE__ */ new Date()).toISOString() : null;
@@ -56056,32 +55969,30 @@ function makeReadlineConfirm() {
56056
55969
  return async (k4) => {
56057
55970
  const readline = await import("readline");
56058
55971
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
56059
- return new Promise((resolve2) => {
55972
+ return new Promise((resolve4) => {
56060
55973
  rl.question(
56061
55974
  `
56062
- Sign payment authorization: ${k4.amount} (atomic) ${k4.tokenName} on ${k4.network} (${k4.chainKey})
55975
+ Sign payment authorization: ${k4.amount} (atomic) ${k4.tokenName} on ${k4.chainKey}
56063
55976
  Token contract: ${k4.asset}
56064
55977
  Recipient: ${k4.payTo}
56065
55978
  Confirm? [y/N] `,
56066
55979
  (a3) => {
56067
55980
  rl.close();
56068
- resolve2(a3.toLowerCase() === "y");
55981
+ resolve4(a3.toLowerCase() === "y");
56069
55982
  }
56070
55983
  );
56071
55984
  });
56072
55985
  };
56073
55986
  }
56074
55987
  async function autoConfirm(k4) {
56075
- info(
56076
- `x402: paying ${k4.amount} ${k4.tokenName} (${k4.asset}) on ${k4.network} (${k4.chainKey}) \u2192 ${k4.payTo}`
56077
- );
55988
+ info(`x402: paying ${k4.amount} ${k4.tokenName} (${k4.asset}) on ${k4.chainKey} \u2192 ${k4.payTo}`);
56078
55989
  return true;
56079
55990
  }
56080
55991
  function makeReadlineApprovalConfirm() {
56081
55992
  return async (c3) => {
56082
55993
  const readline = await import("readline");
56083
55994
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
56084
- return new Promise((resolve2) => {
55995
+ return new Promise((resolve4) => {
56085
55996
  rl.question(
56086
55997
  `
56087
55998
  This token has not yet been approved for Permit2 on ${c3.chain} (chainId ${c3.chainId}).
@@ -56098,7 +56009,7 @@ the approval alone does not move funds. Revokable anytime via
56098
56009
  Approve unlimited Permit2 allowance? [y/N] `,
56099
56010
  (a3) => {
56100
56011
  rl.close();
56101
- resolve2(a3.toLowerCase() === "y");
56012
+ resolve4(a3.toLowerCase() === "y");
56102
56013
  }
56103
56014
  );
56104
56015
  });
@@ -56108,18 +56019,8 @@ async function autoApproveConfirm(c3) {
56108
56019
  warn(`x402: auto-approving Permit2 unlimited allowance for ${c3.token} on ${c3.chain}`);
56109
56020
  return true;
56110
56021
  }
56111
- function supportedChainName(network) {
56112
- if (network.startsWith("eip155:")) {
56113
- return getChainByEvmId(network.slice("eip155:".length))?.name ?? null;
56114
- }
56115
- return getChainById(network)?.name ?? null;
56116
- }
56117
- function filterAndSortAccepts(accepts) {
56118
- const supported = accepts.flatMap((a3) => {
56119
- const chainName = supportedChainName(a3.network);
56120
- return chainName ? [{ ...a3, chainName }] : [];
56121
- });
56122
- return supported.sort((a3, b3) => Number(b3.preferred) - Number(a3.preferred));
56022
+ function sortAccepts(accepts) {
56023
+ return accepts.map((a3) => ({ ...a3, chainName: chainOf(a3.chain).name })).sort((a3, b3) => Number(b3.preferred) - Number(a3.preferred));
56123
56024
  }
56124
56025
  function safeTokenName(s2) {
56125
56026
  return s2.replace(/[\x00-\x1f\x7f]/g, "");
@@ -56166,7 +56067,7 @@ function registerX402Command(program3) {
56166
56067
  'Maximum payment to auto-approve, in atomic units (e.g. "10000" = 0.01 USDC at 6dp)'
56167
56068
  ).option(
56168
56069
  "--prefer-network <network>",
56169
- 'Restrict route to this chain (e.g. "base", "bsc", or CAIP "eip155:8453"). AND-combined with --prefer-method/--prefer-asset.'
56070
+ 'Restrict route to this chain (e.g. "base", "bsc", or any chain form such as "eip155:8453"). AND-combined with --prefer-method/--prefer-asset.'
56170
56071
  ).option(
56171
56072
  "--prefer-method <method>",
56172
56073
  'Restrict route to this transfer method ("eip3009" or "permit2-exact").'
@@ -56189,7 +56090,7 @@ function registerX402Command(program3) {
56189
56090
  method: opts.method,
56190
56091
  body: opts.body,
56191
56092
  maxPaymentAtomic: opts.maxPayment,
56192
- preferNetwork: opts.preferNetwork,
56093
+ preferNetwork: opts.preferNetwork !== void 0 ? resolveChain(opts.preferNetwork) : void 0,
56193
56094
  preferMethod: opts.preferMethod,
56194
56095
  preferAsset: opts.preferAsset,
56195
56096
  provider,
@@ -56224,7 +56125,7 @@ function registerX402Command(program3) {
56224
56125
  process.exitCode = 1;
56225
56126
  return;
56226
56127
  }
56227
- const sorted = filterAndSortAccepts(result.accepts);
56128
+ const sorted = sortAccepts(result.accepts);
56228
56129
  const hasSignableRoute = sorted.some((r3) => r3.preferred);
56229
56130
  const shQuote = (s2) => `'${s2.replace(/'/g, `'\\''`)}'`;
56230
56131
  const cliCommand = (amount) => {
@@ -56305,14 +56206,15 @@ function registerX402Command(program3) {
56305
56206
 
56306
56207
  // src/analytics.ts
56307
56208
  var fs9 = __toESM(require("fs"));
56308
- var os4 = __toESM(require("os"));
56309
- var path6 = __toESM(require("path"));
56209
+ var os3 = __toESM(require("os"));
56210
+ var path12 = __toESM(require("path"));
56310
56211
  var crypto8 = __toESM(require("crypto"));
56212
+ init_dist();
56311
56213
 
56312
56214
  // package.json
56313
56215
  var package_default = {
56314
56216
  name: "@trustwallet/cli",
56315
- version: "0.23.0",
56217
+ version: "0.24.1",
56316
56218
  description: "TWAK CLI \u2014 command-line interface for Trust Wallet Agent Kit",
56317
56219
  main: "dist/index.js",
56318
56220
  types: "dist/index.d.ts",
@@ -56389,10 +56291,9 @@ try {
56389
56291
  } catch (_e6) {
56390
56292
  }
56391
56293
  var AMPLITUDE_API_KEY = process.env.AMPLITUDE_API_KEY || "__AMPLITUDE_API_KEY__";
56392
- var CONFIG_DIR = path6.join(os4.homedir(), ".twak");
56393
- var ID_FILE = path6.join(CONFIG_DIR, "analytics-id");
56394
- var OPT_IN_FILE = path6.join(CONFIG_DIR, "telemetry-on");
56395
- var OPT_OUT_FILE = path6.join(CONFIG_DIR, "telemetry-off");
56294
+ var idFile = () => path12.join(twakHome(), "analytics-id");
56295
+ var optInFile = () => path12.join(twakHome(), "telemetry-on");
56296
+ var optOutFile = () => path12.join(twakHome(), "telemetry-off");
56396
56297
  var initialized2 = false;
56397
56298
  function isOptedOut() {
56398
56299
  if (process.argv.includes("--no-analytics")) return true;
@@ -56400,31 +56301,31 @@ function isOptedOut() {
56400
56301
  if (env === "off" || env === "0" || env === "false") return true;
56401
56302
  if (env === "on" || env === "1" || env === "true") return false;
56402
56303
  try {
56403
- if (fs9.existsSync(OPT_OUT_FILE)) return true;
56404
- return !fs9.existsSync(OPT_IN_FILE);
56304
+ if (fs9.existsSync(optOutFile())) return true;
56305
+ return !fs9.existsSync(optInFile());
56405
56306
  } catch (_e6) {
56406
56307
  return true;
56407
56308
  }
56408
56309
  }
56409
56310
  function setOptOut2(optOut) {
56410
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
56311
+ fs9.mkdirSync(twakHome(), { recursive: true });
56411
56312
  if (optOut) {
56412
- if (fs9.existsSync(OPT_IN_FILE)) fs9.unlinkSync(OPT_IN_FILE);
56413
- fs9.writeFileSync(OPT_OUT_FILE, "");
56313
+ if (fs9.existsSync(optInFile())) fs9.unlinkSync(optInFile());
56314
+ fs9.writeFileSync(optOutFile(), "");
56414
56315
  } else {
56415
- fs9.writeFileSync(OPT_IN_FILE, "");
56416
- if (fs9.existsSync(OPT_OUT_FILE)) fs9.unlinkSync(OPT_OUT_FILE);
56316
+ fs9.writeFileSync(optInFile(), "");
56317
+ if (fs9.existsSync(optOutFile())) fs9.unlinkSync(optOutFile());
56417
56318
  }
56418
56319
  }
56419
56320
  function getUserId() {
56420
56321
  try {
56421
- if (fs9.existsSync(ID_FILE)) return fs9.readFileSync(ID_FILE, "utf-8").trim();
56322
+ if (fs9.existsSync(idFile())) return fs9.readFileSync(idFile(), "utf-8").trim();
56422
56323
  } catch (_e6) {
56423
56324
  }
56424
56325
  const id = crypto8.randomUUID();
56425
56326
  try {
56426
- fs9.mkdirSync(CONFIG_DIR, { recursive: true });
56427
- fs9.writeFileSync(ID_FILE, id);
56327
+ fs9.mkdirSync(twakHome(), { recursive: true });
56328
+ fs9.writeFileSync(idFile(), id);
56428
56329
  } catch (_e6) {
56429
56330
  }
56430
56331
  return id;
@@ -56441,13 +56342,17 @@ function initAnalytics() {
56441
56342
  async function trackEvent(eventName, properties = {}) {
56442
56343
  if (!initialized2 || isOptedOut()) return;
56443
56344
  const globalProps = {
56444
- os_platform: os4.platform(),
56445
- os_arch: os4.arch(),
56345
+ os_platform: os3.platform(),
56346
+ os_arch: os3.arch(),
56446
56347
  node_version: process.version,
56447
56348
  twak_version: package_default.version
56448
56349
  };
56449
56350
  try {
56450
- const result = track2(eventName, { ...globalProps, ...properties }, { user_id: getUserId() });
56351
+ const result = track2(
56352
+ eventName,
56353
+ { ...globalProps, ...properties },
56354
+ { user_id: getUserId() }
56355
+ );
56451
56356
  await result.promise;
56452
56357
  } catch (_e6) {
56453
56358
  }