@anywalletkit/extension-kit 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +42 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +43 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -107,6 +107,7 @@ __export(src_exports, {
|
|
|
107
107
|
earnPlanMatchers: () => earnPlanMatchers,
|
|
108
108
|
encodeApproveCalldata: () => encodeApproveCalldata,
|
|
109
109
|
evmCallMatcher: () => evmCallMatcher,
|
|
110
|
+
evmSignedCallMatcher: () => evmSignedCallMatcher,
|
|
110
111
|
executionFloor: () => executionFloor,
|
|
111
112
|
fromBase64Url: () => fromBase64Url,
|
|
112
113
|
gasLimitExcessive: () => gasLimitExcessive,
|
|
@@ -2496,6 +2497,19 @@ function evmCallMatcher(expected) {
|
|
|
2496
2497
|
const data = expected.data && expected.data !== "0x" ? lc2(expected.data) : void 0;
|
|
2497
2498
|
return (op) => op.kind === "evm-tx" && op.caip2 === expected.caip2 && lc2(op.to) === lc2(expected.to) && (op.data && op.data !== "0x" ? lc2(op.data) : void 0) === data && op.value === expected.value;
|
|
2498
2499
|
}
|
|
2500
|
+
function evmSignedCallMatcher(expected) {
|
|
2501
|
+
const base = lc2(expected.data);
|
|
2502
|
+
return (op) => {
|
|
2503
|
+
if (op.kind !== "evm-tx" || op.caip2 !== expected.caip2 || lc2(op.to) !== lc2(expected.to) || op.value !== expected.value || !op.data) return false;
|
|
2504
|
+
const data = lc2(op.data);
|
|
2505
|
+
if (!data.startsWith(base)) return false;
|
|
2506
|
+
const tail = data.slice(base.length);
|
|
2507
|
+
const word = /^0{60}([0-9a-f]{4})/.exec(tail);
|
|
2508
|
+
if (!word || !/^[0-9a-f]*$/.test(tail)) return false;
|
|
2509
|
+
const n = parseInt(word[1], 16);
|
|
2510
|
+
return n >= 64 && n <= 2048 && tail.length === 64 + 2 * n;
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2499
2513
|
function typedDataMatcher(expected) {
|
|
2500
2514
|
const hash = lc2(expected.typedDataHash);
|
|
2501
2515
|
return (op) => op.kind === "evm-typed-data" && op.caip2 === expected.caip2 && lc2(op.typedDataHash) === hash;
|
|
@@ -2647,8 +2661,14 @@ function swapApprovalPayload(plan, meta) {
|
|
|
2647
2661
|
let source;
|
|
2648
2662
|
if (s.kind === "call") {
|
|
2649
2663
|
const deposit = depositOf(s, plan.approvals.length);
|
|
2650
|
-
|
|
2664
|
+
const permit = s.permit2Transfer !== void 0 ? parsePermit2Transfer(s.permit2Transfer) : void 0;
|
|
2665
|
+
source = { kind: "call", to: s.to, ...s.data ? { data: s.data } : {}, value: s.value.toString(), ...deposit ? { deposit } : {}, ...permit ? { permit2Transfer: permit } : {} };
|
|
2651
2666
|
checks.push(deposit || assigned ? depositCheck : { status: "ok", label: `Calls the ${meta.providerLabel} contract` });
|
|
2667
|
+
if (permit) {
|
|
2668
|
+
const exact = BigInt(permit.amount) === plan.sourceAmount && lc3(permit.spender) === lc3(s.to);
|
|
2669
|
+
const minutes = Math.max(0, Math.ceil((permit.deadline * 1e3 - Date.now()) / 6e4));
|
|
2670
|
+
checks.push(exact ? { status: "ok", label: `Permit2 signature: exactly the amount sold, usable only by ${s.to.slice(0, 6)}\u2026${s.to.slice(-4)} in this swap, expires in ${minutes} min` } : { status: "warn", label: "Permit2 signature does not match this swap (amount or contract)" });
|
|
2671
|
+
}
|
|
2652
2672
|
} else if (s.kind === "token-transfer") {
|
|
2653
2673
|
source = { kind: "token-transfer", token: s.token, recipient: s.recipient, amount: s.amount.toString(), ...s.memo ? { memo: s.memo } : {} };
|
|
2654
2674
|
checks.push(depositCheck);
|
|
@@ -2661,6 +2681,7 @@ function swapApprovalPayload(plan, meta) {
|
|
|
2661
2681
|
checks.push({ status: "ok", label: "Signed order \u2014 no transaction is sent from your wallet" });
|
|
2662
2682
|
}
|
|
2663
2683
|
for (const a of plan.approvals) checks.push(a.amount > plan.sourceAmount ? { status: "warn", label: "Approval is larger than this swap needs" } : { status: "ok", label: "Approval is exactly the amount needed" });
|
|
2684
|
+
if (plan.approvals.some((a) => a.amount > 0n && lc3(a.spender) === lc3(import_protocol_swap2_core.PERMIT2_ADDRESS))) checks.push({ status: "ok", label: "Approval goes to Permit2 (shared by many apps): only the signed permit decides who can use it" });
|
|
2664
2685
|
if (plan.approvals.length > 1) checks.push({ status: "ok", label: `${plan.approvals.length} approvals (reset to 0 first)` });
|
|
2665
2686
|
checks.push(!isOwn ? { status: "warn", label: `Funds arrive at ${plan.recipient.slice(0, 6)}\u2026${plan.recipient.slice(-4)}, not your address` } : assigned ? { status: "unknown", label: `Delivery to your address is the ${meta.providerLabel} server\u2019s promise \u2014 this transaction does not enforce it` } : { status: "ok", label: "Funds arrive at your address" });
|
|
2666
2687
|
let slippage;
|
|
@@ -2691,16 +2712,34 @@ function swapApprovalPayload(plan, meta) {
|
|
|
2691
2712
|
...assigned ? { depositAssignedByProvider: true } : {}
|
|
2692
2713
|
};
|
|
2693
2714
|
}
|
|
2715
|
+
function parsePermit2Transfer(json) {
|
|
2716
|
+
const typedData = parseTypedOrder(json);
|
|
2717
|
+
const m = typedData.message;
|
|
2718
|
+
const token = m.permitted?.token;
|
|
2719
|
+
const amount = m.permitted?.amount;
|
|
2720
|
+
const deadline = m.deadline;
|
|
2721
|
+
if (typedData.primaryType !== "PermitTransferFrom" || typeof token !== "string" || typeof amount !== "string" || !/^[0-9]{1,78}$/.test(amount) || typeof m.spender !== "string" || typeof deadline !== "string" || !/^[0-9]{1,12}$/.test(deadline)) {
|
|
2722
|
+
throw new Error("The swap's Permit2 transfer is not a PermitTransferFrom.");
|
|
2723
|
+
}
|
|
2724
|
+
return { typedData, text: JSON.stringify(typedData, null, 2), token, amount, spender: m.spender, deadline: Number(deadline) };
|
|
2725
|
+
}
|
|
2694
2726
|
function parseTypedOrder(json) {
|
|
2695
2727
|
const t = JSON.parse(json);
|
|
2696
2728
|
if (!t || typeof t !== "object" || !t.domain || typeof t.domain !== "object" || !t.types || typeof t.types !== "object" || !t.message || typeof t.message !== "object") throw new Error("The swap order is not EIP-712 typed data.");
|
|
2697
2729
|
return t;
|
|
2698
2730
|
}
|
|
2699
2731
|
function planMatchers(plan) {
|
|
2700
|
-
const m =
|
|
2732
|
+
const m = [];
|
|
2701
2733
|
const s = plan.source;
|
|
2734
|
+
const permit = s.kind === "call" && s.permit2Transfer !== void 0 && plan.fromChain.startsWith("eip155:");
|
|
2735
|
+
if (permit) {
|
|
2736
|
+
if (!s.data) throw new Error("A Permit2 swap plan carries no calldata.");
|
|
2737
|
+
m.push(typedDataMatcher({ caip2: plan.fromChain, typedDataHash: (0, import_wallet_evm.typedDataHash)(parsePermit2Transfer(s.permit2Transfer).typedData) }));
|
|
2738
|
+
}
|
|
2739
|
+
m.push(...plan.approvals.map((a) => evmCallMatcher({ caip2: plan.fromChain, to: a.token, data: encodeApproveCalldata(a.spender, a.amount), value: 0n })));
|
|
2702
2740
|
if (s.kind === "call") {
|
|
2703
|
-
if (
|
|
2741
|
+
if (permit) m.push(evmSignedCallMatcher({ caip2: plan.fromChain, to: s.to, data: s.data, value: s.value }));
|
|
2742
|
+
else if (plan.fromChain.startsWith("eip155:")) m.push(evmCallMatcher({ caip2: plan.fromChain, to: s.to, data: s.data, value: s.value }));
|
|
2704
2743
|
else if (plan.fromChain.startsWith("solana:")) m.push((op) => op.kind === "solana-tx" && op.to === s.to && op.value === s.value);
|
|
2705
2744
|
else m.push(chainTxMatcher({ chain: plan.fromChain, to: s.to, amount: s.value, memo: s.memo }));
|
|
2706
2745
|
} else if (s.kind === "token-transfer") {
|