@anywalletkit/protocol-swap2-core 0.10.2 → 0.11.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 +21 -0
- package/dist/{chunk-AY7DVYAN.js → chunk-HADKPUH4.js} +2 -2
- package/dist/{chunk-PN76KVPT.js → chunk-MVEAEYYJ.js} +67 -10
- package/dist/chunk-MVEAEYYJ.js.map +1 -0
- package/dist/index.cjs +66 -9
- 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 +4 -2
- package/dist/swap2/base.cjs +66 -9
- package/dist/swap2/base.cjs.map +1 -1
- package/dist/swap2/base.d.cts +60 -1
- package/dist/swap2/base.d.ts +60 -1
- package/dist/swap2/base.js +3 -1
- package/dist/swap2/single.cjs +65 -9
- package/dist/swap2/single.cjs.map +1 -1
- package/dist/swap2/single.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-PN76KVPT.js.map +0 -1
- /package/dist/{chunk-AY7DVYAN.js.map → chunk-HADKPUH4.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
|
+
NATIVE_FEE_CEILING_MAX_MULTIPLE: () => NATIVE_FEE_CEILING_MAX_MULTIPLE,
|
|
25
26
|
SLIPPAGE_ROUNDING_BPS: () => SLIPPAGE_ROUNDING_BPS,
|
|
26
27
|
SWAP2_CHAIN_ALIASES: () => SWAP2_CHAIN_ALIASES,
|
|
27
28
|
SWAP2_ID_PREFIX: () => SWAP2_ID_PREFIX,
|
|
@@ -489,17 +490,71 @@ var NATIVE_FEE_CAP = Object.freeze({
|
|
|
489
490
|
// 20 MNT (≈ $0.53 each)
|
|
490
491
|
"eip155:14": nativeUnits("eip155:14", 1500),
|
|
491
492
|
// 1500 FLR (≈ $0.0067 each)
|
|
492
|
-
"eip155:5042": nativeUnits("eip155:5042", 10)
|
|
493
|
+
"eip155:5042": nativeUnits("eip155:5042", 10),
|
|
493
494
|
// 10 USDC — Arc's gas token, in its 18-decimal native units
|
|
494
495
|
// Katana and Morph are ETH-denominated: the 0.005 ETH default applies.
|
|
496
|
+
// 2026-11-10: Elysium pays gas in HYPE (18 decimals, ≈ $74.5 on li.quest that day) — HyperEVM's 0.1 HYPE ceiling, not
|
|
497
|
+
// the ETH default (0.005 HYPE ≈ $0.37 would refuse ordinary bridge fees).
|
|
498
|
+
"eip155:99901": nativeUnits("eip155:99901", "0.1")
|
|
499
|
+
// 0.1 HYPE
|
|
495
500
|
});
|
|
496
501
|
var DEFAULT_NATIVE_FEE_CAP = 5000000000000000n;
|
|
497
|
-
|
|
502
|
+
var NATIVE_FEE_CEILING_MAX_MULTIPLE = 20n;
|
|
503
|
+
function describeCeilingAnswer(value) {
|
|
504
|
+
if (value === null) return "null";
|
|
505
|
+
if (typeof value === "bigint") return String(value);
|
|
506
|
+
if (typeof value === "string") return `the string "${value.slice(0, 40)}"`;
|
|
507
|
+
if (typeof value === "number" || typeof value === "boolean") return `the ${typeof value} ${String(value)}`;
|
|
508
|
+
if (typeof value === "function") return "a function";
|
|
509
|
+
let thenable = false;
|
|
510
|
+
try {
|
|
511
|
+
thenable = typeof value.then === "function";
|
|
512
|
+
if (thenable) value.then(void 0, () => {
|
|
513
|
+
});
|
|
514
|
+
} catch {
|
|
515
|
+
}
|
|
516
|
+
return thenable ? "a Promise (the hook must answer synchronously)" : typeof value === "object" ? "an object" : `a ${typeof value}`;
|
|
517
|
+
}
|
|
518
|
+
function nativeFeeCap(chain, fee, route) {
|
|
519
|
+
const defaultCap = NATIVE_FEE_CAP[chain] ?? DEFAULT_NATIVE_FEE_CAP;
|
|
520
|
+
const hook = route?.ceiling;
|
|
521
|
+
if (hook === void 0) return defaultCap;
|
|
522
|
+
const maxCeiling = defaultCap * NATIVE_FEE_CEILING_MAX_MULTIPLE;
|
|
523
|
+
const where = `${route.provider} ${chain} \u2192 ${route.destChain}`;
|
|
524
|
+
if (typeof hook !== "function") {
|
|
525
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling is ${describeCeilingAnswer(hook)}, not a function \u2014 the native fee of ${where} is refused`);
|
|
526
|
+
}
|
|
527
|
+
const ctx = Object.freeze({
|
|
528
|
+
provider: route.provider,
|
|
529
|
+
intentId: route.intentId,
|
|
530
|
+
fromChain: chain,
|
|
531
|
+
destChain: route.destChain,
|
|
532
|
+
nativeFee: fee,
|
|
533
|
+
defaultCap,
|
|
534
|
+
maxCeiling
|
|
535
|
+
});
|
|
536
|
+
let answer;
|
|
537
|
+
try {
|
|
538
|
+
answer = hook(ctx);
|
|
539
|
+
} catch (error) {
|
|
540
|
+
const why = (error instanceof Error ? error.message : String(error)).slice(0, 160);
|
|
541
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling threw for ${where} (${why}) \u2014 the native fee is refused`, { cause: error });
|
|
542
|
+
}
|
|
543
|
+
if (answer === void 0) return defaultCap;
|
|
544
|
+
if (typeof answer !== "bigint" || answer < 0n) {
|
|
545
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling returned ${describeCeilingAnswer(answer)} for ${where}, not a non-negative bigint or undefined \u2014 the native fee is refused`);
|
|
546
|
+
}
|
|
547
|
+
if (answer > maxCeiling) {
|
|
548
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling returned ${answer} for ${where}, above the hard maximum ${maxCeiling} (${NATIVE_FEE_CEILING_MAX_MULTIPLE} \xD7 the default cap ${defaultCap}) \u2014 the native fee is refused`);
|
|
549
|
+
}
|
|
550
|
+
return answer;
|
|
551
|
+
}
|
|
552
|
+
function declaredNativeFee(q, chain, route) {
|
|
498
553
|
const raw = q.txRequest?.nativeFee;
|
|
499
554
|
if (raw === void 0) return 0n;
|
|
500
555
|
if (!/^\d+$/.test(raw)) throw new Error("swap2: quote declares a malformed native fee");
|
|
501
556
|
const fee = BigInt(raw);
|
|
502
|
-
const cap =
|
|
557
|
+
const cap = nativeFeeCap(chain, fee, route);
|
|
503
558
|
if (fee > cap) throw new Error(`swap2: quoted native fee ${fee} exceeds the cap ${cap} for ${chain}`);
|
|
504
559
|
return fee;
|
|
505
560
|
}
|
|
@@ -1123,16 +1178,18 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1123
1178
|
const source = this.sourceAsset(executionOptions);
|
|
1124
1179
|
if (!source) throw new Error(`swap2: unknown source token '${executionOptions.fromToken}' on ${this.fromChain}`);
|
|
1125
1180
|
const executionValue = BigInt(unsigned.value);
|
|
1181
|
+
const ceiling = this._config.nativeFeeCeiling;
|
|
1182
|
+
const feeRoute = { provider: q.provider, intentId: q.intentId, destChain: params.destChain, ...ceiling !== void 0 ? { ceiling } : {} };
|
|
1126
1183
|
if (serialized) {
|
|
1127
1184
|
if (executionValue !== (source.contract ? 0n : BigInt(q.sourceAmount))) {
|
|
1128
1185
|
throw new Error("swap2: provider execution amount does not match the validated quote");
|
|
1129
1186
|
}
|
|
1130
1187
|
} else if (source.contract && this.fromChain.startsWith("eip155:")) {
|
|
1131
|
-
const declared = declaredNativeFee(q, this.fromChain);
|
|
1188
|
+
const declared = declaredNativeFee(q, this.fromChain, feeRoute);
|
|
1132
1189
|
if (executionValue !== declared) {
|
|
1133
1190
|
throw new Error(declared === 0n ? "swap2: token execution attempted to attach native value" : `swap2: token execution value ${executionValue} does not match the quoted native fee ${declared}`);
|
|
1134
1191
|
}
|
|
1135
|
-
} else if (!unsigned.typedData && !unsigned.bodyBoc && executionValue !== BigInt(q.sourceAmount) + declaredNativeFee(q, this.fromChain)) {
|
|
1192
|
+
} else if (!unsigned.typedData && !unsigned.bodyBoc && executionValue !== BigInt(q.sourceAmount) + declaredNativeFee(q, this.fromChain, feeRoute)) {
|
|
1136
1193
|
throw new Error("swap2: provider execution amount does not match the validated quote");
|
|
1137
1194
|
}
|
|
1138
1195
|
let tonBody;
|
|
@@ -1141,13 +1198,13 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1141
1198
|
throw new Swap2ValidationError(`swap2: TON cell-body build refused \u2014 ${why}`);
|
|
1142
1199
|
};
|
|
1143
1200
|
const raw = this._config.tonGasCeiling;
|
|
1144
|
-
const
|
|
1145
|
-
if (
|
|
1201
|
+
const ceiling2 = raw === void 0 ? DEFAULT_TON_GAS_CEILING : BigInt(raw);
|
|
1202
|
+
if (ceiling2 < 0n) throw new Swap2ConfigurationError("swap2: tonGasCeiling must be non-negative");
|
|
1146
1203
|
if (provider.remote === true && provider.verifiesBuilds !== true) refuse("a remote provider's cell body needs the app's own validator (remoteProvider verifyBuild)");
|
|
1147
1204
|
tonBody = readTonBody(cellBody);
|
|
1148
1205
|
const input = BigInt(q.sourceAmount);
|
|
1149
1206
|
if (source.contract) {
|
|
1150
|
-
if (executionValue >
|
|
1207
|
+
if (executionValue > ceiling2) refuse(`it attaches ${executionValue} nanoTON to a jetton transfer, more than the ${ceiling2} gas ceiling`);
|
|
1151
1208
|
const t = tonBody.jettonTransfer;
|
|
1152
1209
|
if (!t) refuse("a jetton-source body must be a jetton transfer");
|
|
1153
1210
|
if (t.amount !== input) refuse(`the jetton transfer moves ${t.amount}, not the swap's ${input}`);
|
|
@@ -1157,7 +1214,7 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
1157
1214
|
if (!own) refuse("the account cannot name its own jetton wallet (getJettonWalletAddress), so the target cannot be checked");
|
|
1158
1215
|
if (tonRawAddress(unsigned.to) !== own) refuse(`it is sent to ${unsigned.to}, not this account's ${source.symbol ?? "source"} jetton wallet`);
|
|
1159
1216
|
} else {
|
|
1160
|
-
if (executionValue < input || executionValue - input >
|
|
1217
|
+
if (executionValue < input || executionValue - input > ceiling2) refuse(`it attaches ${executionValue} nanoTON for a ${input} input, more than the ${ceiling2} gas ceiling on top`);
|
|
1161
1218
|
const pinned = provider.remote === true ? [...provider.callTargets?.(this.fromChain) ?? [], ...q.depositAddress ? [q.depositAddress] : []].map(tonRawAddress).filter((a) => !!a) : [];
|
|
1162
1219
|
if (pinned.length && !pinned.includes(tonRawAddress(unsigned.to) ?? "")) refuse(`remote provider '${q.provider}' sends it to ${unsigned.to}, which the app did not pin (remoteProvider callTargets)`);
|
|
1163
1220
|
}
|