@lendasat/lendaswap-sdk-pure 0.2.42 → 0.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_esm-7KJOBTZC.js +3660 -0
- package/dist/_esm-7KJOBTZC.js.map +1 -0
- package/dist/_esm-UGRDSVEV.cjs +3662 -0
- package/dist/_esm-UGRDSVEV.cjs.map +1 -0
- package/dist/api/client.d.ts +0 -4
- package/dist/api/client.d.ts.map +1 -1
- package/dist/base-2KYNAFR3.cjs +109 -0
- package/dist/base-2KYNAFR3.cjs.map +1 -0
- package/dist/base-B6OGU65B.js +7 -0
- package/dist/base-B6OGU65B.js.map +1 -0
- package/dist/ccip-MPMAZOUF.js +5 -0
- package/dist/ccip-MPMAZOUF.js.map +1 -0
- package/dist/ccip-PD37NJHA.cjs +26 -0
- package/dist/ccip-PD37NJHA.cjs.map +1 -0
- package/dist/cctp-bridge/index.cjs +67 -0
- package/dist/cctp-bridge/index.cjs.map +1 -0
- package/dist/cctp-bridge/index.js +51 -15
- package/dist/cctp-bridge/index.js.map +1 -1
- package/dist/cctp-inbound/client.d.ts +21 -19
- package/dist/cctp-inbound/client.d.ts.map +1 -1
- package/dist/cctp-inbound/smartAccount.d.ts +21 -19
- package/dist/cctp-inbound/smartAccount.d.ts.map +1 -1
- package/dist/chunk-3JWT4OW2.js +369 -0
- package/dist/chunk-3JWT4OW2.js.map +1 -0
- package/dist/chunk-A4GKKURK.cjs +430 -0
- package/dist/chunk-A4GKKURK.cjs.map +1 -0
- package/dist/chunk-BZU3R5DJ.cjs +554 -0
- package/dist/chunk-BZU3R5DJ.cjs.map +1 -0
- package/dist/chunk-C4YXYD24.js +418 -0
- package/dist/chunk-C4YXYD24.js.map +1 -0
- package/dist/chunk-CZNQYFDP.js +6141 -0
- package/dist/chunk-CZNQYFDP.js.map +1 -0
- package/dist/chunk-DKTFDGIU.js +2207 -0
- package/dist/chunk-DKTFDGIU.js.map +1 -0
- package/dist/chunk-DNSJDKTP.cjs +96 -0
- package/dist/chunk-DNSJDKTP.cjs.map +1 -0
- package/dist/chunk-EPKFLKTM.js +47093 -0
- package/dist/chunk-EPKFLKTM.js.map +1 -0
- package/dist/chunk-JBVKWKD4.cjs +50 -0
- package/dist/chunk-JBVKWKD4.cjs.map +1 -0
- package/dist/chunk-NPFJAXKV.js +551 -0
- package/dist/chunk-NPFJAXKV.js.map +1 -0
- package/dist/chunk-PKDJZJMV.cjs +2214 -0
- package/dist/chunk-PKDJZJMV.cjs.map +1 -0
- package/dist/chunk-PLDDJCW6.js +43 -0
- package/dist/chunk-PLDDJCW6.js.map +1 -0
- package/dist/chunk-RIOT5VOJ.cjs +47240 -0
- package/dist/chunk-RIOT5VOJ.cjs.map +1 -0
- package/dist/chunk-WVZSHRV7.cjs +431 -0
- package/dist/chunk-WVZSHRV7.cjs.map +1 -0
- package/dist/chunk-YEZOPVAH.js +86 -0
- package/dist/chunk-YEZOPVAH.js.map +1 -0
- package/dist/chunk-YLWPBHMV.cjs +6311 -0
- package/dist/chunk-YLWPBHMV.cjs.map +1 -0
- package/dist/client.d.ts +68 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/compose-quote.d.ts +77 -0
- package/dist/compose-quote.d.ts.map +1 -0
- package/dist/delegate.cjs +23 -0
- package/dist/delegate.cjs.map +1 -0
- package/dist/delegate.js +5 -269
- package/dist/delegate.js.map +1 -1
- package/dist/dist-NE2R4YCX.js +5 -0
- package/dist/dist-NE2R4YCX.js.map +1 -0
- package/dist/dist-VEHYC67F.cjs +550 -0
- package/dist/dist-VEHYC67F.cjs.map +1 -0
- package/dist/esplora.d.ts +14 -0
- package/dist/esplora.d.ts.map +1 -1
- package/dist/generated/api.d.ts +235 -38
- package/dist/generated/api.d.ts.map +1 -1
- package/dist/index.cjs +35461 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35309 -32
- package/dist/index.js.map +1 -1
- package/dist/mine.wasm-JJEJEODX.js +9 -0
- package/dist/mine.wasm-JJEJEODX.js.map +1 -0
- package/dist/mine.wasm-Z3ORSBKN.cjs +12 -0
- package/dist/mine.wasm-Z3ORSBKN.cjs.map +1 -0
- package/dist/node.cjs +166 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.js +157 -18
- package/dist/node.js.map +1 -1
- package/dist/secp256k1-PJCSE4N6.cjs +30 -0
- package/dist/secp256k1-PJCSE4N6.cjs.map +1 -0
- package/dist/secp256k1-VZNNVEPN.js +5 -0
- package/dist/secp256k1-VZNNVEPN.js.map +1 -0
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/types/chain-config.d.ts +50 -0
- package/dist/types/chain-config.d.ts.map +1 -0
- package/dist/types/chain.d.ts +11 -0
- package/dist/types/chain.d.ts.map +1 -0
- package/dist/types/dex-quote.d.ts +85 -0
- package/dist/types/dex-quote.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/network-fees.d.ts +43 -0
- package/dist/types/network-fees.d.ts.map +1 -0
- package/dist/types/quote.d.ts +87 -0
- package/dist/types/quote.d.ts.map +1 -0
- package/dist/types/swap-pairs.d.ts +37 -0
- package/dist/types/swap-pairs.d.ts.map +1 -0
- package/dist/version.d.ts +2 -2
- package/dist/wallet-SCGRX3EN.js +4 -0
- package/dist/wallet-SCGRX3EN.js.map +1 -0
- package/dist/wallet-SZJDXAY7.cjs +45 -0
- package/dist/wallet-SZJDXAY7.cjs.map +1 -0
- package/package.json +23 -10
- package/dist/api/client.js +0 -13
- package/dist/api/client.js.map +0 -1
- package/dist/arkade-network.js +0 -40
- package/dist/arkade-network.js.map +0 -1
- package/dist/arkade.js +0 -61
- package/dist/arkade.js.map +0 -1
- package/dist/cctp/attestation.js +0 -149
- package/dist/cctp/attestation.js.map +0 -1
- package/dist/cctp/constants.js +0 -92
- package/dist/cctp/constants.js.map +0 -1
- package/dist/cctp/fee.js +0 -70
- package/dist/cctp/fee.js.map +0 -1
- package/dist/cctp/index.js +0 -13
- package/dist/cctp/index.js.map +0 -1
- package/dist/cctp/types.js +0 -5
- package/dist/cctp/types.js.map +0 -1
- package/dist/cctp/utils.js +0 -91
- package/dist/cctp/utils.js.map +0 -1
- package/dist/cctp-bridge/bridge.js +0 -74
- package/dist/cctp-bridge/bridge.js.map +0 -1
- package/dist/cctp-inbound/approveAndBurn.js +0 -95
- package/dist/cctp-inbound/approveAndBurn.js.map +0 -1
- package/dist/cctp-inbound/burn.js +0 -66
- package/dist/cctp-inbound/burn.js.map +0 -1
- package/dist/cctp-inbound/chainMap.js +0 -128
- package/dist/cctp-inbound/chainMap.js.map +0 -1
- package/dist/cctp-inbound/client.js +0 -125
- package/dist/cctp-inbound/client.js.map +0 -1
- package/dist/cctp-inbound/eip2612.js +0 -95
- package/dist/cctp-inbound/eip2612.js.map +0 -1
- package/dist/cctp-inbound/evmSignerAdapter.js +0 -82
- package/dist/cctp-inbound/evmSignerAdapter.js.map +0 -1
- package/dist/cctp-inbound/fundSwap.js +0 -95
- package/dist/cctp-inbound/fundSwap.js.map +0 -1
- package/dist/cctp-inbound/index.js +0 -34
- package/dist/cctp-inbound/index.js.map +0 -1
- package/dist/cctp-inbound/permit2.js +0 -32
- package/dist/cctp-inbound/permit2.js.map +0 -1
- package/dist/cctp-inbound/preflight.js +0 -84
- package/dist/cctp-inbound/preflight.js.map +0 -1
- package/dist/cctp-inbound/recover.js +0 -177
- package/dist/cctp-inbound/recover.js.map +0 -1
- package/dist/cctp-inbound/smartAccount.js +0 -117
- package/dist/cctp-inbound/smartAccount.js.map +0 -1
- package/dist/cctp-inbound/submit.js +0 -136
- package/dist/cctp-inbound/submit.js.map +0 -1
- package/dist/cctp-inbound/types.js +0 -5
- package/dist/cctp-inbound/types.js.map +0 -1
- package/dist/cctp-inbound/userOp.js +0 -151
- package/dist/cctp-inbound/userOp.js.map +0 -1
- package/dist/client.js +0 -4126
- package/dist/client.js.map +0 -1
- package/dist/create/arkade-to-lightning.js +0 -76
- package/dist/create/arkade-to-lightning.js.map +0 -1
- package/dist/create/arkade.js +0 -86
- package/dist/create/arkade.js.map +0 -1
- package/dist/create/bitcoin-to-arkade.js +0 -76
- package/dist/create/bitcoin-to-arkade.js.map +0 -1
- package/dist/create/bitcoin.js +0 -77
- package/dist/create/bitcoin.js.map +0 -1
- package/dist/create/evm-to-arkade.js +0 -80
- package/dist/create/evm-to-arkade.js.map +0 -1
- package/dist/create/evm-to-bitcoin.js +0 -82
- package/dist/create/evm-to-bitcoin.js.map +0 -1
- package/dist/create/evm-to-lightning.js +0 -89
- package/dist/create/evm-to-lightning.js.map +0 -1
- package/dist/create/index.js +0 -21
- package/dist/create/index.js.map +0 -1
- package/dist/create/lightning-to-arkade.js +0 -69
- package/dist/create/lightning-to-arkade.js.map +0 -1
- package/dist/create/lightning.js +0 -61
- package/dist/create/lightning.js.map +0 -1
- package/dist/create/retry.js +0 -71
- package/dist/create/retry.js.map +0 -1
- package/dist/create/types.js +0 -5
- package/dist/create/types.js.map +0 -1
- package/dist/escrow/index.js +0 -115
- package/dist/escrow/index.js.map +0 -1
- package/dist/esplora.js +0 -47
- package/dist/esplora.js.map +0 -1
- package/dist/evm/coordinator.js +0 -714
- package/dist/evm/coordinator.js.map +0 -1
- package/dist/evm/htlc.js +0 -278
- package/dist/evm/htlc.js.map +0 -1
- package/dist/evm/index.js +0 -10
- package/dist/evm/index.js.map +0 -1
- package/dist/evm/signing.js +0 -70
- package/dist/evm/signing.js.map +0 -1
- package/dist/evm/wallet.js +0 -133
- package/dist/evm/wallet.js.map +0 -1
- package/dist/generated/api.js +0 -6
- package/dist/generated/api.js.map +0 -1
- package/dist/logging.js +0 -130
- package/dist/logging.js.map +0 -1
- package/dist/price-calculations.js +0 -135
- package/dist/price-calculations.js.map +0 -1
- package/dist/redeem/arkade.js +0 -416
- package/dist/redeem/arkade.js.map +0 -1
- package/dist/redeem/ethereum.js +0 -206
- package/dist/redeem/ethereum.js.map +0 -1
- package/dist/redeem/gasless.js +0 -73
- package/dist/redeem/gasless.js.map +0 -1
- package/dist/redeem/index.js +0 -189
- package/dist/redeem/index.js.map +0 -1
- package/dist/redeem/types.js +0 -36
- package/dist/redeem/types.js.map +0 -1
- package/dist/refund/arkade.js +0 -200
- package/dist/refund/arkade.js.map +0 -1
- package/dist/refund/collab-arkade-evm.js +0 -307
- package/dist/refund/collab-arkade-evm.js.map +0 -1
- package/dist/refund/collab-arkade-lightning.js +0 -245
- package/dist/refund/collab-arkade-lightning.js.map +0 -1
- package/dist/refund/index.js +0 -12
- package/dist/refund/index.js.map +0 -1
- package/dist/refund/onchain.js +0 -366
- package/dist/refund/onchain.js.map +0 -1
- package/dist/signer/index.js +0 -249
- package/dist/signer/index.js.map +0 -1
- package/dist/storage/idb.js +0 -236
- package/dist/storage/idb.js.map +0 -1
- package/dist/storage/index.js +0 -98
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/sqlite.js +0 -206
- package/dist/storage/sqlite.js.map +0 -1
- package/dist/storage/types.js +0 -9
- package/dist/storage/types.js.map +0 -1
- package/dist/tokens.js +0 -322
- package/dist/tokens.js.map +0 -1
- package/dist/usd-price.js +0 -96
- package/dist/usd-price.js.map +0 -1
- package/dist/usdt0-bridge/constants.js +0 -71
- package/dist/usdt0-bridge/constants.js.map +0 -1
- package/dist/usdt0-bridge/index.js +0 -11
- package/dist/usdt0-bridge/index.js.map +0 -1
- package/dist/usdt0-bridge/tracking.js +0 -123
- package/dist/usdt0-bridge/tracking.js.map +0 -1
- package/dist/usdt0-bridge/utils.js +0 -51
- package/dist/usdt0-bridge/utils.js.map +0 -1
- package/dist/version.js +0 -6
- package/dist/version.js.map +0 -1
- package/dist/ws.js +0 -145
- package/dist/ws.js.map +0 -1
package/dist/evm/coordinator.js
DELETED
|
@@ -1,714 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTLCCoordinator contract utilities.
|
|
3
|
-
*
|
|
4
|
-
* Provides helpers for EIP-712 signing and encoding `redeemAndExecute` call data
|
|
5
|
-
* for the HTLCCoordinator contract used in Arkade-to-EVM swaps, and
|
|
6
|
-
* `executeAndCreate` / refund helpers for EVM-to-BTC coordinator swaps.
|
|
7
|
-
*/
|
|
8
|
-
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
9
|
-
import { hexToBytes as nobleFromHex, bytesToHex as nobleToHex, } from "@noble/hashes/utils.js";
|
|
10
|
-
// ── EIP-712 constants ────────────────────────────────────────────────────────
|
|
11
|
-
// hardcoded so that we can potentially support multiple versions
|
|
12
|
-
const EIP712_DOMAIN_TYPEHASH = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)";
|
|
13
|
-
const REDEEM_TYPEHASH = "Redeem(bytes32 preimage,uint256 amount,address token,address sender,uint256 timelock,address caller,address destination,address sweepToken,uint256 minAmountOut,bytes32 callsHash)";
|
|
14
|
-
const HTLC_NAME = "HTLCErc20";
|
|
15
|
-
const HTLC_VERSION = "3";
|
|
16
|
-
// ── redeemAndExecute selector ────────────────────────────────────────────────
|
|
17
|
-
// keccak256("redeemAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256,address,uint8,bytes32,bytes32)")
|
|
18
|
-
const REDEEM_AND_EXECUTE_SELECTOR = keccak256(stringToUtf8Bytes("redeemAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256,address,uint8,bytes32,bytes32)")).slice(0, 10);
|
|
19
|
-
// ── keccak256 ────────────────────────────────────────────────────────────────
|
|
20
|
-
/**
|
|
21
|
-
* Computes keccak256 hash using @noble/hashes.
|
|
22
|
-
*
|
|
23
|
-
* @param input - Hex string (with or without 0x) or Uint8Array
|
|
24
|
-
* @returns 32-byte hex string with 0x prefix
|
|
25
|
-
*/
|
|
26
|
-
export function keccak256(input) {
|
|
27
|
-
const data = typeof input === "string" ? hexToBytes(input) : input;
|
|
28
|
-
const hash = keccak_256(data);
|
|
29
|
-
return `0x${bytesToHex(hash)}`;
|
|
30
|
-
}
|
|
31
|
-
// ── EIP-712 digest ───────────────────────────────────────────────────────────
|
|
32
|
-
/**
|
|
33
|
-
* Builds the EIP-712 digest that the user must sign to authorize
|
|
34
|
-
* the coordinator to call `HTLC.redeem` on their behalf.
|
|
35
|
-
*
|
|
36
|
-
* @param params - The redeem parameters
|
|
37
|
-
* @returns The 32-byte digest as hex string with 0x prefix
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```ts
|
|
41
|
-
* const digest = buildRedeemDigest({
|
|
42
|
-
* htlcAddress: "0x...",
|
|
43
|
-
* chainId: 137,
|
|
44
|
-
* preimage: "0x...",
|
|
45
|
-
* amount: 100000n,
|
|
46
|
-
* token: "0x...", // WBTC
|
|
47
|
-
* sender: "0x...", // server
|
|
48
|
-
* timelock: 1700000000,
|
|
49
|
-
* caller: "0x...", // coordinator
|
|
50
|
-
* });
|
|
51
|
-
* // Sign `digest` with user's EVM wallet
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
export function buildRedeemDigest(params) {
|
|
55
|
-
// Domain separator
|
|
56
|
-
const domainSeparator = keccak256(abiEncode([
|
|
57
|
-
{
|
|
58
|
-
type: "bytes32",
|
|
59
|
-
value: keccak256(stringToUtf8Bytes(EIP712_DOMAIN_TYPEHASH)),
|
|
60
|
-
},
|
|
61
|
-
{ type: "bytes32", value: keccak256(stringToUtf8Bytes(HTLC_NAME)) },
|
|
62
|
-
{ type: "bytes32", value: keccak256(stringToUtf8Bytes(HTLC_VERSION)) },
|
|
63
|
-
{ type: "uint256", value: BigInt(params.chainId) },
|
|
64
|
-
{ type: "address", value: params.htlcAddress },
|
|
65
|
-
]));
|
|
66
|
-
// Struct hash
|
|
67
|
-
const typeHash = keccak256(stringToUtf8Bytes(REDEEM_TYPEHASH));
|
|
68
|
-
const structHash = keccak256(abiEncode([
|
|
69
|
-
{ type: "bytes32", value: typeHash },
|
|
70
|
-
{ type: "bytes32", value: params.preimage },
|
|
71
|
-
{ type: "uint256", value: params.amount },
|
|
72
|
-
{ type: "address", value: params.token },
|
|
73
|
-
{ type: "address", value: params.sender },
|
|
74
|
-
{ type: "uint256", value: BigInt(params.timelock) },
|
|
75
|
-
{ type: "address", value: params.caller },
|
|
76
|
-
{ type: "address", value: params.destination },
|
|
77
|
-
{ type: "address", value: params.sweepToken },
|
|
78
|
-
{ type: "uint256", value: params.minAmountOut },
|
|
79
|
-
{ type: "bytes32", value: params.callsHash },
|
|
80
|
-
]));
|
|
81
|
-
// EIP-712 digest: \x19\x01 ‖ domainSeparator ‖ structHash
|
|
82
|
-
const prefix = new Uint8Array([0x19, 0x01]);
|
|
83
|
-
const domainBytes = hexToBytes(domainSeparator);
|
|
84
|
-
const structBytes = hexToBytes(structHash);
|
|
85
|
-
const message = new Uint8Array(prefix.length + domainBytes.length + structBytes.length);
|
|
86
|
-
message.set(prefix, 0);
|
|
87
|
-
message.set(domainBytes, prefix.length);
|
|
88
|
-
message.set(structBytes, prefix.length + domainBytes.length);
|
|
89
|
-
return keccak256(message);
|
|
90
|
-
}
|
|
91
|
-
// ── Calls builder ────────────────────────────────────────────────────────────
|
|
92
|
-
/**
|
|
93
|
-
* Builds the calls array for `redeemAndExecute` based on 1inch calldata.
|
|
94
|
-
*
|
|
95
|
-
* - If `dexCallData` is provided: returns [approve WBTC to DEX, execute DEX swap]
|
|
96
|
-
* - If `dexCallData` is null/undefined (WBTC target): returns empty array
|
|
97
|
-
*
|
|
98
|
-
* @param wbtcAddress - WBTC token contract address
|
|
99
|
-
* @param amount - WBTC amount to approve
|
|
100
|
-
* @param dexCallData - DEX swap calldata from the creation response (optional)
|
|
101
|
-
* @returns Array of CoordinatorCall structs
|
|
102
|
-
*/
|
|
103
|
-
export function buildRedeemCalls(wbtcAddress, amount, dexCallData) {
|
|
104
|
-
if (!dexCallData) {
|
|
105
|
-
return [];
|
|
106
|
-
}
|
|
107
|
-
// Build approve calldata: WBTC.approve(dex_router, amount)
|
|
108
|
-
const approveData = encodeApprove(dexCallData.to, amount);
|
|
109
|
-
return [
|
|
110
|
-
{
|
|
111
|
-
target: wbtcAddress,
|
|
112
|
-
value: 0n,
|
|
113
|
-
data: approveData,
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
target: dexCallData.to,
|
|
117
|
-
value: BigInt(dexCallData.value || "0"),
|
|
118
|
-
data: dexCallData.data,
|
|
119
|
-
},
|
|
120
|
-
];
|
|
121
|
-
}
|
|
122
|
-
// ── redeemAndExecute calldata ────────────────────────────────────────────────
|
|
123
|
-
/**
|
|
124
|
-
* Encodes the call data for `coordinator.redeemAndExecute(...)`.
|
|
125
|
-
*
|
|
126
|
-
* @param coordinatorAddress - The HTLCCoordinator contract address
|
|
127
|
-
* @param params - All parameters for the call
|
|
128
|
-
* @returns The encoded call data
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* ```ts
|
|
132
|
-
* const txData = encodeRedeemAndExecute("0xCoordinator...", {
|
|
133
|
-
* preimage: "0x...",
|
|
134
|
-
* amount: 100000n,
|
|
135
|
-
* token: "0xWBTC...",
|
|
136
|
-
* sender: "0xServer...",
|
|
137
|
-
* timelock: 1700000000,
|
|
138
|
-
* calls: buildRedeemCalls(wbtcAddr, amount, dexCallData),
|
|
139
|
-
* sweepToken: targetTokenAddr,
|
|
140
|
-
* minAmountOut: 0n,
|
|
141
|
-
* v: 27,
|
|
142
|
-
* r: "0x...",
|
|
143
|
-
* s: "0x...",
|
|
144
|
-
* });
|
|
145
|
-
* // Send transaction: { to: txData.to, data: txData.data }
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
export function encodeRedeemAndExecute(coordinatorAddress, params) {
|
|
149
|
-
// Fixed-length head: 12 slots of 32 bytes each
|
|
150
|
-
// preimage (bytes32), amount (uint256), token (address), sender (address),
|
|
151
|
-
// timelock (uint256), calls_offset (uint256), sweepToken (address),
|
|
152
|
-
// minAmountOut (uint256), destination (address), v (uint8), r (bytes32), s (bytes32)
|
|
153
|
-
const preimage = normalizeBytes32(params.preimage);
|
|
154
|
-
const amount = encodeUint256(params.amount);
|
|
155
|
-
const token = normalizeAddress(params.token);
|
|
156
|
-
const sender = normalizeAddress(params.sender);
|
|
157
|
-
const timelock = encodeUint256(BigInt(params.timelock));
|
|
158
|
-
// Calls is a dynamic type — offset points to where the array data starts.
|
|
159
|
-
// Head has 12 slots × 32 bytes = 384 = 0x180
|
|
160
|
-
const callsOffset = encodeUint256(12n * 32n);
|
|
161
|
-
const sweepToken = normalizeAddress(params.sweepToken);
|
|
162
|
-
const minAmountOut = encodeUint256(params.minAmountOut);
|
|
163
|
-
const destination = normalizeAddress(params.destination);
|
|
164
|
-
const v = encodeUint256(BigInt(params.v));
|
|
165
|
-
const r = normalizeBytes32(params.r);
|
|
166
|
-
const s = normalizeBytes32(params.s);
|
|
167
|
-
// Encode the calls array
|
|
168
|
-
const callsEncoded = encodeCalls(params.calls);
|
|
169
|
-
const data = [
|
|
170
|
-
REDEEM_AND_EXECUTE_SELECTOR,
|
|
171
|
-
preimage,
|
|
172
|
-
amount,
|
|
173
|
-
token,
|
|
174
|
-
sender,
|
|
175
|
-
timelock,
|
|
176
|
-
callsOffset,
|
|
177
|
-
sweepToken,
|
|
178
|
-
minAmountOut,
|
|
179
|
-
destination,
|
|
180
|
-
v,
|
|
181
|
-
r,
|
|
182
|
-
s,
|
|
183
|
-
callsEncoded,
|
|
184
|
-
].join("");
|
|
185
|
-
return {
|
|
186
|
-
to: coordinatorAddress,
|
|
187
|
-
data,
|
|
188
|
-
functionSignature: "redeemAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256,address,uint8,bytes32,bytes32)",
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
// ── refundAndExecute selector ────────────────────────────────────────────────
|
|
192
|
-
// keccak256("refundAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256)")
|
|
193
|
-
const REFUND_AND_EXECUTE_SELECTOR = keccak256(stringToUtf8Bytes("refundAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256)")).slice(0, 10);
|
|
194
|
-
// ── refundTo selector ────────────────────────────────────────────────────────
|
|
195
|
-
// keccak256("refundTo(bytes32,uint256,address,address,uint256)")
|
|
196
|
-
const REFUND_TO_SELECTOR = keccak256(stringToUtf8Bytes("refundTo(bytes32,uint256,address,address,uint256)")).slice(0, 10);
|
|
197
|
-
/**
|
|
198
|
-
* Encodes the call data for `coordinator.refundAndExecute(...)`.
|
|
199
|
-
*
|
|
200
|
-
* Signature: refundAndExecute(bytes32 preimageHash, uint256 amount, address token, address claimAddress, uint256 timelock, Call[] calls, address sweepToken, uint256 minAmountOut)
|
|
201
|
-
*
|
|
202
|
-
* @param coordinatorAddress - The HTLCCoordinator contract address
|
|
203
|
-
* @param params - All parameters for the call
|
|
204
|
-
* @returns The encoded call data
|
|
205
|
-
*/
|
|
206
|
-
export function encodeRefundAndExecute(coordinatorAddress, params) {
|
|
207
|
-
// Head: preimageHash, amount, token, claimAddress, timelock, calls_offset, sweepToken, minAmountOut (8 slots)
|
|
208
|
-
const preimageHash = normalizeBytes32(params.preimageHash);
|
|
209
|
-
const amount = encodeUint256(params.amount);
|
|
210
|
-
const token = normalizeAddress(params.token);
|
|
211
|
-
const claimAddress = normalizeAddress(params.claimAddress);
|
|
212
|
-
const timelock = encodeUint256(BigInt(params.timelock));
|
|
213
|
-
const callsOffset = encodeUint256(8n * 32n);
|
|
214
|
-
const sweepToken = normalizeAddress(params.sweepToken);
|
|
215
|
-
const minAmountOut = encodeUint256(params.minAmountOut);
|
|
216
|
-
// Encode the calls array (tail)
|
|
217
|
-
const callsEncoded = encodeCalls(params.calls);
|
|
218
|
-
const data = [
|
|
219
|
-
REFUND_AND_EXECUTE_SELECTOR,
|
|
220
|
-
preimageHash,
|
|
221
|
-
amount,
|
|
222
|
-
token,
|
|
223
|
-
claimAddress,
|
|
224
|
-
timelock,
|
|
225
|
-
callsOffset,
|
|
226
|
-
sweepToken,
|
|
227
|
-
minAmountOut,
|
|
228
|
-
callsEncoded,
|
|
229
|
-
].join("");
|
|
230
|
-
return {
|
|
231
|
-
to: coordinatorAddress,
|
|
232
|
-
data,
|
|
233
|
-
functionSignature: "refundAndExecute(bytes32,uint256,address,address,uint256,(address,uint256,bytes)[],address,uint256)",
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Encodes the call data for `coordinator.refundTo(...)`.
|
|
238
|
-
*
|
|
239
|
-
* Signature: refundTo(bytes32 preimageHash, uint256 amount, address token, address claimAddress, uint256 timelock)
|
|
240
|
-
*
|
|
241
|
-
* @param coordinatorAddress - The HTLCCoordinator contract address
|
|
242
|
-
* @param params - All parameters for the call
|
|
243
|
-
* @returns The encoded call data
|
|
244
|
-
*/
|
|
245
|
-
export function encodeRefundTo(coordinatorAddress, params) {
|
|
246
|
-
const preimageHash = normalizeBytes32(params.preimageHash);
|
|
247
|
-
const amount = encodeUint256(params.amount);
|
|
248
|
-
const token = normalizeAddress(params.token);
|
|
249
|
-
const claimAddress = normalizeAddress(params.claimAddress);
|
|
250
|
-
const timelock = encodeUint256(BigInt(params.timelock));
|
|
251
|
-
const data = [
|
|
252
|
-
REFUND_TO_SELECTOR,
|
|
253
|
-
preimageHash,
|
|
254
|
-
amount,
|
|
255
|
-
token,
|
|
256
|
-
claimAddress,
|
|
257
|
-
timelock,
|
|
258
|
-
].join("");
|
|
259
|
-
return {
|
|
260
|
-
to: coordinatorAddress,
|
|
261
|
-
data,
|
|
262
|
-
functionSignature: "refundTo(bytes32,uint256,address,address,uint256)",
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
// ── Collaborative EVM refund EIP-712 ─────────────────────────────────────────
|
|
266
|
-
const COORDINATOR_NAME = "HTLCCoordinator";
|
|
267
|
-
const COORDINATOR_VERSION = "3";
|
|
268
|
-
const COLLAB_REFUND_TYPEHASH = "CollabRefund(bytes32 preimageHash,uint256 amount,address token,address claimAddress,uint256 timelock,address caller,address sweepToken,uint256 minAmountOut,bytes32 callsHash)";
|
|
269
|
-
/**
|
|
270
|
-
* Builds the EIP-712 digest for collaborative EVM HTLC refund.
|
|
271
|
-
*
|
|
272
|
-
* The depositor signs this digest to authorize the server to submit
|
|
273
|
-
* `collabRefundTo` or `collabRefundAndExecute` on the coordinator.
|
|
274
|
-
*
|
|
275
|
-
* @param params - CollabRefund parameters
|
|
276
|
-
* @returns The 32-byte digest as hex string with 0x prefix
|
|
277
|
-
*/
|
|
278
|
-
export function buildCollabRefundEvmDigest(params) {
|
|
279
|
-
// Coordinator domain separator
|
|
280
|
-
const domainSeparator = keccak256(abiEncode([
|
|
281
|
-
{
|
|
282
|
-
type: "bytes32",
|
|
283
|
-
value: keccak256(stringToUtf8Bytes(EIP712_DOMAIN_TYPEHASH)),
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
type: "bytes32",
|
|
287
|
-
value: keccak256(stringToUtf8Bytes(COORDINATOR_NAME)),
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
type: "bytes32",
|
|
291
|
-
value: keccak256(stringToUtf8Bytes(COORDINATOR_VERSION)),
|
|
292
|
-
},
|
|
293
|
-
{ type: "uint256", value: BigInt(params.chainId) },
|
|
294
|
-
{ type: "address", value: params.coordinatorAddress },
|
|
295
|
-
]));
|
|
296
|
-
// CollabRefund struct hash
|
|
297
|
-
const typeHash = keccak256(stringToUtf8Bytes(COLLAB_REFUND_TYPEHASH));
|
|
298
|
-
const structHash = keccak256(abiEncode([
|
|
299
|
-
{ type: "bytes32", value: typeHash },
|
|
300
|
-
{ type: "bytes32", value: params.preimageHash },
|
|
301
|
-
{ type: "uint256", value: params.amount },
|
|
302
|
-
{ type: "address", value: params.token },
|
|
303
|
-
{ type: "address", value: params.claimAddress },
|
|
304
|
-
{ type: "uint256", value: BigInt(params.timelock) },
|
|
305
|
-
{ type: "address", value: params.caller },
|
|
306
|
-
{ type: "address", value: params.sweepToken },
|
|
307
|
-
{ type: "uint256", value: params.minAmountOut },
|
|
308
|
-
{ type: "bytes32", value: params.callsHash },
|
|
309
|
-
]));
|
|
310
|
-
// EIP-712 digest: \x19\x01 ‖ domainSeparator ‖ structHash
|
|
311
|
-
const prefix = new Uint8Array([0x19, 0x01]);
|
|
312
|
-
const domainBytes = hexToBytes(domainSeparator);
|
|
313
|
-
const structBytes = hexToBytes(structHash);
|
|
314
|
-
const message = new Uint8Array(prefix.length + domainBytes.length + structBytes.length);
|
|
315
|
-
message.set(prefix, 0);
|
|
316
|
-
message.set(domainBytes, prefix.length);
|
|
317
|
-
message.set(structBytes, prefix.length + domainBytes.length);
|
|
318
|
-
return keccak256(message);
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Builds the EIP-712 typed data structure for CollabRefund.
|
|
322
|
-
*
|
|
323
|
-
* For use with browser wallets via `eth_signTypedData_v4` / wagmi's `signTypedData`.
|
|
324
|
-
*
|
|
325
|
-
* @param params - CollabRefund parameters
|
|
326
|
-
* @returns EIP-712 typed data compatible with viem/wagmi
|
|
327
|
-
*/
|
|
328
|
-
export function buildCollabRefundEvmTypedData(params) {
|
|
329
|
-
return {
|
|
330
|
-
domain: {
|
|
331
|
-
name: COORDINATOR_NAME,
|
|
332
|
-
version: COORDINATOR_VERSION,
|
|
333
|
-
chainId: params.chainId,
|
|
334
|
-
verifyingContract: params.coordinatorAddress,
|
|
335
|
-
},
|
|
336
|
-
types: {
|
|
337
|
-
CollabRefund: [
|
|
338
|
-
{ name: "preimageHash", type: "bytes32" },
|
|
339
|
-
{ name: "amount", type: "uint256" },
|
|
340
|
-
{ name: "token", type: "address" },
|
|
341
|
-
{ name: "claimAddress", type: "address" },
|
|
342
|
-
{ name: "timelock", type: "uint256" },
|
|
343
|
-
{ name: "caller", type: "address" },
|
|
344
|
-
{ name: "sweepToken", type: "address" },
|
|
345
|
-
{ name: "minAmountOut", type: "uint256" },
|
|
346
|
-
{ name: "callsHash", type: "bytes32" },
|
|
347
|
-
],
|
|
348
|
-
},
|
|
349
|
-
primaryType: "CollabRefund",
|
|
350
|
-
message: {
|
|
351
|
-
preimageHash: params.preimageHash,
|
|
352
|
-
amount: params.amount,
|
|
353
|
-
token: params.token,
|
|
354
|
-
claimAddress: params.claimAddress,
|
|
355
|
-
timelock: BigInt(params.timelock),
|
|
356
|
-
caller: params.caller,
|
|
357
|
-
sweepToken: params.sweepToken,
|
|
358
|
-
minAmountOut: params.minAmountOut,
|
|
359
|
-
callsHash: params.callsHash,
|
|
360
|
-
},
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
// ── Permit2 constants ─────────────────────────────────────────────────────────
|
|
364
|
-
/** Canonical Permit2 deployment address (same on all EVM chains) */
|
|
365
|
-
export const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
366
|
-
// Permit2 uses a simpler domain: EIP712Domain(string name, uint256 chainId, address verifyingContract)
|
|
367
|
-
const PERMIT2_DOMAIN_TYPEHASH = "EIP712Domain(string name,uint256 chainId,address verifyingContract)";
|
|
368
|
-
const PERMIT2_NAME = "Permit2";
|
|
369
|
-
// Full type string for permitWitnessTransferFrom — includes sub-types alphabetically
|
|
370
|
-
const PERMIT_WITNESS_TRANSFER_FROM_TYPEHASH = "PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,ExecuteAndCreate witness)" +
|
|
371
|
-
"ExecuteAndCreate(bytes32 preimageHash,address token,address claimAddress,address refundAddress,uint256 timelock,bytes32 callsHash)" +
|
|
372
|
-
"TokenPermissions(address token,uint256 amount)";
|
|
373
|
-
const TOKEN_PERMISSIONS_TYPEHASH = "TokenPermissions(address token,uint256 amount)";
|
|
374
|
-
const EXECUTE_AND_CREATE_WITNESS_TYPEHASH = "ExecuteAndCreate(bytes32 preimageHash,address token,address claimAddress,address refundAddress,uint256 timelock,bytes32 callsHash)";
|
|
375
|
-
// ── Permit2 EIP-712 digest ───────────────────────────────────────────────────
|
|
376
|
-
/**
|
|
377
|
-
* Builds the EIP-712 digest for Permit2 `permitWitnessTransferFrom` with
|
|
378
|
-
* an `ExecuteAndCreate` witness.
|
|
379
|
-
*
|
|
380
|
-
* The user signs this digest to authorize the coordinator to pull their
|
|
381
|
-
* source tokens via Permit2 and execute the swap + HTLC creation.
|
|
382
|
-
*
|
|
383
|
-
* @param params - The Permit2 funding parameters
|
|
384
|
-
* @returns The 32-byte digest as hex string with 0x prefix
|
|
385
|
-
*/
|
|
386
|
-
export function buildPermit2FundingDigest(params) {
|
|
387
|
-
// 1. Permit2 domain separator (simpler than standard EIP-712 — no version)
|
|
388
|
-
const domainSeparator = keccak256(abiEncode([
|
|
389
|
-
{
|
|
390
|
-
type: "bytes32",
|
|
391
|
-
value: keccak256(stringToUtf8Bytes(PERMIT2_DOMAIN_TYPEHASH)),
|
|
392
|
-
},
|
|
393
|
-
{ type: "bytes32", value: keccak256(stringToUtf8Bytes(PERMIT2_NAME)) },
|
|
394
|
-
{ type: "uint256", value: BigInt(params.chainId) },
|
|
395
|
-
{ type: "address", value: PERMIT2_ADDRESS },
|
|
396
|
-
]));
|
|
397
|
-
// 2. TokenPermissions hash
|
|
398
|
-
const tokenPermissionsHash = keccak256(abiEncode([
|
|
399
|
-
{
|
|
400
|
-
type: "bytes32",
|
|
401
|
-
value: keccak256(stringToUtf8Bytes(TOKEN_PERMISSIONS_TYPEHASH)),
|
|
402
|
-
},
|
|
403
|
-
{ type: "address", value: params.sourceToken },
|
|
404
|
-
{ type: "uint256", value: params.sourceAmount },
|
|
405
|
-
]));
|
|
406
|
-
// 3. ExecuteAndCreate witness hash
|
|
407
|
-
const witnessHash = keccak256(abiEncode([
|
|
408
|
-
{
|
|
409
|
-
type: "bytes32",
|
|
410
|
-
value: keccak256(stringToUtf8Bytes(EXECUTE_AND_CREATE_WITNESS_TYPEHASH)),
|
|
411
|
-
},
|
|
412
|
-
{ type: "bytes32", value: params.preimageHash },
|
|
413
|
-
{ type: "address", value: params.lockToken },
|
|
414
|
-
{ type: "address", value: params.claimAddress },
|
|
415
|
-
{ type: "address", value: params.refundAddress },
|
|
416
|
-
{ type: "uint256", value: BigInt(params.timelock) },
|
|
417
|
-
{ type: "bytes32", value: params.callsHash },
|
|
418
|
-
]));
|
|
419
|
-
// 4. Struct hash: PermitWitnessTransferFrom(tokenPermissionsHash, spender, nonce, deadline, witnessHash)
|
|
420
|
-
const structHash = keccak256(abiEncode([
|
|
421
|
-
{
|
|
422
|
-
type: "bytes32",
|
|
423
|
-
value: keccak256(stringToUtf8Bytes(PERMIT_WITNESS_TRANSFER_FROM_TYPEHASH)),
|
|
424
|
-
},
|
|
425
|
-
{ type: "bytes32", value: tokenPermissionsHash },
|
|
426
|
-
{ type: "address", value: params.coordinatorAddress },
|
|
427
|
-
{ type: "uint256", value: params.nonce },
|
|
428
|
-
{ type: "uint256", value: params.deadline },
|
|
429
|
-
{ type: "bytes32", value: witnessHash },
|
|
430
|
-
]));
|
|
431
|
-
// 5. EIP-712 digest: \x19\x01 ‖ domainSeparator ‖ structHash
|
|
432
|
-
const prefix = new Uint8Array([0x19, 0x01]);
|
|
433
|
-
const domainBytes = hexToBytes(domainSeparator);
|
|
434
|
-
const structBytes = hexToBytes(structHash);
|
|
435
|
-
const message = new Uint8Array(prefix.length + domainBytes.length + structBytes.length);
|
|
436
|
-
message.set(prefix, 0);
|
|
437
|
-
message.set(domainBytes, prefix.length);
|
|
438
|
-
message.set(structBytes, prefix.length + domainBytes.length);
|
|
439
|
-
return keccak256(message);
|
|
440
|
-
}
|
|
441
|
-
// ── Permit2 typed data for wallet signing ──────────────────────────────────
|
|
442
|
-
/**
|
|
443
|
-
* Builds the EIP-712 typed data structure for Permit2 `permitWitnessTransferFrom`
|
|
444
|
-
* with an `ExecuteAndCreate` witness.
|
|
445
|
-
*
|
|
446
|
-
* This is intended for the "sovereign" flow where the user's browser wallet
|
|
447
|
-
* signs the Permit2 message via `eth_signTypedData_v4` / wagmi's `signTypedData`.
|
|
448
|
-
*
|
|
449
|
-
* @param params - The Permit2 funding parameters
|
|
450
|
-
* @returns EIP-712 typed data compatible with viem/wagmi's `signTypedData`
|
|
451
|
-
*
|
|
452
|
-
* @example
|
|
453
|
-
* ```ts
|
|
454
|
-
* const typedData = buildPermit2TypedData(params);
|
|
455
|
-
* // In the browser with wagmi:
|
|
456
|
-
* const signature = await walletClient.signTypedData(typedData);
|
|
457
|
-
* ```
|
|
458
|
-
*/
|
|
459
|
-
export function buildPermit2TypedData(params) {
|
|
460
|
-
return {
|
|
461
|
-
domain: {
|
|
462
|
-
name: PERMIT2_NAME,
|
|
463
|
-
chainId: params.chainId,
|
|
464
|
-
verifyingContract: PERMIT2_ADDRESS,
|
|
465
|
-
},
|
|
466
|
-
types: {
|
|
467
|
-
PermitWitnessTransferFrom: [
|
|
468
|
-
{ name: "permitted", type: "TokenPermissions" },
|
|
469
|
-
{ name: "spender", type: "address" },
|
|
470
|
-
{ name: "nonce", type: "uint256" },
|
|
471
|
-
{ name: "deadline", type: "uint256" },
|
|
472
|
-
{ name: "witness", type: "ExecuteAndCreate" },
|
|
473
|
-
],
|
|
474
|
-
TokenPermissions: [
|
|
475
|
-
{ name: "token", type: "address" },
|
|
476
|
-
{ name: "amount", type: "uint256" },
|
|
477
|
-
],
|
|
478
|
-
ExecuteAndCreate: [
|
|
479
|
-
{ name: "preimageHash", type: "bytes32" },
|
|
480
|
-
{ name: "token", type: "address" },
|
|
481
|
-
{ name: "claimAddress", type: "address" },
|
|
482
|
-
{ name: "refundAddress", type: "address" },
|
|
483
|
-
{ name: "timelock", type: "uint256" },
|
|
484
|
-
{ name: "callsHash", type: "bytes32" },
|
|
485
|
-
],
|
|
486
|
-
},
|
|
487
|
-
primaryType: "PermitWitnessTransferFrom",
|
|
488
|
-
message: {
|
|
489
|
-
permitted: {
|
|
490
|
-
token: params.sourceToken,
|
|
491
|
-
amount: params.sourceAmount,
|
|
492
|
-
},
|
|
493
|
-
spender: params.coordinatorAddress,
|
|
494
|
-
nonce: params.nonce,
|
|
495
|
-
deadline: params.deadline,
|
|
496
|
-
witness: {
|
|
497
|
-
preimageHash: params.preimageHash,
|
|
498
|
-
token: params.lockToken,
|
|
499
|
-
claimAddress: params.claimAddress,
|
|
500
|
-
refundAddress: params.refundAddress,
|
|
501
|
-
timelock: BigInt(params.timelock),
|
|
502
|
-
callsHash: params.callsHash,
|
|
503
|
-
},
|
|
504
|
-
},
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
// ── executeAndCreateWithPermit2 selector (overload 1: depositor tracking) ────
|
|
508
|
-
// keccak256("executeAndCreateWithPermit2((address,uint256,bytes)[],bytes32,address,address,uint256,address,((address,uint256),uint256,uint256),bytes)")
|
|
509
|
-
const EXECUTE_AND_CREATE_WITH_PERMIT2_SELECTOR = keccak256(stringToUtf8Bytes("executeAndCreateWithPermit2((address,uint256,bytes)[],bytes32,address,address,uint256,address,((address,uint256),uint256,uint256),bytes)")).slice(0, 10);
|
|
510
|
-
/**
|
|
511
|
-
* Encodes the call data for `coordinator.executeAndCreateWithPermit2(...)` (overload 1).
|
|
512
|
-
*
|
|
513
|
-
* Overload 1 uses depositor tracking: the coordinator becomes the HTLC sender,
|
|
514
|
-
* enabling server-side refundTo/refundAndExecute for expired swaps.
|
|
515
|
-
*
|
|
516
|
-
* Signature: executeAndCreateWithPermit2(
|
|
517
|
-
* Call[] calls,
|
|
518
|
-
* bytes32 preimageHash,
|
|
519
|
-
* address token,
|
|
520
|
-
* address claimAddress,
|
|
521
|
-
* uint256 timelock,
|
|
522
|
-
* address depositor,
|
|
523
|
-
* ((address,uint256),uint256,uint256) permit,
|
|
524
|
-
* bytes signature
|
|
525
|
-
* )
|
|
526
|
-
*
|
|
527
|
-
* @param coordinatorAddress - The HTLCCoordinator contract address
|
|
528
|
-
* @param params - All parameters for the call
|
|
529
|
-
* @returns The encoded call data
|
|
530
|
-
*/
|
|
531
|
-
export function encodeExecuteAndCreateWithPermit2(coordinatorAddress, params) {
|
|
532
|
-
// ABI head layout (11 words):
|
|
533
|
-
// 0: calls offset (dynamic → pointer)
|
|
534
|
-
// 1: preimageHash (bytes32)
|
|
535
|
-
// 2: token (address)
|
|
536
|
-
// 3: claimAddress (address)
|
|
537
|
-
// 4: timelock (uint256)
|
|
538
|
-
// 5: depositor (address)
|
|
539
|
-
// 6: permit.permitted.token (address) ← inline static struct
|
|
540
|
-
// 7: permit.permitted.amount (uint256) ← inline
|
|
541
|
-
// 8: permit.nonce (uint256) ← inline
|
|
542
|
-
// 9: permit.deadline (uint256) ← inline
|
|
543
|
-
// 10: signature offset (dynamic → pointer)
|
|
544
|
-
//
|
|
545
|
-
// Tail:
|
|
546
|
-
// calls data
|
|
547
|
-
// signature data (length + padded bytes)
|
|
548
|
-
const HEAD_WORDS = 11n;
|
|
549
|
-
const preimageHash = normalizeBytes32(params.preimageHash);
|
|
550
|
-
const token = normalizeAddress(params.token);
|
|
551
|
-
const claimAddress = normalizeAddress(params.claimAddress);
|
|
552
|
-
const timelock = encodeUint256(BigInt(params.timelock));
|
|
553
|
-
const depositor = normalizeAddress(params.depositor);
|
|
554
|
-
// Permit struct fields (encoded inline in the head)
|
|
555
|
-
const permitToken = normalizeAddress(params.sourceToken);
|
|
556
|
-
const permitAmount = encodeUint256(params.sourceAmount);
|
|
557
|
-
const permitNonce = encodeUint256(params.nonce);
|
|
558
|
-
const permitDeadline = encodeUint256(params.deadline);
|
|
559
|
-
// Encode the calls array (tail)
|
|
560
|
-
const callsEncoded = encodeCalls(params.calls);
|
|
561
|
-
const callsEncodedBytes = BigInt(callsEncoded.length / 2);
|
|
562
|
-
// Encode signature as dynamic bytes (tail)
|
|
563
|
-
const sigClean = params.signature.startsWith("0x")
|
|
564
|
-
? params.signature.slice(2)
|
|
565
|
-
: params.signature;
|
|
566
|
-
const sigLength = sigClean.length / 2;
|
|
567
|
-
const sigPaddedLength = Math.ceil(sigLength / 32) * 32;
|
|
568
|
-
const signatureEncoded = encodeUint256(BigInt(sigLength)) +
|
|
569
|
-
sigClean.padEnd(sigPaddedLength * 2, "0");
|
|
570
|
-
// Compute offsets (relative to start of params, after selector)
|
|
571
|
-
const callsOffset = HEAD_WORDS * 32n;
|
|
572
|
-
const signatureOffset = callsOffset + callsEncodedBytes;
|
|
573
|
-
const data = [
|
|
574
|
-
EXECUTE_AND_CREATE_WITH_PERMIT2_SELECTOR,
|
|
575
|
-
encodeUint256(callsOffset), // 0: calls offset
|
|
576
|
-
preimageHash, // 1: preimageHash
|
|
577
|
-
token, // 2: token
|
|
578
|
-
claimAddress, // 3: claimAddress
|
|
579
|
-
timelock, // 4: timelock
|
|
580
|
-
depositor, // 5: depositor
|
|
581
|
-
permitToken, // 6: permit.permitted.token
|
|
582
|
-
permitAmount, // 7: permit.permitted.amount
|
|
583
|
-
permitNonce, // 8: permit.nonce
|
|
584
|
-
permitDeadline, // 9: permit.deadline
|
|
585
|
-
encodeUint256(signatureOffset), // 10: signature offset
|
|
586
|
-
callsEncoded, // tail: calls data
|
|
587
|
-
signatureEncoded, // tail: signature data
|
|
588
|
-
].join("");
|
|
589
|
-
return {
|
|
590
|
-
to: coordinatorAddress,
|
|
591
|
-
data,
|
|
592
|
-
functionSignature: "executeAndCreateWithPermit2((address,uint256,bytes)[],bytes32,address,address,uint256,address,((address,uint256),uint256,uint256),bytes)",
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
/**
|
|
596
|
-
* Builds the EIP-712 digest for an EIP-2612 token permit.
|
|
597
|
-
*
|
|
598
|
-
* This is the standard ERC-2612 permit signature that allows gasless
|
|
599
|
-
* token approvals. The user signs this to let `spender` (Permit2) spend
|
|
600
|
-
* their tokens without an on-chain approve transaction.
|
|
601
|
-
*
|
|
602
|
-
* @param params - The EIP-2612 permit parameters
|
|
603
|
-
* @returns The 32-byte digest as hex string with 0x prefix
|
|
604
|
-
*/
|
|
605
|
-
export function buildEip2612PermitDigest(params) {
|
|
606
|
-
const PERMIT_TYPEHASH = keccak256(stringToUtf8Bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"));
|
|
607
|
-
const structHash = keccak256(abiEncode([
|
|
608
|
-
{ type: "bytes32", value: PERMIT_TYPEHASH },
|
|
609
|
-
{ type: "address", value: params.owner },
|
|
610
|
-
{ type: "address", value: params.spender },
|
|
611
|
-
{ type: "uint256", value: params.value },
|
|
612
|
-
{ type: "uint256", value: BigInt(params.nonce) },
|
|
613
|
-
{ type: "uint256", value: params.deadline },
|
|
614
|
-
]));
|
|
615
|
-
// EIP-712 digest: 0x1901 || domainSeparator || structHash
|
|
616
|
-
const prefix = new Uint8Array([0x19, 0x01]);
|
|
617
|
-
const domainBytes = hexToBytes(params.domainSeparator);
|
|
618
|
-
const structBytes = hexToBytes(structHash);
|
|
619
|
-
const message = new Uint8Array(prefix.length + domainBytes.length + structBytes.length);
|
|
620
|
-
message.set(prefix, 0);
|
|
621
|
-
message.set(domainBytes, prefix.length);
|
|
622
|
-
message.set(structBytes, prefix.length + domainBytes.length);
|
|
623
|
-
return keccak256(message);
|
|
624
|
-
}
|
|
625
|
-
// ── Internal encoding helpers ────────────────────────────────────────────────
|
|
626
|
-
/** Encode ERC20 approve(address,uint256) call data */
|
|
627
|
-
function encodeApprove(spender, amount) {
|
|
628
|
-
const selector = "0x095ea7b3";
|
|
629
|
-
return `${selector}${normalizeAddress(spender)}${encodeUint256(amount)}`;
|
|
630
|
-
}
|
|
631
|
-
/** Encode the dynamic (address,uint256,bytes)[] array for ABI */
|
|
632
|
-
function encodeCalls(calls) {
|
|
633
|
-
// Array length
|
|
634
|
-
const length = encodeUint256(BigInt(calls.length));
|
|
635
|
-
if (calls.length === 0) {
|
|
636
|
-
return length;
|
|
637
|
-
}
|
|
638
|
-
// Each element is a tuple (address, uint256, bytes) — a dynamic type.
|
|
639
|
-
// We encode offsets first, then each element's data.
|
|
640
|
-
// Calculate offsets: each element offset is relative to the start of the array data
|
|
641
|
-
// (after the length word). First we have N offset words, then the actual data.
|
|
642
|
-
const elementDataParts = [];
|
|
643
|
-
const offsets = [];
|
|
644
|
-
// First pass: encode each element and compute sizes
|
|
645
|
-
for (const call of calls) {
|
|
646
|
-
const encoded = encodeSingleCall(call);
|
|
647
|
-
elementDataParts.push(encoded);
|
|
648
|
-
}
|
|
649
|
-
// Compute offsets: offset[0] = N * 32, offset[i] = offset[i-1] + size(element[i-1])
|
|
650
|
-
let currentOffset = BigInt(calls.length) * 32n;
|
|
651
|
-
for (let i = 0; i < calls.length; i++) {
|
|
652
|
-
offsets.push(currentOffset);
|
|
653
|
-
// Each encoded element is hex chars / 2 = bytes
|
|
654
|
-
currentOffset += BigInt(elementDataParts[i].length / 2);
|
|
655
|
-
}
|
|
656
|
-
const offsetsEncoded = offsets.map((o) => encodeUint256(o)).join("");
|
|
657
|
-
const dataEncoded = elementDataParts.join("");
|
|
658
|
-
return length + offsetsEncoded + dataEncoded;
|
|
659
|
-
}
|
|
660
|
-
/** Encode a single (address, uint256, bytes) tuple */
|
|
661
|
-
function encodeSingleCall(call) {
|
|
662
|
-
const target = normalizeAddress(call.target);
|
|
663
|
-
const value = encodeUint256(call.value);
|
|
664
|
-
// bytes is dynamic: offset (32 bytes) + length (32 bytes) + padded data
|
|
665
|
-
const bytesOffset = encodeUint256(3n * 32n); // offset after target, value, and this offset word
|
|
666
|
-
const callData = call.data.startsWith("0x") ? call.data.slice(2) : call.data;
|
|
667
|
-
const dataLength = callData.length / 2;
|
|
668
|
-
const bytesLength = encodeUint256(BigInt(dataLength));
|
|
669
|
-
// Pad data to 32-byte boundary
|
|
670
|
-
const paddedLength = Math.ceil(dataLength / 32) * 32;
|
|
671
|
-
const paddedData = callData.padEnd(paddedLength * 2, "0");
|
|
672
|
-
return target + value + bytesOffset + bytesLength + paddedData;
|
|
673
|
-
}
|
|
674
|
-
function abiEncode(values) {
|
|
675
|
-
return values
|
|
676
|
-
.map((v) => {
|
|
677
|
-
switch (v.type) {
|
|
678
|
-
case "bytes32":
|
|
679
|
-
return normalizeBytes32(v.value);
|
|
680
|
-
case "uint256":
|
|
681
|
-
return encodeUint256(v.value);
|
|
682
|
-
case "address":
|
|
683
|
-
return normalizeAddress(v.value);
|
|
684
|
-
default:
|
|
685
|
-
throw new Error(`Unknown ABI type: ${v.type}`);
|
|
686
|
-
}
|
|
687
|
-
})
|
|
688
|
-
.join("");
|
|
689
|
-
}
|
|
690
|
-
function normalizeBytes32(value) {
|
|
691
|
-
let clean = value.replace(/^0x/, "");
|
|
692
|
-
if (clean.length < 64) {
|
|
693
|
-
clean = clean.padStart(64, "0");
|
|
694
|
-
}
|
|
695
|
-
return clean.toLowerCase().slice(0, 64);
|
|
696
|
-
}
|
|
697
|
-
function normalizeAddress(address) {
|
|
698
|
-
const clean = address.replace(/^0x/, "").toLowerCase();
|
|
699
|
-
return clean.padStart(64, "0");
|
|
700
|
-
}
|
|
701
|
-
function encodeUint256(value) {
|
|
702
|
-
return value.toString(16).padStart(64, "0");
|
|
703
|
-
}
|
|
704
|
-
// ── Hex / bytes utilities ────────────────────────────────────────────────────
|
|
705
|
-
function hexToBytes(hex) {
|
|
706
|
-
return nobleFromHex(hex.replace(/^0x/, ""));
|
|
707
|
-
}
|
|
708
|
-
function bytesToHex(bytes) {
|
|
709
|
-
return nobleToHex(bytes);
|
|
710
|
-
}
|
|
711
|
-
function stringToUtf8Bytes(str) {
|
|
712
|
-
return new TextEncoder().encode(str);
|
|
713
|
-
}
|
|
714
|
-
//# sourceMappingURL=coordinator.js.map
|