@anywalletkit/protocol-swap2-core 0.9.0 → 0.10.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/README.md +1 -1
- package/dist/{chunk-REWM3GRK.js → chunk-AY7DVYAN.js} +3 -3
- package/dist/{chunk-ZEN2IXRC.js → chunk-F5TRF52T.js} +9 -3
- package/dist/chunk-F5TRF52T.js.map +1 -0
- package/dist/{chunk-PU5NM3Y6.js → chunk-PN76KVPT.js} +57 -12
- package/dist/chunk-PN76KVPT.js.map +1 -0
- package/dist/index.cjs +61 -13
- 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 +7 -3
- package/dist/server.cjs +13 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +8 -2
- package/dist/server.js.map +1 -1
- package/dist/swap2/base.cjs +56 -11
- package/dist/swap2/base.cjs.map +1 -1
- package/dist/swap2/base.d.cts +18 -0
- package/dist/swap2/base.d.ts +18 -0
- package/dist/swap2/base.js +2 -1
- package/dist/swap2/single.cjs +117 -71
- package/dist/swap2/single.cjs.map +1 -1
- package/dist/swap2/single.js +3 -3
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +13 -0
- package/dist/types.d.ts +13 -0
- package/dist/validate.cjs +8 -2
- package/dist/validate.cjs.map +1 -1
- package/dist/validate.d.cts +10 -1
- package/dist/validate.d.ts +10 -1
- package/dist/validate.js +5 -1
- package/package.json +5 -5
- package/dist/chunk-PU5NM3Y6.js.map +0 -1
- package/dist/chunk-ZEN2IXRC.js.map +0 -1
- /package/dist/{chunk-REWM3GRK.js.map → chunk-AY7DVYAN.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
BaseSwap2Protocol: () => BaseSwap2Protocol,
|
|
24
24
|
NATIVE_DECIMALS: () => NATIVE_DECIMALS,
|
|
25
|
+
SLIPPAGE_ROUNDING_BPS: () => SLIPPAGE_ROUNDING_BPS,
|
|
25
26
|
SWAP2_CHAIN_ALIASES: () => SWAP2_CHAIN_ALIASES,
|
|
26
27
|
SWAP2_ID_PREFIX: () => SWAP2_ID_PREFIX,
|
|
27
28
|
SingleProviderSwap2: () => SingleProviderSwap2,
|
|
@@ -55,6 +56,7 @@ __export(src_exports, {
|
|
|
55
56
|
remoteProvider: () => remoteProvider,
|
|
56
57
|
shortAddress: () => shortAddress,
|
|
57
58
|
slippageClassOf: () => slippageClassOf,
|
|
59
|
+
slippageFloor: () => slippageFloor,
|
|
58
60
|
sourceAssetOf: () => sourceAssetOf,
|
|
59
61
|
suggestSlippage: () => suggestSlippage,
|
|
60
62
|
swap2ChainId: () => swap2ChainId,
|
|
@@ -122,6 +124,11 @@ var Swap2MaybeSentError = class extends Swap2ExecutionError {
|
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
// src/validate.ts
|
|
127
|
+
var SLIPPAGE_ROUNDING_BPS = 1;
|
|
128
|
+
function slippageFloor(dest, slippageBps) {
|
|
129
|
+
const keep = 1e4 - slippageBps - SLIPPAGE_ROUNDING_BPS;
|
|
130
|
+
return keep <= 0 ? 0n : dest * BigInt(keep) / 10000n;
|
|
131
|
+
}
|
|
125
132
|
function validQuote(q, params, provider) {
|
|
126
133
|
try {
|
|
127
134
|
if (q.provider !== provider || q.sourceAmount !== params.amountIn) return false;
|
|
@@ -136,8 +143,7 @@ function validQuote(q, params, provider) {
|
|
|
136
143
|
}
|
|
137
144
|
if (params.slippageBps !== void 0) {
|
|
138
145
|
if (!Number.isInteger(params.slippageBps) || params.slippageBps < 0 || params.slippageBps >= 1e4) return false;
|
|
139
|
-
|
|
140
|
-
if (min < required) return false;
|
|
146
|
+
if (min < slippageFloor(dest, params.slippageBps)) return false;
|
|
141
147
|
}
|
|
142
148
|
if (!Number.isFinite(q.etaSeconds) || q.etaSeconds < 0) return false;
|
|
143
149
|
if (!Number.isFinite(q.reliability) || q.reliability < 0 || q.reliability > 1) return false;
|
|
@@ -571,16 +577,18 @@ function reviewedIdentity(plan) {
|
|
|
571
577
|
return JSON.stringify(pinned, (_k, v) => typeof v === "bigint" ? v.toString() : v);
|
|
572
578
|
}
|
|
573
579
|
var SWAP2_ID_PREFIX = "awk1";
|
|
574
|
-
|
|
580
|
+
var CONFIRMED_SEGMENT = "ok";
|
|
581
|
+
function encodeId(provider, intentId, sourceTxHash, destTxHash, destTxConfirmed = false) {
|
|
575
582
|
const enc = (v) => encodeURIComponent(v).replace(/\./g, "%2E");
|
|
576
|
-
const
|
|
583
|
+
const dest = destTxHash != null ? [destTxHash, ...destTxConfirmed ? [CONFIRMED_SEGMENT] : []] : [];
|
|
584
|
+
const parts = [provider, intentId, ...sourceTxHash != null ? [sourceTxHash, ...dest] : []];
|
|
577
585
|
return `${SWAP2_ID_PREFIX}.${parts.map(enc).join(".")}`;
|
|
578
586
|
}
|
|
579
587
|
function decodeId(id) {
|
|
580
588
|
try {
|
|
581
589
|
if (!id.startsWith(`${SWAP2_ID_PREFIX}.`)) throw new Error("unsupported id version");
|
|
582
590
|
const parts = id.slice(SWAP2_ID_PREFIX.length + 1).split(".");
|
|
583
|
-
if (parts.length < 2 || parts.length >
|
|
591
|
+
if (parts.length < 2 || parts.length > 5 || !parts[0] || !parts[1]) throw new Error("invalid id shape");
|
|
584
592
|
const provider = decodeURIComponent(parts[0]);
|
|
585
593
|
const intentId = decodeURIComponent(parts[1]);
|
|
586
594
|
const sourceTxHash = parts[2] ? decodeURIComponent(parts[2]) : void 0;
|
|
@@ -588,7 +596,8 @@ function decodeId(id) {
|
|
|
588
596
|
if (!/^[A-Za-z0-9_-]+$/.test(provider) || !intentId || parts[2] !== void 0 && !sourceTxHash || parts[3] !== void 0 && !destTxHash) {
|
|
589
597
|
throw new Error("invalid id contents");
|
|
590
598
|
}
|
|
591
|
-
|
|
599
|
+
if (parts[4] !== void 0 && parts[4] !== CONFIRMED_SEGMENT) throw new Error("invalid id contents");
|
|
600
|
+
return { provider, intentId, ...sourceTxHash ? { sourceTxHash } : {}, ...destTxHash ? { destTxHash } : {}, ...parts[4] !== void 0 ? { destTxConfirmed: true } : {} };
|
|
592
601
|
} catch {
|
|
593
602
|
throw new Swap2ValidationError("swap2: malformed swap2 status id");
|
|
594
603
|
}
|
|
@@ -721,13 +730,30 @@ function assertQuoteConstraints(q, options) {
|
|
|
721
730
|
}
|
|
722
731
|
if (options.slippage !== void 0) {
|
|
723
732
|
const scale = 1000000000n;
|
|
724
|
-
const permitted = BigInt(floorScaled(options.slippage, 1e9));
|
|
725
|
-
const required = nominal * (scale - permitted) / scale;
|
|
733
|
+
const permitted = BigInt(floorScaled(options.slippage, 1e9)) + BigInt(SLIPPAGE_ROUNDING_BPS) * 100000n;
|
|
734
|
+
const required = permitted >= scale ? 0n : nominal * (scale - permitted) / scale;
|
|
726
735
|
if (guaranteed < required) {
|
|
727
736
|
throw new Error(`swap2: quote exceeds caller slippage (${options.slippage})`);
|
|
728
737
|
}
|
|
729
738
|
}
|
|
730
739
|
}
|
|
740
|
+
function bridgeOutOf(params, q, toTokenDecimals) {
|
|
741
|
+
let decimals = (0, import_swap2_assets2.resolveAsset)(params.destChain, params.destToken)?.decimals;
|
|
742
|
+
if (decimals === void 0 && toTokenDecimals !== void 0) {
|
|
743
|
+
if (q.destDecimals !== void 0 && q.destDecimals !== toTokenDecimals) {
|
|
744
|
+
throw new Swap2ValidationError(`swap2: the quote's destDecimals ${q.destDecimals} do not match toTokenDecimals ${toTokenDecimals}`);
|
|
745
|
+
}
|
|
746
|
+
decimals = toTokenDecimals;
|
|
747
|
+
}
|
|
748
|
+
return {
|
|
749
|
+
destChain: params.destChain,
|
|
750
|
+
recipient: params.destAddress,
|
|
751
|
+
destToken: params.destToken,
|
|
752
|
+
minAmountOut: q.minDestAmount,
|
|
753
|
+
...decimals !== void 0 ? { destDecimals: decimals } : {},
|
|
754
|
+
...params.slippageBps !== void 0 ? { slippageBps: params.slippageBps } : {}
|
|
755
|
+
};
|
|
756
|
+
}
|
|
731
757
|
function requireExecutionFloor(options) {
|
|
732
758
|
if (options.minAmountOut === void 0) {
|
|
733
759
|
throw new Error("swap2: swap2() requires caller-supplied minAmountOut");
|
|
@@ -826,6 +852,10 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
826
852
|
}
|
|
827
853
|
const destChain = toCaip2(options.toChain, this.fromChain);
|
|
828
854
|
const constraints = callerConstraints(options);
|
|
855
|
+
const toDecimals = options.toTokenDecimals;
|
|
856
|
+
if (toDecimals !== void 0 && (!Number.isInteger(toDecimals) || toDecimals < 0 || toDecimals > 36)) {
|
|
857
|
+
throw new Swap2ValidationError("swap2: toTokenDecimals must be whole decimals in 0..36");
|
|
858
|
+
}
|
|
829
859
|
const amountIn = exactPositiveAmount(options.fromTokenAmount, "fromTokenAmount");
|
|
830
860
|
const source = this.sourceAsset(options);
|
|
831
861
|
const params = {
|
|
@@ -1355,7 +1385,8 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1355
1385
|
maxValueOut: ((source.contract ? 0n : BigInt(q.sourceAmount)) + allowance).toString(),
|
|
1356
1386
|
// Only a same-chain swap lands in this account; a bridge delivers elsewhere.
|
|
1357
1387
|
...params.destChain === this.fromChain ? { tokenIn: { token: params.destToken, minAmount: q.minDestAmount } } : {},
|
|
1358
|
-
...source.contract ? { source: { token: source.contract, maxAmount: q.sourceAmount } } : {}
|
|
1388
|
+
...source.contract ? { source: { token: source.contract, maxAmount: q.sourceAmount } } : {},
|
|
1389
|
+
...params.destChain !== this.fromChain ? { bridgeOut: bridgeOutOf(params, q, executionOptions.toTokenDecimals) } : {}
|
|
1359
1390
|
};
|
|
1360
1391
|
sent = await signer.sendSerializedTransaction(unsigned.serializedTx, expect);
|
|
1361
1392
|
} else if (tokenId) {
|
|
@@ -1439,10 +1470,10 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1439
1470
|
}
|
|
1440
1471
|
/** Status of a swap by the id `swap2()` returned, asked from the provider that executed it. */
|
|
1441
1472
|
async getSwap2Status(id, _options) {
|
|
1442
|
-
const { provider: name, intentId, sourceTxHash, destTxHash } = decodeId(id);
|
|
1473
|
+
const { provider: name, intentId, sourceTxHash, destTxHash, destTxConfirmed } = decodeId(id);
|
|
1443
1474
|
const provider = this.providerFor(name);
|
|
1444
1475
|
if (!provider) throw new Error(`swap2: no swap2 found for id '${id}'`);
|
|
1445
|
-
return mapStatus(await provider.trackIntent({ intentId, ...sourceTxHash != null ? { sourceTxHash } : {}, ...destTxHash != null ? { destTxHash } : {} }));
|
|
1476
|
+
return mapStatus(await provider.trackIntent({ intentId, ...sourceTxHash != null ? { sourceTxHash } : {}, ...destTxHash != null ? { destTxHash, ...destTxConfirmed ? { destTxConfirmed } : {} } : {} }));
|
|
1446
1477
|
}
|
|
1447
1478
|
/**
|
|
1448
1479
|
* Two-phase routes (CCTP-style burn-and-mint): once `getSwap2Status` reports
|
|
@@ -1515,7 +1546,21 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1515
1546
|
});
|
|
1516
1547
|
if (!sent.hash) throw new Swap2ExecutionError("swap2: account did not return a claim transaction hash");
|
|
1517
1548
|
this.emitPhase("broadcast", { hash: sent.hash });
|
|
1518
|
-
|
|
1549
|
+
let confirmed = false;
|
|
1550
|
+
if (typeof signer.waitForTransaction === "function") {
|
|
1551
|
+
try {
|
|
1552
|
+
await signer.waitForTransaction(sent.hash);
|
|
1553
|
+
confirmed = true;
|
|
1554
|
+
} catch (e) {
|
|
1555
|
+
const err = e;
|
|
1556
|
+
const timedOut = /timeout|timed out/i.test(String(err?.name ?? "")) || /timed out|timeout/i.test(String(err?.message ?? ""));
|
|
1557
|
+
const reverted = err?.code === "reverted" || !timedOut && /\breverted\b/i.test(String(err?.message ?? ""));
|
|
1558
|
+
if (reverted) {
|
|
1559
|
+
throw new Swap2ExecutionError(`swap2: the claim transaction ${sent.hash} on ${unsigned.chain} reverted \u2014 poll the status of '${id}' and claim again if it is still action-required`, { cause: e });
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return { hash: sent.hash, chain: unsigned.chain, id: encodeId(name, intentId, sourceTxHash, sent.hash, confirmed) };
|
|
1519
1564
|
}
|
|
1520
1565
|
/** The inherited bridge() has no floor field: quote first, then bind execution
|
|
1521
1566
|
* to that quote's minimum so the inherited convenience API stays safe. */
|
|
@@ -1592,7 +1637,10 @@ function structuredCloneSafe(value) {
|
|
|
1592
1637
|
if (value === null || typeof value !== "object") return value;
|
|
1593
1638
|
if (Array.isArray(value)) return value.map((v) => structuredCloneSafe(v));
|
|
1594
1639
|
const out = {};
|
|
1595
|
-
for (const [k, v] of Object.entries(value))
|
|
1640
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1641
|
+
if (k === "__proto__") Object.defineProperty(out, k, { value: structuredCloneSafe(v), writable: true, enumerable: true, configurable: true });
|
|
1642
|
+
else out[k] = structuredCloneSafe(v);
|
|
1643
|
+
}
|
|
1596
1644
|
return out;
|
|
1597
1645
|
}
|
|
1598
1646
|
function deepFreeze(value) {
|