@anywalletkit/protocol-swap2-usdt0 0.2.0 → 0.3.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/README.md +4 -2
- package/dist/activity.cjs +59 -4
- package/dist/activity.cjs.map +1 -1
- package/dist/activity.js +2 -2
- package/dist/{chunk-DGMQ563D.js → chunk-DLLUIT3G.js} +2 -2
- package/dist/{chunk-7YL2Y3QA.js → chunk-KCJW52GY.js} +58 -2
- package/dist/chunk-KCJW52GY.js.map +1 -0
- package/dist/{chunk-DDUVPDD6.js → chunk-NI4IZ34E.js} +3 -3
- package/dist/{chunk-COIPAOOA.js → chunk-RN3GFNGI.js} +3 -3
- package/dist/config.cjs +58 -2
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +14 -4
- package/dist/config.d.ts +14 -4
- package/dist/config.js +5 -3
- package/dist/index.cjs +81 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -6
- package/dist/protocol.cjs +79 -24
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +4 -4
- package/dist/provider.cjs +79 -24
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.js +3 -3
- package/package.json +7 -7
- package/dist/chunk-7YL2Y3QA.js.map +0 -1
- /package/dist/{chunk-DGMQ563D.js.map → chunk-DLLUIT3G.js.map} +0 -0
- /package/dist/{chunk-DDUVPDD6.js.map → chunk-NI4IZ34E.js.map} +0 -0
- /package/dist/{chunk-COIPAOOA.js.map → chunk-RN3GFNGI.js.map} +0 -0
package/README.md
CHANGED
|
@@ -102,8 +102,10 @@ HyperEVM from the phone, then the status through LayerZero Scan).
|
|
|
102
102
|
|
|
103
103
|
When the provider runs on your server, spread its pins into the app's stub:
|
|
104
104
|
`remoteProvider({name: "usdt0", baseUrl, ...usdt0Pins})`. The engine then lets the EVM route call and
|
|
105
|
-
approve only the USDT0 OFT (and, on Ethereum, the adapter as spender), never an address the backend names
|
|
106
|
-
|
|
105
|
+
approve only the USDT0 OFT (and, on Ethereum, the adapter as spender), never an address the backend names, and
|
|
106
|
+
`usdt0VerifyQuote` decodes the server's `send` on the device: the destination eid, the recipient, the input, a
|
|
107
|
+
`minAmountLD` that keeps the quoted minimum, no options or compose message, the trader as refund and the declared
|
|
108
|
+
native fee as value. Without the pins the stub gets no EVM calldata route (fail closed).
|
|
107
109
|
|
|
108
110
|
## Activity
|
|
109
111
|
|
package/dist/activity.cjs
CHANGED
|
@@ -27,9 +27,10 @@ __export(activity_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(activity_exports);
|
|
29
29
|
var import_activity = require("@anywalletkit/protocol-swap2-core/activity");
|
|
30
|
-
var
|
|
30
|
+
var import_viem2 = require("viem");
|
|
31
31
|
|
|
32
32
|
// src/config.ts
|
|
33
|
+
var import_viem = require("viem");
|
|
33
34
|
var import_util = require("@anywalletkit/protocol-swap2-core/util");
|
|
34
35
|
var LZ_ENDPOINT_A = "0x1a44076050125825900e736c501f859c50fE728c";
|
|
35
36
|
var LZ_ENDPOINT_B = "0x6F475642a6e85809B1c36Fa62763669b1b48DD5B";
|
|
@@ -67,6 +68,59 @@ var USDT0_BY_EID = Object.freeze(
|
|
|
67
68
|
Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x]))
|
|
68
69
|
);
|
|
69
70
|
var USDT0_SYMBOLS = Object.freeze(["USDT0", "USDT", "USD\u20AE0", "USD\u20AE"]);
|
|
71
|
+
var OFT_SEND_ABI = (0, import_viem.parseAbi)([
|
|
72
|
+
"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }",
|
|
73
|
+
"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }",
|
|
74
|
+
"function send(SendParam s, MessagingFee fee, address refundAddress) payable"
|
|
75
|
+
]);
|
|
76
|
+
function usdt0VerifyQuote(params, quote) {
|
|
77
|
+
const src = usdt0ChainFor(params.sourceChain);
|
|
78
|
+
const dst = usdt0ChainFor(params.destChain);
|
|
79
|
+
if (!src || !dst || src === dst) return "not a USDT0 route between two deployments";
|
|
80
|
+
if (params.destToken.startsWith("0x") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;
|
|
81
|
+
const tx = quote.txRequest;
|
|
82
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no OFT call";
|
|
83
|
+
if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;
|
|
84
|
+
if (tx.chainId !== void 0 && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;
|
|
85
|
+
if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== void 0) {
|
|
86
|
+
return src.adapter ? "the Ethereum send approves another spender than the adapter" : "an OFT send needs no approval";
|
|
87
|
+
}
|
|
88
|
+
let sp;
|
|
89
|
+
let fee;
|
|
90
|
+
let refund;
|
|
91
|
+
try {
|
|
92
|
+
const d = (0, import_viem.decodeFunctionData)({ abi: OFT_SEND_ABI, data: tx.data });
|
|
93
|
+
[sp, fee, refund] = d.args;
|
|
94
|
+
} catch {
|
|
95
|
+
return "the call is not send(SendParam, MessagingFee, refund)";
|
|
96
|
+
}
|
|
97
|
+
let amountIn, floor, value;
|
|
98
|
+
try {
|
|
99
|
+
amountIn = BigInt(params.amountIn);
|
|
100
|
+
floor = BigInt(quote.minDestAmount);
|
|
101
|
+
if (params.minAmountOut !== void 0 && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);
|
|
102
|
+
value = BigInt(tx.value ?? "0");
|
|
103
|
+
} catch {
|
|
104
|
+
return "the request does not name amounts";
|
|
105
|
+
}
|
|
106
|
+
if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;
|
|
107
|
+
if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;
|
|
108
|
+
if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;
|
|
109
|
+
if (sp.extraOptions !== "0x" || sp.composeMsg !== "0x" || sp.oftCmd !== "0x") return "the send carries options, a compose message or an OFT command";
|
|
110
|
+
const live = params.dry === false;
|
|
111
|
+
if (params.destAddress || live) {
|
|
112
|
+
if (!(0, import_viem.isAddress)(params.destAddress)) return "the recipient is not an EVM address";
|
|
113
|
+
if (sp.to.toLowerCase() !== (0, import_viem.pad)((0, import_viem.getAddress)(params.destAddress), { size: 32 }).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;
|
|
114
|
+
}
|
|
115
|
+
if (params.refundAddress || live) {
|
|
116
|
+
if (!(0, import_viem.isAddress)(params.refundAddress ?? "")) return "the refund address is not an EVM address";
|
|
117
|
+
if ((0, import_viem.getAddress)(refund) !== (0, import_viem.getAddress)(params.refundAddress)) return `the send refunds ${refund}, not the trader`;
|
|
118
|
+
}
|
|
119
|
+
if (fee.lzTokenFee !== 0n) return "the send pays an LZ-token fee";
|
|
120
|
+
if (value !== fee.nativeFee || (tx.nativeFee ?? "0") !== fee.nativeFee.toString()) return "msg.value is not the declared native fee of the send";
|
|
121
|
+
if (quote.intentId.replace(/~[0-9a-f]{32}$/, "") !== `usdt0:${src.eid}:${dst.eid}`) return "the intent id does not name this send";
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
70
124
|
var usdt0Pins = Object.freeze({
|
|
71
125
|
callTargets: (chain) => {
|
|
72
126
|
const c2 = usdt0ChainFor(chain);
|
|
@@ -75,14 +129,15 @@ var usdt0Pins = Object.freeze({
|
|
|
75
129
|
spenders: (chain) => {
|
|
76
130
|
const c2 = usdt0ChainFor(chain);
|
|
77
131
|
return c2?.adapter ? [c2.oft] : [];
|
|
78
|
-
}
|
|
132
|
+
},
|
|
133
|
+
verifyQuote: usdt0VerifyQuote
|
|
79
134
|
});
|
|
80
135
|
function usdt0ChainFor(chain) {
|
|
81
136
|
return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : void 0;
|
|
82
137
|
}
|
|
83
138
|
|
|
84
139
|
// src/activity.ts
|
|
85
|
-
var SEND_ABI = (0,
|
|
140
|
+
var SEND_ABI = (0, import_viem2.parseAbi)([
|
|
86
141
|
"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }",
|
|
87
142
|
"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }",
|
|
88
143
|
"function send(SendParam sp, MessagingFee fee, address refundAddress)"
|
|
@@ -98,7 +153,7 @@ function sendDestination(tx) {
|
|
|
98
153
|
const data = tx.call?.data;
|
|
99
154
|
if (!data || data.length < 10 + 64 * 2) return null;
|
|
100
155
|
try {
|
|
101
|
-
const [sp] = (0,
|
|
156
|
+
const [sp] = (0, import_viem2.decodeFunctionData)({ abi: SEND_ABI, data }).args;
|
|
102
157
|
return USDT0_BY_EID[sp.dstEid] ?? null;
|
|
103
158
|
} catch {
|
|
104
159
|
return null;
|
package/dist/activity.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/activity.ts","../src/config.ts"],"sourcesContent":["/**\n * Activity recognition for USDT0 on every chain in `config.ts`:\n * - `send(...)` on the chain's OFT is our source leg (\"Bridged USDT0\", or\n * \"Bridged USDT\" on Ethereum where the adapter locks plain USDT);\n * - the inbound leg is the executor's delivery — the user signs nothing, so\n * it is recognized by its effect: the chain's USDT0 minted to the owner\n * (from the zero address), or USDT released by the Ethereum adapter to the\n * owner, inside a transaction that did NOT call the token itself (a plain\n * transfer is not a bridge);\n * - `lzReceive` on the LayerZero endpoint is the owner's own retry of a\n * stored payload (`claimSwap2`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {calledContract, chainLabel, describeSwapLike, matchesCall} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {decodeFunctionData, parseAbi, type Hex} from \"viem\";\nimport {USDT0_BY_EID, USDT0_CHAINS, type Usdt0Chain} from \"./config.js\";\n\nconst SEND_ABI = parseAbi([\n \"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }\",\n \"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }\",\n \"function send(SendParam sp, MessagingFee fee, address refundAddress)\",\n]);\n\nexport const USDT0_MODULE = \"@anywalletkit/protocol-swap2-usdt0\";\n\n/** send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address) — IOFT */\nexport const USDT0_SEND = \"0xc7c7f5b3\";\n/** lzReceive((uint32,bytes32,uint64),address,bytes32,bytes,bytes) — EndpointV2 */\nexport const LZ_RECEIVE = \"0x0c0c389e\";\n\nconst ZERO = \"0x0000000000000000000000000000000000000000\";\n\n/** The symbol the catalog uses on each deployment: USDT where the OFT wraps Tether's USDT, USDT0 elsewhere. */\nfunction symbolFor(chain: Usdt0Chain): string {\n return chain.adapter || [42161, 10, 137].includes(chain.chainId) ? \"USDT\" : \"USDT0\";\n}\n\n/** `send(SendParam, …)` → the destination deployment (dstEid is the first word of the tuple), null when the calldata is absent or foreign. */\nfunction sendDestination(tx: ChainTx): Usdt0Chain | null {\n const data = tx.call?.data;\n if (!data || data.length < 10 + 64 * 2) return null;\n try {\n const [sp] = decodeFunctionData({abi: SEND_ABI, data: data as Hex}).args as unknown as [{dstEid: number}];\n return USDT0_BY_EID[sp.dstEid] ?? null;\n } catch {\n return null;\n }\n}\nconst lc = (a: string) => a.toLowerCase();\n\nexport function describeUsdt0Activity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n const chain = USDT0_CHAINS[tx.chain];\n if (!chain) return null;\n const subtitle = `USDT0 · ${chainLabel(tx.chain)}`;\n if (matchesCall(tx, [chain.oft], [USDT0_SEND])) {\n // The native value is the LayerZero messaging fee (plus the headroom the\n // endpoint refunds), not an asset the owner swapped away: it rides in `fee`\n // next to the gas, and the title names both ends when the calldata says\n // where the tokens go.\n const dst = sendDestination(tx);\n const item = describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", outVerb: \"Bridged\"});\n if (!item) return null;\n const native = item.assetsOut.filter((a) => a.token === null).reduce((sum, a) => sum + a.amount, 0n);\n item.assetsOut = item.assetsOut.filter((a) => a.token !== null);\n if (native > 0n) item.fee = (item.fee ?? 0n) + native;\n const srcSym = item.assetsOut[0]?.symbol ?? symbolFor(chain);\n if (dst) {\n item.title = `Bridged ${srcSym} → ${symbolFor(dst)}`;\n item.subtitle = `USDT0 · ${chainLabel(tx.chain)} → ${dst.name}`;\n } else item.title = `Bridged ${srcSym}`;\n return item;\n }\n if (matchesCall(tx, [chain.endpoint], [LZ_RECEIVE])) {\n return describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", inSuffix: \"via LayerZero\"});\n }\n // Delivery by the LayerZero executor: the token moves out of nowhere (mint)\n // or out of the adapter into the owner, and the call target is not the token.\n const called = calledContract(tx);\n if (called && called === lc(chain.token)) return null;\n const own = new Set([...ctx.own].map(lc));\n const origin = chain.adapter ? lc(chain.oft) : ZERO;\n const delivered = tx.transfers.some((t) => t.token !== null && lc(t.token) === lc(chain.token) && lc(t.from) === origin && own.has(lc(t.to)));\n if (!delivered || own.has(lc(tx.from))) return null;\n return describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", inSuffix: \"via LayerZero\", counterparty: chain.oft});\n}\n","// USDT0 — Tether's LayerZero OFT for USDT. Source: docs.usdt0.to\n// (technical-documentation/deployments, read 2026-10-20) — every row below was\n// then re-read on-chain over public RPCs the same day: the OFT's `token()` is\n// the listed token, `endpoint()` is the listed endpoint (and reports the\n// listed eid), `approvalRequired()` is true only for the Ethereum adapter,\n// `sharedDecimals()` = 6 everywhere, and `peers(eid)` are wired between the\n// chains. `oftVersion()` = (0x02e49c2c, 1) on all of them.\n//\n// Only chains the SDK ships (swap2-assets / wallet-evm) are listed. USDT0 is\n// also deployed on Conflux eSpace (1030, eid 30212), Flare (14, 30295),\n// Hedera (295, 30316), Mantle (5000, 30181), Morph (2818, 30322), Rootstock\n// (30, 30333), Stable (988, 30396), Tempo (4217, 30410), plus HyperCore, IOTA\n// and Stellar (non-EVM) — not wallet chains here, so not routable here.\nimport type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\n\nexport interface Usdt0Chain {\n caip2: string;\n chainId: number;\n /** LayerZero V2 endpoint id. */\n eid: number;\n name: string;\n /** The ERC-20 the user holds: USDT on Ethereum, USDT0 elsewhere (6 decimals everywhere). */\n token: string;\n /**\n * The OFT contract `quoteSend` / `send` are called on. On Ethereum it is the\n * OFT *adapter* that locks USDT (`approvalRequired()` = true, approve the\n * token to it); elsewhere it is the OUpgradeable OFT that burns the caller's\n * USDT0 through the token's mint/burn role — no approval.\n */\n oft: string;\n /** LayerZero V2 EndpointV2 on that chain (`lzReceive` retries of a stored payload go here). */\n endpoint: string;\n /** True on Ethereum: the OFT is a lockbox adapter in front of plain USDT. */\n adapter: boolean;\n}\n\nconst LZ_ENDPOINT_A = \"0x1a44076050125825900e736c501f859c50fE728c\";\nconst LZ_ENDPOINT_B = \"0x6F475642a6e85809B1c36Fa62763669b1b48DD5B\";\n\nconst c = (chainId: number, eid: number, name: string, token: string, oft: string, endpoint: string, adapter = false): Usdt0Chain => ({\n caip2: `eip155:${chainId}`, chainId, eid, name, token, oft, endpoint, adapter,\n});\n\n/** CAIP-2 → USDT0 deployment. */\nexport const USDT0_CHAINS: Readonly<Record<string, Usdt0Chain>> = Object.freeze(Object.fromEntries([\n c(1, 30101, \"Ethereum\", \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", \"0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee\", LZ_ENDPOINT_A, true),\n c(42161, 30110, \"Arbitrum\", \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\", \"0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92\", LZ_ENDPOINT_A),\n c(10, 30111, \"OP Mainnet\", \"0x01bFF41798a0BcF287b996046Ca68b395DbC1071\", \"0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD\", LZ_ENDPOINT_A),\n c(137, 30109, \"Polygon PoS\", \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\", \"0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13\", LZ_ENDPOINT_A),\n c(999, 30367, \"HyperEVM\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98\", \"0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9\"),\n c(57073, 30339, \"Ink\", \"0x0200C29006150606B650577BBE7B6248F58470c1\", \"0x1cB6De532588fCA4a21B7209DE7C456AF8434A65\", \"0xca29f3A6f966Cb2fc0dE625F8f325c0C46dbE958\"),\n c(80094, 30362, \"Berachain\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x3Dc96399109df5ceb2C226664A086140bD0379cB\", LZ_ENDPOINT_B),\n c(130, 30320, \"Unichain\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3\", LZ_ENDPOINT_B),\n c(1329, 30280, \"Sei\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0x56Fe74A2e3b484b921c447357203431a3485CC60\", LZ_ENDPOINT_A),\n c(9745, 30383, \"Plasma\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x02ca37966753bDdDf11216B73B16C1dE756A7CF9\", LZ_ENDPOINT_B),\n c(143, 30390, \"Monad\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(4326, 30398, \"MegaETH\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(196, 30274, \"X Layer\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x94bcCa6BdfD6a61817aB0E960BfedE4984505554\", LZ_ENDPOINT_A),\n // 2026-10-20 (evm-chains-6 batch): docs.usdt0.to deployments, re-read on-chain (token(), approvalRequired() = false,\n // sharedDecimals() = 6, endpoint(), peers(30110) = the Arbitrum OFT).\n c(5000, 30181, \"Mantle\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_A),\n c(2818, 30322, \"Morph\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_B),\n c(14, 30295, \"Flare\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x567287d2A9829215a37e3B88843d32f9221E7588\", LZ_ENDPOINT_A),\n].map((x) => [x.caip2, x])));\n\n/** LayerZero eid → deployment. */\nexport const USDT0_BY_EID: Readonly<Record<number, Usdt0Chain>> = Object.freeze(\n Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x])),\n);\n\n/** LayerZero Scan — message status by source transaction hash. */\nexport const LZ_SCAN_API = \"https://scan.layerzero-api.com\";\n\n/** Token symbols the catalog uses for the same asset across chains. */\nexport const USDT0_SYMBOLS: readonly string[] = Object.freeze([\"USDT0\", \"USDT\", \"USD₮0\", \"USD₮\"]);\n\nexport const usdt0 = {\n supportsChain(chain: string): boolean {\n return isEvm(chain) && !!USDT0_CHAINS[`eip155:${evmRef(chain)}`];\n },\n supports(from: string, to: string): boolean {\n return from !== to && this.supportsChain(from) && this.supportsChain(to);\n },\n};\n\n/**\n * The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum) —\n * the app's pins for `remoteProvider({name: \"usdt0\", baseUrl, ...usdt0Pins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const usdt0Pins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c ? [c.oft] : []; },\n spenders: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c?.adapter ? [c.oft] : []; },\n});\nfunction usdt0ChainFor(chain: string): Usdt0Chain | undefined {\n return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : undefined;\n}\n"],"mappings":"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","names":["c"]}
|
|
1
|
+
{"version":3,"sources":["../src/activity.ts","../src/config.ts"],"sourcesContent":["/**\n * Activity recognition for USDT0 on every chain in `config.ts`:\n * - `send(...)` on the chain's OFT is our source leg (\"Bridged USDT0\", or\n * \"Bridged USDT\" on Ethereum where the adapter locks plain USDT);\n * - the inbound leg is the executor's delivery — the user signs nothing, so\n * it is recognized by its effect: the chain's USDT0 minted to the owner\n * (from the zero address), or USDT released by the Ethereum adapter to the\n * owner, inside a transaction that did NOT call the token itself (a plain\n * transfer is not a bridge);\n * - `lzReceive` on the LayerZero endpoint is the owner's own retry of a\n * stored payload (`claimSwap2`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {calledContract, chainLabel, describeSwapLike, matchesCall} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {decodeFunctionData, parseAbi, type Hex} from \"viem\";\nimport {USDT0_BY_EID, USDT0_CHAINS, type Usdt0Chain} from \"./config.js\";\n\nconst SEND_ABI = parseAbi([\n \"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }\",\n \"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }\",\n \"function send(SendParam sp, MessagingFee fee, address refundAddress)\",\n]);\n\nexport const USDT0_MODULE = \"@anywalletkit/protocol-swap2-usdt0\";\n\n/** send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address) — IOFT */\nexport const USDT0_SEND = \"0xc7c7f5b3\";\n/** lzReceive((uint32,bytes32,uint64),address,bytes32,bytes,bytes) — EndpointV2 */\nexport const LZ_RECEIVE = \"0x0c0c389e\";\n\nconst ZERO = \"0x0000000000000000000000000000000000000000\";\n\n/** The symbol the catalog uses on each deployment: USDT where the OFT wraps Tether's USDT, USDT0 elsewhere. */\nfunction symbolFor(chain: Usdt0Chain): string {\n return chain.adapter || [42161, 10, 137].includes(chain.chainId) ? \"USDT\" : \"USDT0\";\n}\n\n/** `send(SendParam, …)` → the destination deployment (dstEid is the first word of the tuple), null when the calldata is absent or foreign. */\nfunction sendDestination(tx: ChainTx): Usdt0Chain | null {\n const data = tx.call?.data;\n if (!data || data.length < 10 + 64 * 2) return null;\n try {\n const [sp] = decodeFunctionData({abi: SEND_ABI, data: data as Hex}).args as unknown as [{dstEid: number}];\n return USDT0_BY_EID[sp.dstEid] ?? null;\n } catch {\n return null;\n }\n}\nconst lc = (a: string) => a.toLowerCase();\n\nexport function describeUsdt0Activity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n const chain = USDT0_CHAINS[tx.chain];\n if (!chain) return null;\n const subtitle = `USDT0 · ${chainLabel(tx.chain)}`;\n if (matchesCall(tx, [chain.oft], [USDT0_SEND])) {\n // The native value is the LayerZero messaging fee (plus the headroom the\n // endpoint refunds), not an asset the owner swapped away: it rides in `fee`\n // next to the gas, and the title names both ends when the calldata says\n // where the tokens go.\n const dst = sendDestination(tx);\n const item = describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", outVerb: \"Bridged\"});\n if (!item) return null;\n const native = item.assetsOut.filter((a) => a.token === null).reduce((sum, a) => sum + a.amount, 0n);\n item.assetsOut = item.assetsOut.filter((a) => a.token !== null);\n if (native > 0n) item.fee = (item.fee ?? 0n) + native;\n const srcSym = item.assetsOut[0]?.symbol ?? symbolFor(chain);\n if (dst) {\n item.title = `Bridged ${srcSym} → ${symbolFor(dst)}`;\n item.subtitle = `USDT0 · ${chainLabel(tx.chain)} → ${dst.name}`;\n } else item.title = `Bridged ${srcSym}`;\n return item;\n }\n if (matchesCall(tx, [chain.endpoint], [LZ_RECEIVE])) {\n return describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", inSuffix: \"via LayerZero\"});\n }\n // Delivery by the LayerZero executor: the token moves out of nowhere (mint)\n // or out of the adapter into the owner, and the call target is not the token.\n const called = calledContract(tx);\n if (called && called === lc(chain.token)) return null;\n const own = new Set([...ctx.own].map(lc));\n const origin = chain.adapter ? lc(chain.oft) : ZERO;\n const delivered = tx.transfers.some((t) => t.token !== null && lc(t.token) === lc(chain.token) && lc(t.from) === origin && own.has(lc(t.to)));\n if (!delivered || own.has(lc(tx.from))) return null;\n return describeSwapLike(tx, ctx, {protocol: USDT0_MODULE, subtitle, kind: \"bridge\", inSuffix: \"via LayerZero\", counterparty: chain.oft});\n}\n","// USDT0 — Tether's LayerZero OFT for USDT. Source: docs.usdt0.to\n// (technical-documentation/deployments, read 2026-10-20) — every row below was\n// then re-read on-chain over public RPCs the same day: the OFT's `token()` is\n// the listed token, `endpoint()` is the listed endpoint (and reports the\n// listed eid), `approvalRequired()` is true only for the Ethereum adapter,\n// `sharedDecimals()` = 6 everywhere, and `peers(eid)` are wired between the\n// chains. `oftVersion()` = (0x02e49c2c, 1) on all of them.\n//\n// Only chains the SDK ships (swap2-assets / wallet-evm) are listed. USDT0 is\n// also deployed on Conflux eSpace (1030, eid 30212), Flare (14, 30295),\n// Hedera (295, 30316), Mantle (5000, 30181), Morph (2818, 30322), Rootstock\n// (30, 30333), Stable (988, 30396), Tempo (4217, 30410), plus HyperCore, IOTA\n// and Stellar (non-EVM) — not wallet chains here, so not routable here.\nimport {decodeFunctionData, getAddress, isAddress, pad, parseAbi, type Hex} from \"viem\";\nimport type {Quote, QuoteParams, RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\n\nexport interface Usdt0Chain {\n caip2: string;\n chainId: number;\n /** LayerZero V2 endpoint id. */\n eid: number;\n name: string;\n /** The ERC-20 the user holds: USDT on Ethereum, USDT0 elsewhere (6 decimals everywhere). */\n token: string;\n /**\n * The OFT contract `quoteSend` / `send` are called on. On Ethereum it is the\n * OFT *adapter* that locks USDT (`approvalRequired()` = true, approve the\n * token to it); elsewhere it is the OUpgradeable OFT that burns the caller's\n * USDT0 through the token's mint/burn role — no approval.\n */\n oft: string;\n /** LayerZero V2 EndpointV2 on that chain (`lzReceive` retries of a stored payload go here). */\n endpoint: string;\n /** True on Ethereum: the OFT is a lockbox adapter in front of plain USDT. */\n adapter: boolean;\n}\n\nconst LZ_ENDPOINT_A = \"0x1a44076050125825900e736c501f859c50fE728c\";\nconst LZ_ENDPOINT_B = \"0x6F475642a6e85809B1c36Fa62763669b1b48DD5B\";\n\nconst c = (chainId: number, eid: number, name: string, token: string, oft: string, endpoint: string, adapter = false): Usdt0Chain => ({\n caip2: `eip155:${chainId}`, chainId, eid, name, token, oft, endpoint, adapter,\n});\n\n/** CAIP-2 → USDT0 deployment. */\nexport const USDT0_CHAINS: Readonly<Record<string, Usdt0Chain>> = Object.freeze(Object.fromEntries([\n c(1, 30101, \"Ethereum\", \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", \"0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee\", LZ_ENDPOINT_A, true),\n c(42161, 30110, \"Arbitrum\", \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\", \"0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92\", LZ_ENDPOINT_A),\n c(10, 30111, \"OP Mainnet\", \"0x01bFF41798a0BcF287b996046Ca68b395DbC1071\", \"0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD\", LZ_ENDPOINT_A),\n c(137, 30109, \"Polygon PoS\", \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\", \"0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13\", LZ_ENDPOINT_A),\n c(999, 30367, \"HyperEVM\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98\", \"0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9\"),\n c(57073, 30339, \"Ink\", \"0x0200C29006150606B650577BBE7B6248F58470c1\", \"0x1cB6De532588fCA4a21B7209DE7C456AF8434A65\", \"0xca29f3A6f966Cb2fc0dE625F8f325c0C46dbE958\"),\n c(80094, 30362, \"Berachain\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x3Dc96399109df5ceb2C226664A086140bD0379cB\", LZ_ENDPOINT_B),\n c(130, 30320, \"Unichain\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3\", LZ_ENDPOINT_B),\n c(1329, 30280, \"Sei\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0x56Fe74A2e3b484b921c447357203431a3485CC60\", LZ_ENDPOINT_A),\n c(9745, 30383, \"Plasma\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x02ca37966753bDdDf11216B73B16C1dE756A7CF9\", LZ_ENDPOINT_B),\n c(143, 30390, \"Monad\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(4326, 30398, \"MegaETH\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(196, 30274, \"X Layer\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x94bcCa6BdfD6a61817aB0E960BfedE4984505554\", LZ_ENDPOINT_A),\n // 2026-10-20 (evm-chains-6 batch): docs.usdt0.to deployments, re-read on-chain (token(), approvalRequired() = false,\n // sharedDecimals() = 6, endpoint(), peers(30110) = the Arbitrum OFT).\n c(5000, 30181, \"Mantle\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_A),\n c(2818, 30322, \"Morph\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_B),\n c(14, 30295, \"Flare\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x567287d2A9829215a37e3B88843d32f9221E7588\", LZ_ENDPOINT_A),\n].map((x) => [x.caip2, x])));\n\n/** LayerZero eid → deployment. */\nexport const USDT0_BY_EID: Readonly<Record<number, Usdt0Chain>> = Object.freeze(\n Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x])),\n);\n\n/** LayerZero Scan — message status by source transaction hash. */\nexport const LZ_SCAN_API = \"https://scan.layerzero-api.com\";\n\n/** Token symbols the catalog uses for the same asset across chains. */\nexport const USDT0_SYMBOLS: readonly string[] = Object.freeze([\"USDT0\", \"USDT\", \"USD₮0\", \"USD₮\"]);\n\nexport const usdt0 = {\n supportsChain(chain: string): boolean {\n return isEvm(chain) && !!USDT0_CHAINS[`eip155:${evmRef(chain)}`];\n },\n supports(from: string, to: string): boolean {\n return from !== to && this.supportsChain(from) && this.supportsChain(to);\n },\n};\n\nconst OFT_SEND_ABI = parseAbi([\n \"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }\",\n \"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }\",\n \"function send(SendParam s, MessagingFee fee, address refundAddress) payable\",\n]);\n\n/**\n * A remote USDT0 quote's `send`, decoded on the device against the app's own request (scan 2026-10-30, F3): exactly\n * `send(SendParam, MessagingFee, refund)` on the source OFT; the destination chain's eid; the recipient as `to`; the\n * input as `amountLD`; a `minAmountLD` no larger than the input that guarantees the quoted minimum and the caller's\n * floor; empty `extraOptions`, `composeMsg` and `oftCmd` (what the provider sends); no LZ-token fee; the trader as\n * refund; `msg.value` = the declared native fee = the call's `nativeFee`; the adapter as spender on Ethereum only.\n * The reason it fails, or null. The engine's native-fee ceiling bounds the fee itself.\n */\nexport function usdt0VerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const src = usdt0ChainFor(params.sourceChain);\n const dst = usdt0ChainFor(params.destChain);\n if (!src || !dst || src === dst) return \"not a USDT0 route between two deployments\";\n if (params.destToken.startsWith(\"0x\") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no OFT call\";\n if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;\n if (tx.chainId !== undefined && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;\n if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== undefined) {\n return src.adapter ? \"the Ethereum send approves another spender than the adapter\" : \"an OFT send needs no approval\";\n }\n let sp: {dstEid: number; to: Hex; amountLD: bigint; minAmountLD: bigint; extraOptions: Hex; composeMsg: Hex; oftCmd: Hex};\n let fee: {nativeFee: bigint; lzTokenFee: bigint};\n let refund: string;\n try {\n const d = decodeFunctionData({abi: OFT_SEND_ABI, data: tx.data as Hex});\n [sp, fee, refund] = d.args as unknown as [typeof sp, typeof fee, string];\n } catch {\n return \"the call is not send(SendParam, MessagingFee, refund)\";\n }\n let amountIn: bigint, floor: bigint, value: bigint;\n try {\n amountIn = BigInt(params.amountIn);\n floor = BigInt(quote.minDestAmount);\n if (params.minAmountOut !== undefined && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;\n if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;\n if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;\n if (sp.extraOptions !== \"0x\" || sp.composeMsg !== \"0x\" || sp.oftCmd !== \"0x\") return \"the send carries options, a compose message or an OFT command\";\n // A dry quote without addresses prices the provider's placeholders; it is never built (the engine re-quotes live).\n const live = params.dry === false;\n if (params.destAddress || live) {\n if (!isAddress(params.destAddress)) return \"the recipient is not an EVM address\";\n if (sp.to.toLowerCase() !== pad(getAddress(params.destAddress), {size: 32}).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;\n }\n if (params.refundAddress || live) {\n if (!isAddress(params.refundAddress ?? \"\")) return \"the refund address is not an EVM address\";\n if (getAddress(refund) !== getAddress(params.refundAddress!)) return `the send refunds ${refund}, not the trader`;\n }\n if (fee.lzTokenFee !== 0n) return \"the send pays an LZ-token fee\";\n if (value !== fee.nativeFee || (tx.nativeFee ?? \"0\") !== fee.nativeFee.toString()) return \"msg.value is not the declared native fee of the send\";\n if (quote.intentId.replace(/~[0-9a-f]{32}$/, \"\") !== `usdt0:${src.eid}:${dst.eid}`) return \"the intent id does not name this send\";\n return null;\n}\n\n/**\n * The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum), and\n * {@link usdt0VerifyQuote} — the app's pins for `remoteProvider({name: \"usdt0\", baseUrl, ...usdt0Pins})` (scan\n * 2026-10-27 modules, F8/F16; the send's arguments since scan 2026-10-30, F3).\n */\nexport const usdt0Pins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c ? [c.oft] : []; },\n spenders: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c?.adapter ? [c.oft] : []; },\n verifyQuote: usdt0VerifyQuote,\n});\nfunction usdt0ChainFor(chain: string): Usdt0Chain | undefined {\n return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : undefined;\n}\n"],"mappings":"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","names":["import_viem","c"]}
|
package/dist/activity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
USDT0_BY_EID,
|
|
3
3
|
USDT0_CHAINS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KCJW52GY.js";
|
|
5
5
|
|
|
6
6
|
// src/activity.ts
|
|
7
7
|
import { calledContract, chainLabel, describeSwapLike, matchesCall } from "@anywalletkit/protocol-swap2-core/activity";
|
|
@@ -65,4 +65,4 @@ export {
|
|
|
65
65
|
LZ_RECEIVE,
|
|
66
66
|
describeUsdt0Activity
|
|
67
67
|
};
|
|
68
|
-
//# sourceMappingURL=chunk-
|
|
68
|
+
//# sourceMappingURL=chunk-DLLUIT3G.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
|
+
import { decodeFunctionData, getAddress, isAddress, pad, parseAbi } from "viem";
|
|
2
3
|
import { evmRef, isEvm } from "@anywalletkit/protocol-swap2-core/util";
|
|
3
4
|
var LZ_ENDPOINT_A = "0x1a44076050125825900e736c501f859c50fE728c";
|
|
4
5
|
var LZ_ENDPOINT_B = "0x6F475642a6e85809B1c36Fa62763669b1b48DD5B";
|
|
@@ -45,6 +46,59 @@ var usdt0 = {
|
|
|
45
46
|
return from !== to && this.supportsChain(from) && this.supportsChain(to);
|
|
46
47
|
}
|
|
47
48
|
};
|
|
49
|
+
var OFT_SEND_ABI = parseAbi([
|
|
50
|
+
"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }",
|
|
51
|
+
"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }",
|
|
52
|
+
"function send(SendParam s, MessagingFee fee, address refundAddress) payable"
|
|
53
|
+
]);
|
|
54
|
+
function usdt0VerifyQuote(params, quote) {
|
|
55
|
+
const src = usdt0ChainFor(params.sourceChain);
|
|
56
|
+
const dst = usdt0ChainFor(params.destChain);
|
|
57
|
+
if (!src || !dst || src === dst) return "not a USDT0 route between two deployments";
|
|
58
|
+
if (params.destToken.startsWith("0x") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;
|
|
59
|
+
const tx = quote.txRequest;
|
|
60
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no OFT call";
|
|
61
|
+
if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;
|
|
62
|
+
if (tx.chainId !== void 0 && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;
|
|
63
|
+
if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== void 0) {
|
|
64
|
+
return src.adapter ? "the Ethereum send approves another spender than the adapter" : "an OFT send needs no approval";
|
|
65
|
+
}
|
|
66
|
+
let sp;
|
|
67
|
+
let fee;
|
|
68
|
+
let refund;
|
|
69
|
+
try {
|
|
70
|
+
const d = decodeFunctionData({ abi: OFT_SEND_ABI, data: tx.data });
|
|
71
|
+
[sp, fee, refund] = d.args;
|
|
72
|
+
} catch {
|
|
73
|
+
return "the call is not send(SendParam, MessagingFee, refund)";
|
|
74
|
+
}
|
|
75
|
+
let amountIn, floor, value;
|
|
76
|
+
try {
|
|
77
|
+
amountIn = BigInt(params.amountIn);
|
|
78
|
+
floor = BigInt(quote.minDestAmount);
|
|
79
|
+
if (params.minAmountOut !== void 0 && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);
|
|
80
|
+
value = BigInt(tx.value ?? "0");
|
|
81
|
+
} catch {
|
|
82
|
+
return "the request does not name amounts";
|
|
83
|
+
}
|
|
84
|
+
if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;
|
|
85
|
+
if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;
|
|
86
|
+
if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;
|
|
87
|
+
if (sp.extraOptions !== "0x" || sp.composeMsg !== "0x" || sp.oftCmd !== "0x") return "the send carries options, a compose message or an OFT command";
|
|
88
|
+
const live = params.dry === false;
|
|
89
|
+
if (params.destAddress || live) {
|
|
90
|
+
if (!isAddress(params.destAddress)) return "the recipient is not an EVM address";
|
|
91
|
+
if (sp.to.toLowerCase() !== pad(getAddress(params.destAddress), { size: 32 }).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;
|
|
92
|
+
}
|
|
93
|
+
if (params.refundAddress || live) {
|
|
94
|
+
if (!isAddress(params.refundAddress ?? "")) return "the refund address is not an EVM address";
|
|
95
|
+
if (getAddress(refund) !== getAddress(params.refundAddress)) return `the send refunds ${refund}, not the trader`;
|
|
96
|
+
}
|
|
97
|
+
if (fee.lzTokenFee !== 0n) return "the send pays an LZ-token fee";
|
|
98
|
+
if (value !== fee.nativeFee || (tx.nativeFee ?? "0") !== fee.nativeFee.toString()) return "msg.value is not the declared native fee of the send";
|
|
99
|
+
if (quote.intentId.replace(/~[0-9a-f]{32}$/, "") !== `usdt0:${src.eid}:${dst.eid}`) return "the intent id does not name this send";
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
48
102
|
var usdt0Pins = Object.freeze({
|
|
49
103
|
callTargets: (chain) => {
|
|
50
104
|
const c2 = usdt0ChainFor(chain);
|
|
@@ -53,7 +107,8 @@ var usdt0Pins = Object.freeze({
|
|
|
53
107
|
spenders: (chain) => {
|
|
54
108
|
const c2 = usdt0ChainFor(chain);
|
|
55
109
|
return c2?.adapter ? [c2.oft] : [];
|
|
56
|
-
}
|
|
110
|
+
},
|
|
111
|
+
verifyQuote: usdt0VerifyQuote
|
|
57
112
|
});
|
|
58
113
|
function usdt0ChainFor(chain) {
|
|
59
114
|
return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : void 0;
|
|
@@ -65,6 +120,7 @@ export {
|
|
|
65
120
|
LZ_SCAN_API,
|
|
66
121
|
USDT0_SYMBOLS,
|
|
67
122
|
usdt0,
|
|
123
|
+
usdt0VerifyQuote,
|
|
68
124
|
usdt0Pins
|
|
69
125
|
};
|
|
70
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-KCJW52GY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["// USDT0 — Tether's LayerZero OFT for USDT. Source: docs.usdt0.to\n// (technical-documentation/deployments, read 2026-10-20) — every row below was\n// then re-read on-chain over public RPCs the same day: the OFT's `token()` is\n// the listed token, `endpoint()` is the listed endpoint (and reports the\n// listed eid), `approvalRequired()` is true only for the Ethereum adapter,\n// `sharedDecimals()` = 6 everywhere, and `peers(eid)` are wired between the\n// chains. `oftVersion()` = (0x02e49c2c, 1) on all of them.\n//\n// Only chains the SDK ships (swap2-assets / wallet-evm) are listed. USDT0 is\n// also deployed on Conflux eSpace (1030, eid 30212), Flare (14, 30295),\n// Hedera (295, 30316), Mantle (5000, 30181), Morph (2818, 30322), Rootstock\n// (30, 30333), Stable (988, 30396), Tempo (4217, 30410), plus HyperCore, IOTA\n// and Stellar (non-EVM) — not wallet chains here, so not routable here.\nimport {decodeFunctionData, getAddress, isAddress, pad, parseAbi, type Hex} from \"viem\";\nimport type {Quote, QuoteParams, RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\n\nexport interface Usdt0Chain {\n caip2: string;\n chainId: number;\n /** LayerZero V2 endpoint id. */\n eid: number;\n name: string;\n /** The ERC-20 the user holds: USDT on Ethereum, USDT0 elsewhere (6 decimals everywhere). */\n token: string;\n /**\n * The OFT contract `quoteSend` / `send` are called on. On Ethereum it is the\n * OFT *adapter* that locks USDT (`approvalRequired()` = true, approve the\n * token to it); elsewhere it is the OUpgradeable OFT that burns the caller's\n * USDT0 through the token's mint/burn role — no approval.\n */\n oft: string;\n /** LayerZero V2 EndpointV2 on that chain (`lzReceive` retries of a stored payload go here). */\n endpoint: string;\n /** True on Ethereum: the OFT is a lockbox adapter in front of plain USDT. */\n adapter: boolean;\n}\n\nconst LZ_ENDPOINT_A = \"0x1a44076050125825900e736c501f859c50fE728c\";\nconst LZ_ENDPOINT_B = \"0x6F475642a6e85809B1c36Fa62763669b1b48DD5B\";\n\nconst c = (chainId: number, eid: number, name: string, token: string, oft: string, endpoint: string, adapter = false): Usdt0Chain => ({\n caip2: `eip155:${chainId}`, chainId, eid, name, token, oft, endpoint, adapter,\n});\n\n/** CAIP-2 → USDT0 deployment. */\nexport const USDT0_CHAINS: Readonly<Record<string, Usdt0Chain>> = Object.freeze(Object.fromEntries([\n c(1, 30101, \"Ethereum\", \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", \"0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee\", LZ_ENDPOINT_A, true),\n c(42161, 30110, \"Arbitrum\", \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\", \"0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92\", LZ_ENDPOINT_A),\n c(10, 30111, \"OP Mainnet\", \"0x01bFF41798a0BcF287b996046Ca68b395DbC1071\", \"0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD\", LZ_ENDPOINT_A),\n c(137, 30109, \"Polygon PoS\", \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\", \"0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13\", LZ_ENDPOINT_A),\n c(999, 30367, \"HyperEVM\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98\", \"0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9\"),\n c(57073, 30339, \"Ink\", \"0x0200C29006150606B650577BBE7B6248F58470c1\", \"0x1cB6De532588fCA4a21B7209DE7C456AF8434A65\", \"0xca29f3A6f966Cb2fc0dE625F8f325c0C46dbE958\"),\n c(80094, 30362, \"Berachain\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x3Dc96399109df5ceb2C226664A086140bD0379cB\", LZ_ENDPOINT_B),\n c(130, 30320, \"Unichain\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3\", LZ_ENDPOINT_B),\n c(1329, 30280, \"Sei\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0x56Fe74A2e3b484b921c447357203431a3485CC60\", LZ_ENDPOINT_A),\n c(9745, 30383, \"Plasma\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x02ca37966753bDdDf11216B73B16C1dE756A7CF9\", LZ_ENDPOINT_B),\n c(143, 30390, \"Monad\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(4326, 30398, \"MegaETH\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(196, 30274, \"X Layer\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x94bcCa6BdfD6a61817aB0E960BfedE4984505554\", LZ_ENDPOINT_A),\n // 2026-10-20 (evm-chains-6 batch): docs.usdt0.to deployments, re-read on-chain (token(), approvalRequired() = false,\n // sharedDecimals() = 6, endpoint(), peers(30110) = the Arbitrum OFT).\n c(5000, 30181, \"Mantle\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_A),\n c(2818, 30322, \"Morph\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_B),\n c(14, 30295, \"Flare\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x567287d2A9829215a37e3B88843d32f9221E7588\", LZ_ENDPOINT_A),\n].map((x) => [x.caip2, x])));\n\n/** LayerZero eid → deployment. */\nexport const USDT0_BY_EID: Readonly<Record<number, Usdt0Chain>> = Object.freeze(\n Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x])),\n);\n\n/** LayerZero Scan — message status by source transaction hash. */\nexport const LZ_SCAN_API = \"https://scan.layerzero-api.com\";\n\n/** Token symbols the catalog uses for the same asset across chains. */\nexport const USDT0_SYMBOLS: readonly string[] = Object.freeze([\"USDT0\", \"USDT\", \"USD₮0\", \"USD₮\"]);\n\nexport const usdt0 = {\n supportsChain(chain: string): boolean {\n return isEvm(chain) && !!USDT0_CHAINS[`eip155:${evmRef(chain)}`];\n },\n supports(from: string, to: string): boolean {\n return from !== to && this.supportsChain(from) && this.supportsChain(to);\n },\n};\n\nconst OFT_SEND_ABI = parseAbi([\n \"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }\",\n \"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }\",\n \"function send(SendParam s, MessagingFee fee, address refundAddress) payable\",\n]);\n\n/**\n * A remote USDT0 quote's `send`, decoded on the device against the app's own request (scan 2026-10-30, F3): exactly\n * `send(SendParam, MessagingFee, refund)` on the source OFT; the destination chain's eid; the recipient as `to`; the\n * input as `amountLD`; a `minAmountLD` no larger than the input that guarantees the quoted minimum and the caller's\n * floor; empty `extraOptions`, `composeMsg` and `oftCmd` (what the provider sends); no LZ-token fee; the trader as\n * refund; `msg.value` = the declared native fee = the call's `nativeFee`; the adapter as spender on Ethereum only.\n * The reason it fails, or null. The engine's native-fee ceiling bounds the fee itself.\n */\nexport function usdt0VerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const src = usdt0ChainFor(params.sourceChain);\n const dst = usdt0ChainFor(params.destChain);\n if (!src || !dst || src === dst) return \"not a USDT0 route between two deployments\";\n if (params.destToken.startsWith(\"0x\") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no OFT call\";\n if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;\n if (tx.chainId !== undefined && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;\n if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== undefined) {\n return src.adapter ? \"the Ethereum send approves another spender than the adapter\" : \"an OFT send needs no approval\";\n }\n let sp: {dstEid: number; to: Hex; amountLD: bigint; minAmountLD: bigint; extraOptions: Hex; composeMsg: Hex; oftCmd: Hex};\n let fee: {nativeFee: bigint; lzTokenFee: bigint};\n let refund: string;\n try {\n const d = decodeFunctionData({abi: OFT_SEND_ABI, data: tx.data as Hex});\n [sp, fee, refund] = d.args as unknown as [typeof sp, typeof fee, string];\n } catch {\n return \"the call is not send(SendParam, MessagingFee, refund)\";\n }\n let amountIn: bigint, floor: bigint, value: bigint;\n try {\n amountIn = BigInt(params.amountIn);\n floor = BigInt(quote.minDestAmount);\n if (params.minAmountOut !== undefined && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;\n if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;\n if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;\n if (sp.extraOptions !== \"0x\" || sp.composeMsg !== \"0x\" || sp.oftCmd !== \"0x\") return \"the send carries options, a compose message or an OFT command\";\n // A dry quote without addresses prices the provider's placeholders; it is never built (the engine re-quotes live).\n const live = params.dry === false;\n if (params.destAddress || live) {\n if (!isAddress(params.destAddress)) return \"the recipient is not an EVM address\";\n if (sp.to.toLowerCase() !== pad(getAddress(params.destAddress), {size: 32}).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;\n }\n if (params.refundAddress || live) {\n if (!isAddress(params.refundAddress ?? \"\")) return \"the refund address is not an EVM address\";\n if (getAddress(refund) !== getAddress(params.refundAddress!)) return `the send refunds ${refund}, not the trader`;\n }\n if (fee.lzTokenFee !== 0n) return \"the send pays an LZ-token fee\";\n if (value !== fee.nativeFee || (tx.nativeFee ?? \"0\") !== fee.nativeFee.toString()) return \"msg.value is not the declared native fee of the send\";\n if (quote.intentId.replace(/~[0-9a-f]{32}$/, \"\") !== `usdt0:${src.eid}:${dst.eid}`) return \"the intent id does not name this send\";\n return null;\n}\n\n/**\n * The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum), and\n * {@link usdt0VerifyQuote} — the app's pins for `remoteProvider({name: \"usdt0\", baseUrl, ...usdt0Pins})` (scan\n * 2026-10-27 modules, F8/F16; the send's arguments since scan 2026-10-30, F3).\n */\nexport const usdt0Pins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c ? [c.oft] : []; },\n spenders: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c?.adapter ? [c.oft] : []; },\n verifyQuote: usdt0VerifyQuote,\n});\nfunction usdt0ChainFor(chain: string): Usdt0Chain | undefined {\n return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : undefined;\n}\n"],"mappings":"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","names":["c"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
usdt0Provider
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RN3GFNGI.js";
|
|
4
4
|
import {
|
|
5
5
|
usdt0
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KCJW52GY.js";
|
|
7
7
|
|
|
8
8
|
// src/protocol.ts
|
|
9
9
|
import { SingleProviderSwap2 } from "@anywalletkit/protocol-swap2-core/swap2/single";
|
|
@@ -24,4 +24,4 @@ var Usdt0Swap2Protocol = class extends SingleProviderSwap2 {
|
|
|
24
24
|
export {
|
|
25
25
|
Usdt0Swap2Protocol
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
27
|
+
//# sourceMappingURL=chunk-NI4IZ34E.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
describeUsdt0Activity
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DLLUIT3G.js";
|
|
4
4
|
import {
|
|
5
5
|
LZ_SCAN_API,
|
|
6
6
|
USDT0_BY_EID,
|
|
7
7
|
USDT0_CHAINS,
|
|
8
8
|
USDT0_SYMBOLS,
|
|
9
9
|
usdt0
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KCJW52GY.js";
|
|
11
11
|
|
|
12
12
|
// src/provider.ts
|
|
13
13
|
import { createPublicClient, encodeFunctionData, fallback, getAddress, http, isAddress, pad, parseAbi } from "viem";
|
|
@@ -341,4 +341,4 @@ export {
|
|
|
341
341
|
usdt0Provider,
|
|
342
342
|
USDT0_STATUS_MAP
|
|
343
343
|
};
|
|
344
|
-
//# sourceMappingURL=chunk-
|
|
344
|
+
//# sourceMappingURL=chunk-RN3GFNGI.js.map
|
package/dist/config.cjs
CHANGED
|
@@ -25,9 +25,11 @@ __export(config_exports, {
|
|
|
25
25
|
USDT0_CHAINS: () => USDT0_CHAINS,
|
|
26
26
|
USDT0_SYMBOLS: () => USDT0_SYMBOLS,
|
|
27
27
|
usdt0: () => usdt0,
|
|
28
|
-
usdt0Pins: () => usdt0Pins
|
|
28
|
+
usdt0Pins: () => usdt0Pins,
|
|
29
|
+
usdt0VerifyQuote: () => usdt0VerifyQuote
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(config_exports);
|
|
32
|
+
var import_viem = require("viem");
|
|
31
33
|
var import_util = require("@anywalletkit/protocol-swap2-core/util");
|
|
32
34
|
var LZ_ENDPOINT_A = "0x1a44076050125825900e736c501f859c50fE728c";
|
|
33
35
|
var LZ_ENDPOINT_B = "0x6F475642a6e85809B1c36Fa62763669b1b48DD5B";
|
|
@@ -74,6 +76,59 @@ var usdt0 = {
|
|
|
74
76
|
return from !== to && this.supportsChain(from) && this.supportsChain(to);
|
|
75
77
|
}
|
|
76
78
|
};
|
|
79
|
+
var OFT_SEND_ABI = (0, import_viem.parseAbi)([
|
|
80
|
+
"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }",
|
|
81
|
+
"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }",
|
|
82
|
+
"function send(SendParam s, MessagingFee fee, address refundAddress) payable"
|
|
83
|
+
]);
|
|
84
|
+
function usdt0VerifyQuote(params, quote) {
|
|
85
|
+
const src = usdt0ChainFor(params.sourceChain);
|
|
86
|
+
const dst = usdt0ChainFor(params.destChain);
|
|
87
|
+
if (!src || !dst || src === dst) return "not a USDT0 route between two deployments";
|
|
88
|
+
if (params.destToken.startsWith("0x") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;
|
|
89
|
+
const tx = quote.txRequest;
|
|
90
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no OFT call";
|
|
91
|
+
if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;
|
|
92
|
+
if (tx.chainId !== void 0 && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;
|
|
93
|
+
if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== void 0) {
|
|
94
|
+
return src.adapter ? "the Ethereum send approves another spender than the adapter" : "an OFT send needs no approval";
|
|
95
|
+
}
|
|
96
|
+
let sp;
|
|
97
|
+
let fee;
|
|
98
|
+
let refund;
|
|
99
|
+
try {
|
|
100
|
+
const d = (0, import_viem.decodeFunctionData)({ abi: OFT_SEND_ABI, data: tx.data });
|
|
101
|
+
[sp, fee, refund] = d.args;
|
|
102
|
+
} catch {
|
|
103
|
+
return "the call is not send(SendParam, MessagingFee, refund)";
|
|
104
|
+
}
|
|
105
|
+
let amountIn, floor, value;
|
|
106
|
+
try {
|
|
107
|
+
amountIn = BigInt(params.amountIn);
|
|
108
|
+
floor = BigInt(quote.minDestAmount);
|
|
109
|
+
if (params.minAmountOut !== void 0 && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);
|
|
110
|
+
value = BigInt(tx.value ?? "0");
|
|
111
|
+
} catch {
|
|
112
|
+
return "the request does not name amounts";
|
|
113
|
+
}
|
|
114
|
+
if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;
|
|
115
|
+
if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;
|
|
116
|
+
if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;
|
|
117
|
+
if (sp.extraOptions !== "0x" || sp.composeMsg !== "0x" || sp.oftCmd !== "0x") return "the send carries options, a compose message or an OFT command";
|
|
118
|
+
const live = params.dry === false;
|
|
119
|
+
if (params.destAddress || live) {
|
|
120
|
+
if (!(0, import_viem.isAddress)(params.destAddress)) return "the recipient is not an EVM address";
|
|
121
|
+
if (sp.to.toLowerCase() !== (0, import_viem.pad)((0, import_viem.getAddress)(params.destAddress), { size: 32 }).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;
|
|
122
|
+
}
|
|
123
|
+
if (params.refundAddress || live) {
|
|
124
|
+
if (!(0, import_viem.isAddress)(params.refundAddress ?? "")) return "the refund address is not an EVM address";
|
|
125
|
+
if ((0, import_viem.getAddress)(refund) !== (0, import_viem.getAddress)(params.refundAddress)) return `the send refunds ${refund}, not the trader`;
|
|
126
|
+
}
|
|
127
|
+
if (fee.lzTokenFee !== 0n) return "the send pays an LZ-token fee";
|
|
128
|
+
if (value !== fee.nativeFee || (tx.nativeFee ?? "0") !== fee.nativeFee.toString()) return "msg.value is not the declared native fee of the send";
|
|
129
|
+
if (quote.intentId.replace(/~[0-9a-f]{32}$/, "") !== `usdt0:${src.eid}:${dst.eid}`) return "the intent id does not name this send";
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
77
132
|
var usdt0Pins = Object.freeze({
|
|
78
133
|
callTargets: (chain) => {
|
|
79
134
|
const c2 = usdt0ChainFor(chain);
|
|
@@ -82,7 +137,8 @@ var usdt0Pins = Object.freeze({
|
|
|
82
137
|
spenders: (chain) => {
|
|
83
138
|
const c2 = usdt0ChainFor(chain);
|
|
84
139
|
return c2?.adapter ? [c2.oft] : [];
|
|
85
|
-
}
|
|
140
|
+
},
|
|
141
|
+
verifyQuote: usdt0VerifyQuote
|
|
86
142
|
});
|
|
87
143
|
function usdt0ChainFor(chain) {
|
|
88
144
|
return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : void 0;
|
package/dist/config.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["// USDT0 — Tether's LayerZero OFT for USDT. Source: docs.usdt0.to\n// (technical-documentation/deployments, read 2026-10-20) — every row below was\n// then re-read on-chain over public RPCs the same day: the OFT's `token()` is\n// the listed token, `endpoint()` is the listed endpoint (and reports the\n// listed eid), `approvalRequired()` is true only for the Ethereum adapter,\n// `sharedDecimals()` = 6 everywhere, and `peers(eid)` are wired between the\n// chains. `oftVersion()` = (0x02e49c2c, 1) on all of them.\n//\n// Only chains the SDK ships (swap2-assets / wallet-evm) are listed. USDT0 is\n// also deployed on Conflux eSpace (1030, eid 30212), Flare (14, 30295),\n// Hedera (295, 30316), Mantle (5000, 30181), Morph (2818, 30322), Rootstock\n// (30, 30333), Stable (988, 30396), Tempo (4217, 30410), plus HyperCore, IOTA\n// and Stellar (non-EVM) — not wallet chains here, so not routable here.\nimport type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\n\nexport interface Usdt0Chain {\n caip2: string;\n chainId: number;\n /** LayerZero V2 endpoint id. */\n eid: number;\n name: string;\n /** The ERC-20 the user holds: USDT on Ethereum, USDT0 elsewhere (6 decimals everywhere). */\n token: string;\n /**\n * The OFT contract `quoteSend` / `send` are called on. On Ethereum it is the\n * OFT *adapter* that locks USDT (`approvalRequired()` = true, approve the\n * token to it); elsewhere it is the OUpgradeable OFT that burns the caller's\n * USDT0 through the token's mint/burn role — no approval.\n */\n oft: string;\n /** LayerZero V2 EndpointV2 on that chain (`lzReceive` retries of a stored payload go here). */\n endpoint: string;\n /** True on Ethereum: the OFT is a lockbox adapter in front of plain USDT. */\n adapter: boolean;\n}\n\nconst LZ_ENDPOINT_A = \"0x1a44076050125825900e736c501f859c50fE728c\";\nconst LZ_ENDPOINT_B = \"0x6F475642a6e85809B1c36Fa62763669b1b48DD5B\";\n\nconst c = (chainId: number, eid: number, name: string, token: string, oft: string, endpoint: string, adapter = false): Usdt0Chain => ({\n caip2: `eip155:${chainId}`, chainId, eid, name, token, oft, endpoint, adapter,\n});\n\n/** CAIP-2 → USDT0 deployment. */\nexport const USDT0_CHAINS: Readonly<Record<string, Usdt0Chain>> = Object.freeze(Object.fromEntries([\n c(1, 30101, \"Ethereum\", \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", \"0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee\", LZ_ENDPOINT_A, true),\n c(42161, 30110, \"Arbitrum\", \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\", \"0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92\", LZ_ENDPOINT_A),\n c(10, 30111, \"OP Mainnet\", \"0x01bFF41798a0BcF287b996046Ca68b395DbC1071\", \"0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD\", LZ_ENDPOINT_A),\n c(137, 30109, \"Polygon PoS\", \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\", \"0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13\", LZ_ENDPOINT_A),\n c(999, 30367, \"HyperEVM\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98\", \"0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9\"),\n c(57073, 30339, \"Ink\", \"0x0200C29006150606B650577BBE7B6248F58470c1\", \"0x1cB6De532588fCA4a21B7209DE7C456AF8434A65\", \"0xca29f3A6f966Cb2fc0dE625F8f325c0C46dbE958\"),\n c(80094, 30362, \"Berachain\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x3Dc96399109df5ceb2C226664A086140bD0379cB\", LZ_ENDPOINT_B),\n c(130, 30320, \"Unichain\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3\", LZ_ENDPOINT_B),\n c(1329, 30280, \"Sei\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0x56Fe74A2e3b484b921c447357203431a3485CC60\", LZ_ENDPOINT_A),\n c(9745, 30383, \"Plasma\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x02ca37966753bDdDf11216B73B16C1dE756A7CF9\", LZ_ENDPOINT_B),\n c(143, 30390, \"Monad\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(4326, 30398, \"MegaETH\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(196, 30274, \"X Layer\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x94bcCa6BdfD6a61817aB0E960BfedE4984505554\", LZ_ENDPOINT_A),\n // 2026-10-20 (evm-chains-6 batch): docs.usdt0.to deployments, re-read on-chain (token(), approvalRequired() = false,\n // sharedDecimals() = 6, endpoint(), peers(30110) = the Arbitrum OFT).\n c(5000, 30181, \"Mantle\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_A),\n c(2818, 30322, \"Morph\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_B),\n c(14, 30295, \"Flare\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x567287d2A9829215a37e3B88843d32f9221E7588\", LZ_ENDPOINT_A),\n].map((x) => [x.caip2, x])));\n\n/** LayerZero eid → deployment. */\nexport const USDT0_BY_EID: Readonly<Record<number, Usdt0Chain>> = Object.freeze(\n Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x])),\n);\n\n/** LayerZero Scan — message status by source transaction hash. */\nexport const LZ_SCAN_API = \"https://scan.layerzero-api.com\";\n\n/** Token symbols the catalog uses for the same asset across chains. */\nexport const USDT0_SYMBOLS: readonly string[] = Object.freeze([\"USDT0\", \"USDT\", \"USD₮0\", \"USD₮\"]);\n\nexport const usdt0 = {\n supportsChain(chain: string): boolean {\n return isEvm(chain) && !!USDT0_CHAINS[`eip155:${evmRef(chain)}`];\n },\n supports(from: string, to: string): boolean {\n return from !== to && this.supportsChain(from) && this.supportsChain(to);\n },\n};\n\n/**\n * The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum) —\n * the app's pins for `remoteProvider({name: \"usdt0\", baseUrl, ...usdt0Pins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const usdt0Pins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c ? [c.oft] : []; },\n spenders: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c?.adapter ? [c.oft] : []; },\n});\nfunction usdt0ChainFor(chain: string): Usdt0Chain | undefined {\n return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,kBAA4B;AAuB5B,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAEtB,IAAM,IAAI,CAAC,SAAiB,KAAa,MAAc,OAAe,KAAa,UAAkB,UAAU,WAAuB;AAAA,EACpI,OAAO,UAAU,OAAO;AAAA,EAAI;AAAA,EAAS;AAAA,EAAK;AAAA,EAAM;AAAA,EAAO;AAAA,EAAK;AAAA,EAAU;AACxE;AAGO,IAAM,eAAqD,OAAO,OAAO,OAAO,YAAY;AAAA,EACjG,EAAE,GAAG,OAAO,YAAY,8CAA8C,8CAA8C,eAAe,IAAI;AAAA,EACvI,EAAE,OAAO,OAAO,YAAY,8CAA8C,8CAA8C,aAAa;AAAA,EACrI,EAAE,IAAI,OAAO,cAAc,8CAA8C,8CAA8C,aAAa;AAAA,EACpI,EAAE,KAAK,OAAO,eAAe,8CAA8C,8CAA8C,aAAa;AAAA,EACtI,EAAE,KAAK,OAAO,YAAY,8CAA8C,8CAA8C,4CAA4C;AAAA,EAClK,EAAE,OAAO,OAAO,OAAO,8CAA8C,8CAA8C,4CAA4C;AAAA,EAC/J,EAAE,OAAO,OAAO,aAAa,8CAA8C,8CAA8C,aAAa;AAAA,EACtI,EAAE,KAAK,OAAO,YAAY,8CAA8C,8CAA8C,aAAa;AAAA,EACnI,EAAE,MAAM,OAAO,OAAO,8CAA8C,8CAA8C,aAAa;AAAA,EAC/H,EAAE,MAAM,OAAO,UAAU,8CAA8C,8CAA8C,aAAa;AAAA,EAClI,EAAE,KAAK,OAAO,SAAS,8CAA8C,8CAA8C,aAAa;AAAA,EAChI,EAAE,MAAM,OAAO,WAAW,8CAA8C,8CAA8C,aAAa;AAAA,EACnI,EAAE,KAAK,OAAO,WAAW,8CAA8C,8CAA8C,aAAa;AAAA;AAAA;AAAA,EAGlI,EAAE,KAAM,OAAO,UAAU,8CAA8C,8CAA8C,aAAa;AAAA,EAClI,EAAE,MAAM,OAAO,SAAS,8CAA8C,8CAA8C,aAAa;AAAA,EACjI,EAAE,IAAI,OAAO,SAAS,8CAA8C,8CAA8C,aAAa;AACjI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAGpB,IAAM,eAAqD,OAAO;AAAA,EACvE,OAAO,YAAY,OAAO,OAAO,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACvE;AAGO,IAAM,cAAc;AAGpB,IAAM,gBAAmC,OAAO,OAAO,CAAC,SAAS,QAAQ,cAAS,WAAM,CAAC;AAEzF,IAAM,QAAQ;AAAA,EACnB,cAAc,OAAwB;AACpC,eAAO,mBAAM,KAAK,KAAK,CAAC,CAAC,aAAa,cAAU,oBAAO,KAAK,CAAC,EAAE;AAAA,EACjE;AAAA,EACA,SAAS,MAAc,IAAqB;AAC1C,WAAO,SAAS,MAAM,KAAK,cAAc,IAAI,KAAK,KAAK,cAAc,EAAE;AAAA,EACzE;AACF;AAMO,IAAM,YAAwB,OAAO,OAAO;AAAA,EACjD,aAAa,CAAC,UAAqC;AAAE,UAAMA,KAAI,cAAc,KAAK;AAAG,WAAOA,KAAI,CAACA,GAAE,GAAG,IAAI,CAAC;AAAA,EAAG;AAAA,EAC9G,UAAU,CAAC,UAAqC;AAAE,UAAMA,KAAI,cAAc,KAAK;AAAG,WAAOA,IAAG,UAAU,CAACA,GAAE,GAAG,IAAI,CAAC;AAAA,EAAG;AACtH,CAAC;AACD,SAAS,cAAc,OAAuC;AAC5D,SAAO,OAAO,UAAU,eAAe,KAAK,cAAc,KAAK,IAAI,aAAa,KAAK,IAAI;AAC3F;","names":["c"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["// USDT0 — Tether's LayerZero OFT for USDT. Source: docs.usdt0.to\n// (technical-documentation/deployments, read 2026-10-20) — every row below was\n// then re-read on-chain over public RPCs the same day: the OFT's `token()` is\n// the listed token, `endpoint()` is the listed endpoint (and reports the\n// listed eid), `approvalRequired()` is true only for the Ethereum adapter,\n// `sharedDecimals()` = 6 everywhere, and `peers(eid)` are wired between the\n// chains. `oftVersion()` = (0x02e49c2c, 1) on all of them.\n//\n// Only chains the SDK ships (swap2-assets / wallet-evm) are listed. USDT0 is\n// also deployed on Conflux eSpace (1030, eid 30212), Flare (14, 30295),\n// Hedera (295, 30316), Mantle (5000, 30181), Morph (2818, 30322), Rootstock\n// (30, 30333), Stable (988, 30396), Tempo (4217, 30410), plus HyperCore, IOTA\n// and Stellar (non-EVM) — not wallet chains here, so not routable here.\nimport {decodeFunctionData, getAddress, isAddress, pad, parseAbi, type Hex} from \"viem\";\nimport type {Quote, QuoteParams, RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\n\nexport interface Usdt0Chain {\n caip2: string;\n chainId: number;\n /** LayerZero V2 endpoint id. */\n eid: number;\n name: string;\n /** The ERC-20 the user holds: USDT on Ethereum, USDT0 elsewhere (6 decimals everywhere). */\n token: string;\n /**\n * The OFT contract `quoteSend` / `send` are called on. On Ethereum it is the\n * OFT *adapter* that locks USDT (`approvalRequired()` = true, approve the\n * token to it); elsewhere it is the OUpgradeable OFT that burns the caller's\n * USDT0 through the token's mint/burn role — no approval.\n */\n oft: string;\n /** LayerZero V2 EndpointV2 on that chain (`lzReceive` retries of a stored payload go here). */\n endpoint: string;\n /** True on Ethereum: the OFT is a lockbox adapter in front of plain USDT. */\n adapter: boolean;\n}\n\nconst LZ_ENDPOINT_A = \"0x1a44076050125825900e736c501f859c50fE728c\";\nconst LZ_ENDPOINT_B = \"0x6F475642a6e85809B1c36Fa62763669b1b48DD5B\";\n\nconst c = (chainId: number, eid: number, name: string, token: string, oft: string, endpoint: string, adapter = false): Usdt0Chain => ({\n caip2: `eip155:${chainId}`, chainId, eid, name, token, oft, endpoint, adapter,\n});\n\n/** CAIP-2 → USDT0 deployment. */\nexport const USDT0_CHAINS: Readonly<Record<string, Usdt0Chain>> = Object.freeze(Object.fromEntries([\n c(1, 30101, \"Ethereum\", \"0xdAC17F958D2ee523a2206206994597C13D831ec7\", \"0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee\", LZ_ENDPOINT_A, true),\n c(42161, 30110, \"Arbitrum\", \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\", \"0x14E4A1B13bf7F943c8ff7C51fb60FA964A298D92\", LZ_ENDPOINT_A),\n c(10, 30111, \"OP Mainnet\", \"0x01bFF41798a0BcF287b996046Ca68b395DbC1071\", \"0xF03b4d9AC1D5d1E7c4cEf54C2A313b9fe051A0aD\", LZ_ENDPOINT_A),\n c(137, 30109, \"Polygon PoS\", \"0xc2132D05D31c914a87C6611C10748AEb04B58e8F\", \"0x6BA10300f0DC58B7a1e4c0e41f5daBb7D7829e13\", LZ_ENDPOINT_A),\n c(999, 30367, \"HyperEVM\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x904861a24F30EC96ea7CFC3bE9EA4B476d237e98\", \"0x3A73033C0b1407574C76BdBAc67f126f6b4a9AA9\"),\n c(57073, 30339, \"Ink\", \"0x0200C29006150606B650577BBE7B6248F58470c1\", \"0x1cB6De532588fCA4a21B7209DE7C456AF8434A65\", \"0xca29f3A6f966Cb2fc0dE625F8f325c0C46dbE958\"),\n c(80094, 30362, \"Berachain\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x3Dc96399109df5ceb2C226664A086140bD0379cB\", LZ_ENDPOINT_B),\n c(130, 30320, \"Unichain\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0xc07bE8994D035631c36fb4a89C918CeFB2f03EC3\", LZ_ENDPOINT_B),\n c(1329, 30280, \"Sei\", \"0x9151434b16b9763660705744891fA906F660EcC5\", \"0x56Fe74A2e3b484b921c447357203431a3485CC60\", LZ_ENDPOINT_A),\n c(9745, 30383, \"Plasma\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x02ca37966753bDdDf11216B73B16C1dE756A7CF9\", LZ_ENDPOINT_B),\n c(143, 30390, \"Monad\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(4326, 30398, \"MegaETH\", \"0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb\", \"0x9151434b16b9763660705744891fA906F660EcC5\", LZ_ENDPOINT_B),\n c(196, 30274, \"X Layer\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0x94bcCa6BdfD6a61817aB0E960BfedE4984505554\", LZ_ENDPOINT_A),\n // 2026-10-20 (evm-chains-6 batch): docs.usdt0.to deployments, re-read on-chain (token(), approvalRequired() = false,\n // sharedDecimals() = 6, endpoint(), peers(30110) = the Arbitrum OFT).\n c(5000, 30181, \"Mantle\", \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_A),\n c(2818, 30322, \"Morph\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0xcb768e263FB1C62214E7cab4AA8d036D76dc59CC\", LZ_ENDPOINT_B),\n c(14, 30295, \"Flare\", \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\", \"0x567287d2A9829215a37e3B88843d32f9221E7588\", LZ_ENDPOINT_A),\n].map((x) => [x.caip2, x])));\n\n/** LayerZero eid → deployment. */\nexport const USDT0_BY_EID: Readonly<Record<number, Usdt0Chain>> = Object.freeze(\n Object.fromEntries(Object.values(USDT0_CHAINS).map((x) => [x.eid, x])),\n);\n\n/** LayerZero Scan — message status by source transaction hash. */\nexport const LZ_SCAN_API = \"https://scan.layerzero-api.com\";\n\n/** Token symbols the catalog uses for the same asset across chains. */\nexport const USDT0_SYMBOLS: readonly string[] = Object.freeze([\"USDT0\", \"USDT\", \"USD₮0\", \"USD₮\"]);\n\nexport const usdt0 = {\n supportsChain(chain: string): boolean {\n return isEvm(chain) && !!USDT0_CHAINS[`eip155:${evmRef(chain)}`];\n },\n supports(from: string, to: string): boolean {\n return from !== to && this.supportsChain(from) && this.supportsChain(to);\n },\n};\n\nconst OFT_SEND_ABI = parseAbi([\n \"struct SendParam { uint32 dstEid; bytes32 to; uint256 amountLD; uint256 minAmountLD; bytes extraOptions; bytes composeMsg; bytes oftCmd; }\",\n \"struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; }\",\n \"function send(SendParam s, MessagingFee fee, address refundAddress) payable\",\n]);\n\n/**\n * A remote USDT0 quote's `send`, decoded on the device against the app's own request (scan 2026-10-30, F3): exactly\n * `send(SendParam, MessagingFee, refund)` on the source OFT; the destination chain's eid; the recipient as `to`; the\n * input as `amountLD`; a `minAmountLD` no larger than the input that guarantees the quoted minimum and the caller's\n * floor; empty `extraOptions`, `composeMsg` and `oftCmd` (what the provider sends); no LZ-token fee; the trader as\n * refund; `msg.value` = the declared native fee = the call's `nativeFee`; the adapter as spender on Ethereum only.\n * The reason it fails, or null. The engine's native-fee ceiling bounds the fee itself.\n */\nexport function usdt0VerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const src = usdt0ChainFor(params.sourceChain);\n const dst = usdt0ChainFor(params.destChain);\n if (!src || !dst || src === dst) return \"not a USDT0 route between two deployments\";\n if (params.destToken.startsWith(\"0x\") && params.destToken.toLowerCase() !== dst.token.toLowerCase()) return `destination token ${params.destToken} is not USDT0 on ${dst.name}`;\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no OFT call\";\n if (tx.to.toLowerCase() !== src.oft.toLowerCase()) return `the call targets ${tx.to}, not the ${src.name} OFT`;\n if (tx.chainId !== undefined && tx.chainId !== src.chainId) return `the call is for chain ${tx.chainId}, not ${src.chainId}`;\n if (src.adapter ? !tx.approvalAddress || tx.approvalAddress.toLowerCase() !== src.oft.toLowerCase() : tx.approvalAddress !== undefined) {\n return src.adapter ? \"the Ethereum send approves another spender than the adapter\" : \"an OFT send needs no approval\";\n }\n let sp: {dstEid: number; to: Hex; amountLD: bigint; minAmountLD: bigint; extraOptions: Hex; composeMsg: Hex; oftCmd: Hex};\n let fee: {nativeFee: bigint; lzTokenFee: bigint};\n let refund: string;\n try {\n const d = decodeFunctionData({abi: OFT_SEND_ABI, data: tx.data as Hex});\n [sp, fee, refund] = d.args as unknown as [typeof sp, typeof fee, string];\n } catch {\n return \"the call is not send(SendParam, MessagingFee, refund)\";\n }\n let amountIn: bigint, floor: bigint, value: bigint;\n try {\n amountIn = BigInt(params.amountIn);\n floor = BigInt(quote.minDestAmount);\n if (params.minAmountOut !== undefined && BigInt(params.minAmountOut) > floor) floor = BigInt(params.minAmountOut);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (sp.dstEid !== dst.eid) return `the send goes to eid ${sp.dstEid}, not ${dst.name} (${dst.eid})`;\n if (sp.amountLD !== amountIn || BigInt(quote.sourceAmount) !== amountIn) return `the send moves ${sp.amountLD}, not the ${amountIn} input`;\n if (sp.minAmountLD > sp.amountLD || sp.minAmountLD <= 0n || sp.minAmountLD < floor) return `the send's minAmountLD ${sp.minAmountLD} is below the ${floor} minimum`;\n if (sp.extraOptions !== \"0x\" || sp.composeMsg !== \"0x\" || sp.oftCmd !== \"0x\") return \"the send carries options, a compose message or an OFT command\";\n // A dry quote without addresses prices the provider's placeholders; it is never built (the engine re-quotes live).\n const live = params.dry === false;\n if (params.destAddress || live) {\n if (!isAddress(params.destAddress)) return \"the recipient is not an EVM address\";\n if (sp.to.toLowerCase() !== pad(getAddress(params.destAddress), {size: 32}).toLowerCase()) return `the send delivers to ${sp.to}, not the recipient`;\n }\n if (params.refundAddress || live) {\n if (!isAddress(params.refundAddress ?? \"\")) return \"the refund address is not an EVM address\";\n if (getAddress(refund) !== getAddress(params.refundAddress!)) return `the send refunds ${refund}, not the trader`;\n }\n if (fee.lzTokenFee !== 0n) return \"the send pays an LZ-token fee\";\n if (value !== fee.nativeFee || (tx.nativeFee ?? \"0\") !== fee.nativeFee.toString()) return \"msg.value is not the declared native fee of the send\";\n if (quote.intentId.replace(/~[0-9a-f]{32}$/, \"\") !== `usdt0:${src.eid}:${dst.eid}`) return \"the intent id does not name this send\";\n return null;\n}\n\n/**\n * The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum), and\n * {@link usdt0VerifyQuote} — the app's pins for `remoteProvider({name: \"usdt0\", baseUrl, ...usdt0Pins})` (scan\n * 2026-10-27 modules, F8/F16; the send's arguments since scan 2026-10-30, F3).\n */\nexport const usdt0Pins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c ? [c.oft] : []; },\n spenders: (chain: string): readonly string[] => { const c = usdt0ChainFor(chain); return c?.adapter ? [c.oft] : []; },\n verifyQuote: usdt0VerifyQuote,\n});\nfunction usdt0ChainFor(chain: string): Usdt0Chain | undefined {\n return Object.prototype.hasOwnProperty.call(USDT0_CHAINS, chain) ? USDT0_CHAINS[chain] : undefined;\n}\n"],"mappings":"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","names":["c"]}
|
package/dist/config.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RemotePins } from '@anywalletkit/protocol-swap2-core/types';
|
|
1
|
+
import { RemotePins, QuoteParams, Quote } from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
|
|
3
3
|
interface Usdt0Chain {
|
|
4
4
|
caip2: string;
|
|
@@ -33,9 +33,19 @@ declare const usdt0: {
|
|
|
33
33
|
supports(from: string, to: string): boolean;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* A remote USDT0 quote's `send`, decoded on the device against the app's own request (scan 2026-10-30, F3): exactly
|
|
37
|
+
* `send(SendParam, MessagingFee, refund)` on the source OFT; the destination chain's eid; the recipient as `to`; the
|
|
38
|
+
* input as `amountLD`; a `minAmountLD` no larger than the input that guarantees the quoted minimum and the caller's
|
|
39
|
+
* floor; empty `extraOptions`, `composeMsg` and `oftCmd` (what the provider sends); no LZ-token fee; the trader as
|
|
40
|
+
* refund; `msg.value` = the declared native fee = the call's `nativeFee`; the adapter as spender on Ethereum only.
|
|
41
|
+
* The reason it fails, or null. The engine's native-fee ceiling bounds the fee itself.
|
|
42
|
+
*/
|
|
43
|
+
declare function usdt0VerifyQuote(params: QuoteParams, quote: Quote): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum), and
|
|
46
|
+
* {@link usdt0VerifyQuote} — the app's pins for `remoteProvider({name: "usdt0", baseUrl, ...usdt0Pins})` (scan
|
|
47
|
+
* 2026-10-27 modules, F8/F16; the send's arguments since scan 2026-10-30, F3).
|
|
38
48
|
*/
|
|
39
49
|
declare const usdt0Pins: RemotePins;
|
|
40
50
|
|
|
41
|
-
export { LZ_SCAN_API, USDT0_BY_EID, USDT0_CHAINS, USDT0_SYMBOLS, type Usdt0Chain, usdt0, usdt0Pins };
|
|
51
|
+
export { LZ_SCAN_API, USDT0_BY_EID, USDT0_CHAINS, USDT0_SYMBOLS, type Usdt0Chain, usdt0, usdt0Pins, usdt0VerifyQuote };
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RemotePins } from '@anywalletkit/protocol-swap2-core/types';
|
|
1
|
+
import { RemotePins, QuoteParams, Quote } from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
|
|
3
3
|
interface Usdt0Chain {
|
|
4
4
|
caip2: string;
|
|
@@ -33,9 +33,19 @@ declare const usdt0: {
|
|
|
33
33
|
supports(from: string, to: string): boolean;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* A remote USDT0 quote's `send`, decoded on the device against the app's own request (scan 2026-10-30, F3): exactly
|
|
37
|
+
* `send(SendParam, MessagingFee, refund)` on the source OFT; the destination chain's eid; the recipient as `to`; the
|
|
38
|
+
* input as `amountLD`; a `minAmountLD` no larger than the input that guarantees the quoted minimum and the caller's
|
|
39
|
+
* floor; empty `extraOptions`, `composeMsg` and `oftCmd` (what the provider sends); no LZ-token fee; the trader as
|
|
40
|
+
* refund; `msg.value` = the declared native fee = the call's `nativeFee`; the adapter as spender on Ethereum only.
|
|
41
|
+
* The reason it fails, or null. The engine's native-fee ceiling bounds the fee itself.
|
|
42
|
+
*/
|
|
43
|
+
declare function usdt0VerifyQuote(params: QuoteParams, quote: Quote): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* The USDT0 OFT a send calls on a chain, and the adapter it approves where one locks USDT (Ethereum), and
|
|
46
|
+
* {@link usdt0VerifyQuote} — the app's pins for `remoteProvider({name: "usdt0", baseUrl, ...usdt0Pins})` (scan
|
|
47
|
+
* 2026-10-27 modules, F8/F16; the send's arguments since scan 2026-10-30, F3).
|
|
38
48
|
*/
|
|
39
49
|
declare const usdt0Pins: RemotePins;
|
|
40
50
|
|
|
41
|
-
export { LZ_SCAN_API, USDT0_BY_EID, USDT0_CHAINS, USDT0_SYMBOLS, type Usdt0Chain, usdt0, usdt0Pins };
|
|
51
|
+
export { LZ_SCAN_API, USDT0_BY_EID, USDT0_CHAINS, USDT0_SYMBOLS, type Usdt0Chain, usdt0, usdt0Pins, usdt0VerifyQuote };
|
package/dist/config.js
CHANGED
|
@@ -4,14 +4,16 @@ import {
|
|
|
4
4
|
USDT0_CHAINS,
|
|
5
5
|
USDT0_SYMBOLS,
|
|
6
6
|
usdt0,
|
|
7
|
-
usdt0Pins
|
|
8
|
-
|
|
7
|
+
usdt0Pins,
|
|
8
|
+
usdt0VerifyQuote
|
|
9
|
+
} from "./chunk-KCJW52GY.js";
|
|
9
10
|
export {
|
|
10
11
|
LZ_SCAN_API,
|
|
11
12
|
USDT0_BY_EID,
|
|
12
13
|
USDT0_CHAINS,
|
|
13
14
|
USDT0_SYMBOLS,
|
|
14
15
|
usdt0,
|
|
15
|
-
usdt0Pins
|
|
16
|
+
usdt0Pins,
|
|
17
|
+
usdt0VerifyQuote
|
|
16
18
|
};
|
|
17
19
|
//# sourceMappingURL=config.js.map
|