@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/swap2/base.d.cts
CHANGED
|
@@ -45,6 +45,35 @@ declare const NATIVE_DECIMALS: Readonly<Record<string, number>>;
|
|
|
45
45
|
declare function nativeDecimals(chain: string): number;
|
|
46
46
|
/** `whole` native coins (an integer, or a decimal string such as "0.005") in `chain`'s base units. */
|
|
47
47
|
declare function nativeUnits(chain: string, whole: number | string): bigint;
|
|
48
|
+
/**
|
|
49
|
+
* The hard maximum of {@link Swap2EngineConfig.nativeFeeCeiling}: it may name at most this many times the chain's
|
|
50
|
+
* default cap (0.1 ETH on Ethereum and the ETH-denominated L2s, 2000 CELO on Celo). A value above it is refused, so a
|
|
51
|
+
* units slip (wei for gwei, an extra zero) or a "no limit" sentinel cannot switch the ceiling off.
|
|
52
|
+
*/
|
|
53
|
+
declare const NATIVE_FEE_CEILING_MAX_MULTIPLE = 20n;
|
|
54
|
+
/** What {@link Swap2EngineConfig.nativeFeeCeiling} is asked about: the native fee one execution's quote declares. */
|
|
55
|
+
interface Swap2NativeFeeCeilingContext {
|
|
56
|
+
/**
|
|
57
|
+
* The provider the route came from, e.g. `"usdt0"`: the name it is installed under (the router binds every quote to
|
|
58
|
+
* its provider's name, so a quote cannot claim another venue's).
|
|
59
|
+
*/
|
|
60
|
+
readonly provider: string;
|
|
61
|
+
/**
|
|
62
|
+
* The quote's intent id as the provider wrote it, e.g. `"usdt0-mesh:30101:30420"` (USDT0 Legacy Mesh, Ethereum →
|
|
63
|
+
* Tron). Through a swap2 server (`remoteProvider`) it ends in `~<token>`: match its start.
|
|
64
|
+
*/
|
|
65
|
+
readonly intentId: string;
|
|
66
|
+
/** CAIP-2 of the source chain, where the fee is paid (`"eip155:1"`). */
|
|
67
|
+
readonly fromChain: string;
|
|
68
|
+
/** CAIP-2 of the destination in the catalog form: Tron is `"tron:728126428"` whichever form the app passed. */
|
|
69
|
+
readonly destChain: string;
|
|
70
|
+
/** The native fee the quote declares, in base units of the source chain's native coin. */
|
|
71
|
+
readonly nativeFee: bigint;
|
|
72
|
+
/** The engine's own cap for `fromChain`: what applies when the hook returns `undefined`. */
|
|
73
|
+
readonly defaultCap: bigint;
|
|
74
|
+
/** The most the hook may return: {@link NATIVE_FEE_CEILING_MAX_MULTIPLE} × `defaultCap`. */
|
|
75
|
+
readonly maxCeiling: bigint;
|
|
76
|
+
}
|
|
48
77
|
type Swap2ExecutionPhase = "approving" | "requoting" | "preflight" | "signing" | "broadcast";
|
|
49
78
|
interface Swap2ExecutionPhaseDetail {
|
|
50
79
|
/** approving: which approval of how many (USDT on Ethereum needs two). */
|
|
@@ -85,6 +114,36 @@ interface Swap2EngineConfig extends Swap2ProtocolConfig {
|
|
|
85
114
|
* refused (scan 2026-10-27 modules, F7).
|
|
86
115
|
*/
|
|
87
116
|
tonGasCeiling?: bigint | number | string;
|
|
117
|
+
/**
|
|
118
|
+
* The app's native-fee ceiling for a route. A route may charge native coin on top of the input (a bridge's messaging
|
|
119
|
+
* fee, declared by the quote); the engine refuses a fee above its per-chain cap (0.005 ETH on Ethereum and on chains
|
|
120
|
+
* without a row, 100 CELO on Celo, …). This hook is asked for every execution pass whose quote declares a native fee, before
|
|
121
|
+
* that pass's review and approvals (once, unless the quote expires during an approval and the engine re-quotes: the
|
|
122
|
+
* fresh quote is asked again; a refusal then revokes the allowance just granted):
|
|
123
|
+
*
|
|
124
|
+
* - a non-negative `bigint` is the cap for that execution, in place of the chain's own (higher or lower; `0n` refuses
|
|
125
|
+
* any fee). It may be at most {@link NATIVE_FEE_CEILING_MAX_MULTIPLE} × the chain's cap (`ctx.maxCeiling`);
|
|
126
|
+
* - `undefined` keeps the chain's cap, exactly as without the hook;
|
|
127
|
+
* - anything else (a number, a string, `null`, a Promise), a value above `ctx.maxCeiling`, or a throw refuses the
|
|
128
|
+
* execution (`Swap2ConfigurationError`). There is no answer that removes the cap. The option itself is a function or
|
|
129
|
+
* left out: any other value (`null` included) refuses every execution that declares a native fee.
|
|
130
|
+
*
|
|
131
|
+
* Route policy is the app's: match the provider, the destination and the intent id, and leave every other route to
|
|
132
|
+
* the default. USDT0 Legacy Mesh into Tron (LayerZero eid 30420; its fee, 0.0053 ETH / 170 CELO on 2026-11-12 plus
|
|
133
|
+
* the provider's 25 % headroom, is above the default caps):
|
|
134
|
+
*
|
|
135
|
+
* ```ts
|
|
136
|
+
* const TRON_MESH = new Map([["eip155:1", 10n ** 16n], ["eip155:42161", 10n ** 16n], ["eip155:42220", 300n * 10n ** 18n]]);
|
|
137
|
+
* nativeFeeCeiling: ({provider, intentId, fromChain, destChain}) =>
|
|
138
|
+
* provider === "usdt0" && destChain === "tron:728126428" && /^usdt0-mesh:\d+:30420(?:~|$)/.test(intentId)
|
|
139
|
+
* ? TRON_MESH.get(fromChain) // 0.01 ETH on Ethereum and Arbitrum, 300 CELO on Celo; other sources: the default
|
|
140
|
+
* : undefined
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Only execution (`swap2()`) applies a native-fee cap: `quoteSwap2` and the router's route list do not check one, so
|
|
144
|
+
* they list a route whose fee is above the cap, and its `swap2()` refuses it.
|
|
145
|
+
*/
|
|
146
|
+
nativeFeeCeiling?: (ctx: Swap2NativeFeeCeilingContext) => bigint | undefined;
|
|
88
147
|
/**
|
|
89
148
|
* Review gate: called once the live quote is built and every payload/value
|
|
90
149
|
* check has passed, BEFORE any approval or signature. It receives a copy of
|
|
@@ -326,4 +385,4 @@ declare abstract class BaseSwap2Protocol extends Swap2Protocol {
|
|
|
326
385
|
getSupportedTokens(options?: Swap2SupportedTokensOptions): Promise<Swap2SupportedToken[]>;
|
|
327
386
|
}
|
|
328
387
|
|
|
329
|
-
export { BaseSwap2Protocol, NATIVE_DECIMALS, SWAP2_CHAIN_ALIASES, SWAP2_ID_PREFIX, type SerializedExecutionExpectation, type Swap2Account, type Swap2EngineConfig, type Swap2ExecutionPhase, type Swap2ExecutionPhaseDetail, type Swap2ExecutionPlan, type TonBodySummary, nativeDecimals, nativeUnits, normalizeTypedDomain, swap2ChainId };
|
|
388
|
+
export { BaseSwap2Protocol, NATIVE_DECIMALS, NATIVE_FEE_CEILING_MAX_MULTIPLE, SWAP2_CHAIN_ALIASES, SWAP2_ID_PREFIX, type SerializedExecutionExpectation, type Swap2Account, type Swap2EngineConfig, type Swap2ExecutionPhase, type Swap2ExecutionPhaseDetail, type Swap2ExecutionPlan, type Swap2NativeFeeCeilingContext, type TonBodySummary, nativeDecimals, nativeUnits, normalizeTypedDomain, swap2ChainId };
|
package/dist/swap2/base.d.ts
CHANGED
|
@@ -45,6 +45,35 @@ declare const NATIVE_DECIMALS: Readonly<Record<string, number>>;
|
|
|
45
45
|
declare function nativeDecimals(chain: string): number;
|
|
46
46
|
/** `whole` native coins (an integer, or a decimal string such as "0.005") in `chain`'s base units. */
|
|
47
47
|
declare function nativeUnits(chain: string, whole: number | string): bigint;
|
|
48
|
+
/**
|
|
49
|
+
* The hard maximum of {@link Swap2EngineConfig.nativeFeeCeiling}: it may name at most this many times the chain's
|
|
50
|
+
* default cap (0.1 ETH on Ethereum and the ETH-denominated L2s, 2000 CELO on Celo). A value above it is refused, so a
|
|
51
|
+
* units slip (wei for gwei, an extra zero) or a "no limit" sentinel cannot switch the ceiling off.
|
|
52
|
+
*/
|
|
53
|
+
declare const NATIVE_FEE_CEILING_MAX_MULTIPLE = 20n;
|
|
54
|
+
/** What {@link Swap2EngineConfig.nativeFeeCeiling} is asked about: the native fee one execution's quote declares. */
|
|
55
|
+
interface Swap2NativeFeeCeilingContext {
|
|
56
|
+
/**
|
|
57
|
+
* The provider the route came from, e.g. `"usdt0"`: the name it is installed under (the router binds every quote to
|
|
58
|
+
* its provider's name, so a quote cannot claim another venue's).
|
|
59
|
+
*/
|
|
60
|
+
readonly provider: string;
|
|
61
|
+
/**
|
|
62
|
+
* The quote's intent id as the provider wrote it, e.g. `"usdt0-mesh:30101:30420"` (USDT0 Legacy Mesh, Ethereum →
|
|
63
|
+
* Tron). Through a swap2 server (`remoteProvider`) it ends in `~<token>`: match its start.
|
|
64
|
+
*/
|
|
65
|
+
readonly intentId: string;
|
|
66
|
+
/** CAIP-2 of the source chain, where the fee is paid (`"eip155:1"`). */
|
|
67
|
+
readonly fromChain: string;
|
|
68
|
+
/** CAIP-2 of the destination in the catalog form: Tron is `"tron:728126428"` whichever form the app passed. */
|
|
69
|
+
readonly destChain: string;
|
|
70
|
+
/** The native fee the quote declares, in base units of the source chain's native coin. */
|
|
71
|
+
readonly nativeFee: bigint;
|
|
72
|
+
/** The engine's own cap for `fromChain`: what applies when the hook returns `undefined`. */
|
|
73
|
+
readonly defaultCap: bigint;
|
|
74
|
+
/** The most the hook may return: {@link NATIVE_FEE_CEILING_MAX_MULTIPLE} × `defaultCap`. */
|
|
75
|
+
readonly maxCeiling: bigint;
|
|
76
|
+
}
|
|
48
77
|
type Swap2ExecutionPhase = "approving" | "requoting" | "preflight" | "signing" | "broadcast";
|
|
49
78
|
interface Swap2ExecutionPhaseDetail {
|
|
50
79
|
/** approving: which approval of how many (USDT on Ethereum needs two). */
|
|
@@ -85,6 +114,36 @@ interface Swap2EngineConfig extends Swap2ProtocolConfig {
|
|
|
85
114
|
* refused (scan 2026-10-27 modules, F7).
|
|
86
115
|
*/
|
|
87
116
|
tonGasCeiling?: bigint | number | string;
|
|
117
|
+
/**
|
|
118
|
+
* The app's native-fee ceiling for a route. A route may charge native coin on top of the input (a bridge's messaging
|
|
119
|
+
* fee, declared by the quote); the engine refuses a fee above its per-chain cap (0.005 ETH on Ethereum and on chains
|
|
120
|
+
* without a row, 100 CELO on Celo, …). This hook is asked for every execution pass whose quote declares a native fee, before
|
|
121
|
+
* that pass's review and approvals (once, unless the quote expires during an approval and the engine re-quotes: the
|
|
122
|
+
* fresh quote is asked again; a refusal then revokes the allowance just granted):
|
|
123
|
+
*
|
|
124
|
+
* - a non-negative `bigint` is the cap for that execution, in place of the chain's own (higher or lower; `0n` refuses
|
|
125
|
+
* any fee). It may be at most {@link NATIVE_FEE_CEILING_MAX_MULTIPLE} × the chain's cap (`ctx.maxCeiling`);
|
|
126
|
+
* - `undefined` keeps the chain's cap, exactly as without the hook;
|
|
127
|
+
* - anything else (a number, a string, `null`, a Promise), a value above `ctx.maxCeiling`, or a throw refuses the
|
|
128
|
+
* execution (`Swap2ConfigurationError`). There is no answer that removes the cap. The option itself is a function or
|
|
129
|
+
* left out: any other value (`null` included) refuses every execution that declares a native fee.
|
|
130
|
+
*
|
|
131
|
+
* Route policy is the app's: match the provider, the destination and the intent id, and leave every other route to
|
|
132
|
+
* the default. USDT0 Legacy Mesh into Tron (LayerZero eid 30420; its fee, 0.0053 ETH / 170 CELO on 2026-11-12 plus
|
|
133
|
+
* the provider's 25 % headroom, is above the default caps):
|
|
134
|
+
*
|
|
135
|
+
* ```ts
|
|
136
|
+
* const TRON_MESH = new Map([["eip155:1", 10n ** 16n], ["eip155:42161", 10n ** 16n], ["eip155:42220", 300n * 10n ** 18n]]);
|
|
137
|
+
* nativeFeeCeiling: ({provider, intentId, fromChain, destChain}) =>
|
|
138
|
+
* provider === "usdt0" && destChain === "tron:728126428" && /^usdt0-mesh:\d+:30420(?:~|$)/.test(intentId)
|
|
139
|
+
* ? TRON_MESH.get(fromChain) // 0.01 ETH on Ethereum and Arbitrum, 300 CELO on Celo; other sources: the default
|
|
140
|
+
* : undefined
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Only execution (`swap2()`) applies a native-fee cap: `quoteSwap2` and the router's route list do not check one, so
|
|
144
|
+
* they list a route whose fee is above the cap, and its `swap2()` refuses it.
|
|
145
|
+
*/
|
|
146
|
+
nativeFeeCeiling?: (ctx: Swap2NativeFeeCeilingContext) => bigint | undefined;
|
|
88
147
|
/**
|
|
89
148
|
* Review gate: called once the live quote is built and every payload/value
|
|
90
149
|
* check has passed, BEFORE any approval or signature. It receives a copy of
|
|
@@ -326,4 +385,4 @@ declare abstract class BaseSwap2Protocol extends Swap2Protocol {
|
|
|
326
385
|
getSupportedTokens(options?: Swap2SupportedTokensOptions): Promise<Swap2SupportedToken[]>;
|
|
327
386
|
}
|
|
328
387
|
|
|
329
|
-
export { BaseSwap2Protocol, NATIVE_DECIMALS, SWAP2_CHAIN_ALIASES, SWAP2_ID_PREFIX, type SerializedExecutionExpectation, type Swap2Account, type Swap2EngineConfig, type Swap2ExecutionPhase, type Swap2ExecutionPhaseDetail, type Swap2ExecutionPlan, type TonBodySummary, nativeDecimals, nativeUnits, normalizeTypedDomain, swap2ChainId };
|
|
388
|
+
export { BaseSwap2Protocol, NATIVE_DECIMALS, NATIVE_FEE_CEILING_MAX_MULTIPLE, SWAP2_CHAIN_ALIASES, SWAP2_ID_PREFIX, type SerializedExecutionExpectation, type Swap2Account, type Swap2EngineConfig, type Swap2ExecutionPhase, type Swap2ExecutionPhaseDetail, type Swap2ExecutionPlan, type Swap2NativeFeeCeilingContext, type TonBodySummary, nativeDecimals, nativeUnits, normalizeTypedDomain, swap2ChainId };
|
package/dist/swap2/base.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BaseSwap2Protocol,
|
|
3
3
|
NATIVE_DECIMALS,
|
|
4
|
+
NATIVE_FEE_CEILING_MAX_MULTIPLE,
|
|
4
5
|
SWAP2_CHAIN_ALIASES,
|
|
5
6
|
SWAP2_ID_PREFIX,
|
|
6
7
|
nativeDecimals,
|
|
7
8
|
nativeUnits,
|
|
8
9
|
normalizeTypedDomain,
|
|
9
10
|
swap2ChainId
|
|
10
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-MVEAEYYJ.js";
|
|
11
12
|
import "../chunk-IVR3SREQ.js";
|
|
12
13
|
import "../chunk-F5TRF52T.js";
|
|
13
14
|
import "../chunk-2KC734UX.js";
|
|
14
15
|
export {
|
|
15
16
|
BaseSwap2Protocol,
|
|
16
17
|
NATIVE_DECIMALS,
|
|
18
|
+
NATIVE_FEE_CEILING_MAX_MULTIPLE,
|
|
17
19
|
SWAP2_CHAIN_ALIASES,
|
|
18
20
|
SWAP2_ID_PREFIX,
|
|
19
21
|
nativeDecimals,
|
package/dist/swap2/single.cjs
CHANGED
|
@@ -286,17 +286,71 @@ var NATIVE_FEE_CAP = Object.freeze({
|
|
|
286
286
|
// 20 MNT (≈ $0.53 each)
|
|
287
287
|
"eip155:14": nativeUnits("eip155:14", 1500),
|
|
288
288
|
// 1500 FLR (≈ $0.0067 each)
|
|
289
|
-
"eip155:5042": nativeUnits("eip155:5042", 10)
|
|
289
|
+
"eip155:5042": nativeUnits("eip155:5042", 10),
|
|
290
290
|
// 10 USDC — Arc's gas token, in its 18-decimal native units
|
|
291
291
|
// Katana and Morph are ETH-denominated: the 0.005 ETH default applies.
|
|
292
|
+
// 2026-11-10: Elysium pays gas in HYPE (18 decimals, ≈ $74.5 on li.quest that day) — HyperEVM's 0.1 HYPE ceiling, not
|
|
293
|
+
// the ETH default (0.005 HYPE ≈ $0.37 would refuse ordinary bridge fees).
|
|
294
|
+
"eip155:99901": nativeUnits("eip155:99901", "0.1")
|
|
295
|
+
// 0.1 HYPE
|
|
292
296
|
});
|
|
293
297
|
var DEFAULT_NATIVE_FEE_CAP = 5000000000000000n;
|
|
294
|
-
|
|
298
|
+
var NATIVE_FEE_CEILING_MAX_MULTIPLE = 20n;
|
|
299
|
+
function describeCeilingAnswer(value) {
|
|
300
|
+
if (value === null) return "null";
|
|
301
|
+
if (typeof value === "bigint") return String(value);
|
|
302
|
+
if (typeof value === "string") return `the string "${value.slice(0, 40)}"`;
|
|
303
|
+
if (typeof value === "number" || typeof value === "boolean") return `the ${typeof value} ${String(value)}`;
|
|
304
|
+
if (typeof value === "function") return "a function";
|
|
305
|
+
let thenable = false;
|
|
306
|
+
try {
|
|
307
|
+
thenable = typeof value.then === "function";
|
|
308
|
+
if (thenable) value.then(void 0, () => {
|
|
309
|
+
});
|
|
310
|
+
} catch {
|
|
311
|
+
}
|
|
312
|
+
return thenable ? "a Promise (the hook must answer synchronously)" : typeof value === "object" ? "an object" : `a ${typeof value}`;
|
|
313
|
+
}
|
|
314
|
+
function nativeFeeCap(chain, fee, route) {
|
|
315
|
+
const defaultCap = NATIVE_FEE_CAP[chain] ?? DEFAULT_NATIVE_FEE_CAP;
|
|
316
|
+
const hook = route?.ceiling;
|
|
317
|
+
if (hook === void 0) return defaultCap;
|
|
318
|
+
const maxCeiling = defaultCap * NATIVE_FEE_CEILING_MAX_MULTIPLE;
|
|
319
|
+
const where = `${route.provider} ${chain} \u2192 ${route.destChain}`;
|
|
320
|
+
if (typeof hook !== "function") {
|
|
321
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling is ${describeCeilingAnswer(hook)}, not a function \u2014 the native fee of ${where} is refused`);
|
|
322
|
+
}
|
|
323
|
+
const ctx = Object.freeze({
|
|
324
|
+
provider: route.provider,
|
|
325
|
+
intentId: route.intentId,
|
|
326
|
+
fromChain: chain,
|
|
327
|
+
destChain: route.destChain,
|
|
328
|
+
nativeFee: fee,
|
|
329
|
+
defaultCap,
|
|
330
|
+
maxCeiling
|
|
331
|
+
});
|
|
332
|
+
let answer;
|
|
333
|
+
try {
|
|
334
|
+
answer = hook(ctx);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
const why = (error instanceof Error ? error.message : String(error)).slice(0, 160);
|
|
337
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling threw for ${where} (${why}) \u2014 the native fee is refused`, { cause: error });
|
|
338
|
+
}
|
|
339
|
+
if (answer === void 0) return defaultCap;
|
|
340
|
+
if (typeof answer !== "bigint" || answer < 0n) {
|
|
341
|
+
throw new Swap2ConfigurationError(`swap2: nativeFeeCeiling returned ${describeCeilingAnswer(answer)} for ${where}, not a non-negative bigint or undefined \u2014 the native fee is refused`);
|
|
342
|
+
}
|
|
343
|
+
if (answer > maxCeiling) {
|
|
344
|
+
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`);
|
|
345
|
+
}
|
|
346
|
+
return answer;
|
|
347
|
+
}
|
|
348
|
+
function declaredNativeFee(q, chain, route) {
|
|
295
349
|
const raw = q.txRequest?.nativeFee;
|
|
296
350
|
if (raw === void 0) return 0n;
|
|
297
351
|
if (!/^\d+$/.test(raw)) throw new Error("swap2: quote declares a malformed native fee");
|
|
298
352
|
const fee = BigInt(raw);
|
|
299
|
-
const cap =
|
|
353
|
+
const cap = nativeFeeCap(chain, fee, route);
|
|
300
354
|
if (fee > cap) throw new Error(`swap2: quoted native fee ${fee} exceeds the cap ${cap} for ${chain}`);
|
|
301
355
|
return fee;
|
|
302
356
|
}
|
|
@@ -920,16 +974,18 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
920
974
|
const source = this.sourceAsset(executionOptions);
|
|
921
975
|
if (!source) throw new Error(`swap2: unknown source token '${executionOptions.fromToken}' on ${this.fromChain}`);
|
|
922
976
|
const executionValue = BigInt(unsigned.value);
|
|
977
|
+
const ceiling = this._config.nativeFeeCeiling;
|
|
978
|
+
const feeRoute = { provider: q.provider, intentId: q.intentId, destChain: params.destChain, ...ceiling !== void 0 ? { ceiling } : {} };
|
|
923
979
|
if (serialized) {
|
|
924
980
|
if (executionValue !== (source.contract ? 0n : BigInt(q.sourceAmount))) {
|
|
925
981
|
throw new Error("swap2: provider execution amount does not match the validated quote");
|
|
926
982
|
}
|
|
927
983
|
} else if (source.contract && this.fromChain.startsWith("eip155:")) {
|
|
928
|
-
const declared = declaredNativeFee(q, this.fromChain);
|
|
984
|
+
const declared = declaredNativeFee(q, this.fromChain, feeRoute);
|
|
929
985
|
if (executionValue !== declared) {
|
|
930
986
|
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}`);
|
|
931
987
|
}
|
|
932
|
-
} else if (!unsigned.typedData && !unsigned.bodyBoc && executionValue !== BigInt(q.sourceAmount) + declaredNativeFee(q, this.fromChain)) {
|
|
988
|
+
} else if (!unsigned.typedData && !unsigned.bodyBoc && executionValue !== BigInt(q.sourceAmount) + declaredNativeFee(q, this.fromChain, feeRoute)) {
|
|
933
989
|
throw new Error("swap2: provider execution amount does not match the validated quote");
|
|
934
990
|
}
|
|
935
991
|
let tonBody;
|
|
@@ -938,13 +994,13 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
938
994
|
throw new Swap2ValidationError(`swap2: TON cell-body build refused \u2014 ${why}`);
|
|
939
995
|
};
|
|
940
996
|
const raw = this._config.tonGasCeiling;
|
|
941
|
-
const
|
|
942
|
-
if (
|
|
997
|
+
const ceiling2 = raw === void 0 ? DEFAULT_TON_GAS_CEILING : BigInt(raw);
|
|
998
|
+
if (ceiling2 < 0n) throw new Swap2ConfigurationError("swap2: tonGasCeiling must be non-negative");
|
|
943
999
|
if (provider.remote === true && provider.verifiesBuilds !== true) refuse("a remote provider's cell body needs the app's own validator (remoteProvider verifyBuild)");
|
|
944
1000
|
tonBody = readTonBody(cellBody);
|
|
945
1001
|
const input = BigInt(q.sourceAmount);
|
|
946
1002
|
if (source.contract) {
|
|
947
|
-
if (executionValue >
|
|
1003
|
+
if (executionValue > ceiling2) refuse(`it attaches ${executionValue} nanoTON to a jetton transfer, more than the ${ceiling2} gas ceiling`);
|
|
948
1004
|
const t = tonBody.jettonTransfer;
|
|
949
1005
|
if (!t) refuse("a jetton-source body must be a jetton transfer");
|
|
950
1006
|
if (t.amount !== input) refuse(`the jetton transfer moves ${t.amount}, not the swap's ${input}`);
|
|
@@ -954,7 +1010,7 @@ var BaseSwap2Protocol = class extends import_core.Swap2Protocol {
|
|
|
954
1010
|
if (!own) refuse("the account cannot name its own jetton wallet (getJettonWalletAddress), so the target cannot be checked");
|
|
955
1011
|
if (tonRawAddress(unsigned.to) !== own) refuse(`it is sent to ${unsigned.to}, not this account's ${source.symbol ?? "source"} jetton wallet`);
|
|
956
1012
|
} else {
|
|
957
|
-
if (executionValue < input || executionValue - input >
|
|
1013
|
+
if (executionValue < input || executionValue - input > ceiling2) refuse(`it attaches ${executionValue} nanoTON for a ${input} input, more than the ${ceiling2} gas ceiling on top`);
|
|
958
1014
|
const pinned = provider.remote === true ? [...provider.callTargets?.(this.fromChain) ?? [], ...q.depositAddress ? [q.depositAddress] : []].map(tonRawAddress).filter((a) => !!a) : [];
|
|
959
1015
|
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)`);
|
|
960
1016
|
}
|