@trustwallet/cli 0.24.3 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/onramp.d.ts.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/index.js +295 -216
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -3437,24 +3437,42 @@ async function resolveDecimals(search, chain2, params) {
|
|
|
3437
3437
|
}
|
|
3438
3438
|
const isNative = params.isNative ?? address.toLowerCase() === getNativeAddressPlaceholder(chain2).toLowerCase();
|
|
3439
3439
|
const known = lookupKnownTokenDecimals(chain2, isNative ? void 0 : address);
|
|
3440
|
-
const
|
|
3440
|
+
const needsDecimals = known === void 0 && !isNative;
|
|
3441
3441
|
let searched;
|
|
3442
|
-
if (
|
|
3443
|
-
|
|
3442
|
+
if (needsDecimals || carriesRawEvmAddress(token)) {
|
|
3443
|
+
let matches;
|
|
3444
|
+
try {
|
|
3445
|
+
matches = await search.searchTokens({ query: address, chains: [chain2] });
|
|
3446
|
+
} catch (err) {
|
|
3447
|
+
if (needsDecimals) {
|
|
3448
|
+
throw new CommandError(
|
|
3449
|
+
"NETWORK_ERROR",
|
|
3450
|
+
`Could not look up the decimals of ${token} on ${chain2}: the token search failed (${errorMessage(err)}). Retry.`
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
matches = [];
|
|
3454
|
+
}
|
|
3444
3455
|
const match = matches.find((m2) => m2.address.toLowerCase() === address.toLowerCase());
|
|
3445
3456
|
if (match) {
|
|
3446
3457
|
if (match.address) address = match.address;
|
|
3447
3458
|
if (typeof match.decimals === "number") searched = match.decimals;
|
|
3448
3459
|
}
|
|
3449
3460
|
}
|
|
3450
|
-
const
|
|
3451
|
-
if (
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3461
|
+
const resolved = known !== void 0 ? { address, decimals: known, source: "registry" } : searched !== void 0 ? { address, decimals: searched, source: "search" } : void 0;
|
|
3462
|
+
if (resolved) {
|
|
3463
|
+
if (explicit !== void 0 && explicit !== resolved.decimals) {
|
|
3464
|
+
throw new CommandError(
|
|
3465
|
+
"VALIDATION_ERROR",
|
|
3466
|
+
`${token} on ${chain2} has ${resolved.decimals} decimals (from the ${resolved.source === "registry" ? "token registry" : "token search"}), but ${explicit} was passed. Omit decimals for tokens twak knows, and check that this is the token you meant.`
|
|
3467
|
+
);
|
|
3468
|
+
}
|
|
3469
|
+
return resolved;
|
|
3456
3470
|
}
|
|
3457
|
-
return { address, decimals };
|
|
3471
|
+
if (explicit !== void 0) return { address, decimals: explicit, source: "caller" };
|
|
3472
|
+
throw new CommandError(
|
|
3473
|
+
"VALIDATION_ERROR",
|
|
3474
|
+
`Could not determine decimals for ${token} on ${chain2}: twak does not know this token. Provide decimals explicitly if you know them.`
|
|
3475
|
+
);
|
|
3458
3476
|
}
|
|
3459
3477
|
async function resolveAddress(search, chain2, params) {
|
|
3460
3478
|
const { token, address } = params;
|
|
@@ -6453,7 +6471,6 @@ __export(dist_exports, {
|
|
|
6453
6471
|
getAmberDomainsByCoinId: () => getAmberDomainsByCoinId,
|
|
6454
6472
|
getCoinType: () => getCoinType,
|
|
6455
6473
|
getWalletCore: () => getWalletCore,
|
|
6456
|
-
humanAmountToWei: () => humanAmountToWei,
|
|
6457
6474
|
initTrustSDK: () => initTrustSDK,
|
|
6458
6475
|
isInitialized: () => isInitialized,
|
|
6459
6476
|
patchNaasSession: () => patchNaasSession,
|
|
@@ -7060,13 +7077,6 @@ function chainKeyToDefinedChain(chainKey) {
|
|
|
7060
7077
|
const chain2 = isTestnet(chainKey) ? new import_trust_sdk3.CustomChain(ct5, chainConfig.chainId) : new import_trust_sdk3.DefinedChain(ct5);
|
|
7061
7078
|
return { chain: chain2, chainConfig };
|
|
7062
7079
|
}
|
|
7063
|
-
function humanAmountToWei(amount, decimals = 18) {
|
|
7064
|
-
const parts = amount.split(".");
|
|
7065
|
-
const whole = BigInt(parts[0] || "0");
|
|
7066
|
-
if (parts.length === 1) return whole * 10n ** BigInt(decimals);
|
|
7067
|
-
const frac = parts[1].padEnd(decimals, "0").slice(0, decimals);
|
|
7068
|
-
return whole * 10n ** BigInt(decimals) + BigInt(frac);
|
|
7069
|
-
}
|
|
7070
7080
|
function createPendingTransaction(client, chainKey, hash) {
|
|
7071
7081
|
return {
|
|
7072
7082
|
hash,
|
|
@@ -7109,16 +7119,6 @@ function requireCoinType(coinId) {
|
|
|
7109
7119
|
}
|
|
7110
7120
|
return ct5;
|
|
7111
7121
|
}
|
|
7112
|
-
function getCoinDecimals(coinId) {
|
|
7113
|
-
try {
|
|
7114
|
-
const wc3 = getWalletCore();
|
|
7115
|
-
const ct5 = requireCoinType(coinId);
|
|
7116
|
-
return wc3.CoinTypeConfiguration.getDecimals(ct5);
|
|
7117
|
-
} catch {
|
|
7118
|
-
const chainKey = mainnetChainKeyForCoinId(coinId);
|
|
7119
|
-
return chainKey ? chainOf(chainKey).decimals : 18;
|
|
7120
|
-
}
|
|
7121
|
-
}
|
|
7122
7122
|
function tokenTypeForCoinId(coinId) {
|
|
7123
7123
|
switch (coinId) {
|
|
7124
7124
|
// Tron
|
|
@@ -7627,25 +7627,15 @@ var init_dist3 = __esm({
|
|
|
7627
7627
|
const ct5 = requireCoinType(coinId);
|
|
7628
7628
|
const account = this.getAccountFromSigner(chainKey);
|
|
7629
7629
|
const asset = contractAddress ? new import_trust_sdk2.Asset.Token(account, contractAddress, tokenTypeForCoinId(coinId)) : new import_trust_sdk2.Asset.Coin(account);
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
const known = lookupKnownTokenDecimals(chainKey, contractAddress);
|
|
7635
|
-
if (known === void 0) {
|
|
7636
|
-
throw new TwakValidationError(
|
|
7637
|
-
`Cannot determine decimals for ${params.assetId}; pass decimals explicitly.`
|
|
7638
|
-
);
|
|
7639
|
-
}
|
|
7640
|
-
decimals = known;
|
|
7641
|
-
} else {
|
|
7642
|
-
decimals = getCoinDecimals(coinId);
|
|
7630
|
+
if (params.atomicAmount < 0n) {
|
|
7631
|
+
throw new TwakValidationError(
|
|
7632
|
+
`atomicAmount must not be negative, got ${params.atomicAmount}.`
|
|
7633
|
+
);
|
|
7643
7634
|
}
|
|
7644
|
-
const amountWei = humanAmountToWei(params.amount, decimals);
|
|
7645
7635
|
const transaction = new import_trust_sdk2.TransactionTransfer(
|
|
7646
7636
|
params.to,
|
|
7647
7637
|
asset,
|
|
7648
|
-
|
|
7638
|
+
params.atomicAmount.toString(),
|
|
7649
7639
|
false,
|
|
7650
7640
|
params.memo || null
|
|
7651
7641
|
);
|
|
@@ -7722,7 +7712,7 @@ var init_dist3 = __esm({
|
|
|
7722
7712
|
const transaction = new import_trust_sdk2.TransactionTransfer(
|
|
7723
7713
|
params.to,
|
|
7724
7714
|
asset,
|
|
7725
|
-
params.
|
|
7715
|
+
params.atomicAmount.toString(),
|
|
7726
7716
|
false,
|
|
7727
7717
|
params.memo || null
|
|
7728
7718
|
);
|
|
@@ -8352,7 +8342,7 @@ var init_dist3 = __esm({
|
|
|
8352
8342
|
const result = await this.blockchainClient.transfer({
|
|
8353
8343
|
assetId,
|
|
8354
8344
|
to: params.to,
|
|
8355
|
-
|
|
8345
|
+
atomicAmount: 0n,
|
|
8356
8346
|
hdWallet,
|
|
8357
8347
|
chainKey
|
|
8358
8348
|
});
|
|
@@ -41911,10 +41901,13 @@ var WalletConnectProvider = class extends WalletProvider {
|
|
|
41911
41901
|
`transfer on ${chainKey} is not supported in WalletConnect mode (EVM-only). Switch to local wallet mode for ${chainKey} transfers.`
|
|
41912
41902
|
);
|
|
41913
41903
|
}
|
|
41914
|
-
|
|
41915
|
-
|
|
41904
|
+
const { atomicAmount } = request;
|
|
41905
|
+
if (atomicAmount < 0n) {
|
|
41906
|
+
throw new TransferError(
|
|
41907
|
+
"VALIDATION_ERROR",
|
|
41908
|
+
`atomicAmount must not be negative, got ${atomicAmount}.`
|
|
41909
|
+
);
|
|
41916
41910
|
}
|
|
41917
|
-
const atomicAmount = BigInt(parseAmount(request.amount, request.decimals));
|
|
41918
41911
|
const { contractAddress } = parseTokenId(request.assetId);
|
|
41919
41912
|
if (contractAddress) {
|
|
41920
41913
|
assertEvmAddress(contractAddress, "tokenAddress");
|
|
@@ -43309,9 +43302,9 @@ var TransferExecutor = class {
|
|
|
43309
43302
|
`Unknown token: ${assetId} on ${chainKey}. Use a contract address (0x...) or a supported symbol.`
|
|
43310
43303
|
);
|
|
43311
43304
|
}
|
|
43312
|
-
let resolvedTo;
|
|
43305
|
+
let resolvedTo = params.to;
|
|
43313
43306
|
try {
|
|
43314
|
-
resolvedTo = await resolveAddressOrName(params.to);
|
|
43307
|
+
if (params.resolveNames !== false) resolvedTo = await resolveAddressOrName(params.to);
|
|
43315
43308
|
} catch (err) {
|
|
43316
43309
|
const msg = errorMessage(err);
|
|
43317
43310
|
if (msg.includes("Could not resolve name")) {
|
|
@@ -43336,7 +43329,7 @@ var TransferExecutor = class {
|
|
|
43336
43329
|
isNative: !contractAddress,
|
|
43337
43330
|
explicitDecimals: params.decimals ?? null
|
|
43338
43331
|
});
|
|
43339
|
-
parseAmount(params.amount, decimals);
|
|
43332
|
+
const atomicAmount = BigInt(parseAmount(params.amount, decimals));
|
|
43340
43333
|
if (!params.safety?.skip) {
|
|
43341
43334
|
const maxUsd = params.safety?.maxUsd ?? DEFAULT_MAX_TRANSFER_USD;
|
|
43342
43335
|
const warnThreshold = params.safety?.warnThresholdUsd ?? DEFAULT_WARN_THRESHOLD_USD;
|
|
@@ -43371,8 +43364,7 @@ var TransferExecutor = class {
|
|
|
43371
43364
|
chainKey,
|
|
43372
43365
|
assetId,
|
|
43373
43366
|
to: resolvedTo,
|
|
43374
|
-
|
|
43375
|
-
decimals,
|
|
43367
|
+
atomicAmount,
|
|
43376
43368
|
memo: params.memo
|
|
43377
43369
|
});
|
|
43378
43370
|
} catch (err) {
|
|
@@ -44483,8 +44475,21 @@ var SwapClient = class {
|
|
|
44483
44475
|
}
|
|
44484
44476
|
return transactions;
|
|
44485
44477
|
}
|
|
44478
|
+
/**
|
|
44479
|
+
* Search Trust's asset index, which covers mainnets only. A testnet shares
|
|
44480
|
+
* its mainnet's coin ID, so querying it would return mainnet assets (and
|
|
44481
|
+
* their decimals) for testnet addresses: testnet chains are left out of the
|
|
44482
|
+
* query, and a search on testnets only has no results.
|
|
44483
|
+
*/
|
|
44486
44484
|
async searchTokens(params) {
|
|
44487
|
-
|
|
44485
|
+
let coinIds;
|
|
44486
|
+
if (params.networks) {
|
|
44487
|
+
coinIds = params.networks;
|
|
44488
|
+
} else {
|
|
44489
|
+
const chains = (params.chains ?? mainnetChainKeys()).filter((c3) => !isTestnet(c3));
|
|
44490
|
+
if (chains.length === 0) return [];
|
|
44491
|
+
coinIds = chains.map(coinIdOf).join(",");
|
|
44492
|
+
}
|
|
44488
44493
|
const queryParams = new URLSearchParams({
|
|
44489
44494
|
networks: coinIds,
|
|
44490
44495
|
exactQuery: params.query,
|
|
@@ -44837,7 +44842,7 @@ function registerTransferCommand(program3) {
|
|
|
44837
44842
|
"Chain key (e.g., base, ethereum). When set, --token is a token contract address; omit --token to send the native coin."
|
|
44838
44843
|
).option(
|
|
44839
44844
|
"--decimals <n>",
|
|
44840
|
-
"Token decimals
|
|
44845
|
+
"Token decimals, only for a token twak does not know (rejected if it contradicts the registry or token search)"
|
|
44841
44846
|
).option(
|
|
44842
44847
|
"--confirm-to <address>",
|
|
44843
44848
|
"Pin the expected resolved address \u2014 transfer is rejected if resolution returns a different address"
|
|
@@ -44943,7 +44948,7 @@ init_dist();
|
|
|
44943
44948
|
function registerSwapCommand(program3) {
|
|
44944
44949
|
attachPaymasterOption(program3.command("swap")).description("Quote or execute a token swap").argument("<amountOrFrom>", "Amount to swap, or source token when using --usd").argument("<fromOrTo>", "Source token, or destination token when using --usd").argument("[to]", "Destination token (omit when using --usd with 2 args)").option("--chain <id>", "Chain", "ethereum").option("--to-chain <id>", "Destination chain (for cross-chain swaps)").option("--slippage <pct>", "Slippage tolerance %", "1").option(
|
|
44945
44950
|
"--decimals <n>",
|
|
44946
|
-
"Source token decimals
|
|
44951
|
+
"Source token decimals, only for a token twak does not know (rejected if it contradicts the registry or token search)"
|
|
44947
44952
|
).option("--usd <amount>", "Swap a USD-equivalent amount of the source token").option("--quote-only", "Get quote without executing").option("--password <password>", "Wallet password (required to execute)").option("--json", "JSON output").action(
|
|
44948
44953
|
async (amountOrFrom, fromOrTo, toOrUndefined, opts) => {
|
|
44949
44954
|
try {
|
|
@@ -47168,7 +47173,6 @@ var import_zod11 = require("zod");
|
|
|
47168
47173
|
init_dist();
|
|
47169
47174
|
var import_zod12 = require("zod");
|
|
47170
47175
|
init_dist();
|
|
47171
|
-
init_dist4();
|
|
47172
47176
|
var import_zod13 = require("zod");
|
|
47173
47177
|
init_dist();
|
|
47174
47178
|
var import_zod14 = require("zod");
|
|
@@ -48002,9 +48006,34 @@ var ActionProvider = class {
|
|
|
48002
48006
|
var ActionRegistry = class {
|
|
48003
48007
|
providers = [];
|
|
48004
48008
|
actions = /* @__PURE__ */ new Map();
|
|
48009
|
+
withheld = /* @__PURE__ */ new Set();
|
|
48010
|
+
readOnly;
|
|
48011
|
+
constructor(options = {}) {
|
|
48012
|
+
this.readOnly = options.readOnly ?? false;
|
|
48013
|
+
}
|
|
48014
|
+
/**
|
|
48015
|
+
* Throws when an action name is already registered (served or withheld) or
|
|
48016
|
+
* repeated within the provider: two actions under one name is a wiring bug,
|
|
48017
|
+
* and letting one silently replace the other would change what a tool name
|
|
48018
|
+
* does without notice. Nothing is registered when it throws.
|
|
48019
|
+
*/
|
|
48005
48020
|
register(provider) {
|
|
48021
|
+
const actions = provider.getActions();
|
|
48022
|
+
const seen = /* @__PURE__ */ new Set();
|
|
48023
|
+
for (const { name: name2 } of actions) {
|
|
48024
|
+
if (seen.has(name2) || this.actions.has(name2) || this.withheld.has(name2)) {
|
|
48025
|
+
throw new Error(
|
|
48026
|
+
`Action "${name2}" from provider "${provider.name}" is already registered; action names must be unique.`
|
|
48027
|
+
);
|
|
48028
|
+
}
|
|
48029
|
+
seen.add(name2);
|
|
48030
|
+
}
|
|
48006
48031
|
this.providers.push(provider);
|
|
48007
|
-
for (const action of
|
|
48032
|
+
for (const action of actions) {
|
|
48033
|
+
if (this.readOnly && !action.annotations.readOnly) {
|
|
48034
|
+
this.withheld.add(action.name);
|
|
48035
|
+
continue;
|
|
48036
|
+
}
|
|
48008
48037
|
this.actions.set(action.name, action);
|
|
48009
48038
|
}
|
|
48010
48039
|
}
|
|
@@ -48015,12 +48044,32 @@ var ActionRegistry = class {
|
|
|
48015
48044
|
getAction(name2) {
|
|
48016
48045
|
return this.actions.get(name2);
|
|
48017
48046
|
}
|
|
48047
|
+
/**
|
|
48048
|
+
* The error for a call to an action that read-only mode withheld, so the
|
|
48049
|
+
* caller learns why instead of seeing an unknown action. Undefined for any
|
|
48050
|
+
* other name.
|
|
48051
|
+
*/
|
|
48052
|
+
withheldError(name2) {
|
|
48053
|
+
if (!this.withheld.has(name2)) return void 0;
|
|
48054
|
+
return {
|
|
48055
|
+
code: "READ_ONLY",
|
|
48056
|
+
message: `${name2} is not available: this server is read-only (twak serve --read-only) and serves only tools that read. Restart it without --read-only to use ${name2}.`
|
|
48057
|
+
};
|
|
48058
|
+
}
|
|
48018
48059
|
getProviders() {
|
|
48019
48060
|
return this.providers;
|
|
48020
48061
|
}
|
|
48021
48062
|
};
|
|
48022
48063
|
var CHAIN_DESC = 'Chain (e.g., "ethereum", "bsc", "solana"). Accepts chain key, CAIP-2 ("eip155:1"), EVM chainId ("56", "0x38"), aliases ("matic", "op"), and asset IDs ("c60").';
|
|
48023
48064
|
var TOKEN_ADDR_DESC = "Token contract address (ERC-20 / SPL). Omit for the chain native coin (ETH, BNB, SOL, etc.).";
|
|
48065
|
+
var READS_REMOTE = { readOnly: true, openWorld: true };
|
|
48066
|
+
var READS_LOCAL = { readOnly: true, openWorld: false };
|
|
48067
|
+
var SIGNS = {
|
|
48068
|
+
readOnly: false,
|
|
48069
|
+
destructive: true,
|
|
48070
|
+
idempotent: false,
|
|
48071
|
+
openWorld: true
|
|
48072
|
+
};
|
|
48024
48073
|
var BalanceActionProvider = class extends ActionProvider {
|
|
48025
48074
|
name = "balance";
|
|
48026
48075
|
description = "Check token balances and holdings";
|
|
@@ -48030,6 +48079,7 @@ var BalanceActionProvider = class extends ActionProvider {
|
|
|
48030
48079
|
getBalance() {
|
|
48031
48080
|
return {
|
|
48032
48081
|
name: "get_balance",
|
|
48082
|
+
annotations: READS_REMOTE,
|
|
48033
48083
|
description: 'Read the on-chain balance of a single asset for a wallet address. Omit `tokenAddress` for the chain native coin (ETH, BNB, SOL, BTC, ...). Provide `tokenAddress` to read an ERC-20 / SPL token (e.g. tokenAddress="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" with chain="base" for USDC on Base).',
|
|
48034
48084
|
schema: import_zod3.z.object({
|
|
48035
48085
|
address: import_zod3.z.string().describe("Wallet address on the specified chain."),
|
|
@@ -48045,6 +48095,7 @@ var BalanceActionProvider = class extends ActionProvider {
|
|
|
48045
48095
|
getTokenHoldings() {
|
|
48046
48096
|
return {
|
|
48047
48097
|
name: "get_token_holdings",
|
|
48098
|
+
annotations: READS_REMOTE,
|
|
48048
48099
|
description: "Get ERC-20 / SPL token holdings for a wallet address on a chain. Returns the list of tokens the address holds. Omit `tokenAddress` to list all token holdings on the chain.",
|
|
48049
48100
|
schema: import_zod3.z.object({
|
|
48050
48101
|
address: import_zod3.z.string().describe("Wallet address on the specified chain."),
|
|
@@ -48092,6 +48143,7 @@ var BalanceActionProvider = class extends ActionProvider {
|
|
|
48092
48143
|
searchAssets() {
|
|
48093
48144
|
return {
|
|
48094
48145
|
name: "search_assets",
|
|
48146
|
+
annotations: READS_REMOTE,
|
|
48095
48147
|
description: "Search for tokens by name, symbol, or address",
|
|
48096
48148
|
schema: import_zod3.z.object({
|
|
48097
48149
|
query: import_zod3.z.string().describe("Search query"),
|
|
@@ -48133,6 +48185,7 @@ var TransferActionProvider = class extends ActionProvider {
|
|
|
48133
48185
|
transfer() {
|
|
48134
48186
|
return {
|
|
48135
48187
|
name: "transfer",
|
|
48188
|
+
annotations: SIGNS,
|
|
48136
48189
|
description: 'Transfer native or ERC-20 tokens to a destination address. Resolves ENS for the "to" field, applies a USD safety cap, and works with both the local agent wallet (any supported chain \u2014 EVM, Solana, Bitcoin, \u2026) and an external WalletConnect-paired wallet (EVM chains only).',
|
|
48137
48190
|
schema: import_zod4.z.object({
|
|
48138
48191
|
chain: import_zod4.z.string().describe(CHAIN_DESC),
|
|
@@ -48140,7 +48193,7 @@ var TransferActionProvider = class extends ActionProvider {
|
|
|
48140
48193
|
amount: import_zod4.z.string().describe('Amount in human-readable format (e.g., "1.5", "0.01")'),
|
|
48141
48194
|
tokenAddress: import_zod4.z.string().trim().min(1).optional().describe(TOKEN_ADDR_DESC),
|
|
48142
48195
|
decimals: import_zod4.z.coerce.number().int().min(0).max(36).optional().describe(
|
|
48143
|
-
"Token decimals
|
|
48196
|
+
"Token decimals, only for a token twak does not know. Omit it otherwise: twak resolves decimals from its registry or the Trust token search, and rejects a value that contradicts them. Needed only when the transfer fails asking for decimals."
|
|
48144
48197
|
),
|
|
48145
48198
|
memo: import_zod4.z.string().optional().describe("Optional memo/note (local agent wallet only)."),
|
|
48146
48199
|
confirmTo: import_zod4.z.string().optional().describe(
|
|
@@ -48201,6 +48254,7 @@ var SwapActionProvider = class extends ActionProvider {
|
|
|
48201
48254
|
swap() {
|
|
48202
48255
|
return {
|
|
48203
48256
|
name: "swap",
|
|
48257
|
+
annotations: SIGNS,
|
|
48204
48258
|
description: "Execute a token swap via Trust Wallet (supports all chains including cross-chain)",
|
|
48205
48259
|
schema: import_zod5.z.object({
|
|
48206
48260
|
fromChain: import_zod5.z.string().describe(`Source chain. ${CHAIN_DESC}`),
|
|
@@ -48278,6 +48332,7 @@ var SwapActionProvider = class extends ActionProvider {
|
|
|
48278
48332
|
getSwapQuote() {
|
|
48279
48333
|
return {
|
|
48280
48334
|
name: "get_swap_quote",
|
|
48335
|
+
annotations: READS_REMOTE,
|
|
48281
48336
|
description: "Get a swap quote without executing",
|
|
48282
48337
|
schema: import_zod5.z.object({
|
|
48283
48338
|
fromChain: import_zod5.z.string().describe(`Source chain. ${CHAIN_DESC}`),
|
|
@@ -48346,6 +48401,7 @@ var SwapActionProvider = class extends ActionProvider {
|
|
|
48346
48401
|
getTokenPrice() {
|
|
48347
48402
|
return {
|
|
48348
48403
|
name: "get_token_price",
|
|
48404
|
+
annotations: READS_REMOTE,
|
|
48349
48405
|
description: "Get current USD price for a token",
|
|
48350
48406
|
schema: import_zod5.z.object({
|
|
48351
48407
|
chain: import_zod5.z.string().describe(CHAIN_DESC),
|
|
@@ -48398,6 +48454,7 @@ var SecurityActionProvider = class extends ActionProvider {
|
|
|
48398
48454
|
validateTransaction() {
|
|
48399
48455
|
return {
|
|
48400
48456
|
name: "validate_transaction",
|
|
48457
|
+
annotations: READS_REMOTE,
|
|
48401
48458
|
description: "Validate an address or transaction for security. Provide `chain` (and optional `tokenAddress`) to scope the validation to a specific asset; omit both for a generic address check.",
|
|
48402
48459
|
schema: import_zod6.z.object({
|
|
48403
48460
|
address: import_zod6.z.string().describe("Address to validate"),
|
|
@@ -48421,6 +48478,7 @@ var SecurityActionProvider = class extends ActionProvider {
|
|
|
48421
48478
|
getAssetInfo() {
|
|
48422
48479
|
return {
|
|
48423
48480
|
name: "get_asset_info",
|
|
48481
|
+
annotations: READS_REMOTE,
|
|
48424
48482
|
description: "Get detailed information about an asset (name, symbol, price, market cap). Omit `tokenAddress` for the chain native coin.",
|
|
48425
48483
|
schema: import_zod6.z.object({
|
|
48426
48484
|
chain: import_zod6.z.string().describe(CHAIN_DESC),
|
|
@@ -48449,6 +48507,7 @@ var HistoryActionProvider = class extends ActionProvider {
|
|
|
48449
48507
|
getTransactionHistory() {
|
|
48450
48508
|
return {
|
|
48451
48509
|
name: "get_transaction_history",
|
|
48510
|
+
annotations: READS_REMOTE,
|
|
48452
48511
|
description: "Get transaction history for an address",
|
|
48453
48512
|
schema: import_zod7.z.object({
|
|
48454
48513
|
address: import_zod7.z.string().describe("Wallet address"),
|
|
@@ -48466,6 +48525,7 @@ var HistoryActionProvider = class extends ActionProvider {
|
|
|
48466
48525
|
getTransactionDetails() {
|
|
48467
48526
|
return {
|
|
48468
48527
|
name: "get_transaction_details",
|
|
48528
|
+
annotations: READS_REMOTE,
|
|
48469
48529
|
description: "Get details of a specific transaction by hash",
|
|
48470
48530
|
schema: import_zod7.z.object({
|
|
48471
48531
|
hash: import_zod7.z.string().describe("Transaction hash"),
|
|
@@ -48482,6 +48542,7 @@ var HistoryActionProvider = class extends ActionProvider {
|
|
|
48482
48542
|
getSwapHistory() {
|
|
48483
48543
|
return {
|
|
48484
48544
|
name: "get_swap_history",
|
|
48545
|
+
annotations: READS_REMOTE,
|
|
48485
48546
|
description: "Get swap transaction history",
|
|
48486
48547
|
schema: import_zod7.z.object({
|
|
48487
48548
|
address: import_zod7.z.string().describe("Wallet address"),
|
|
@@ -48509,6 +48570,7 @@ var AlertActionProvider = class extends ActionProvider {
|
|
|
48509
48570
|
createAlert() {
|
|
48510
48571
|
return {
|
|
48511
48572
|
name: "create_alert",
|
|
48573
|
+
annotations: { readOnly: false, destructive: false, idempotent: false, openWorld: false },
|
|
48512
48574
|
description: "Create a price alert. Triggers when the asset price crosses a target. Omit `tokenAddress` to watch the chain native coin (ETH, BNB, SOL, etc.).",
|
|
48513
48575
|
schema: import_zod8.z.object({
|
|
48514
48576
|
chain: import_zod8.z.string().describe(CHAIN_DESC),
|
|
@@ -48535,6 +48597,7 @@ var AlertActionProvider = class extends ActionProvider {
|
|
|
48535
48597
|
listAlerts() {
|
|
48536
48598
|
return {
|
|
48537
48599
|
name: "list_alerts",
|
|
48600
|
+
annotations: READS_LOCAL,
|
|
48538
48601
|
description: "List all price alerts",
|
|
48539
48602
|
schema: import_zod8.z.object({
|
|
48540
48603
|
activeOnly: import_zod8.z.boolean().optional().default(false).describe("Only show active alerts")
|
|
@@ -48549,6 +48612,9 @@ var AlertActionProvider = class extends ActionProvider {
|
|
|
48549
48612
|
checkAlerts() {
|
|
48550
48613
|
return {
|
|
48551
48614
|
name: "check_alerts",
|
|
48615
|
+
// Destructive: an alert that fires is deactivated, so later checks and
|
|
48616
|
+
// the watcher no longer evaluate it.
|
|
48617
|
+
annotations: { readOnly: false, destructive: true, idempotent: false, openWorld: true },
|
|
48552
48618
|
description: "Check active alerts against current prices and trigger any that match",
|
|
48553
48619
|
schema: import_zod8.z.object({}),
|
|
48554
48620
|
invoke: async (ctx, _input) => {
|
|
@@ -48578,6 +48644,7 @@ var AlertActionProvider = class extends ActionProvider {
|
|
|
48578
48644
|
deleteAlert() {
|
|
48579
48645
|
return {
|
|
48580
48646
|
name: "delete_alert",
|
|
48647
|
+
annotations: { readOnly: false, destructive: true, idempotent: true, openWorld: false },
|
|
48581
48648
|
description: "Delete a price alert by ID",
|
|
48582
48649
|
schema: import_zod8.z.object({
|
|
48583
48650
|
id: import_zod8.z.string().describe("Alert ID to delete")
|
|
@@ -48608,6 +48675,7 @@ var AgentWalletActionProvider = class extends ActionProvider {
|
|
|
48608
48675
|
getAddress() {
|
|
48609
48676
|
return {
|
|
48610
48677
|
name: "get_address",
|
|
48678
|
+
annotations: READS_LOCAL,
|
|
48611
48679
|
description: "Get the active wallet's address for a specific chain.",
|
|
48612
48680
|
schema: import_zod9.z.object({
|
|
48613
48681
|
chain: import_zod9.z.string().describe(CHAIN_DESC)
|
|
@@ -48623,6 +48691,7 @@ var AgentWalletActionProvider = class extends ActionProvider {
|
|
|
48623
48691
|
listAddresses() {
|
|
48624
48692
|
return {
|
|
48625
48693
|
name: "list_addresses",
|
|
48694
|
+
annotations: READS_LOCAL,
|
|
48626
48695
|
description: "Get the active wallet's addresses for every supported chain. Returns one address per chain.",
|
|
48627
48696
|
schema: import_zod9.z.object({}),
|
|
48628
48697
|
invoke: async () => {
|
|
@@ -48638,6 +48707,7 @@ var AgentWalletActionProvider = class extends ActionProvider {
|
|
|
48638
48707
|
walletBalance() {
|
|
48639
48708
|
return {
|
|
48640
48709
|
name: "wallet_balance",
|
|
48710
|
+
annotations: READS_REMOTE,
|
|
48641
48711
|
description: "Read the native-coin balance (BNB on BSC, ETH on Ethereum / Base / Arbitrum, SOL on Solana, etc.) for the active wallet on a specific chain. For ERC-20 / SPL token balances, use `get_balance`.",
|
|
48642
48712
|
schema: import_zod9.z.object({
|
|
48643
48713
|
chain: import_zod9.z.string().describe(CHAIN_DESC)
|
|
@@ -48654,6 +48724,7 @@ var AgentWalletActionProvider = class extends ActionProvider {
|
|
|
48654
48724
|
walletPortfolio() {
|
|
48655
48725
|
return {
|
|
48656
48726
|
name: "wallet_portfolio",
|
|
48727
|
+
annotations: READS_REMOTE,
|
|
48657
48728
|
description: "Read the active wallet's full portfolio across chains: native-coin and known-token balances, each with its USD value, plus the total USD. Operates on the active wallet (local HD or WalletConnect-paired) \u2014 takes no address. Native rows are returned for every queried chain (even at zero balance); zero-balance token rows are omitted. Use `wallet_balance` for a single native balance or `get_balance` for one specific token.",
|
|
48658
48729
|
schema: import_zod9.z.object({
|
|
48659
48730
|
chains: import_zod9.z.string().optional().describe(
|
|
@@ -48689,6 +48760,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
48689
48760
|
tokenBalance() {
|
|
48690
48761
|
return {
|
|
48691
48762
|
name: "token_balance",
|
|
48763
|
+
annotations: READS_REMOTE,
|
|
48692
48764
|
description: "Get balance for a specific token or native asset on a chain.",
|
|
48693
48765
|
schema: import_zod10.z.object({
|
|
48694
48766
|
chain: import_zod10.z.string().describe(CHAIN_DESC),
|
|
@@ -48708,6 +48780,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
48708
48780
|
approveToken() {
|
|
48709
48781
|
return {
|
|
48710
48782
|
name: "approve_token",
|
|
48783
|
+
annotations: SIGNS,
|
|
48711
48784
|
description: `Approve a spender to use ERC-20 tokens on your behalf. SAFETY: when amount is "unlimited" (or the MaxUint256 decimal string), you MUST surface the risk to the user and get their explicit consent before calling this tool \u2014 unlimited approvals grant the spender access to ALL of the user's tokens of this type, including future transfers, and have been used in many drainer attacks. Prefer a finite amount equal to the immediate need. Use revoke_token_approval (or amount: "0") to revoke an existing approval.`,
|
|
48712
48785
|
schema: import_zod10.z.object({
|
|
48713
48786
|
chain: import_zod10.z.string().describe(CHAIN_DESC),
|
|
@@ -48739,6 +48812,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
48739
48812
|
revokeTokenApproval() {
|
|
48740
48813
|
return {
|
|
48741
48814
|
name: "revoke_token_approval",
|
|
48815
|
+
annotations: SIGNS,
|
|
48742
48816
|
description: "Revoke an ERC-20 token approval by setting the spender allowance to 0. Use this to remove a previously-granted allowance \u2014 especially important after unlimited approvals or any approval you no longer need. This is the inverse of approve_token.",
|
|
48743
48817
|
schema: import_zod10.z.object({
|
|
48744
48818
|
chain: import_zod10.z.string().describe(CHAIN_DESC),
|
|
@@ -48768,6 +48842,7 @@ var TokenActionProvider = class extends ActionProvider {
|
|
|
48768
48842
|
checkAllowance() {
|
|
48769
48843
|
return {
|
|
48770
48844
|
name: "check_allowance",
|
|
48845
|
+
annotations: READS_REMOTE,
|
|
48771
48846
|
description: "Check the ERC-20 allowance for a spender address.",
|
|
48772
48847
|
schema: import_zod10.z.object({
|
|
48773
48848
|
chain: import_zod10.z.string().describe(CHAIN_DESC),
|
|
@@ -48808,6 +48883,7 @@ var MarketActionProvider = class extends ActionProvider {
|
|
|
48808
48883
|
getTrendingTokens() {
|
|
48809
48884
|
return {
|
|
48810
48885
|
name: "get_trending_tokens",
|
|
48886
|
+
annotations: READS_REMOTE,
|
|
48811
48887
|
description: "Get a list of trending tokens by market activity",
|
|
48812
48888
|
schema: import_zod11.z.object({
|
|
48813
48889
|
limit: import_zod11.z.coerce.number().optional().default(20).describe("Number of tokens to return (default 20)")
|
|
@@ -48821,6 +48897,7 @@ var MarketActionProvider = class extends ActionProvider {
|
|
|
48821
48897
|
checkTokenRisk() {
|
|
48822
48898
|
return {
|
|
48823
48899
|
name: "check_token_risk",
|
|
48900
|
+
annotations: READS_REMOTE,
|
|
48824
48901
|
description: "Check security and risk information for a token (honeypot detection, audit status, freeze authority). Omit `tokenAddress` to check the chain native coin.",
|
|
48825
48902
|
schema: import_zod11.z.object({
|
|
48826
48903
|
chain: import_zod11.z.string().describe(CHAIN_DESC),
|
|
@@ -48850,7 +48927,7 @@ var MarketActionProvider = class extends ActionProvider {
|
|
|
48850
48927
|
}
|
|
48851
48928
|
};
|
|
48852
48929
|
var DEFAULT_MAX_OFFRAMP_USD = 1e4;
|
|
48853
|
-
function validateOfframpInput(input2
|
|
48930
|
+
function validateOfframpInput(input2) {
|
|
48854
48931
|
if (!isEvmAddress(input2.depositAddress)) {
|
|
48855
48932
|
throw new TransferError(
|
|
48856
48933
|
"VALIDATION_ERROR",
|
|
@@ -48860,42 +48937,11 @@ function validateOfframpInput(input2, chainKey, nativeDecimals) {
|
|
|
48860
48937
|
if (input2.tokenAddress && !isEvmAddress(input2.tokenAddress)) {
|
|
48861
48938
|
throw new TransferError("VALIDATION_ERROR", `Malformed tokenAddress: ${input2.tokenAddress}`);
|
|
48862
48939
|
}
|
|
48863
|
-
let decimals;
|
|
48864
|
-
if (input2.tokenAddress) {
|
|
48865
|
-
if (input2.decimals === void 0) {
|
|
48866
|
-
throw new TransferError(
|
|
48867
|
-
"VALIDATION_ERROR",
|
|
48868
|
-
`decimals is required for ERC-20 token ${input2.tokenAddress} on ${chainKey}. Pass the token's decimals explicitly (6 for USDC/USDT, 18 for DAI, etc.) \u2014 silently defaulting to 18 could over-pay the provider by orders of magnitude.`
|
|
48869
|
-
);
|
|
48870
|
-
}
|
|
48871
|
-
decimals = input2.decimals;
|
|
48872
|
-
} else {
|
|
48873
|
-
decimals = nativeDecimals;
|
|
48874
|
-
}
|
|
48875
48940
|
try {
|
|
48876
|
-
assertStrictPositiveAmount(input2.cryptoAmount
|
|
48941
|
+
assertStrictPositiveAmount(input2.cryptoAmount);
|
|
48877
48942
|
} catch (err) {
|
|
48878
48943
|
throw new TransferError("VALIDATION_ERROR", errorMessage(err));
|
|
48879
48944
|
}
|
|
48880
|
-
return decimals;
|
|
48881
|
-
}
|
|
48882
|
-
async function checkOfframpUsdCap(priceLookup, maxUsd, chainKey, tokenAddress, cryptoAmount) {
|
|
48883
|
-
try {
|
|
48884
|
-
const tokenInfo = tokenAddress ? resolveToken(tokenAddress, chainKey) : void 0;
|
|
48885
|
-
const lookupAddress2 = tokenInfo?.address ?? tokenAddress ?? "";
|
|
48886
|
-
const price = await priceLookup.getTokenPrice(chainKey, lookupAddress2);
|
|
48887
|
-
if (price && price > 0) {
|
|
48888
|
-
const usdValue = parseFloat(cryptoAmount) * price;
|
|
48889
|
-
if (usdValue > maxUsd) {
|
|
48890
|
-
return {
|
|
48891
|
-
code: "USD_LIMIT_EXCEEDED",
|
|
48892
|
-
message: `Off-ramp payout value ~$${usdValue.toFixed(2)} USD exceeds safety limit of $${maxUsd}. Use the CLI with --max-usd ${Math.ceil(usdValue)} or --skip-safety-check to proceed.`
|
|
48893
|
-
};
|
|
48894
|
-
}
|
|
48895
|
-
}
|
|
48896
|
-
} catch {
|
|
48897
|
-
}
|
|
48898
|
-
return void 0;
|
|
48899
48945
|
}
|
|
48900
48946
|
function buildFollowUp(chain2, tokenAddress, address, direction, paymentMethod) {
|
|
48901
48947
|
if (!chain2) return void 0;
|
|
@@ -48953,19 +48999,16 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
48953
48999
|
// transfer/swap/erc20 actions already follow. Explicit `walletAddress`
|
|
48954
49000
|
// overrides the derivation for agents operating on behalf of other users.
|
|
48955
49001
|
//
|
|
48956
|
-
//
|
|
48957
|
-
//
|
|
48958
|
-
//
|
|
48959
|
-
//
|
|
48960
|
-
//
|
|
48961
|
-
|
|
48962
|
-
// Normalize across action providers in a follow-up.
|
|
48963
|
-
constructor(walletContext, priceLookup, maxTransferUsd = DEFAULT_MAX_OFFRAMP_USD, blockchainClient) {
|
|
49002
|
+
// The off-ramp payout (confirm_offramp_transfer) goes through the same
|
|
49003
|
+
// TransferExecutor as `transfer`: `swapClient` resolves the token's decimals
|
|
49004
|
+
// and price, and `maxTransferUsd` caps the payout. Off-ramp sends crypto to
|
|
49005
|
+
// a third-party deposit address, so the cap matters even more here than for
|
|
49006
|
+
// peer-to-peer transfers.
|
|
49007
|
+
constructor(walletContext, swapClient, maxTransferUsd = DEFAULT_MAX_OFFRAMP_USD) {
|
|
48964
49008
|
super();
|
|
48965
49009
|
this.walletContext = walletContext;
|
|
48966
|
-
this.
|
|
49010
|
+
this.swapClient = swapClient;
|
|
48967
49011
|
this.maxTransferUsd = maxTransferUsd;
|
|
48968
|
-
this.blockchainClient = blockchainClient;
|
|
48969
49012
|
}
|
|
48970
49013
|
name = "onramp";
|
|
48971
49014
|
description = "Fiat on-ramp and off-ramp \u2014 buy crypto with fiat (USD, EUR, etc.) or sell crypto for fiat payouts. On-ramp: two-step flow (get quote \u2192 get checkout URL), provider sends crypto to the destination address. Off-ramp: three-step flow (get quote \u2192 get checkout URL \u2192 confirm_offramp_transfer). The off-ramp checkout URL runs in a plain browser which has no access to wallet keys, so the payout transaction must be broadcast natively via confirm_offramp_transfer once the user has read the provider's deposit address and exact amount. Destination/source address auto-derives from the configured wallet using the asset's chain. IMPORTANT: TWAK has no background polling or completion webhook for ramps. Tool responses include a `followUp` hint telling the agent exactly which balance tool to poll (with args and timing) to observe completion.";
|
|
@@ -48991,6 +49034,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
48991
49034
|
getOnrampQuote() {
|
|
48992
49035
|
return {
|
|
48993
49036
|
name: "get_onramp_quote",
|
|
49037
|
+
annotations: READS_REMOTE,
|
|
48994
49038
|
description: "Step 1 of buying crypto with fiat: get quotes from available payment providers (MoonPay, Transak, etc.) for a given fiat amount. Returns an array of quotes each with a quoteId \u2014 pass one to get_onramp_url to generate the checkout redirect.",
|
|
48995
49039
|
schema: import_zod12.z.object({
|
|
48996
49040
|
fiatAmount: import_zod12.z.coerce.number().positive().describe("Amount of fiat currency to spend (e.g., 100 for $100)."),
|
|
@@ -49032,6 +49076,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49032
49076
|
getOnrampUrl() {
|
|
49033
49077
|
return {
|
|
49034
49078
|
name: "get_onramp_url",
|
|
49079
|
+
annotations: READS_REMOTE,
|
|
49035
49080
|
description: "Step 2 of buying crypto with fiat: exchange a quoteId from get_onramp_quote for a browser redirect URL. The user opens that URL to complete KYC and payment with the provider; on success, the provider sends the purchased crypto to the destination address. After this tool returns a URL, poll the balance tool named in the `followUp` field to observe the incoming funds \u2014 there is no background polling, webhook, or push notification.",
|
|
49036
49081
|
schema: import_zod12.z.object({
|
|
49037
49082
|
quoteId: import_zod12.z.string().describe("Quote ID returned by get_onramp_quote."),
|
|
@@ -49082,6 +49127,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49082
49127
|
getOfframpQuote() {
|
|
49083
49128
|
return {
|
|
49084
49129
|
name: "get_offramp_quote",
|
|
49130
|
+
annotations: READS_REMOTE,
|
|
49085
49131
|
description: "Step 1 of selling crypto for fiat: get quotes from available providers for converting a crypto amount into fiat. Returns an array of quotes each with a quoteId \u2014 pass one to get_offramp_url to generate the checkout redirect for completing KYC and order creation. The provider page cannot sign the payout (no key access in the browser); the agent must broadcast it natively via confirm_offramp_transfer once the deposit address is known.",
|
|
49086
49132
|
schema: import_zod12.z.object({
|
|
49087
49133
|
cryptoAmount: import_zod12.z.coerce.number().positive().describe("Amount of crypto to sell (e.g., 0.1 for 0.1 ETH)."),
|
|
@@ -49135,6 +49181,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49135
49181
|
getOfframpUrl() {
|
|
49136
49182
|
return {
|
|
49137
49183
|
name: "get_offramp_url",
|
|
49184
|
+
annotations: READS_REMOTE,
|
|
49138
49185
|
description: "Step 2 of selling crypto for fiat: exchange a quoteId from get_offramp_quote for a browser checkout URL. The user opens that URL to complete KYC and order creation with the provider; the provider then displays a deposit address (plus a memo/tag on chains that require one) and the exact amount to send. The agent must then call confirm_offramp_transfer with those values to sign and broadcast the payout natively \u2014 the browser has no access to wallet keys and cannot sign the transfer itself. After the payout broadcasts, poll the balance tool named in the `followUp` field to observe the outgoing tx. Fiat payout arrives separately via the provider.",
|
|
49139
49186
|
schema: import_zod12.z.object({
|
|
49140
49187
|
quoteId: import_zod12.z.string().describe("Quote ID returned by get_offramp_quote."),
|
|
@@ -49186,6 +49233,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49186
49233
|
confirmOfframpTransfer() {
|
|
49187
49234
|
return {
|
|
49188
49235
|
name: "confirm_offramp_transfer",
|
|
49236
|
+
annotations: SIGNS,
|
|
49189
49237
|
description: "Step 3 of selling crypto for fiat: sign and broadcast the payout transaction to the provider's deposit address. Call this AFTER the user has completed KYC in the browser and can read the deposit address + exact amount the provider displayed. Works with any wallet provider that implements sendTransaction (the local agent wallet, or a WalletConnect-paired external wallet). EVM-only \u2014 non-EVM chains (BTC, Solana, Cosmos, etc.) are not supported by this action. Returns a tx hash on success; fiat payout from the provider then arrives separately (no on-chain signal for that step).",
|
|
49190
49238
|
schema: import_zod12.z.object({
|
|
49191
49239
|
depositAddress: import_zod12.z.string().describe(
|
|
@@ -49198,8 +49246,8 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49198
49246
|
tokenAddress: import_zod12.z.string().trim().min(1).optional().describe(
|
|
49199
49247
|
"ERC-20 token contract address. Omit for the chain native coin. This action is EVM-only \u2014 non-EVM tokens are rejected."
|
|
49200
49248
|
),
|
|
49201
|
-
decimals: import_zod12.z.coerce.number().optional().describe(
|
|
49202
|
-
"Token decimals
|
|
49249
|
+
decimals: import_zod12.z.coerce.number().int().min(0).max(36).optional().describe(
|
|
49250
|
+
"Token decimals, only for a token twak does not know. Omit it otherwise: twak resolves decimals from its registry or the Trust token search, and rejects a value that contradicts them. Ignored for native coins."
|
|
49203
49251
|
),
|
|
49204
49252
|
memo: import_zod12.z.string().optional().describe(
|
|
49205
49253
|
"Memo / destination tag. Not used on EVM chains, so supplying one on EVM is a no-op warning. Exists in the schema for forward-compat with non-EVM chains."
|
|
@@ -49209,7 +49257,7 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49209
49257
|
)
|
|
49210
49258
|
}),
|
|
49211
49259
|
invoke: async (_ctx, input2) => {
|
|
49212
|
-
const
|
|
49260
|
+
const wallet = this.walletContext.activeWallet();
|
|
49213
49261
|
const { chainKey } = resolveAsset(input2.chain);
|
|
49214
49262
|
const chainDef = chainOf(chainKey);
|
|
49215
49263
|
if (chainDef.namespace !== "eip155") {
|
|
@@ -49218,48 +49266,30 @@ var OnrampActionProvider = class extends ActionProvider {
|
|
|
49218
49266
|
`confirm_offramp_transfer is EVM-only. ${chainKey} is not supported.`
|
|
49219
49267
|
);
|
|
49220
49268
|
}
|
|
49221
|
-
|
|
49222
|
-
|
|
49223
|
-
|
|
49224
|
-
|
|
49225
|
-
|
|
49226
|
-
|
|
49227
|
-
|
|
49228
|
-
|
|
49229
|
-
|
|
49230
|
-
|
|
49231
|
-
|
|
49232
|
-
|
|
49233
|
-
let hash;
|
|
49234
|
-
if (input2.tokenAddress) {
|
|
49235
|
-
if (!this.blockchainClient) {
|
|
49236
|
-
throw new TransferError(
|
|
49237
|
-
"WALLET_NOT_FOUND",
|
|
49238
|
-
"Chain client not available \u2014 off-ramp token payout requires a configured blockchain client"
|
|
49239
|
-
);
|
|
49240
|
-
}
|
|
49241
|
-
const pending = await this.blockchainClient.contract(erc20).withAddress(input2.tokenAddress, chainKey).write.transfer([input2.depositAddress, BigInt(atomic)], signer);
|
|
49242
|
-
hash = pending.hash;
|
|
49243
|
-
} else {
|
|
49244
|
-
hash = await signer.sendTransaction({
|
|
49245
|
-
chainKey,
|
|
49246
|
-
to: input2.depositAddress,
|
|
49247
|
-
data: "0x",
|
|
49248
|
-
value: "0x" + BigInt(atomic).toString(16)
|
|
49249
|
-
});
|
|
49269
|
+
validateOfframpInput(input2);
|
|
49270
|
+
const result = await new TransferExecutor({ wallet, swapClient: this.swapClient }).execute({
|
|
49271
|
+
chain: chainKey,
|
|
49272
|
+
to: input2.depositAddress,
|
|
49273
|
+
resolveNames: false,
|
|
49274
|
+
amount: input2.cryptoAmount,
|
|
49275
|
+
tokenAddress: input2.tokenAddress,
|
|
49276
|
+
decimals: input2.decimals,
|
|
49277
|
+
safety: { maxUsd: this.maxTransferUsd }
|
|
49278
|
+
});
|
|
49279
|
+
if (!result.success) {
|
|
49280
|
+
return { success: false, code: result.code, message: result.message };
|
|
49250
49281
|
}
|
|
49251
|
-
const explorerUrl = getExplorerTxUrl(chainKey, hash) || void 0;
|
|
49252
49282
|
return {
|
|
49253
49283
|
success: true,
|
|
49254
|
-
hash,
|
|
49255
|
-
chain: chainKey,
|
|
49284
|
+
hash: result.hash,
|
|
49285
|
+
chain: result.chainKey,
|
|
49256
49286
|
tokenAddress: input2.tokenAddress,
|
|
49257
|
-
to:
|
|
49287
|
+
to: result.to,
|
|
49258
49288
|
amount: input2.cryptoAmount,
|
|
49259
49289
|
memoIgnored: input2.memo ? `A memo was supplied (${input2.memo}) but EVM transactions have no memo field \u2014 it was ignored. If the provider requires a memo, they likely expect a non-EVM chain.` : void 0,
|
|
49260
49290
|
quoteId: input2.quoteId,
|
|
49261
|
-
explorer: explorerUrl,
|
|
49262
|
-
summary: `Off-ramp payout of ${input2.cryptoAmount}${input2.tokenAddress ? ` ${input2.tokenAddress.slice(0, 10)}\u2026` : ` ${chainDef.symbol}`} broadcast to ${
|
|
49291
|
+
explorer: result.explorerUrl,
|
|
49292
|
+
summary: `Off-ramp payout of ${input2.cryptoAmount}${input2.tokenAddress ? ` ${input2.tokenAddress.slice(0, 10)}\u2026` : ` ${chainDef.symbol}`} broadcast to ${result.to} on ${chainKey}. Fiat payout from the provider arrives separately.`
|
|
49263
49293
|
};
|
|
49264
49294
|
}
|
|
49265
49295
|
};
|
|
@@ -49287,6 +49317,8 @@ var AutomateActionProvider = class extends ActionProvider {
|
|
|
49287
49317
|
createAutomation() {
|
|
49288
49318
|
return {
|
|
49289
49319
|
name: "create_automation",
|
|
49320
|
+
// Destructive: the automation later trades with the agent wallet, unattended.
|
|
49321
|
+
annotations: { readOnly: false, destructive: true, idempotent: false, openWorld: false },
|
|
49290
49322
|
description: "Create a DCA (recurring buy) or limit order (buy/sell when a price condition is met). The rule is saved immediately but only EXECUTES while a watcher is polling \u2014 either this MCP server was started with `twak serve --watch`, or a separate `twak watch` process is running. With no watcher, the rule stays pending and nothing is swapped; use run_automation_now to execute one on demand (only available while no watcher is running). Execution uses the local agent wallet; the watcher stays idle in WalletConnect mode.",
|
|
49291
49323
|
schema: import_zod13.z.object({
|
|
49292
49324
|
type: import_zod13.z.enum(["dca", "limit"]).describe("Automation type: dca (recurring) or limit (price trigger)"),
|
|
@@ -49336,6 +49368,7 @@ var AutomateActionProvider = class extends ActionProvider {
|
|
|
49336
49368
|
listAutomations() {
|
|
49337
49369
|
return {
|
|
49338
49370
|
name: "list_automations",
|
|
49371
|
+
annotations: READS_LOCAL,
|
|
49339
49372
|
description: 'List automation rules (DCA and limit orders). Note: "active" means scheduled, not necessarily firing \u2014 rules only execute while a watcher runs (`twak serve --watch` or `twak watch`).',
|
|
49340
49373
|
schema: import_zod13.z.object({
|
|
49341
49374
|
activeOnly: import_zod13.z.boolean().optional().default(true).describe("Only show active automations")
|
|
@@ -49351,6 +49384,7 @@ var AutomateActionProvider = class extends ActionProvider {
|
|
|
49351
49384
|
deleteAutomation() {
|
|
49352
49385
|
return {
|
|
49353
49386
|
name: "delete_automation",
|
|
49387
|
+
annotations: { readOnly: false, destructive: true, idempotent: true, openWorld: false },
|
|
49354
49388
|
description: "Delete (deactivate) an automation rule",
|
|
49355
49389
|
schema: import_zod13.z.object({
|
|
49356
49390
|
id: import_zod13.z.string().describe("Automation ID to delete")
|
|
@@ -49368,6 +49402,7 @@ var AutomateActionProvider = class extends ActionProvider {
|
|
|
49368
49402
|
runAutomationNow() {
|
|
49369
49403
|
return {
|
|
49370
49404
|
name: "run_automation_now",
|
|
49405
|
+
annotations: SIGNS,
|
|
49371
49406
|
description: "Execute an automation immediately \u2014 runs the swap now regardless of its schedule. Only available while no watcher is running: when this server was started with `serve --watch` the watcher owns execution, the tool is hidden, and invocations are rejected with WATCHER_ACTIVE to prevent double execution.",
|
|
49372
49407
|
hidden: this.watcherActive,
|
|
49373
49408
|
schema: import_zod13.z.object({
|
|
@@ -49461,7 +49496,11 @@ var X402ActionProvider = class extends ActionProvider {
|
|
|
49461
49496
|
x402Quote() {
|
|
49462
49497
|
return {
|
|
49463
49498
|
name: "x402_quote",
|
|
49464
|
-
|
|
49499
|
+
// Not read-only: the request is sent with the caller's method before
|
|
49500
|
+
// any 402 check, so a POST or DELETE to an endpoint that does not ask
|
|
49501
|
+
// for payment runs as a normal request.
|
|
49502
|
+
annotations: { readOnly: false, destructive: true, idempotent: false, openWorld: true },
|
|
49503
|
+
description: 'Preview the payment requirements at an x402 payment-gated endpoint WITHOUT signing or paying. Returns the full list of payment options (each entry has chain, asset address, tokenName, amount, transferMethod, requiresApproval, and a pre-formatted `description` string). CRITICAL \u2014 after this returns, ALWAYS surface ALL entries in `accepts[]` to the user (as a short numbered list: chain \xB7 token \xB7 amount \xB7 method \xB7 "preferred" tag if applicable) and ask which to use BEFORE calling x402_request. Do not silently pick the `preferred` entry just because it is marked preferred \u2014 that is the picker default if no override is passed, but the user deserves to see every option (other chains may have cheaper gas, the user may hold balance only on a specific chain, etc.). The only exception: if you have already done a balance check and only one entry is viable, you may proceed with that one after noting the others as "unavailable (no balance)". IMPORTANT: each entry in `accepts[]` is an INDEPENDENT payment option \u2014 a unique (chain, token, transfer method) triple. Do NOT merge entries by chain (e.g. "BSC USDC via EIP-3009 or Permit2" is wrong if BSC USDC is only offered via Permit2 and a separate BSC entry for a different token offers EIP-3009). Read each entry as its own row; use the per-entry `description` field verbatim when surfacing options to the user. Once the user picks, call x402_request with the agreed maxPaymentAtomic plus optionally preferNetwork/preferMethod/preferAsset to disambiguate. INTERPRETING `requiresApproval`: `false` (EIP-3009, e.g. USDC on Base / Ethereum) \u2014 gasless. Sign the payment and you are done. No setup, no on-chain tx for the buyer, ever. `true` (Permit2, e.g. USDC on BSC) \u2014 the industry-standard Permit2 flow used by Uniswap, 1inch, and most major DeFi apps. THE FIRST x402_request to a Permit2 endpoint for a given token+chain broadcasts a one-time `approve(Permit2, MAX_UINT256)` tx (the buyer pays the gas \u2014 usually a few cents on BSC / Base, more on Ethereum mainnet). The allowance granted is unlimited for the canonical Permit2 contract at 0x000000000022D473030F116dDEE9F6B43aC78BA3. After that, every future Permit2 payment for that token is signature-only (gasless). Revocable any time via `twak erc20 revoke`. The per-call spend is still capped at the request `maxPaymentAtomic` \u2014 unlimited allowance does NOT mean unlimited per-call spend. When `requiresApproval: true` AND the buyer has not used Permit2 for that token on that chain before, the agent SHOULD tell the user concretely what is about to happen (one-time approval on <chain> for <token>, gas paid in the chain native token, then the payment) before calling x402_request. BALANCE CHECK \u2014 AFTER this quote returns and BEFORE recommending any route or showing the menu to the user, check the wallet balance for every viable entry in `accepts`. For each entry: call `get_address(chain)` to find the wallet address on that chain, then `get_balance` for the entry\'s asset (or `wallet_balance(chain)` for native coins). Filter or annotate the menu \u2014 only recommend routes where the wallet has enough of the asset to cover `amount`. If a Permit2 entry needs a first-time approval (`requiresApproval: true`), also confirm the wallet holds some native chain gas (gas amount varies by chain). If no viable route has sufficient balance, tell the user upfront \u2014 do not present a menu that includes routes they cannot pay. This avoids the failure mode where the agent recommends a chain the user has no balance on and the user finds out only after committing. No wallet required: nothing is signed or paid. The request is sent with the given method and body, so a method other than GET can change state on an endpoint that does not answer 402; quote with GET unless the endpoint requires another method. HTTPS-only; private IPs and non-HTTPS schemes are rejected.',
|
|
49465
49504
|
schema: import_zod14.z.object({
|
|
49466
49505
|
url: import_zod14.z.string().describe(
|
|
49467
49506
|
"Target endpoint URL. Must be HTTPS. Resolves via DNS; private/local IPs are rejected."
|
|
@@ -49477,6 +49516,7 @@ var X402ActionProvider = class extends ActionProvider {
|
|
|
49477
49516
|
x402Request() {
|
|
49478
49517
|
return {
|
|
49479
49518
|
name: "x402_request",
|
|
49519
|
+
annotations: SIGNS,
|
|
49480
49520
|
description: "Make an HTTP request to an x402 payment-gated endpoint. Handles the full flow: sends the initial request, parses any 402 challenge, signs an EIP-3009 or Permit2 payment authorization with the agent wallet, retries with the X-Payment header. PAYMENT METHODS: x402 endpoints offer one or more options in their 402 response. EIP-3009 is gasless for the buyer (no setup, no approval) \u2014 preferred when available, e.g. USDC on Base / Ethereum. Permit2 needs a one-time approve(Permit2, MAX) tx on the chain (the buyer pays the gas \u2014 usually a few cents on BSC / Base, more on Ethereum mainnet), then every future Permit2 payment for that token is signature-only. Permit2 is required when the token does not support EIP-3009 \u2014 e.g. USDC on BSC. SAFETY \u2014 autoApprove decision: When autoApprove=true (default), this action silently broadcasts the one-time Permit2 approval if your wallet has not yet approved the canonical Permit2 contract for that token. The approval is to the same Permit2 contract Uniswap, 1inch, and most major DeFi apps use \u2014 it is not exotic infrastructure. The approval alone does not move funds; each subsequent payment still needs a fresh signature. Revocable any time via `twak erc20 revoke`. For first-time use of an endpoint you SHOULD tell the user concretely what is about to happen (one-time approval on <chain> for <token>, gas paid in the chain native token, then the payment) and get their go-ahead before calling. After the approval lands, subsequent Permit2 payments for that token are free of further approvals. Set autoApprove=false to surface code: 'PERMIT2_APPROVAL_REQUIRED' instead of broadcasting \u2014 useful when the user is not around or you want to handle the approval out-of-band. maxPaymentAtomic is the user's pre-commitment to a maximum payment in the asset's smallest unit (e.g. \"10000\" = 0.01 USDC at 6 decimals). If the server demands more than this cap, the call returns code: 'PAYMENT_AMOUNT_EXCEEDED' \u2014 DO NOT retry with a higher cap without asking the user. BALANCE CHECK \u2014 Before calling this action, verify the wallet holds enough of the chosen asset on the chosen chain. Call `get_address(chain)` to find the wallet address, then `get_balance` for the asset (or `wallet_balance(chain)` for native coins). For Permit2 first-time use, also confirm the wallet holds some native chain gas (amount varies by chain). Surface insufficient balance to the user BEFORE calling this action \u2014 a failed payment mid-flow can leave the wallet in a half-state (e.g. Permit2 approval broadcast, then the transfer signature fails). The balance check should already have happened during the `x402_quote` flow that produced the menu; redo it here only if you skipped quote or the balance might have changed since. WALLET \u2014 Signs through whichever wallet mode is active for this session (local by default; switchable via `switch_wallet_mode`). If mode='local', signs in-process (no external prompt). If mode='walletconnect', signs over the WalletConnect relay \u2014 the user must approve each signature on their paired wallet. To retrieve the active wallet's address for a chain (e.g. to call `wallet_balance` / `get_balance`), call `get_address` with the chain key (e.g. \"bsc\", \"base\"), or `list_addresses` for all chains at once. HTTPS-only; non-HTTPS schemes and private IPs are rejected before any payment signing.",
|
|
49481
49521
|
schema: import_zod14.z.object({
|
|
49482
49522
|
url: import_zod14.z.string().describe(
|
|
@@ -49591,6 +49631,9 @@ var WalletModeActionProvider = class extends ActionProvider {
|
|
|
49591
49631
|
switchWalletMode() {
|
|
49592
49632
|
return {
|
|
49593
49633
|
name: "switch_wallet_mode",
|
|
49634
|
+
// Local mode revokes the WalletConnect session; walletconnect mode starts
|
|
49635
|
+
// a pairing through the relay.
|
|
49636
|
+
annotations: { readOnly: false, destructive: true, idempotent: false, openWorld: true },
|
|
49594
49637
|
description: 'Switch the active wallet mode for this MCP server session. IMPORTANT: the LOCAL agent wallet is auto-bound at server startup when one is configured, so most users do NOT need to call this \u2014 signing actions just work. Call this ONLY when the user explicitly asks to switch. Two flows: (a) user wants to sign on their phone via Trust Wallet (or any WC-compatible wallet) \u2192 mode="walletconnect"; (b) user wants to switch back from WalletConnect to the local wallet \u2192 mode="local". \n\nDISCOVERABILITY: most users do not know WalletConnect is an option. When the user first asks about wallet operations or signing in a fresh conversation, briefly mention that they can optionally switch to signing via Trust Wallet on their phone (more secure: keys never leave their device) by saying so \u2014 then call switch_wallet_mode if they opt in. Do not push it on every signing call; just surface it once early on or when the user expresses security concerns.\n\nFor mode="walletconnect": returns a pairing payload (URI, mobile deep link, inline QR image). Surface the QR to the user, then poll get_wallet_status every few seconds until state leaves "wc-pairing": "wc-connected" means the user approved; "unbound" means the pairing ended, and lastError says why (USER_REJECTED, WC_PAIRING_EXPIRED after about 5 minutes, or WC_PAIRING_FAILED). Do not retry a signing action before "wc-connected". Do NOT call switch_wallet_mode while a signing action is in flight: switching disconnects the prior WC relay session, which can break the in-flight signature; wait for the current action to settle before changing modes.',
|
|
49595
49638
|
schema: import_zod15.z.object({
|
|
49596
49639
|
mode: import_zod15.z.enum(["local", "walletconnect"]).describe(
|
|
@@ -49617,6 +49660,7 @@ var WalletModeActionProvider = class extends ActionProvider {
|
|
|
49617
49660
|
getWalletStatus() {
|
|
49618
49661
|
return {
|
|
49619
49662
|
name: "get_wallet_status",
|
|
49663
|
+
annotations: READS_LOCAL,
|
|
49620
49664
|
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 / expiry, when state="wc-pairing"), `lastError` (why the wallet went away or a pairing ended), and `twakHome`: the folder this server keeps its files in (wallet, WalletConnect session, credentials), set from TWAK_HOME when the server started (default ~/.twak). After switch_wallet_mode({mode: "walletconnect"}), poll this every few seconds until state leaves "wc-pairing": "wc-connected" means the user approved and signing actions are usable; "unbound" means the pairing ended without a session, and lastError.code says why: USER_REJECTED (declined in the wallet), WC_PAIRING_EXPIRED (not approved within about 5 minutes) or WC_PAIRING_FAILED. Ask the user before starting a new pairing. While pairing, the response carries `pairing.deepLink` (tap on a phone) and the raw `pairing.uri`. The QR image is returned only with showQr=true: pass it when the user asks to see the QR again (e.g. "show me the QR", "I can\'t see it"), not when polling. Do NOT try to render the QR yourself from the URI or the response JSON.',
|
|
49621
49665
|
schema: import_zod15.z.object({
|
|
49622
49666
|
showQr: import_zod15.z.boolean().optional().describe(
|
|
@@ -49642,6 +49686,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
49642
49686
|
register() {
|
|
49643
49687
|
return {
|
|
49644
49688
|
name: "erc8004_register",
|
|
49689
|
+
annotations: SIGNS,
|
|
49645
49690
|
description: "Mint a new ERC-8004 agent identity on-chain. The caller becomes the owner of an NFT token whose ID is the agentId. The supplied agentURI is stored on-chain as the token URI and should point to the agent registration JSON (https, ipfs, or a data: inline). Optionally pass metadata entries to set them atomically in the same mint transaction.",
|
|
49646
49691
|
schema: import_zod16.z.object({
|
|
49647
49692
|
agentURI: import_zod16.z.string().min(1).describe(
|
|
@@ -49673,6 +49718,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
49673
49718
|
setUri() {
|
|
49674
49719
|
return {
|
|
49675
49720
|
name: "erc8004_set_uri",
|
|
49721
|
+
annotations: SIGNS,
|
|
49676
49722
|
description: "Update the agentURI of an existing ERC-8004 agent identity. Caller must own the NFT.",
|
|
49677
49723
|
schema: import_zod16.z.object({
|
|
49678
49724
|
agentId: agentIdSchema,
|
|
@@ -49691,6 +49737,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
49691
49737
|
setMetadata() {
|
|
49692
49738
|
return {
|
|
49693
49739
|
name: "erc8004_set_metadata",
|
|
49740
|
+
annotations: SIGNS,
|
|
49694
49741
|
description: "Set a metadata entry on an ERC-8004 agent identity. The value is stored on-chain as bytes \u2014 `0x`-prefixed hex inputs are decoded as-is; any other string is UTF-8 encoded.",
|
|
49695
49742
|
schema: import_zod16.z.object({
|
|
49696
49743
|
agentId: agentIdSchema,
|
|
@@ -49714,6 +49761,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
49714
49761
|
getMetadata() {
|
|
49715
49762
|
return {
|
|
49716
49763
|
name: "erc8004_get_metadata",
|
|
49764
|
+
annotations: READS_REMOTE,
|
|
49717
49765
|
description: "Read a metadata entry from an ERC-8004 agent identity. Returns the raw on-chain bytes as a `0x`-prefixed hex string; an unset key returns `0x` (empty bytes).",
|
|
49718
49766
|
schema: import_zod16.z.object({
|
|
49719
49767
|
agentId: agentIdSchema,
|
|
@@ -49736,6 +49784,7 @@ var Erc8004ActionProvider = class extends ActionProvider {
|
|
|
49736
49784
|
show() {
|
|
49737
49785
|
return {
|
|
49738
49786
|
name: "erc8004_show",
|
|
49787
|
+
annotations: READS_REMOTE,
|
|
49739
49788
|
description: "Read the on-chain state of an ERC-8004 agent identity: owner, agentWallet (or null if unset), and agentURI.",
|
|
49740
49789
|
schema: import_zod16.z.object({
|
|
49741
49790
|
agentId: agentIdSchema,
|
|
@@ -49802,6 +49851,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49802
49851
|
createJob() {
|
|
49803
49852
|
return {
|
|
49804
49853
|
name: "erc8183_create_job",
|
|
49854
|
+
annotations: SIGNS,
|
|
49805
49855
|
description: "Create a new ERC-8183 job. The caller becomes the client. The job starts in `Open` status with no escrow; set a budget then fund it to move it to `Funded`.",
|
|
49806
49856
|
schema: import_zod17.z.object({
|
|
49807
49857
|
provider: evmAddressSchema.describe(
|
|
@@ -49837,6 +49887,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49837
49887
|
setProvider() {
|
|
49838
49888
|
return {
|
|
49839
49889
|
name: "erc8183_set_provider",
|
|
49890
|
+
annotations: SIGNS,
|
|
49840
49891
|
description: "Set or change the provider (worker) address for a job (client only, while the job is still `Open`). Use the zero address to unset.",
|
|
49841
49892
|
schema: import_zod17.z.object({
|
|
49842
49893
|
jobId: jobIdSchema,
|
|
@@ -49858,6 +49909,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49858
49909
|
setBudget() {
|
|
49859
49910
|
return {
|
|
49860
49911
|
name: "erc8183_set_budget",
|
|
49912
|
+
annotations: SIGNS,
|
|
49861
49913
|
description: "Set the escrow budget for a job (atomic units of the contract payment token). Does not transfer funds \u2014 call `erc8183_fund` to deposit the budget into escrow.",
|
|
49862
49914
|
schema: import_zod17.z.object({
|
|
49863
49915
|
jobId: jobIdSchema,
|
|
@@ -49879,6 +49931,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49879
49931
|
fund() {
|
|
49880
49932
|
return {
|
|
49881
49933
|
name: "erc8183_fund",
|
|
49934
|
+
annotations: SIGNS,
|
|
49882
49935
|
description: "Fund a job: deposits the on-chain budget into escrow. The escrow pulls the payment token via transferFrom, so this first sends an ERC-20 approval for the exact budget, then calls fund \u2014 two transactions. Moves the job to `Funded`. Pass `expectedBudget` to pin the amount instead of reading it on-chain.",
|
|
49883
49936
|
schema: import_zod17.z.object({
|
|
49884
49937
|
jobId: jobIdSchema,
|
|
@@ -49908,6 +49961,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49908
49961
|
submit() {
|
|
49909
49962
|
return {
|
|
49910
49963
|
name: "erc8183_submit",
|
|
49964
|
+
annotations: SIGNS,
|
|
49911
49965
|
description: "Submit a deliverable for a funded job (provider only). The deliverable is a bytes32 commitment (e.g. a content hash). Moves the job to `Submitted`.",
|
|
49912
49966
|
schema: import_zod17.z.object({
|
|
49913
49967
|
jobId: jobIdSchema,
|
|
@@ -49933,6 +49987,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49933
49987
|
complete() {
|
|
49934
49988
|
return {
|
|
49935
49989
|
name: "erc8183_complete",
|
|
49990
|
+
annotations: SIGNS,
|
|
49936
49991
|
description: "Mark a submitted job complete (evaluator only). Releases escrow: the platform fee goes to the treasury and the remainder to the provider. Moves the job to `Completed`.",
|
|
49937
49992
|
schema: import_zod17.z.object({
|
|
49938
49993
|
jobId: jobIdSchema,
|
|
@@ -49960,6 +50015,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49960
50015
|
reject() {
|
|
49961
50016
|
return {
|
|
49962
50017
|
name: "erc8183_reject",
|
|
50018
|
+
annotations: SIGNS,
|
|
49963
50019
|
description: "Reject a job (evaluator after submission, or client while still Open). Refunds the client if the job was funded. Moves the job to `Rejected`.",
|
|
49964
50020
|
schema: import_zod17.z.object({
|
|
49965
50021
|
jobId: jobIdSchema,
|
|
@@ -49987,6 +50043,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
49987
50043
|
claimRefund() {
|
|
49988
50044
|
return {
|
|
49989
50045
|
name: "erc8183_claim_refund",
|
|
50046
|
+
annotations: SIGNS,
|
|
49990
50047
|
description: "Claim a refund for an expired job (client only, after the job has passed its expiry without completion). Returns the escrowed budget to the client.",
|
|
49991
50048
|
schema: import_zod17.z.object({
|
|
49992
50049
|
jobId: jobIdSchema,
|
|
@@ -50008,6 +50065,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50008
50065
|
status() {
|
|
50009
50066
|
return {
|
|
50010
50067
|
name: "erc8183_status",
|
|
50068
|
+
annotations: READS_REMOTE,
|
|
50011
50069
|
description: "Read the on-chain state of a job: client, provider, evaluator, description, budget, status, expiry, submission, deliverable, and the contract payment token.",
|
|
50012
50070
|
schema: import_zod17.z.object({
|
|
50013
50071
|
jobId: jobIdSchema,
|
|
@@ -50038,6 +50096,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50038
50096
|
policyInfo() {
|
|
50039
50097
|
return {
|
|
50040
50098
|
name: "erc8183_policy_info",
|
|
50099
|
+
annotations: READS_REMOTE,
|
|
50041
50100
|
description: "Read the dispute-policy state of a job: the registered policy address, dispute window, submission time, dispute/vote tallies, and when the job becomes settleable (submittedAt + disputeWindow). Use before `erc8183_settle` to check timing, and before `erc8183_dispute`/`erc8183_vote_reject` to avoid opaque reverts.",
|
|
50042
50101
|
schema: import_zod17.z.object({
|
|
50043
50102
|
jobId: jobIdSchema,
|
|
@@ -50067,6 +50126,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50067
50126
|
registerJob() {
|
|
50068
50127
|
return {
|
|
50069
50128
|
name: "erc8183_register_job",
|
|
50129
|
+
annotations: SIGNS,
|
|
50070
50130
|
description: "Register a job with a dispute policy via the EvaluatorRouter. Defaults to the deployed OptimisticPolicy when no policy address is given.",
|
|
50071
50131
|
schema: import_zod17.z.object({
|
|
50072
50132
|
jobId: jobIdSchema,
|
|
@@ -50083,6 +50143,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50083
50143
|
settle() {
|
|
50084
50144
|
return {
|
|
50085
50145
|
name: "erc8183_settle",
|
|
50146
|
+
annotations: SIGNS,
|
|
50086
50147
|
description: "Settle a job through its registered policy via the EvaluatorRouter, finalising the outcome (release or refund) based on the policy verdict.",
|
|
50087
50148
|
schema: import_zod17.z.object({
|
|
50088
50149
|
jobId: jobIdSchema,
|
|
@@ -50099,6 +50160,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50099
50160
|
markExpired() {
|
|
50100
50161
|
return {
|
|
50101
50162
|
name: "erc8183_mark_expired",
|
|
50163
|
+
annotations: SIGNS,
|
|
50102
50164
|
description: "Finalise a registered job that has passed its expiry without completion, via the EvaluatorRouter (permissionless). Moves the job to `Expired`, after which the client can claim a refund.",
|
|
50103
50165
|
schema: import_zod17.z.object({
|
|
50104
50166
|
jobId: jobIdSchema,
|
|
@@ -50115,6 +50177,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50115
50177
|
dispute() {
|
|
50116
50178
|
return {
|
|
50117
50179
|
name: "erc8183_dispute",
|
|
50180
|
+
annotations: SIGNS,
|
|
50118
50181
|
description: "Raise a dispute on a job via the OptimisticPolicy (client only, within the dispute window). Opens the job to voter rejection.",
|
|
50119
50182
|
schema: import_zod17.z.object({
|
|
50120
50183
|
jobId: jobIdSchema,
|
|
@@ -50130,6 +50193,7 @@ var Erc8183ActionProvider = class extends ActionProvider {
|
|
|
50130
50193
|
voteReject() {
|
|
50131
50194
|
return {
|
|
50132
50195
|
name: "erc8183_vote_reject",
|
|
50196
|
+
annotations: SIGNS,
|
|
50133
50197
|
description: "Cast a reject vote on a disputed job via the OptimisticPolicy (whitelisted voters only). When the reject quorum is reached the job is rejected.",
|
|
50134
50198
|
schema: import_zod17.z.object({
|
|
50135
50199
|
jobId: jobIdSchema,
|
|
@@ -50172,6 +50236,8 @@ var CompetitionActionProvider = class extends ActionProvider {
|
|
|
50172
50236
|
register() {
|
|
50173
50237
|
return {
|
|
50174
50238
|
name: "competition_register",
|
|
50239
|
+
// Idempotent: once registered, it returns without sending a transaction.
|
|
50240
|
+
annotations: { readOnly: false, destructive: true, idempotent: true, openWorld: true },
|
|
50175
50241
|
description: "Register the agent wallet for BNB HACK: AI TRADING AGENT EDITION on BSC. Registers the agent's own signing wallet (msg.sender). Idempotent \u2014 if already registered, returns success without sending a transaction. Fails if the registration window is not open (before it opens or after the deadline).",
|
|
50176
50242
|
schema: import_zod18.z.object({}),
|
|
50177
50243
|
invoke: async () => {
|
|
@@ -50228,6 +50294,7 @@ var CompetitionActionProvider = class extends ActionProvider {
|
|
|
50228
50294
|
status() {
|
|
50229
50295
|
return {
|
|
50230
50296
|
name: "competition_status",
|
|
50297
|
+
annotations: READS_REMOTE,
|
|
50231
50298
|
description: "Check whether the agent wallet is registered for BNB HACK: AI TRADING AGENT EDITION, when registration opens and closes, and whether the window is currently open.",
|
|
50232
50299
|
schema: import_zod18.z.object({}),
|
|
50233
50300
|
invoke: async () => {
|
|
@@ -54910,6 +54977,27 @@ When the user first engages with signing operations in a fresh conversation, bri
|
|
|
54910
54977
|
To switch mid-session, call \`switch_wallet_mode\`. The new mode applies to subsequent calls; in-flight signing keeps using its captured wallet. A WalletConnect session is stored on disk and resumed when the server restarts, until it expires (about 7 days) or is revoked; choosing local mode revokes it.
|
|
54911
54978
|
|
|
54912
54979
|
If a tool returns CREDENTIALS_MISSING, the Trust Wallet API credentials are not set up yet: ask the user to run \`twak init\` (or \`twak setup\`) with their access ID and HMAC secret. The tools work as soon as the credentials are saved; no server restart is needed.`;
|
|
54980
|
+
var READ_ONLY_SERVER_INSTRUCTIONS = `This twak server is read-only (\`twak serve --read-only\`): it serves only tools that read, such as prices, quotes, balances, history and wallet addresses. It cannot sign, send, swap, approve, or change alerts, automations or the wallet mode; calling such a tool returns READ_ONLY. To do any of that, the user restarts \`twak serve\` without --read-only.
|
|
54981
|
+
|
|
54982
|
+
The wallet was chosen when the server started: the WalletConnect session resumed from a previous pairing if there was one, otherwise the local agent wallet. Wallet reads (get_address, list_addresses, wallet_balance, ...) use its addresses, and get_wallet_status shows which one it is. To read another wallet, the user pairs it with \`twak wallet connect\` (or switches back to the local wallet) and restarts the server. If a tool returns WALLET_NOT_BOUND or the WalletConnect session ended, tell the user that; switch_wallet_mode is not available on this server.
|
|
54983
|
+
|
|
54984
|
+
If a tool returns CREDENTIALS_MISSING, the Trust Wallet API credentials are not set up yet: ask the user to run \`twak init\` (or \`twak setup\`) with their access ID and HMAC secret. The tools work as soon as the credentials are saved; no server restart is needed.`;
|
|
54985
|
+
function toToolAnnotations(annotations) {
|
|
54986
|
+
if (annotations.readOnly) {
|
|
54987
|
+
return {
|
|
54988
|
+
readOnlyHint: true,
|
|
54989
|
+
destructiveHint: false,
|
|
54990
|
+
idempotentHint: true,
|
|
54991
|
+
openWorldHint: annotations.openWorld
|
|
54992
|
+
};
|
|
54993
|
+
}
|
|
54994
|
+
return {
|
|
54995
|
+
readOnlyHint: false,
|
|
54996
|
+
destructiveHint: annotations.destructive,
|
|
54997
|
+
idempotentHint: annotations.idempotent,
|
|
54998
|
+
openWorldHint: annotations.openWorld
|
|
54999
|
+
};
|
|
55000
|
+
}
|
|
54913
55001
|
var TwakMcpServer = class {
|
|
54914
55002
|
server;
|
|
54915
55003
|
registry;
|
|
@@ -54921,7 +55009,10 @@ var TwakMcpServer = class {
|
|
|
54921
55009
|
this.beforeInvoke = options.beforeInvoke;
|
|
54922
55010
|
this.server = new Server(
|
|
54923
55011
|
{ name: "twak", version: "0.1.0" },
|
|
54924
|
-
{
|
|
55012
|
+
{
|
|
55013
|
+
capabilities: { tools: {} },
|
|
55014
|
+
instructions: registry.readOnly ? READ_ONLY_SERVER_INSTRUCTIONS : SERVER_INSTRUCTIONS
|
|
55015
|
+
}
|
|
54925
55016
|
);
|
|
54926
55017
|
this.setupHandlers();
|
|
54927
55018
|
}
|
|
@@ -54932,7 +55023,8 @@ var TwakMcpServer = class {
|
|
|
54932
55023
|
tools: actions.map((action) => ({
|
|
54933
55024
|
name: action.name,
|
|
54934
55025
|
description: action.description,
|
|
54935
|
-
inputSchema: zodToJsonSchema(action.schema)
|
|
55026
|
+
inputSchema: zodToJsonSchema(action.schema),
|
|
55027
|
+
annotations: toToolAnnotations(action.annotations)
|
|
54936
55028
|
}))
|
|
54937
55029
|
};
|
|
54938
55030
|
});
|
|
@@ -54940,16 +55032,12 @@ var TwakMcpServer = class {
|
|
|
54940
55032
|
const { name: name2, arguments: args } = request.params;
|
|
54941
55033
|
const action = this.registry.getAction(name2);
|
|
54942
55034
|
if (!action) {
|
|
55035
|
+
const payload = this.registry.withheldError(name2) ?? {
|
|
55036
|
+
code: "VALIDATION_ERROR",
|
|
55037
|
+
message: `Unknown tool: ${name2}`
|
|
55038
|
+
};
|
|
54943
55039
|
return {
|
|
54944
|
-
content: [
|
|
54945
|
-
{
|
|
54946
|
-
type: "text",
|
|
54947
|
-
text: JSON.stringify({
|
|
54948
|
-
code: "VALIDATION_ERROR",
|
|
54949
|
-
message: `Unknown tool: ${name2}`
|
|
54950
|
-
})
|
|
54951
|
-
}
|
|
54952
|
-
],
|
|
55040
|
+
content: [{ type: "text", text: JSON.stringify(payload) }],
|
|
54953
55041
|
isError: true
|
|
54954
55042
|
};
|
|
54955
55043
|
}
|
|
@@ -55111,7 +55199,11 @@ var TwakRestServer = class {
|
|
|
55111
55199
|
res.writeHead(200);
|
|
55112
55200
|
res.end(
|
|
55113
55201
|
JSON.stringify({
|
|
55114
|
-
actions: actions.map((a3) => ({
|
|
55202
|
+
actions: actions.map((a3) => ({
|
|
55203
|
+
name: a3.name,
|
|
55204
|
+
description: a3.description,
|
|
55205
|
+
annotations: a3.annotations
|
|
55206
|
+
}))
|
|
55115
55207
|
})
|
|
55116
55208
|
);
|
|
55117
55209
|
return;
|
|
@@ -55125,9 +55217,12 @@ var TwakRestServer = class {
|
|
|
55125
55217
|
const actionName = match[1];
|
|
55126
55218
|
const action = this.registry.getAction(actionName);
|
|
55127
55219
|
if (!action) {
|
|
55128
|
-
|
|
55220
|
+
const withheld = this.registry.withheldError(actionName);
|
|
55221
|
+
res.writeHead(withheld ? 403 : 404);
|
|
55129
55222
|
res.end(
|
|
55130
|
-
JSON.stringify(
|
|
55223
|
+
JSON.stringify(
|
|
55224
|
+
withheld ?? { code: "VALIDATION_ERROR", message: `Unknown action: ${actionName}` }
|
|
55225
|
+
)
|
|
55131
55226
|
);
|
|
55132
55227
|
return;
|
|
55133
55228
|
}
|
|
@@ -55262,8 +55357,16 @@ function registerServeCommand(program3) {
|
|
|
55262
55357
|
"--watch-interval <duration>",
|
|
55263
55358
|
"Automation poll interval when --watch is set \u2014 e.g. 30s, 5m, 1h (min 5s)",
|
|
55264
55359
|
"60"
|
|
55360
|
+
).option(
|
|
55361
|
+
"--read-only",
|
|
55362
|
+
"Serve only tools that read (prices, quotes, balances, history, addresses); tools that sign or change state are not listed and cannot be called"
|
|
55265
55363
|
).action(async (opts) => {
|
|
55266
55364
|
if (!opts.rest) routeConsoleToStderr();
|
|
55365
|
+
if (opts.readOnly && opts.watch) {
|
|
55366
|
+
error("--read-only cannot be combined with --watch: the watcher signs automations");
|
|
55367
|
+
process.exit(1);
|
|
55368
|
+
return;
|
|
55369
|
+
}
|
|
55267
55370
|
let autoLockMinutes;
|
|
55268
55371
|
if (opts.autoLock) {
|
|
55269
55372
|
autoLockMinutes = parseInt(opts.autoLock, 10);
|
|
@@ -55335,7 +55438,7 @@ function registerServeCommand(program3) {
|
|
|
55335
55438
|
warn(`${errorMessage(err)} Tool calls report this error until it is resolved.`);
|
|
55336
55439
|
}
|
|
55337
55440
|
}
|
|
55338
|
-
const registry = new ActionRegistry();
|
|
55441
|
+
const registry = new ActionRegistry({ readOnly: Boolean(opts.readOnly) });
|
|
55339
55442
|
registry.register(new BalanceActionProvider());
|
|
55340
55443
|
registry.register(
|
|
55341
55444
|
new WalletModeActionProvider({ walletContext, agentWallet: () => walletLoader.load() })
|
|
@@ -55348,9 +55451,7 @@ function registerServeCommand(program3) {
|
|
|
55348
55451
|
registry.register(new AgentWalletActionProvider(walletContext));
|
|
55349
55452
|
registry.register(new TokenActionProvider(chainClient, walletContext));
|
|
55350
55453
|
registry.register(new MarketActionProvider());
|
|
55351
|
-
registry.register(
|
|
55352
|
-
new OnrampActionProvider(walletContext, swapClient, void 0, chainClient)
|
|
55353
|
-
);
|
|
55454
|
+
registry.register(new OnrampActionProvider(walletContext, swapClient));
|
|
55354
55455
|
registry.register(
|
|
55355
55456
|
new AutomateActionProvider(
|
|
55356
55457
|
automationStore,
|
|
@@ -55430,7 +55531,7 @@ function registerServeCommand(program3) {
|
|
|
55430
55531
|
const mcpServer = new TwakMcpServer(registry, context, {
|
|
55431
55532
|
beforeInvoke: () => bootstrap.ensureReady()
|
|
55432
55533
|
});
|
|
55433
|
-
console.error(
|
|
55534
|
+
console.error(`TW Agent MCP server starting${opts.readOnly ? " (read-only)" : ""}...`);
|
|
55434
55535
|
await mcpServer.start();
|
|
55435
55536
|
}
|
|
55436
55537
|
});
|
|
@@ -55734,6 +55835,9 @@ ${url}`);
|
|
|
55734
55835
|
).requiredOption("--asset <id>", "Crypto asset ID being sold (e.g., c60 for ETH, c0 for BTC)").requiredOption("--to <address>", "Deposit address shown by the provider after KYC").requiredOption(
|
|
55735
55836
|
"--amount <n>",
|
|
55736
55837
|
"Exact amount to send, in human-readable format (must match the amount the provider displays)"
|
|
55838
|
+
).option(
|
|
55839
|
+
"--decimals <n>",
|
|
55840
|
+
"Token decimals, only for a token twak does not know (rejected if it contradicts the registry or token search)"
|
|
55737
55841
|
).option(
|
|
55738
55842
|
"--memo <tag>",
|
|
55739
55843
|
"Memo / destination tag required by some chains (Cosmos, XRP, Stellar, BNB Beacon). Include this when the provider displays one \u2014 funds can be unrecoverable without it."
|
|
@@ -55764,72 +55868,47 @@ ${url}`);
|
|
|
55764
55868
|
`Unsupported coin type in asset ID: ${opts.asset}`
|
|
55765
55869
|
);
|
|
55766
55870
|
}
|
|
55767
|
-
const parsedAmount = parseFloat(opts.amount);
|
|
55768
|
-
if (!Number.isFinite(parsedAmount) || parsedAmount <= 0) {
|
|
55769
|
-
throw new TransferError("VALIDATION_ERROR", "--amount must be a positive number");
|
|
55770
|
-
}
|
|
55771
|
-
const httpClient = await getClient();
|
|
55772
|
-
let decimals;
|
|
55773
|
-
try {
|
|
55774
|
-
const assetInfo = await new SecurityService(httpClient).getAssetInfo(opts.asset);
|
|
55775
|
-
decimals = assetInfo.decimals;
|
|
55776
|
-
} catch {
|
|
55777
|
-
}
|
|
55778
55871
|
try {
|
|
55779
|
-
assertStrictPositiveAmount(opts.amount
|
|
55872
|
+
assertStrictPositiveAmount(opts.amount);
|
|
55780
55873
|
} catch (err) {
|
|
55781
55874
|
throw new TransferError("VALIDATION_ERROR", errorMessage(err));
|
|
55782
55875
|
}
|
|
55783
|
-
|
|
55876
|
+
let safety;
|
|
55877
|
+
if (opts.skipSafetyCheck) {
|
|
55878
|
+
safety = { skip: true };
|
|
55879
|
+
} else {
|
|
55784
55880
|
const maxUsd = parseFloat(opts.maxUsd ?? String(DEFAULT_MAX_OFFRAMP_USD2));
|
|
55785
55881
|
if (!Number.isFinite(maxUsd) || maxUsd <= 0) {
|
|
55786
55882
|
throw new TransferError("VALIDATION_ERROR", "--max-usd must be a positive number");
|
|
55787
55883
|
}
|
|
55788
|
-
|
|
55789
|
-
const tokenInfo = resolveToken(opts.asset, chainKey);
|
|
55790
|
-
if (tokenInfo) {
|
|
55791
|
-
const swapClient = new SwapClient(httpClient);
|
|
55792
|
-
const price = await swapClient.getTokenPrice(chainKey, tokenInfo.address);
|
|
55793
|
-
if (price && price > 0) {
|
|
55794
|
-
const usdValue = parsedAmount * price;
|
|
55795
|
-
if (usdValue > maxUsd) {
|
|
55796
|
-
throw new TransferError(
|
|
55797
|
-
"USD_LIMIT_EXCEEDED",
|
|
55798
|
-
`Payout value ~$${usdValue.toFixed(2)} USD exceeds safety limit of $${maxUsd}. Re-run with --max-usd ${Math.ceil(usdValue)} or --skip-safety-check to proceed.`
|
|
55799
|
-
);
|
|
55800
|
-
}
|
|
55801
|
-
if (usdValue > 1e3) {
|
|
55802
|
-
warn(`High-value off-ramp payout: ~$${usdValue.toFixed(2)} USD`);
|
|
55803
|
-
}
|
|
55804
|
-
}
|
|
55805
|
-
}
|
|
55806
|
-
} catch (err) {
|
|
55807
|
-
if (err instanceof CommandError) throw err;
|
|
55808
|
-
warn(
|
|
55809
|
-
"Could not verify payout USD value (price lookup failed). Use --skip-safety-check to suppress."
|
|
55810
|
-
);
|
|
55811
|
-
}
|
|
55884
|
+
safety = { maxUsd };
|
|
55812
55885
|
}
|
|
55813
55886
|
const address = await provider.getAddress(chainKey);
|
|
55814
55887
|
warn(
|
|
55815
55888
|
`About to send ${opts.amount} ${opts.asset} from ${address} to third-party off-ramp deposit address ${opts.to}${opts.memo ? ` (memo: ${opts.memo})` : ""}. This address is not under your control \u2014 verify it matches what the provider displayed before continuing.`
|
|
55816
55889
|
);
|
|
55817
|
-
|
|
55818
|
-
|
|
55819
|
-
|
|
55820
|
-
|
|
55821
|
-
|
|
55822
|
-
|
|
55823
|
-
|
|
55824
|
-
|
|
55825
|
-
|
|
55826
|
-
|
|
55827
|
-
|
|
55828
|
-
|
|
55829
|
-
|
|
55830
|
-
|
|
55890
|
+
const { contractAddress } = parseTokenId(opts.asset);
|
|
55891
|
+
const executor = new TransferExecutor({
|
|
55892
|
+
wallet: provider,
|
|
55893
|
+
swapClient: new SwapClient(await getClient()),
|
|
55894
|
+
onInfo: info,
|
|
55895
|
+
onWarn: warn
|
|
55896
|
+
});
|
|
55897
|
+
const result = await executor.execute({
|
|
55898
|
+
// Mainnet by construction — onramp has no --chain input and derives
|
|
55899
|
+
// chainKey from the asset's coinId via mainnetChainKeyForCoinId.
|
|
55900
|
+
chain: chainKey,
|
|
55901
|
+
to: opts.to,
|
|
55902
|
+
resolveNames: false,
|
|
55903
|
+
amount: opts.amount,
|
|
55904
|
+
tokenAddress: contractAddress,
|
|
55905
|
+
decimals: opts.decimals,
|
|
55906
|
+
memo: opts.memo,
|
|
55907
|
+
safety
|
|
55908
|
+
});
|
|
55909
|
+
if (!result.success) {
|
|
55910
|
+
throw new CommandError(result.code, result.message);
|
|
55831
55911
|
}
|
|
55832
|
-
const explorerUrl = getExplorerTxUrl(result.chainKey, result.hash);
|
|
55833
55912
|
success("Off-ramp payout broadcast!");
|
|
55834
55913
|
if (!opts.json) {
|
|
55835
55914
|
info(
|
|
@@ -55840,13 +55919,13 @@ ${url}`);
|
|
|
55840
55919
|
{
|
|
55841
55920
|
hash: result.hash,
|
|
55842
55921
|
chain: result.chainKey,
|
|
55843
|
-
from:
|
|
55844
|
-
to:
|
|
55922
|
+
from: result.from,
|
|
55923
|
+
to: result.to,
|
|
55845
55924
|
amount: opts.amount,
|
|
55846
55925
|
asset: opts.asset,
|
|
55847
55926
|
memo: opts.memo,
|
|
55848
55927
|
quoteId: opts.quoteId,
|
|
55849
|
-
explorer: explorerUrl
|
|
55928
|
+
explorer: result.explorerUrl
|
|
55850
55929
|
},
|
|
55851
55930
|
opts.json
|
|
55852
55931
|
);
|
|
@@ -56319,7 +56398,7 @@ init_dist();
|
|
|
56319
56398
|
// package.json
|
|
56320
56399
|
var package_default = {
|
|
56321
56400
|
name: "@trustwallet/cli",
|
|
56322
|
-
version: "0.
|
|
56401
|
+
version: "0.25.0",
|
|
56323
56402
|
description: "TWAK CLI \u2014 command-line interface for Trust Wallet Agent Kit",
|
|
56324
56403
|
main: "dist/index.js",
|
|
56325
56404
|
types: "dist/index.d.ts",
|