@anywalletkit/protocol-swap2-wrap 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 +3 -2
- package/dist/activity.cjs +50 -3
- package/dist/activity.cjs.map +1 -1
- package/dist/activity.js +1 -1
- package/dist/{chunk-FUAB7KLL.js → chunk-4BUCH5HA.js} +2 -2
- package/dist/{chunk-AEJD6XTY.js → chunk-KB57Z5SA.js} +53 -5
- package/dist/chunk-KB57Z5SA.js.map +1 -0
- package/dist/index.cjs +52 -4
- 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 +6 -4
- package/dist/protocol.cjs +50 -3
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +52 -4
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +12 -4
- package/dist/provider.d.ts +12 -4
- package/dist/provider.js +5 -3
- package/package.json +6 -6
- package/dist/chunk-AEJD6XTY.js.map +0 -1
- /package/dist/{chunk-FUAB7KLL.js.map → chunk-4BUCH5HA.js.map} +0 -0
package/README.md
CHANGED
|
@@ -20,8 +20,9 @@ On npm: [@anywalletkit/protocol-swap2-wrap](https://www.npmjs.com/package/@anywa
|
|
|
20
20
|
|
|
21
21
|
When the provider runs on your server, spread its pins into the app's stub:
|
|
22
22
|
`remoteProvider({name: "wrap", baseUrl, ...wrapPins})`. The engine then lets the EVM route call and
|
|
23
|
-
approve only the wrapped-native contract (no spender), never an address the backend names
|
|
24
|
-
|
|
23
|
+
approve only the wrapped-native contract (no spender), never an address the backend names, and `wrapVerifyQuote`
|
|
24
|
+
checks the call on the device: `deposit()` with the input as value, or `withdraw(input)` with no value, for the
|
|
25
|
+
sender. Without the pins the stub gets no EVM calldata route (fail closed).
|
|
25
26
|
|
|
26
27
|
## Activity
|
|
27
28
|
|
package/dist/activity.cjs
CHANGED
|
@@ -73,13 +73,60 @@ var WETH_ABI = (0, import_viem.parseAbi)([
|
|
|
73
73
|
"function symbol() view returns (string)",
|
|
74
74
|
"function decimals() view returns (uint8)"
|
|
75
75
|
]);
|
|
76
|
+
function wrappedFor(chain) {
|
|
77
|
+
const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;
|
|
78
|
+
return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
79
|
+
}
|
|
80
|
+
function wrapVerifyQuote(params, quote) {
|
|
81
|
+
const w = wrappedFor(params.sourceChain);
|
|
82
|
+
if (!w || params.destChain !== params.sourceChain) return "not a same-chain wrap on a pinned wrapped native";
|
|
83
|
+
const src = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
84
|
+
if (!src) return `unknown source token ${params.sourceToken}`;
|
|
85
|
+
const nativeIn = !src.contract;
|
|
86
|
+
const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && (0, import_viem.getAddress)(src.contract) === (0, import_viem.getAddress)(w.address);
|
|
87
|
+
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
88
|
+
const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && (0, import_viem.getAddress)(params.destToken) === (0, import_viem.getAddress)(w.address);
|
|
89
|
+
const wrap = nativeIn && destIsWrapped;
|
|
90
|
+
if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} \u2194 ${w.symbol}`;
|
|
91
|
+
if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || (0, import_viem.getAddress)(params.refundAddress) !== (0, import_viem.getAddress)(params.destAddress))) {
|
|
92
|
+
return "wrapping pays the sender's own address";
|
|
93
|
+
}
|
|
94
|
+
const tx = quote.txRequest;
|
|
95
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no wrapped-native call";
|
|
96
|
+
if ((0, import_viem.getAddress)(tx.to) !== (0, import_viem.getAddress)(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;
|
|
97
|
+
if (tx.approvalAddress !== void 0) return "a wrap approves nothing";
|
|
98
|
+
if (tx.chainId !== void 0 && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;
|
|
99
|
+
let amount, value;
|
|
100
|
+
try {
|
|
101
|
+
amount = BigInt(params.amountIn);
|
|
102
|
+
value = BigInt(tx.value ?? "0");
|
|
103
|
+
} catch {
|
|
104
|
+
return "the request does not name amounts";
|
|
105
|
+
}
|
|
106
|
+
if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;
|
|
107
|
+
let call;
|
|
108
|
+
try {
|
|
109
|
+
call = (0, import_viem.decodeFunctionData)({ abi: WETH_ABI, data: tx.data });
|
|
110
|
+
} catch {
|
|
111
|
+
return "the call is neither deposit() nor withdraw(amount)";
|
|
112
|
+
}
|
|
113
|
+
if (wrap) {
|
|
114
|
+
if (call.functionName !== "deposit" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;
|
|
115
|
+
if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;
|
|
116
|
+
} else {
|
|
117
|
+
if (call.functionName !== "withdraw") return `${call.functionName} is not withdraw(amount)`;
|
|
118
|
+
if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;
|
|
119
|
+
if (value !== 0n) return "withdraw attaches no value";
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
76
123
|
var wrapPins = Object.freeze({
|
|
77
124
|
callTargets: (chain) => {
|
|
78
|
-
const
|
|
79
|
-
const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
125
|
+
const w = wrappedFor(chain);
|
|
80
126
|
return w ? [w.address] : [];
|
|
81
127
|
},
|
|
82
|
-
spenders: () => []
|
|
128
|
+
spenders: () => [],
|
|
129
|
+
verifyQuote: wrapVerifyQuote
|
|
83
130
|
});
|
|
84
131
|
|
|
85
132
|
// src/activity.ts
|
package/dist/activity.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/activity.ts","../src/provider.ts"],"sourcesContent":["/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves) — the\n * app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n});\n"],"mappings":"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","names":["import_util"]}
|
|
1
|
+
{"version":3,"sources":["../src/activity.ts","../src/provider.ts"],"sourcesContent":["/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\nfunction wrappedFor(chain: string): {address: `0x${string}`; symbol: string} | undefined {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n}\n\n/**\n * A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →\n * wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;\n * on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The\n * reason it fails, or null.\n */\nexport function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const w = wrappedFor(params.sourceChain);\n if (!w || params.destChain !== params.sourceChain) return \"not a same-chain wrap on a pinned wrapped native\";\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return `unknown source token ${params.sourceToken}`;\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} ↔ ${w.symbol}`;\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {\n return \"wrapping pays the sender's own address\";\n }\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no wrapped-native call\";\n if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;\n if (tx.approvalAddress !== undefined) return \"a wrap approves nothing\";\n if (tx.chainId !== undefined && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;\n let amount: bigint, value: bigint;\n try {\n amount = BigInt(params.amountIn);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;\n let call: {functionName: string; args?: readonly unknown[]};\n try {\n call = decodeFunctionData({abi: WETH_ABI, data: tx.data as Hex});\n } catch {\n return \"the call is neither deposit() nor withdraw(amount)\";\n }\n if (wrap) {\n if (call.functionName !== \"deposit\" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;\n if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;\n } else {\n if (call.functionName !== \"withdraw\") return `${call.functionName} is not withdraw(amount)`;\n if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;\n if (value !== 0n) return \"withdraw attaches no value\";\n }\n return null;\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and\n * {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan\n * 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const w = wrappedFor(chain);\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n verifyQuote: wrapVerifyQuote,\n});\n"],"mappings":"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","names":["import_util"]}
|
package/dist/activity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WRAPPED_NATIVE,
|
|
3
3
|
wrapProvider
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KB57Z5SA.js";
|
|
5
5
|
|
|
6
6
|
// src/protocol.ts
|
|
7
7
|
import { SingleProviderSwap2 } from "@anywalletkit/protocol-swap2-core/swap2/single";
|
|
@@ -27,4 +27,4 @@ var WrapSwap2Protocol = class extends SingleProviderSwap2 {
|
|
|
27
27
|
export {
|
|
28
28
|
WrapSwap2Protocol
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
30
|
+
//# sourceMappingURL=chunk-4BUCH5HA.js.map
|
|
@@ -3,7 +3,7 @@ import { assetLabel, describeSwapLike, matchesCall, ownerAssets } from "@anywall
|
|
|
3
3
|
import { evmRef as evmRef2, isEvm as isEvm2 } from "@anywalletkit/protocol-swap2-core/util";
|
|
4
4
|
|
|
5
5
|
// src/provider.ts
|
|
6
|
-
import { decodeFunctionResult, encodeFunctionData, getAddress, parseAbi } from "viem";
|
|
6
|
+
import { decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi } from "viem";
|
|
7
7
|
import { ccAsset } from "@anywalletkit/swap2-assets";
|
|
8
8
|
import { evmRef, isEvm, timeoutSignal } from "@anywalletkit/protocol-swap2-core/util";
|
|
9
9
|
var WRAPPED_NATIVE = Object.freeze({
|
|
@@ -170,13 +170,60 @@ function wrapProvider(config) {
|
|
|
170
170
|
}
|
|
171
171
|
};
|
|
172
172
|
}
|
|
173
|
+
function wrappedFor(chain) {
|
|
174
|
+
const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;
|
|
175
|
+
return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
176
|
+
}
|
|
177
|
+
function wrapVerifyQuote(params, quote) {
|
|
178
|
+
const w = wrappedFor(params.sourceChain);
|
|
179
|
+
if (!w || params.destChain !== params.sourceChain) return "not a same-chain wrap on a pinned wrapped native";
|
|
180
|
+
const src = ccAsset(params.sourceChain, params.sourceToken);
|
|
181
|
+
if (!src) return `unknown source token ${params.sourceToken}`;
|
|
182
|
+
const nativeIn = !src.contract;
|
|
183
|
+
const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);
|
|
184
|
+
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
185
|
+
const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);
|
|
186
|
+
const wrap = nativeIn && destIsWrapped;
|
|
187
|
+
if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} \u2194 ${w.symbol}`;
|
|
188
|
+
if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {
|
|
189
|
+
return "wrapping pays the sender's own address";
|
|
190
|
+
}
|
|
191
|
+
const tx = quote.txRequest;
|
|
192
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no wrapped-native call";
|
|
193
|
+
if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;
|
|
194
|
+
if (tx.approvalAddress !== void 0) return "a wrap approves nothing";
|
|
195
|
+
if (tx.chainId !== void 0 && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;
|
|
196
|
+
let amount, value;
|
|
197
|
+
try {
|
|
198
|
+
amount = BigInt(params.amountIn);
|
|
199
|
+
value = BigInt(tx.value ?? "0");
|
|
200
|
+
} catch {
|
|
201
|
+
return "the request does not name amounts";
|
|
202
|
+
}
|
|
203
|
+
if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;
|
|
204
|
+
let call;
|
|
205
|
+
try {
|
|
206
|
+
call = decodeFunctionData({ abi: WETH_ABI, data: tx.data });
|
|
207
|
+
} catch {
|
|
208
|
+
return "the call is neither deposit() nor withdraw(amount)";
|
|
209
|
+
}
|
|
210
|
+
if (wrap) {
|
|
211
|
+
if (call.functionName !== "deposit" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;
|
|
212
|
+
if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;
|
|
213
|
+
} else {
|
|
214
|
+
if (call.functionName !== "withdraw") return `${call.functionName} is not withdraw(amount)`;
|
|
215
|
+
if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;
|
|
216
|
+
if (value !== 0n) return "withdraw attaches no value";
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
173
220
|
var wrapPins = Object.freeze({
|
|
174
221
|
callTargets: (chain) => {
|
|
175
|
-
const
|
|
176
|
-
const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
222
|
+
const w = wrappedFor(chain);
|
|
177
223
|
return w ? [w.address] : [];
|
|
178
224
|
},
|
|
179
|
-
spenders: () => []
|
|
225
|
+
spenders: () => [],
|
|
226
|
+
verifyQuote: wrapVerifyQuote
|
|
180
227
|
});
|
|
181
228
|
|
|
182
229
|
// src/activity.ts
|
|
@@ -208,6 +255,7 @@ export {
|
|
|
208
255
|
describeWrapActivity,
|
|
209
256
|
WRAPPED_NATIVE,
|
|
210
257
|
wrapProvider,
|
|
258
|
+
wrapVerifyQuote,
|
|
211
259
|
wrapPins
|
|
212
260
|
};
|
|
213
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-KB57Z5SA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/activity.ts","../src/provider.ts"],"sourcesContent":["/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\nfunction wrappedFor(chain: string): {address: `0x${string}`; symbol: string} | undefined {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n}\n\n/**\n * A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →\n * wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;\n * on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The\n * reason it fails, or null.\n */\nexport function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const w = wrappedFor(params.sourceChain);\n if (!w || params.destChain !== params.sourceChain) return \"not a same-chain wrap on a pinned wrapped native\";\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return `unknown source token ${params.sourceToken}`;\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} ↔ ${w.symbol}`;\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {\n return \"wrapping pays the sender's own address\";\n }\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no wrapped-native call\";\n if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;\n if (tx.approvalAddress !== undefined) return \"a wrap approves nothing\";\n if (tx.chainId !== undefined && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;\n let amount: bigint, value: bigint;\n try {\n amount = BigInt(params.amountIn);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;\n let call: {functionName: string; args?: readonly unknown[]};\n try {\n call = decodeFunctionData({abi: WETH_ABI, data: tx.data as Hex});\n } catch {\n return \"the call is neither deposit() nor withdraw(amount)\";\n }\n if (wrap) {\n if (call.functionName !== \"deposit\" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;\n if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;\n } else {\n if (call.functionName !== \"withdraw\") return `${call.functionName} is not withdraw(amount)`;\n if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;\n if (value !== 0n) return \"withdraw attaches no value\";\n }\n return null;\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and\n * {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan\n * 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const w = wrappedFor(chain);\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n verifyQuote: wrapVerifyQuote,\n});\n"],"mappings":"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","names":["evmRef","isEvm","isEvm","evmRef"]}
|
package/dist/index.cjs
CHANGED
|
@@ -28,7 +28,8 @@ __export(src_exports, {
|
|
|
28
28
|
default: () => WrapSwap2Protocol,
|
|
29
29
|
describeWrapActivity: () => describeWrapActivity,
|
|
30
30
|
wrapPins: () => wrapPins,
|
|
31
|
-
wrapProvider: () => wrapProvider
|
|
31
|
+
wrapProvider: () => wrapProvider,
|
|
32
|
+
wrapVerifyQuote: () => wrapVerifyQuote
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(src_exports);
|
|
34
35
|
|
|
@@ -226,13 +227,60 @@ function wrapProvider(config) {
|
|
|
226
227
|
}
|
|
227
228
|
};
|
|
228
229
|
}
|
|
230
|
+
function wrappedFor(chain) {
|
|
231
|
+
const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;
|
|
232
|
+
return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
233
|
+
}
|
|
234
|
+
function wrapVerifyQuote(params, quote) {
|
|
235
|
+
const w = wrappedFor(params.sourceChain);
|
|
236
|
+
if (!w || params.destChain !== params.sourceChain) return "not a same-chain wrap on a pinned wrapped native";
|
|
237
|
+
const src = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
238
|
+
if (!src) return `unknown source token ${params.sourceToken}`;
|
|
239
|
+
const nativeIn = !src.contract;
|
|
240
|
+
const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && (0, import_viem.getAddress)(src.contract) === (0, import_viem.getAddress)(w.address);
|
|
241
|
+
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
242
|
+
const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && (0, import_viem.getAddress)(params.destToken) === (0, import_viem.getAddress)(w.address);
|
|
243
|
+
const wrap = nativeIn && destIsWrapped;
|
|
244
|
+
if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} \u2194 ${w.symbol}`;
|
|
245
|
+
if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || (0, import_viem.getAddress)(params.refundAddress) !== (0, import_viem.getAddress)(params.destAddress))) {
|
|
246
|
+
return "wrapping pays the sender's own address";
|
|
247
|
+
}
|
|
248
|
+
const tx = quote.txRequest;
|
|
249
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no wrapped-native call";
|
|
250
|
+
if ((0, import_viem.getAddress)(tx.to) !== (0, import_viem.getAddress)(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;
|
|
251
|
+
if (tx.approvalAddress !== void 0) return "a wrap approves nothing";
|
|
252
|
+
if (tx.chainId !== void 0 && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;
|
|
253
|
+
let amount, value;
|
|
254
|
+
try {
|
|
255
|
+
amount = BigInt(params.amountIn);
|
|
256
|
+
value = BigInt(tx.value ?? "0");
|
|
257
|
+
} catch {
|
|
258
|
+
return "the request does not name amounts";
|
|
259
|
+
}
|
|
260
|
+
if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;
|
|
261
|
+
let call;
|
|
262
|
+
try {
|
|
263
|
+
call = (0, import_viem.decodeFunctionData)({ abi: WETH_ABI, data: tx.data });
|
|
264
|
+
} catch {
|
|
265
|
+
return "the call is neither deposit() nor withdraw(amount)";
|
|
266
|
+
}
|
|
267
|
+
if (wrap) {
|
|
268
|
+
if (call.functionName !== "deposit" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;
|
|
269
|
+
if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;
|
|
270
|
+
} else {
|
|
271
|
+
if (call.functionName !== "withdraw") return `${call.functionName} is not withdraw(amount)`;
|
|
272
|
+
if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;
|
|
273
|
+
if (value !== 0n) return "withdraw attaches no value";
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
229
277
|
var wrapPins = Object.freeze({
|
|
230
278
|
callTargets: (chain) => {
|
|
231
|
-
const
|
|
232
|
-
const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
279
|
+
const w = wrappedFor(chain);
|
|
233
280
|
return w ? [w.address] : [];
|
|
234
281
|
},
|
|
235
|
-
spenders: () => []
|
|
282
|
+
spenders: () => [],
|
|
283
|
+
verifyQuote: wrapVerifyQuote
|
|
236
284
|
});
|
|
237
285
|
|
|
238
286
|
// src/protocol.ts
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.ts","../src/activity.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./provider.js\";\nexport {WrapSwap2Protocol} from \"./protocol.js\";\nexport {WrapSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\nexport type { WrapSwap2Config } from \"./protocol.js\"\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves) — the\n * app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE, wrapProvider, type WrapProviderConfig} from \"./provider.js\";\n\nexport interface WrapSwap2Config extends Swap2EngineConfig, WrapProviderConfig {}\n\n/** Wrap / unwrap the native coin on one account (ETH ↔ WETH and friends). */\nexport class WrapSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n private readonly _rpcUrls: WrapProviderConfig[\"rpcUrls\"];\n private readonly _wrapped: NonNullable<WrapProviderConfig[\"wrapped\"]>;\n constructor(account: Swap2Account | undefined, config: WrapSwap2Config) {\n super(account, config);\n this.provider = wrapProvider(config);\n this._rpcUrls = config.rpcUrls ?? {};\n this._wrapped = config.wrapped ?? WRAPPED_NATIVE;\n }\n protected override chainSupported(caip2: string): boolean {\n return isEvm(caip2) && !!this._wrapped[evmRef(caip2)] && !!this._rpcUrls[evmRef(caip2)]?.length;\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return fromChain === toChain && this.chainSupported(fromChain);\n }\n}\n"],"mappings":"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","names":["import_util","import_util"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.ts","../src/activity.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./provider.js\";\nexport {WrapSwap2Protocol} from \"./protocol.js\";\nexport {WrapSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\nexport type { WrapSwap2Config } from \"./protocol.js\"\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\nfunction wrappedFor(chain: string): {address: `0x${string}`; symbol: string} | undefined {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n}\n\n/**\n * A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →\n * wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;\n * on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The\n * reason it fails, or null.\n */\nexport function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const w = wrappedFor(params.sourceChain);\n if (!w || params.destChain !== params.sourceChain) return \"not a same-chain wrap on a pinned wrapped native\";\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return `unknown source token ${params.sourceToken}`;\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} ↔ ${w.symbol}`;\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {\n return \"wrapping pays the sender's own address\";\n }\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no wrapped-native call\";\n if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;\n if (tx.approvalAddress !== undefined) return \"a wrap approves nothing\";\n if (tx.chainId !== undefined && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;\n let amount: bigint, value: bigint;\n try {\n amount = BigInt(params.amountIn);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;\n let call: {functionName: string; args?: readonly unknown[]};\n try {\n call = decodeFunctionData({abi: WETH_ABI, data: tx.data as Hex});\n } catch {\n return \"the call is neither deposit() nor withdraw(amount)\";\n }\n if (wrap) {\n if (call.functionName !== \"deposit\" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;\n if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;\n } else {\n if (call.functionName !== \"withdraw\") return `${call.functionName} is not withdraw(amount)`;\n if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;\n if (value !== 0n) return \"withdraw attaches no value\";\n }\n return null;\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and\n * {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan\n * 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const w = wrappedFor(chain);\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n verifyQuote: wrapVerifyQuote,\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE, wrapProvider, type WrapProviderConfig} from \"./provider.js\";\n\nexport interface WrapSwap2Config extends Swap2EngineConfig, WrapProviderConfig {}\n\n/** Wrap / unwrap the native coin on one account (ETH ↔ WETH and friends). */\nexport class WrapSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n private readonly _rpcUrls: WrapProviderConfig[\"rpcUrls\"];\n private readonly _wrapped: NonNullable<WrapProviderConfig[\"wrapped\"]>;\n constructor(account: Swap2Account | undefined, config: WrapSwap2Config) {\n super(account, config);\n this.provider = wrapProvider(config);\n this._rpcUrls = config.rpcUrls ?? {};\n this._wrapped = config.wrapped ?? WRAPPED_NATIVE;\n }\n protected override chainSupported(caip2: string): boolean {\n return isEvm(caip2) && !!this._wrapped[evmRef(caip2)] && !!this._rpcUrls[evmRef(caip2)]?.length;\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return fromChain === toChain && this.chainSupported(fromChain);\n }\n}\n"],"mappings":"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","names":["import_util","import_util"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { WRAPPED_NATIVE, WrapProviderConfig, wrapPins, wrapProvider } from './provider.cjs';
|
|
1
|
+
export { WRAPPED_NATIVE, WrapProviderConfig, wrapPins, wrapProvider, wrapVerifyQuote } from './provider.cjs';
|
|
2
2
|
export { WrapSwap2Config, WrapSwap2Protocol, WrapSwap2Protocol as default } from './protocol.cjs';
|
|
3
3
|
export { WETH_DEPOSIT, WETH_WITHDRAW, WRAP_MODULE, describeWrapActivity } from './activity.cjs';
|
|
4
4
|
import '@anywalletkit/protocol-swap2-core/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { WRAPPED_NATIVE, WrapProviderConfig, wrapPins, wrapProvider } from './provider.js';
|
|
1
|
+
export { WRAPPED_NATIVE, WrapProviderConfig, wrapPins, wrapProvider, wrapVerifyQuote } from './provider.js';
|
|
2
2
|
export { WrapSwap2Config, WrapSwap2Protocol, WrapSwap2Protocol as default } from './protocol.js';
|
|
3
3
|
export { WETH_DEPOSIT, WETH_WITHDRAW, WRAP_MODULE, describeWrapActivity } from './activity.js';
|
|
4
4
|
import '@anywalletkit/protocol-swap2-core/types';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WrapSwap2Protocol
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4BUCH5HA.js";
|
|
4
4
|
import {
|
|
5
5
|
WETH_DEPOSIT,
|
|
6
6
|
WETH_WITHDRAW,
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
WRAP_MODULE,
|
|
9
9
|
describeWrapActivity,
|
|
10
10
|
wrapPins,
|
|
11
|
-
wrapProvider
|
|
12
|
-
|
|
11
|
+
wrapProvider,
|
|
12
|
+
wrapVerifyQuote
|
|
13
|
+
} from "./chunk-KB57Z5SA.js";
|
|
13
14
|
export {
|
|
14
15
|
WETH_DEPOSIT,
|
|
15
16
|
WETH_WITHDRAW,
|
|
@@ -19,6 +20,7 @@ export {
|
|
|
19
20
|
WrapSwap2Protocol as default,
|
|
20
21
|
describeWrapActivity,
|
|
21
22
|
wrapPins,
|
|
22
|
-
wrapProvider
|
|
23
|
+
wrapProvider,
|
|
24
|
+
wrapVerifyQuote
|
|
23
25
|
};
|
|
24
26
|
//# sourceMappingURL=index.js.map
|
package/dist/protocol.cjs
CHANGED
|
@@ -220,13 +220,60 @@ function wrapProvider(config) {
|
|
|
220
220
|
}
|
|
221
221
|
};
|
|
222
222
|
}
|
|
223
|
+
function wrappedFor(chain) {
|
|
224
|
+
const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;
|
|
225
|
+
return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
226
|
+
}
|
|
227
|
+
function wrapVerifyQuote(params, quote) {
|
|
228
|
+
const w = wrappedFor(params.sourceChain);
|
|
229
|
+
if (!w || params.destChain !== params.sourceChain) return "not a same-chain wrap on a pinned wrapped native";
|
|
230
|
+
const src = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
231
|
+
if (!src) return `unknown source token ${params.sourceToken}`;
|
|
232
|
+
const nativeIn = !src.contract;
|
|
233
|
+
const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && (0, import_viem.getAddress)(src.contract) === (0, import_viem.getAddress)(w.address);
|
|
234
|
+
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
235
|
+
const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && (0, import_viem.getAddress)(params.destToken) === (0, import_viem.getAddress)(w.address);
|
|
236
|
+
const wrap = nativeIn && destIsWrapped;
|
|
237
|
+
if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} \u2194 ${w.symbol}`;
|
|
238
|
+
if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || (0, import_viem.getAddress)(params.refundAddress) !== (0, import_viem.getAddress)(params.destAddress))) {
|
|
239
|
+
return "wrapping pays the sender's own address";
|
|
240
|
+
}
|
|
241
|
+
const tx = quote.txRequest;
|
|
242
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no wrapped-native call";
|
|
243
|
+
if ((0, import_viem.getAddress)(tx.to) !== (0, import_viem.getAddress)(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;
|
|
244
|
+
if (tx.approvalAddress !== void 0) return "a wrap approves nothing";
|
|
245
|
+
if (tx.chainId !== void 0 && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;
|
|
246
|
+
let amount, value;
|
|
247
|
+
try {
|
|
248
|
+
amount = BigInt(params.amountIn);
|
|
249
|
+
value = BigInt(tx.value ?? "0");
|
|
250
|
+
} catch {
|
|
251
|
+
return "the request does not name amounts";
|
|
252
|
+
}
|
|
253
|
+
if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;
|
|
254
|
+
let call;
|
|
255
|
+
try {
|
|
256
|
+
call = (0, import_viem.decodeFunctionData)({ abi: WETH_ABI, data: tx.data });
|
|
257
|
+
} catch {
|
|
258
|
+
return "the call is neither deposit() nor withdraw(amount)";
|
|
259
|
+
}
|
|
260
|
+
if (wrap) {
|
|
261
|
+
if (call.functionName !== "deposit" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;
|
|
262
|
+
if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;
|
|
263
|
+
} else {
|
|
264
|
+
if (call.functionName !== "withdraw") return `${call.functionName} is not withdraw(amount)`;
|
|
265
|
+
if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;
|
|
266
|
+
if (value !== 0n) return "withdraw attaches no value";
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
223
270
|
var wrapPins = Object.freeze({
|
|
224
271
|
callTargets: (chain) => {
|
|
225
|
-
const
|
|
226
|
-
const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
272
|
+
const w = wrappedFor(chain);
|
|
227
273
|
return w ? [w.address] : [];
|
|
228
274
|
},
|
|
229
|
-
spenders: () => []
|
|
275
|
+
spenders: () => [],
|
|
276
|
+
verifyQuote: wrapVerifyQuote
|
|
230
277
|
});
|
|
231
278
|
|
|
232
279
|
// src/protocol.ts
|
package/dist/protocol.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol.ts","../src/provider.ts","../src/activity.ts"],"sourcesContent":["import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE, wrapProvider, type WrapProviderConfig} from \"./provider.js\";\n\nexport interface WrapSwap2Config extends Swap2EngineConfig, WrapProviderConfig {}\n\n/** Wrap / unwrap the native coin on one account (ETH ↔ WETH and friends). */\nexport class WrapSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n private readonly _rpcUrls: WrapProviderConfig[\"rpcUrls\"];\n private readonly _wrapped: NonNullable<WrapProviderConfig[\"wrapped\"]>;\n constructor(account: Swap2Account | undefined, config: WrapSwap2Config) {\n super(account, config);\n this.provider = wrapProvider(config);\n this._rpcUrls = config.rpcUrls ?? {};\n this._wrapped = config.wrapped ?? WRAPPED_NATIVE;\n }\n protected override chainSupported(caip2: string): boolean {\n return isEvm(caip2) && !!this._wrapped[evmRef(caip2)] && !!this._rpcUrls[evmRef(caip2)]?.length;\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return fromChain === toChain && this.chainSupported(fromChain);\n }\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves) — the\n * app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n"],"mappings":"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","names":["import_util","import_util"]}
|
|
1
|
+
{"version":3,"sources":["../src/protocol.ts","../src/provider.ts","../src/activity.ts"],"sourcesContent":["import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE, wrapProvider, type WrapProviderConfig} from \"./provider.js\";\n\nexport interface WrapSwap2Config extends Swap2EngineConfig, WrapProviderConfig {}\n\n/** Wrap / unwrap the native coin on one account (ETH ↔ WETH and friends). */\nexport class WrapSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n private readonly _rpcUrls: WrapProviderConfig[\"rpcUrls\"];\n private readonly _wrapped: NonNullable<WrapProviderConfig[\"wrapped\"]>;\n constructor(account: Swap2Account | undefined, config: WrapSwap2Config) {\n super(account, config);\n this.provider = wrapProvider(config);\n this._rpcUrls = config.rpcUrls ?? {};\n this._wrapped = config.wrapped ?? WRAPPED_NATIVE;\n }\n protected override chainSupported(caip2: string): boolean {\n return isEvm(caip2) && !!this._wrapped[evmRef(caip2)] && !!this._rpcUrls[evmRef(caip2)]?.length;\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return fromChain === toChain && this.chainSupported(fromChain);\n }\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\nfunction wrappedFor(chain: string): {address: `0x${string}`; symbol: string} | undefined {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n}\n\n/**\n * A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →\n * wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;\n * on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The\n * reason it fails, or null.\n */\nexport function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const w = wrappedFor(params.sourceChain);\n if (!w || params.destChain !== params.sourceChain) return \"not a same-chain wrap on a pinned wrapped native\";\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return `unknown source token ${params.sourceToken}`;\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} ↔ ${w.symbol}`;\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {\n return \"wrapping pays the sender's own address\";\n }\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no wrapped-native call\";\n if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;\n if (tx.approvalAddress !== undefined) return \"a wrap approves nothing\";\n if (tx.chainId !== undefined && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;\n let amount: bigint, value: bigint;\n try {\n amount = BigInt(params.amountIn);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;\n let call: {functionName: string; args?: readonly unknown[]};\n try {\n call = decodeFunctionData({abi: WETH_ABI, data: tx.data as Hex});\n } catch {\n return \"the call is neither deposit() nor withdraw(amount)\";\n }\n if (wrap) {\n if (call.functionName !== \"deposit\" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;\n if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;\n } else {\n if (call.functionName !== \"withdraw\") return `${call.functionName} is not withdraw(amount)`;\n if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;\n if (value !== 0n) return \"withdraw attaches no value\";\n }\n return null;\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and\n * {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan\n * 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const w = wrappedFor(chain);\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n verifyQuote: wrapVerifyQuote,\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n"],"mappings":"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","names":["import_util","import_util"]}
|
package/dist/protocol.js
CHANGED
package/dist/provider.cjs
CHANGED
|
@@ -22,7 +22,8 @@ var provider_exports = {};
|
|
|
22
22
|
__export(provider_exports, {
|
|
23
23
|
WRAPPED_NATIVE: () => WRAPPED_NATIVE,
|
|
24
24
|
wrapPins: () => wrapPins,
|
|
25
|
-
wrapProvider: () => wrapProvider
|
|
25
|
+
wrapProvider: () => wrapProvider,
|
|
26
|
+
wrapVerifyQuote: () => wrapVerifyQuote
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(provider_exports);
|
|
28
29
|
var import_viem = require("viem");
|
|
@@ -218,12 +219,59 @@ function wrapProvider(config) {
|
|
|
218
219
|
}
|
|
219
220
|
};
|
|
220
221
|
}
|
|
222
|
+
function wrappedFor(chain) {
|
|
223
|
+
const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;
|
|
224
|
+
return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
225
|
+
}
|
|
226
|
+
function wrapVerifyQuote(params, quote) {
|
|
227
|
+
const w = wrappedFor(params.sourceChain);
|
|
228
|
+
if (!w || params.destChain !== params.sourceChain) return "not a same-chain wrap on a pinned wrapped native";
|
|
229
|
+
const src = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
230
|
+
if (!src) return `unknown source token ${params.sourceToken}`;
|
|
231
|
+
const nativeIn = !src.contract;
|
|
232
|
+
const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && (0, import_viem.getAddress)(src.contract) === (0, import_viem.getAddress)(w.address);
|
|
233
|
+
const nativeOut = /^0x0+$/.test(params.destToken);
|
|
234
|
+
const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && (0, import_viem.getAddress)(params.destToken) === (0, import_viem.getAddress)(w.address);
|
|
235
|
+
const wrap = nativeIn && destIsWrapped;
|
|
236
|
+
if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} \u2194 ${w.symbol}`;
|
|
237
|
+
if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || (0, import_viem.getAddress)(params.refundAddress) !== (0, import_viem.getAddress)(params.destAddress))) {
|
|
238
|
+
return "wrapping pays the sender's own address";
|
|
239
|
+
}
|
|
240
|
+
const tx = quote.txRequest;
|
|
241
|
+
if (!tx?.data || !tx.to || tx.serializedTx !== void 0) return "the quote carries no wrapped-native call";
|
|
242
|
+
if ((0, import_viem.getAddress)(tx.to) !== (0, import_viem.getAddress)(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;
|
|
243
|
+
if (tx.approvalAddress !== void 0) return "a wrap approves nothing";
|
|
244
|
+
if (tx.chainId !== void 0 && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;
|
|
245
|
+
let amount, value;
|
|
246
|
+
try {
|
|
247
|
+
amount = BigInt(params.amountIn);
|
|
248
|
+
value = BigInt(tx.value ?? "0");
|
|
249
|
+
} catch {
|
|
250
|
+
return "the request does not name amounts";
|
|
251
|
+
}
|
|
252
|
+
if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;
|
|
253
|
+
let call;
|
|
254
|
+
try {
|
|
255
|
+
call = (0, import_viem.decodeFunctionData)({ abi: WETH_ABI, data: tx.data });
|
|
256
|
+
} catch {
|
|
257
|
+
return "the call is neither deposit() nor withdraw(amount)";
|
|
258
|
+
}
|
|
259
|
+
if (wrap) {
|
|
260
|
+
if (call.functionName !== "deposit" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;
|
|
261
|
+
if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;
|
|
262
|
+
} else {
|
|
263
|
+
if (call.functionName !== "withdraw") return `${call.functionName} is not withdraw(amount)`;
|
|
264
|
+
if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;
|
|
265
|
+
if (value !== 0n) return "withdraw attaches no value";
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
221
269
|
var wrapPins = Object.freeze({
|
|
222
270
|
callTargets: (chain) => {
|
|
223
|
-
const
|
|
224
|
-
const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : void 0;
|
|
271
|
+
const w = wrappedFor(chain);
|
|
225
272
|
return w ? [w.address] : [];
|
|
226
273
|
},
|
|
227
|
-
spenders: () => []
|
|
274
|
+
spenders: () => [],
|
|
275
|
+
verifyQuote: wrapVerifyQuote
|
|
228
276
|
});
|
|
229
277
|
//# sourceMappingURL=provider.cjs.map
|
package/dist/provider.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts","../src/activity.ts"],"sourcesContent":["import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves) — the\n * app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n"],"mappings":"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","names":["import_util"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts","../src/activity.ts"],"sourcesContent":["import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionData, decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\nfunction wrappedFor(chain: string): {address: `0x${string}`; symbol: string} | undefined {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n return Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n}\n\n/**\n * A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →\n * wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;\n * on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The\n * reason it fails, or null.\n */\nexport function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null {\n const w = wrappedFor(params.sourceChain);\n if (!w || params.destChain !== params.sourceChain) return \"not a same-chain wrap on a pinned wrapped native\";\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return `unknown source token ${params.sourceToken}`;\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n if (!wrap && !(srcIsWrapped && nativeOut)) return `only ${w.symbol.slice(1)} ↔ ${w.symbol}`;\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && (!/^0x[0-9a-fA-F]{40}$/.test(params.destAddress) || getAddress(params.refundAddress) !== getAddress(params.destAddress))) {\n return \"wrapping pays the sender's own address\";\n }\n const tx = quote.txRequest;\n if (!tx?.data || !tx.to || tx.serializedTx !== undefined) return \"the quote carries no wrapped-native call\";\n if (getAddress(tx.to) !== getAddress(w.address)) return `the call targets ${tx.to}, not ${w.symbol}`;\n if (tx.approvalAddress !== undefined) return \"a wrap approves nothing\";\n if (tx.chainId !== undefined && `eip155:${tx.chainId}` !== params.sourceChain) return `the call is for chain ${tx.chainId}`;\n let amount: bigint, value: bigint;\n try {\n amount = BigInt(params.amountIn);\n value = BigInt(tx.value ?? \"0\");\n } catch {\n return \"the request does not name amounts\";\n }\n if (BigInt(quote.sourceAmount) !== amount) return `the quote moves ${quote.sourceAmount}, not the ${amount} input`;\n let call: {functionName: string; args?: readonly unknown[]};\n try {\n call = decodeFunctionData({abi: WETH_ABI, data: tx.data as Hex});\n } catch {\n return \"the call is neither deposit() nor withdraw(amount)\";\n }\n if (wrap) {\n if (call.functionName !== \"deposit\" || tx.data.length !== 10) return `${call.functionName} is not deposit()`;\n if (value !== amount) return `deposit() attaches ${value}, not the ${amount} input`;\n } else {\n if (call.functionName !== \"withdraw\") return `${call.functionName} is not withdraw(amount)`;\n if (call.args?.[0] !== amount) return `withdraw(${String(call.args?.[0])}) is not the ${amount} input`;\n if (value !== 0n) return \"withdraw attaches no value\";\n }\n return null;\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and\n * {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan\n * 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const w = wrappedFor(chain);\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n verifyQuote: wrapVerifyQuote,\n});\n","/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n"],"mappings":"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","names":["import_util"]}
|
package/dist/provider.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RemotePins, CrossChainProvider } from '@anywalletkit/protocol-swap2-core/types';
|
|
1
|
+
import { RemotePins, CrossChainProvider, QuoteParams, Quote } from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The chain's canonical wrapped native token (WETH9-style `deposit()` /
|
|
@@ -28,9 +28,17 @@ interface WrapProviderConfig {
|
|
|
28
28
|
*/
|
|
29
29
|
declare function wrapProvider(config: WrapProviderConfig): CrossChainProvider;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →
|
|
32
|
+
* wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;
|
|
33
|
+
* on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The
|
|
34
|
+
* reason it fails, or null.
|
|
35
|
+
*/
|
|
36
|
+
declare function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and
|
|
39
|
+
* {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: "wrap", baseUrl, ...wrapPins})` (scan
|
|
40
|
+
* 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).
|
|
33
41
|
*/
|
|
34
42
|
declare const wrapPins: RemotePins;
|
|
35
43
|
|
|
36
|
-
export { WRAPPED_NATIVE, type WrapProviderConfig, wrapPins, wrapProvider };
|
|
44
|
+
export { WRAPPED_NATIVE, type WrapProviderConfig, wrapPins, wrapProvider, wrapVerifyQuote };
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RemotePins, CrossChainProvider } from '@anywalletkit/protocol-swap2-core/types';
|
|
1
|
+
import { RemotePins, CrossChainProvider, QuoteParams, Quote } from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* The chain's canonical wrapped native token (WETH9-style `deposit()` /
|
|
@@ -28,9 +28,17 @@ interface WrapProviderConfig {
|
|
|
28
28
|
*/
|
|
29
29
|
declare function wrapProvider(config: WrapProviderConfig): CrossChainProvider;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* A remote wrap / unwrap quote, decoded on the device against the app's own request (scan 2026-10-30, F3): native →
|
|
32
|
+
* wrapped is exactly `deposit()` with the input as value; wrapped → native is exactly `withdraw(input)` with no value;
|
|
33
|
+
* on the chain's wrapped native, no approval, and (as WETH9 pays `msg.sender`) a recipient that is the sender. The
|
|
34
|
+
* reason it fails, or null.
|
|
35
|
+
*/
|
|
36
|
+
declare function wrapVerifyQuote(params: QuoteParams, quote: Quote): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves), and
|
|
39
|
+
* {@link wrapVerifyQuote} — the app's pins for `remoteProvider({name: "wrap", baseUrl, ...wrapPins})` (scan
|
|
40
|
+
* 2026-10-27 modules, F8/F16; the call itself since scan 2026-10-30, F3).
|
|
33
41
|
*/
|
|
34
42
|
declare const wrapPins: RemotePins;
|
|
35
43
|
|
|
36
|
-
export { WRAPPED_NATIVE, type WrapProviderConfig, wrapPins, wrapProvider };
|
|
44
|
+
export { WRAPPED_NATIVE, type WrapProviderConfig, wrapPins, wrapProvider, wrapVerifyQuote };
|
package/dist/provider.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WRAPPED_NATIVE,
|
|
3
3
|
wrapPins,
|
|
4
|
-
wrapProvider
|
|
5
|
-
|
|
4
|
+
wrapProvider,
|
|
5
|
+
wrapVerifyQuote
|
|
6
|
+
} from "./chunk-KB57Z5SA.js";
|
|
6
7
|
export {
|
|
7
8
|
WRAPPED_NATIVE,
|
|
8
9
|
wrapPins,
|
|
9
|
-
wrapProvider
|
|
10
|
+
wrapProvider,
|
|
11
|
+
wrapVerifyQuote
|
|
10
12
|
};
|
|
11
13
|
//# sourceMappingURL=provider.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anywalletkit/protocol-swap2-wrap",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Wrap and unwrap the native coin (ETH↔WETH, BNB↔WBNB, POL↔WPOL…) on 13 EVM chains as a swap2 venue: 1:1, no pool, wrapped tokens verified on-chain.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://docs.anywallet.tech",
|
|
@@ -45,17 +45,17 @@
|
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"viem": "^2.57.2",
|
|
48
|
-
"@anywalletkit/
|
|
49
|
-
"@anywalletkit/swap2-
|
|
48
|
+
"@anywalletkit/swap2-assets": "0.2.2",
|
|
49
|
+
"@anywalletkit/protocol-swap2-core": "0.9.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@anywalletkit/core": "0.
|
|
52
|
+
"@anywalletkit/core": "0.7.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^22",
|
|
56
56
|
"vitest": "^5.0.3",
|
|
57
|
-
"@anywalletkit/core": "0.
|
|
58
|
-
"@anywalletkit/conformance": "0.4.
|
|
57
|
+
"@anywalletkit/core": "0.7.0",
|
|
58
|
+
"@anywalletkit/conformance": "0.4.6"
|
|
59
59
|
},
|
|
60
60
|
"keywords": [
|
|
61
61
|
"wrap",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/activity.ts","../src/provider.ts"],"sourcesContent":["/**\n * Activity recognition for the Wrap module: WETH9 `deposit()` → `wrap`\n * (\"Wrapped ETH\"), `withdraw(uint256)` → `unwrap` (\"Unwrapped WETH\"), on the\n * wrapper the table (or the caller's override) names for the chain.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {assetLabel, describeSwapLike, matchesCall, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {evmRef, isEvm} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {WRAPPED_NATIVE} from \"./provider.js\";\n\nexport const WRAP_MODULE = \"@anywalletkit/protocol-swap2-wrap\";\n\n/** deposit() */\nexport const WETH_DEPOSIT = \"0xd0e30db0\";\n/** withdraw(uint256 wad) */\nexport const WETH_WITHDRAW = \"0x2e1a7d4d\";\n\nexport function describeWrapActivity(\n tx: ChainTx,\n ctx: DescribeActivityContext,\n wrapped: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = WRAPPED_NATIVE,\n): ActivityItem | null {\n if (!isEvm(tx.chain)) return null;\n const w = wrapped[evmRef(tx.chain)];\n if (!w) return null;\n const isDeposit = matchesCall(tx, [w.address], [WETH_DEPOSIT]);\n const isWithdraw = !isDeposit && matchesCall(tx, [w.address], [WETH_WITHDRAW]);\n if (!isDeposit && !isWithdraw) return null;\n const {assetsIn, assetsOut} = ownerAssets(tx, ctx);\n const native = [...assetsIn, ...assetsOut].find((a) => a.token === null);\n const nativeLabel = native ? assetLabel(tx, native) : w.symbol.replace(/^[Ww]/, \"\");\n return describeSwapLike(tx, ctx, {\n protocol: WRAP_MODULE,\n subtitle: w.symbol,\n kind: isDeposit ? \"wrap\" : \"unwrap\",\n title: isDeposit ? `Wrapped ${nativeLabel}` : `Unwrapped ${w.symbol}`,\n });\n}\n","import type {RemotePins} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {decodeFunctionResult, encodeFunctionData, getAddress, parseAbi, type Hex} from \"viem\";\nimport {describeWrapActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {evmRef, isEvm, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * The chain's canonical wrapped native token (WETH9-style `deposit()` /\n * `withdraw(uint256)`). Every entry was checked on-chain 2026-10-12: symbol,\n * 18 decimals, non-zero supply, and `deposit()` succeeding for a funded sender.\n * The provider re-checks symbol + decimals once per chain before quoting.\n */\nexport const WRAPPED_NATIVE: Readonly<Record<number, {address: `0x${string}`; symbol: string}>> = Object.freeze({\n 1: {address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\", symbol: \"WETH\"},\n 10: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 56: {address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\", symbol: \"WBNB\"},\n 100: {address: \"0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d\", symbol: \"WXDAI\"},\n 130: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 137: {address: \"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270\", symbol: \"WPOL\"},\n 143: {address: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\", symbol: \"WMON\"},\n 999: {address: \"0x5555555555555555555555555555555555555555\", symbol: \"WHYPE\"},\n 324: {address: \"0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91\", symbol: \"WETH\"},\n 4326: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 9745: {address: \"0x6100E367285b01F48D07953803A2d8dCA5D19873\", symbol: \"WXPL\"},\n 146: {address: \"0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38\", symbol: \"wS\"},\n 59144: {address: \"0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f\", symbol: \"WETH\"},\n 8453: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 42161: {address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\", symbol: \"WETH\"},\n 43114: {address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\", symbol: \"WAVAX\"},\n 80094: {address: \"0x6969696969696969696969696969696969696969\", symbol: \"WBERA\"},\n 534352: {address: \"0x5300000000000000000000000000000000000004\", symbol: \"WETH\"},\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer — verified on-chain (symbol, decimals, supply, deposit()).\n 480: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 1329: {address: \"0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7\", symbol: \"WSEI\"},\n 57073: {address: \"0x4200000000000000000000000000000000000006\", symbol: \"WETH\"},\n 98866: {address: \"0xEa237441c92CAe6FC17Caaf9a7acB3f953be4bd1\", symbol: \"WPLUME\"},\n 196: {address: \"0xe538905cf8410324e03A5A23C1c177a474D59b2b\", symbol: \"WOKB\"},\n // 2026-10-14: Mantle, Katana, Morph, Flare — symbol, 18 decimals, supply, deposit()/withdraw() selectors in the\n // bytecode and eth_estimateGas of deposit() with value from a funded sender, all checked on-chain. Katana's WETH9 is\n // Vault Bridge's vbETH (the on-chain symbol the verify step compares against; the catalog shows it as WETH).\n // Arc has no wrapper by design: its native USDC already exposes an ERC-20 interface (docs.arc.network).\n 5000: {address: \"0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8\", symbol: \"WMNT\"},\n 747474: {address: \"0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62\", symbol: \"vbETH\"},\n 2818: {address: \"0x5300000000000000000000000000000000000011\", symbol: \"WETH\"},\n 14: {address: \"0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d\", symbol: \"WFLR\"},\n});\n\nconst WETH_ABI = parseAbi([\n \"function deposit() payable\",\n \"function withdraw(uint256 wad)\",\n \"function symbol() view returns (string)\",\n \"function decimals() view returns (uint8)\",\n]);\n/** deposit/withdraw on WETH9 cost ~30-45k; a generous cap, the account still estimates. */\nconst GAS_LIMIT = \"90000\";\n\nexport interface WrapProviderConfig {\n enabled?: boolean;\n /** JSON-RPC endpoints per EVM chain id (on-chain token check + receipt tracking). */\n rpcUrls: Readonly<Record<number, readonly string[]>>;\n /** Override the wrapped tokens (tests, new chains). Still verified on-chain before use. */\n wrapped?: Readonly<Record<number, {address: `0x${string}`; symbol: string}>>;\n}\n\n/**\n * Native ↔ wrapped native as a swap2 venue: `deposit()` with value to wrap,\n * `withdraw(amount)` to unwrap. 1:1, no pool, no slippage, no approval. WETH9\n * credits and pays `msg.sender`, so the recipient must be the sender — a wrap\n * \"to someone else\" is refused rather than silently paid to the wrong place.\n */\nexport function wrapProvider(config: WrapProviderConfig): CrossChainProvider {\n const wrapped = config.wrapped ?? WRAPPED_NATIVE;\n const verified = new Map<number, Promise<void>>();\n\n const chainIdOf = (caip2: string): number | null => {\n if (!isEvm(caip2)) return null;\n const id = evmRef(caip2);\n return wrapped[id] && config.rpcUrls[id]?.length ? id : null;\n };\n\n async function rpc(chainId: number, method: string, params: unknown[]): Promise<unknown> {\n let lastErr: unknown;\n for (const url of config.rpcUrls[chainId] ?? []) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\"content-type\": \"application/json\"},\n body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}),\n signal: timeoutSignal(10_000),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result ?? null;\n } catch (e) {\n lastErr = e;\n }\n }\n throw new Error(`wrap: no RPC answered on chain ${chainId} (${lastErr instanceof Error ? lastErr.message : String(lastErr)})`);\n }\n\n function verify(chainId: number): Promise<void> {\n let p = verified.get(chainId);\n if (!p) {\n const w = wrapped[chainId]!;\n p = (async () => {\n const read = async (fn: \"symbol\" | \"decimals\") =>\n decodeFunctionResult({abi: WETH_ABI, functionName: fn, data: (await rpc(chainId, \"eth_call\", [{to: w.address, data: encodeFunctionData({abi: WETH_ABI, functionName: fn})}, \"latest\"])) as Hex});\n const [symbol, decimals] = await Promise.all([read(\"symbol\"), read(\"decimals\")]);\n if (symbol !== w.symbol || Number(decimals) !== 18) throw new Error(`wrap: ${w.address} on chain ${chainId} is not ${w.symbol} — refusing`);\n })();\n p.catch(() => verified.delete(chainId));\n verified.set(chainId, p);\n }\n return p;\n }\n\n return {\n name: \"wrap\",\n describeActivity: (tx, ctx) => describeWrapActivity(tx, ctx, wrapped),\n supportsSameChain: true,\n enabled: () => config.enabled ?? true,\n supportsChain: (caip2: string) => chainIdOf(caip2) !== null,\n supportsChainPair: (from: string, to: string) => from === to && chainIdOf(from) !== null,\n supportsRoute(from: Asset, to: Asset): boolean {\n return from.chain === to.chain && chainIdOf(from.chain) !== null;\n },\n\n async getQuote(params: QuoteParams): Promise<Quote | null> {\n const refuse = (why: string): null => {\n params.onRefusal?.(`wrap: ${why}`);\n return null;\n };\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n if (params.sourceChain !== params.destChain) return refuse(\"same-chain only\");\n const chainId = chainIdOf(params.sourceChain);\n if (chainId === null) return refuse(`no wrapped native token or RPC for ${params.sourceChain}`);\n const w = wrapped[chainId]!;\n const src = ccAsset(params.sourceChain, params.sourceToken);\n if (!src) return refuse(`unknown source token ${params.sourceToken}`);\n const nativeIn = !src.contract;\n const srcIsWrapped = !!src.contract && /^0x[0-9a-fA-F]{40}$/.test(src.contract) && getAddress(src.contract) === getAddress(w.address);\n const nativeOut = /^0x0+$/.test(params.destToken);\n const destIsWrapped = /^0x[0-9a-fA-F]{40}$/.test(params.destToken) && !nativeOut && getAddress(params.destToken) === getAddress(w.address);\n const wrap = nativeIn && destIsWrapped;\n const unwrap = srcIsWrapped && nativeOut;\n if (!wrap && !unwrap) return refuse(`only ${w.symbol.slice(1)} ↔ ${w.symbol}`);\n // WETH9 credits / pays msg.sender: the recipient can only be the sender.\n if (params.refundAddress && /^0x[0-9a-fA-F]{40}$/.test(params.refundAddress) && getAddress(params.refundAddress) !== getAddress(params.destAddress)) {\n return refuse(\"wrapping pays the sender's own address — send the result separately\");\n }\n let amount: bigint;\n try {\n amount = BigInt(params.amountIn);\n } catch {\n return refuse(\"amount is not an integer\");\n }\n if (amount <= 0n) return refuse(\"amount must be positive\");\n if (params.minAmountOut !== undefined && amount < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${amount} < floor=${params.minAmountOut})`);\n try {\n await verify(chainId);\n } catch (e) {\n return refuse(e instanceof Error ? e.message.replace(/^wrap: /, \"\") : String(e));\n }\n const data = wrap ? encodeFunctionData({abi: WETH_ABI, functionName: \"deposit\"}) : encodeFunctionData({abi: WETH_ABI, functionName: \"withdraw\", args: [amount]});\n return {\n provider: \"wrap\",\n intentId: `wrap:${chainId}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {to: w.address, data, value: wrap ? amount.toString() : \"0\", chainId, gasLimit: GAS_LIMIT},\n sourceAmount: amount.toString(),\n destAmount: amount.toString(),\n minDestAmount: amount.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: 0.995,\n validUntilMs: Date.now() + 5 * 60_000,\n providerData: {action: wrap ? \"wrap\" : \"unwrap\", token: w.address},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx?.to || !tx.data) throw new Error(\"swap2: wrap quote has no transaction request\");\n return {chain: \"\", to: tx.to, value: tx.value ?? \"0\", data: tx.data, ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}), ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {})};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"};\n const chainId = Number(ref.intentId.split(\":\")[1]);\n if (!wrapped[chainId] || !config.rpcUrls[chainId]?.length) return {state: \"pending\"};\n try {\n const receipt = (await rpc(chainId, \"eth_getTransactionReceipt\", [ref.sourceTxHash])) as {status?: string} | null;\n if (!receipt) return {state: \"pending\"};\n return receipt.status === \"0x1\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"failed\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n\n/**\n * The wrapped-native contract a wrap / unwrap calls on a chain (no spender: neither approves) — the\n * app's pins for `remoteProvider({name: \"wrap\", baseUrl, ...wrapPins})` (scan 2026-10-27 modules, F8/F16).\n */\nexport const wrapPins: RemotePins = Object.freeze({\n callTargets: (chain: string): readonly string[] => {\n const id = /^eip155:[0-9]+$/.test(chain) ? Number(chain.slice(7)) : NaN;\n const w = Object.prototype.hasOwnProperty.call(WRAPPED_NATIVE, id) ? WRAPPED_NATIVE[id] : undefined;\n return w ? [w.address] : [];\n },\n spenders: (): readonly string[] => [],\n});\n"],"mappings":"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","names":["evmRef","isEvm","isEvm","evmRef"]}
|
|
File without changes
|