@anywalletkit/protocol-swap2-relay 0.1.1 → 0.1.2
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-WRIKAUWI.js → chunk-C3I2XYSW.js} +92 -84
- package/dist/chunk-C3I2XYSW.js.map +1 -0
- package/dist/{chunk-CCMNAZZB.js → chunk-JTPYU26F.js} +72 -29
- package/dist/chunk-JTPYU26F.js.map +1 -0
- package/dist/{chunk-UVHDMGM5.js → chunk-MDXHT7HY.js} +5 -3
- package/dist/chunk-MDXHT7HY.js.map +1 -0
- package/dist/{chunk-7LPLU3MB.js → chunk-TBFD7BPZ.js} +2 -2
- package/dist/index.cjs +163 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -4
- package/dist/order.cjs +4 -2
- package/dist/order.cjs.map +1 -1
- package/dist/order.d.cts +9 -1
- package/dist/order.d.ts +9 -1
- package/dist/order.js +1 -1
- package/dist/protocol.cjs +163 -110
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +4 -4
- package/dist/provider.cjs +163 -110
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.js +3 -3
- package/dist/verify.cjs +94 -84
- package/dist/verify.cjs.map +1 -1
- package/dist/verify.d.cts +2 -1
- package/dist/verify.d.ts +2 -1
- package/dist/verify.js +2 -2
- package/package.json +5 -5
- package/dist/chunk-CCMNAZZB.js.map +0 -1
- package/dist/chunk-UVHDMGM5.js.map +0 -1
- package/dist/chunk-WRIKAUWI.js.map +0 -1
- /package/dist/{chunk-7LPLU3MB.js.map → chunk-TBFD7BPZ.js.map} +0 -0
package/dist/verify.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(verify_exports, {
|
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(verify_exports);
|
|
41
41
|
var import_viem2 = require("viem");
|
|
42
|
+
var import_errors2 = require("@anywalletkit/protocol-swap2-core/errors");
|
|
42
43
|
var import_util = require("@anywalletkit/protocol-swap2-core/util");
|
|
43
44
|
|
|
44
45
|
// src/config.ts
|
|
@@ -93,13 +94,15 @@ var RELAY_CLOCK_SKEW_S = 300;
|
|
|
93
94
|
|
|
94
95
|
// src/order.ts
|
|
95
96
|
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
97
|
+
var import_errors = require("@anywalletkit/protocol-swap2-core/errors");
|
|
96
98
|
var import_viem = require("viem");
|
|
97
99
|
var RelayRefusal = class extends Error {
|
|
98
100
|
code;
|
|
99
|
-
constructor(code, detail) {
|
|
101
|
+
constructor(code, detail, reason) {
|
|
100
102
|
super(`relay: ${detail} [${code}]`);
|
|
101
103
|
this.name = "RelayRefusal";
|
|
102
104
|
this.code = code;
|
|
105
|
+
if (reason !== void 0) (0, import_errors.withReason)(this, reason);
|
|
103
106
|
}
|
|
104
107
|
};
|
|
105
108
|
var RELAY_ORDER_TYPES = {
|
|
@@ -156,7 +159,7 @@ var MAX_BYTES_HEX = 2 + 2 * 1024;
|
|
|
156
159
|
var MAX_TEXT = 64;
|
|
157
160
|
var U256_MAX = (1n << 256n) - 1n;
|
|
158
161
|
var bad = (what) => {
|
|
159
|
-
throw new RelayRefusal("order-malformed", `the order's ${what}
|
|
162
|
+
throw new RelayRefusal("order-malformed", `the order's ${what}`, "upstream_unavailable");
|
|
160
163
|
};
|
|
161
164
|
function rec(v, what) {
|
|
162
165
|
if (v === null || typeof v !== "object" || Array.isArray(v)) bad(`${what} is not an object`);
|
|
@@ -280,10 +283,10 @@ var clearedOrders = /* @__PURE__ */ new Map();
|
|
|
280
283
|
function relayClearOrder(id, stage, nowMs = Date.now()) {
|
|
281
284
|
const key = `${stage}:${id.toLowerCase()}`;
|
|
282
285
|
const until = clearedOrders.get(key);
|
|
283
|
-
if (until !== void 0 && until > nowMs) throw new RelayRefusal("order-reused", `order ${id} was already cleared for a deposit \u2014 quote again
|
|
286
|
+
if (until !== void 0 && until > nowMs) throw new RelayRefusal("order-reused", `order ${id} was already cleared for a deposit \u2014 quote again`, "policy_refused");
|
|
284
287
|
if (clearedOrders.size >= CLEARED_MAX) {
|
|
285
288
|
for (const [k, t] of clearedOrders) if (t <= nowMs) clearedOrders.delete(k);
|
|
286
|
-
if (clearedOrders.size >= CLEARED_MAX) throw new RelayRefusal("order-reused", "too many deposits cleared in the last minutes \u2014 try again later");
|
|
289
|
+
if (clearedOrders.size >= CLEARED_MAX) throw new RelayRefusal("order-reused", "too many deposits cleared in the last minutes \u2014 try again later", "policy_refused");
|
|
287
290
|
}
|
|
288
291
|
clearedOrders.set(key, nowMs + CLEARED_TTL_MS);
|
|
289
292
|
}
|
|
@@ -325,24 +328,24 @@ function buildRelayDeposit(source, depositor, token, amount, id) {
|
|
|
325
328
|
};
|
|
326
329
|
}
|
|
327
330
|
function checkRequest(r) {
|
|
328
|
-
const invalid = (what) => {
|
|
329
|
-
throw new RelayRefusal("request-invalid", what);
|
|
331
|
+
const invalid = (what, reason) => {
|
|
332
|
+
throw new RelayRefusal("request-invalid", what, reason);
|
|
330
333
|
};
|
|
331
334
|
if (r === null || typeof r !== "object") invalid("no request to check the order against");
|
|
332
335
|
const source = relayChain(r.sourceChain);
|
|
333
336
|
const dest = relayChain(r.destChain);
|
|
334
|
-
if (!source) throw new RelayRefusal("chain-unsupported", `source chain ${String(r.sourceChain)} is not a pinned Relay chain
|
|
335
|
-
if (!dest) throw new RelayRefusal("chain-unsupported", `destination chain ${String(r.destChain)} is not a pinned Relay chain
|
|
336
|
-
if (source === dest) throw new RelayRefusal("chain-unsupported", "source and destination are the same chain");
|
|
337
|
+
if (!source) throw new RelayRefusal("chain-unsupported", `source chain ${String(r.sourceChain)} is not a pinned Relay chain`, "unsupported_pair");
|
|
338
|
+
if (!dest) throw new RelayRefusal("chain-unsupported", `destination chain ${String(r.destChain)} is not a pinned Relay chain`, "unsupported_pair");
|
|
339
|
+
if (source === dest) throw new RelayRefusal("chain-unsupported", "source and destination are the same chain", "unsupported_pair");
|
|
337
340
|
for (const [what, v] of [["input token", r.sourceToken], ["output token", r.destToken], ["depositor", r.depositor], ["recipient", r.recipient]]) {
|
|
338
341
|
if (typeof v !== "string" || !ADDRESS.test(v)) invalid(`the ${what} is not an address`);
|
|
339
342
|
}
|
|
340
|
-
if (/^0x0{40}$/.test(r.depositor)) invalid("the depositor is the zero address");
|
|
341
|
-
if (/^0x0{40}$/.test(r.recipient)) invalid("the recipient is the zero address");
|
|
343
|
+
if (/^0x0{40}$/.test(r.depositor)) invalid("the depositor is the zero address", "recipient_mismatch");
|
|
344
|
+
if (/^0x0{40}$/.test(r.recipient)) invalid("the recipient is the zero address", "recipient_mismatch");
|
|
342
345
|
if (typeof r.amount !== "bigint" || r.amount <= 0n || r.amount > U256_MAX2) invalid("the amount is not a positive integer");
|
|
343
346
|
if (r.minAmountOut !== void 0 && (typeof r.minAmountOut !== "bigint" || r.minAmountOut < 0n)) invalid("the output floor is not an unsigned integer");
|
|
344
347
|
if (r.slippageBps !== void 0 && (!Number.isInteger(r.slippageBps) || r.slippageBps < 0 || r.slippageBps > RELAY_MAX_SLIPPAGE_BPS)) {
|
|
345
|
-
invalid(`slippage must be a whole number of basis points up to ${RELAY_MAX_SLIPPAGE_BPS}
|
|
348
|
+
invalid(`slippage must be a whole number of basis points up to ${RELAY_MAX_SLIPPAGE_BPS}`, "policy_refused");
|
|
346
349
|
}
|
|
347
350
|
const nowMs = r.nowMs ?? Date.now();
|
|
348
351
|
if (!Number.isFinite(nowMs) || nowMs <= 0) invalid("the clock is not a time");
|
|
@@ -352,143 +355,143 @@ var isAddr = (bytes2, addr) => bytes2.length === 42 && bytes2 === lower(addr);
|
|
|
352
355
|
function checkDeadline(code, what, deadline, nowS) {
|
|
353
356
|
const left = deadline - nowS;
|
|
354
357
|
if (left > RELAY_ORDER_LIFETIME_S + RELAY_CLOCK_SKEW_S) {
|
|
355
|
-
throw new RelayRefusal(code, `${what} is ${left} s away, past the ${RELAY_ORDER_LIFETIME_S} s an order lives
|
|
358
|
+
throw new RelayRefusal(code, `${what} is ${left} s away, past the ${RELAY_ORDER_LIFETIME_S} s an order lives`, "policy_refused");
|
|
356
359
|
}
|
|
357
360
|
if (left < RELAY_ORDER_LIFETIME_S - RELAY_MAX_ORDER_AGE_S) {
|
|
358
|
-
throw new RelayRefusal(code, `${what} is ${left} s away: the order is older than ${RELAY_MAX_ORDER_AGE_S} s or already past it
|
|
361
|
+
throw new RelayRefusal(code, `${what} is ${left} s away: the order is older than ${RELAY_MAX_ORDER_AGE_S} s or already past it`, "quote_expired");
|
|
359
362
|
}
|
|
360
363
|
}
|
|
361
364
|
function wordAddress(word) {
|
|
362
365
|
return /^0{24}/.test(word) ? `0x${word.slice(24)}` : null;
|
|
363
366
|
}
|
|
364
367
|
function checkDepositTarget(tx, source) {
|
|
365
|
-
if (tx === null || typeof tx !== "object") throw new RelayRefusal("tx-calldata", "there is no deposit transaction");
|
|
368
|
+
if (tx === null || typeof tx !== "object") throw new RelayRefusal("tx-calldata", "there is no deposit transaction", "policy_refused");
|
|
366
369
|
if (tx.chainId !== source.chainId) {
|
|
367
|
-
throw new RelayRefusal("tx-chain", `the deposit is for chain ${String(tx.chainId)}, not ${source.chainId}
|
|
370
|
+
throw new RelayRefusal("tx-chain", `the deposit is for chain ${String(tx.chainId)}, not ${source.chainId}`, "vault_mismatch");
|
|
368
371
|
}
|
|
369
372
|
if (typeof tx.to !== "string" || !ADDRESS.test(tx.to) || lower(tx.to) !== source.depository) {
|
|
370
|
-
throw new RelayRefusal("tx-target", `the deposit calls ${String(tx.to)}, not the ${source.name} depository ${source.depository} \u2014 routes that first swap on the source chain go through a router and are not signed by this module
|
|
373
|
+
throw new RelayRefusal("tx-target", `the deposit calls ${String(tx.to)}, not the ${source.name} depository ${source.depository} \u2014 routes that first swap on the source chain go through a router and are not signed by this module`, "vault_mismatch");
|
|
371
374
|
}
|
|
372
375
|
}
|
|
373
376
|
function checkDepositTx(tx, source, request, order, id) {
|
|
374
377
|
checkDepositTarget(tx, source);
|
|
375
378
|
if (typeof tx.data !== "string" || !/^0x(?:[0-9a-fA-F]{2})*$/.test(tx.data) || tx.data.length < 10) {
|
|
376
|
-
throw new RelayRefusal("tx-calldata", "the deposit has no calldata");
|
|
379
|
+
throw new RelayRefusal("tx-calldata", "the deposit has no calldata", "policy_refused");
|
|
377
380
|
}
|
|
378
381
|
const data = lower(tx.data);
|
|
379
382
|
const selector = data.slice(0, 10);
|
|
380
383
|
const input = order.inputs[0].payment;
|
|
381
384
|
const native = isNative(input.currency);
|
|
382
385
|
if (selector === RELAY_DEPOSIT_ERC20_ALLOWANCE) {
|
|
383
|
-
throw new RelayRefusal("tx-selector", "the deposit uses depositErc20 without an amount, which takes the whole allowance");
|
|
386
|
+
throw new RelayRefusal("tx-selector", "the deposit uses depositErc20 without an amount, which takes the whole allowance", "policy_refused");
|
|
384
387
|
}
|
|
385
388
|
if (selector !== RELAY_DEPOSIT_NATIVE && selector !== RELAY_DEPOSIT_ERC20) {
|
|
386
|
-
throw new RelayRefusal("tx-selector", `the deposit calls ${selector}, not a known deposit function
|
|
389
|
+
throw new RelayRefusal("tx-selector", `the deposit calls ${selector}, not a known deposit function`, "policy_refused");
|
|
387
390
|
}
|
|
388
391
|
if (selector === RELAY_DEPOSIT_NATIVE !== native) {
|
|
389
|
-
throw new RelayRefusal("tx-selector", `the deposit calls ${native ? "depositErc20" : "depositNative"} for an order whose input is ${native ? "the native coin" : "a token"}
|
|
392
|
+
throw new RelayRefusal("tx-selector", `the deposit calls ${native ? "depositErc20" : "depositNative"} for an order whose input is ${native ? "the native coin" : "a token"}`, "policy_refused");
|
|
390
393
|
}
|
|
391
394
|
const words = native ? 2 : 4;
|
|
392
395
|
if (data.length !== 10 + 64 * words) {
|
|
393
|
-
throw new RelayRefusal("tx-calldata", `the deposit calldata is ${(data.length - 2) / 2} bytes, not ${4 + 32 * words}
|
|
396
|
+
throw new RelayRefusal("tx-calldata", `the deposit calldata is ${(data.length - 2) / 2} bytes, not ${4 + 32 * words}`, "policy_refused");
|
|
394
397
|
}
|
|
395
398
|
const word = (i) => data.slice(10 + 64 * i, 74 + 64 * i);
|
|
396
399
|
const depositor = wordAddress(word(0));
|
|
397
|
-
if (depositor === null) throw new RelayRefusal("tx-calldata", "the depositor argument is not a padded address");
|
|
400
|
+
if (depositor === null) throw new RelayRefusal("tx-calldata", "the depositor argument is not a padded address", "policy_refused");
|
|
398
401
|
if (depositor !== lower(request.depositor)) {
|
|
399
|
-
throw new RelayRefusal("tx-depositor", `the deposit is credited to ${depositor}, not to the sender ${lower(request.depositor)}
|
|
402
|
+
throw new RelayRefusal("tx-depositor", `the deposit is credited to ${depositor}, not to the sender ${lower(request.depositor)}`, "recipient_mismatch");
|
|
400
403
|
}
|
|
401
404
|
if (!native) {
|
|
402
405
|
const token = wordAddress(word(1));
|
|
403
|
-
if (token === null) throw new RelayRefusal("tx-calldata", "the token argument is not a padded address");
|
|
404
|
-
if (token !== input.currency) throw new RelayRefusal("tx-token", `the deposit moves ${token}, the order's input is ${input.currency}
|
|
406
|
+
if (token === null) throw new RelayRefusal("tx-calldata", "the token argument is not a padded address", "policy_refused");
|
|
407
|
+
if (token !== input.currency) throw new RelayRefusal("tx-token", `the deposit moves ${token}, the order's input is ${input.currency}`, "policy_refused");
|
|
405
408
|
const amount = BigInt(`0x${word(2)}`);
|
|
406
|
-
if (amount !== input.amount) throw new RelayRefusal("tx-amount", `the deposit moves ${amount}, the order's input is ${input.amount}
|
|
409
|
+
if (amount !== input.amount) throw new RelayRefusal("tx-amount", `the deposit moves ${amount}, the order's input is ${input.amount}`, "policy_refused");
|
|
407
410
|
}
|
|
408
411
|
const txId = `0x${word(native ? 1 : 3)}`;
|
|
409
|
-
if (txId !== id) throw new RelayRefusal("tx-id", `the deposit names order ${txId}, the order received hashes to ${id}
|
|
412
|
+
if (txId !== id) throw new RelayRefusal("tx-id", `the deposit names order ${txId}, the order received hashes to ${id}`, "recipient_unverifiable");
|
|
410
413
|
const value = typeof tx.value === "string" && /^(?:0|[1-9]\d{0,77})$/.test(tx.value) ? BigInt(tx.value) : null;
|
|
411
414
|
const wantValue = native ? input.amount : 0n;
|
|
412
415
|
if (value === null || value !== wantValue) {
|
|
413
|
-
throw new RelayRefusal("tx-value", `the deposit sends ${String(tx.value)} wei, it must send ${wantValue}
|
|
416
|
+
throw new RelayRefusal("tx-value", `the deposit sends ${String(tx.value)} wei, it must send ${wantValue}`, "policy_refused");
|
|
414
417
|
}
|
|
415
418
|
}
|
|
416
419
|
function verifyRelayOrder(request, protocol, deposit) {
|
|
417
420
|
const { source, dest, nowS } = checkRequest(request);
|
|
418
421
|
if (deposit !== void 0) checkDepositTarget(deposit, source);
|
|
419
422
|
if (protocol === null || typeof protocol !== "object") {
|
|
420
|
-
throw new RelayRefusal("protocol-data-missing", "the quote carries no order (protocol.v2) \u2014 nothing to check the deposit against");
|
|
423
|
+
throw new RelayRefusal("protocol-data-missing", "the quote carries no order (protocol.v2) \u2014 nothing to check the deposit against", "upstream_unavailable");
|
|
421
424
|
}
|
|
422
425
|
if (protocol.orderData === void 0 || protocol.orderData === null) {
|
|
423
|
-
throw new RelayRefusal("protocol-data-missing", "the quote carries no order data \u2014 nothing to check the deposit against");
|
|
426
|
+
throw new RelayRefusal("protocol-data-missing", "the quote carries no order data \u2014 nothing to check the deposit against", "upstream_unavailable");
|
|
424
427
|
}
|
|
425
428
|
if (protocol.hubType !== "onchain") {
|
|
426
|
-
throw new RelayRefusal("hub-type", `the order settles through a "${String(protocol.hubType)}" hub, only "onchain" is read
|
|
429
|
+
throw new RelayRefusal("hub-type", `the order settles through a "${String(protocol.hubType)}" hub, only "onchain" is read`, "unsupported_pair");
|
|
427
430
|
}
|
|
428
431
|
const order = parseRelayOrder(protocol.orderData);
|
|
429
|
-
if (order.version !== RELAY_ORDER_VERSION) throw new RelayRefusal("order-version", `order version "${order.version}" is not ${RELAY_ORDER_VERSION}
|
|
430
|
-
if (order.inputs.length !== 1) throw new RelayRefusal("order-inputs", `the order has ${order.inputs.length} inputs, exactly one is signed for
|
|
431
|
-
if (order.output.payments.length !== 1) throw new RelayRefusal("order-payments", `the order pays ${order.output.payments.length} outputs, exactly one is accepted
|
|
432
|
-
if (order.output.calls.length !== 0) throw new RelayRefusal("order-calls", "the order runs calls on the destination \u2014 only plain payments are accepted");
|
|
433
|
-
if (order.fees.length !== 0) throw new RelayRefusal("order-fees", "the order carries order-level fees, which this module does not show and does not accept");
|
|
432
|
+
if (order.version !== RELAY_ORDER_VERSION) throw new RelayRefusal("order-version", `order version "${order.version}" is not ${RELAY_ORDER_VERSION}`, "upstream_unavailable");
|
|
433
|
+
if (order.inputs.length !== 1) throw new RelayRefusal("order-inputs", `the order has ${order.inputs.length} inputs, exactly one is signed for`, "policy_refused");
|
|
434
|
+
if (order.output.payments.length !== 1) throw new RelayRefusal("order-payments", `the order pays ${order.output.payments.length} outputs, exactly one is accepted`, "policy_refused");
|
|
435
|
+
if (order.output.calls.length !== 0) throw new RelayRefusal("order-calls", "the order runs calls on the destination \u2014 only plain payments are accepted", "policy_refused");
|
|
436
|
+
if (order.fees.length !== 0) throw new RelayRefusal("order-fees", "the order carries order-level fees, which this module does not show and does not accept", "policy_refused");
|
|
434
437
|
const input = order.inputs[0];
|
|
435
438
|
const pay = order.output.payments[0];
|
|
436
|
-
if (input.payment.weight === 0n) throw new RelayRefusal("input-weight", "the order's input has zero weight");
|
|
439
|
+
if (input.payment.weight === 0n) throw new RelayRefusal("input-weight", "the order's input has zero weight", "policy_refused");
|
|
437
440
|
if (!RELAY_SOLVERS.some((s) => s.address === order.solver && s.chainId === order.solverChainId)) {
|
|
438
|
-
throw new RelayRefusal("solver-not-pinned", `solver ${order.solver} on "${order.solverChainId}" is not a pinned Relay solver
|
|
441
|
+
throw new RelayRefusal("solver-not-pinned", `solver ${order.solver} on "${order.solverChainId}" is not a pinned Relay solver`, "recipient_unverifiable");
|
|
439
442
|
}
|
|
440
|
-
if (order.output.chainId !== dest.slug) throw new RelayRefusal("output-chain", `the order pays on "${order.output.chainId}", the request is for ${dest.name} ("${dest.slug}")
|
|
441
|
-
if (!isAddr(pay.recipient, request.recipient)) throw new RelayRefusal("output-recipient", `the order pays ${pay.recipient}, not the recipient ${lower(request.recipient)}
|
|
442
|
-
if (!isAddr(pay.currency, request.destToken)) throw new RelayRefusal("output-currency", `the order pays in ${pay.currency}, the request is for ${lower(request.destToken)}
|
|
443
|
-
if (pay.minimumAmount <= 0n) throw new RelayRefusal("output-minimum", "the order's minimum output is zero");
|
|
443
|
+
if (order.output.chainId !== dest.slug) throw new RelayRefusal("output-chain", `the order pays on "${order.output.chainId}", the request is for ${dest.name} ("${dest.slug}")`, "recipient_mismatch");
|
|
444
|
+
if (!isAddr(pay.recipient, request.recipient)) throw new RelayRefusal("output-recipient", `the order pays ${pay.recipient}, not the recipient ${lower(request.recipient)}`, "recipient_mismatch");
|
|
445
|
+
if (!isAddr(pay.currency, request.destToken)) throw new RelayRefusal("output-currency", `the order pays in ${pay.currency}, the request is for ${lower(request.destToken)}`, "price_check_failed");
|
|
446
|
+
if (pay.minimumAmount <= 0n) throw new RelayRefusal("output-minimum", "the order's minimum output is zero", "price_check_failed");
|
|
444
447
|
if (request.minAmountOut !== void 0 && pay.minimumAmount < request.minAmountOut) {
|
|
445
|
-
throw new RelayRefusal("output-minimum", `the order's minimum output ${pay.minimumAmount} is under the caller's floor ${request.minAmountOut}
|
|
448
|
+
throw new RelayRefusal("output-minimum", `the order's minimum output ${pay.minimumAmount} is under the caller's floor ${request.minAmountOut}`, "price_check_failed");
|
|
446
449
|
}
|
|
447
|
-
if (pay.expectedAmount < pay.minimumAmount) throw new RelayRefusal("output-expected", `the order expects ${pay.expectedAmount}, less than its own minimum ${pay.minimumAmount}
|
|
450
|
+
if (pay.expectedAmount < pay.minimumAmount) throw new RelayRefusal("output-expected", `the order expects ${pay.expectedAmount}, less than its own minimum ${pay.minimumAmount}`, "price_check_failed");
|
|
448
451
|
const slippage = BigInt(request.slippageBps ?? RELAY_DEFAULT_SLIPPAGE_BPS);
|
|
449
452
|
const floor = pay.expectedAmount * (10000n - slippage) / 10000n;
|
|
450
453
|
if (pay.minimumAmount < floor) {
|
|
451
|
-
throw new RelayRefusal("output-minimum", `the order's minimum output ${pay.minimumAmount} is more than ${slippage} bps under its expected ${pay.expectedAmount}
|
|
454
|
+
throw new RelayRefusal("output-minimum", `the order's minimum output ${pay.minimumAmount} is more than ${slippage} bps under its expected ${pay.expectedAmount}`, "price_check_failed");
|
|
452
455
|
}
|
|
453
456
|
checkDeadline("output-deadline", "the output deadline", order.output.deadline, nowS);
|
|
454
|
-
if (input.payment.chainId !== source.slug) throw new RelayRefusal("input-chain", `the order is funded on "${input.payment.chainId}", the request sends on ${source.name} ("${source.slug}")
|
|
455
|
-
if (!isAddr(input.payment.currency, request.sourceToken)) throw new RelayRefusal("input-currency", `the order is funded in ${input.payment.currency}, the request sends ${lower(request.sourceToken)}
|
|
456
|
-
if (input.payment.amount !== request.amount) throw new RelayRefusal("input-amount", `the order is funded with ${input.payment.amount}, the request sends ${request.amount}
|
|
457
|
+
if (input.payment.chainId !== source.slug) throw new RelayRefusal("input-chain", `the order is funded on "${input.payment.chainId}", the request sends on ${source.name} ("${source.slug}")`, "policy_refused");
|
|
458
|
+
if (!isAddr(input.payment.currency, request.sourceToken)) throw new RelayRefusal("input-currency", `the order is funded in ${input.payment.currency}, the request sends ${lower(request.sourceToken)}`, "policy_refused");
|
|
459
|
+
if (input.payment.amount !== request.amount) throw new RelayRefusal("input-amount", `the order is funded with ${input.payment.amount}, the request sends ${request.amount}`, "policy_refused");
|
|
457
460
|
let originRefund = false;
|
|
458
461
|
for (const refund of input.refunds) {
|
|
459
462
|
if (refund.chainId === source.slug) {
|
|
460
|
-
if (!isAddr(refund.recipient, request.depositor)) throw new RelayRefusal("refund-recipient", `a source-chain refund goes to ${refund.recipient}, not the sender ${lower(request.depositor)}
|
|
461
|
-
if (refund.currency !== input.payment.currency) throw new RelayRefusal("refund-currency", `a source-chain refund is in ${refund.currency}, not the token sent
|
|
463
|
+
if (!isAddr(refund.recipient, request.depositor)) throw new RelayRefusal("refund-recipient", `a source-chain refund goes to ${refund.recipient}, not the sender ${lower(request.depositor)}`, "recipient_mismatch");
|
|
464
|
+
if (refund.currency !== input.payment.currency) throw new RelayRefusal("refund-currency", `a source-chain refund is in ${refund.currency}, not the token sent`, "policy_refused");
|
|
462
465
|
originRefund = true;
|
|
463
466
|
} else if (refund.chainId === dest.slug) {
|
|
464
467
|
if (!isAddr(refund.recipient, request.recipient) && !isAddr(refund.recipient, request.depositor)) {
|
|
465
|
-
throw new RelayRefusal("refund-recipient", `a destination-chain refund goes to ${refund.recipient}, neither the recipient nor the sender
|
|
468
|
+
throw new RelayRefusal("refund-recipient", `a destination-chain refund goes to ${refund.recipient}, neither the recipient nor the sender`, "recipient_mismatch");
|
|
466
469
|
}
|
|
467
|
-
if (refund.currency.length !== 42) throw new RelayRefusal("refund-currency", "a destination-chain refund names no token");
|
|
470
|
+
if (refund.currency.length !== 42) throw new RelayRefusal("refund-currency", "a destination-chain refund names no token", "policy_refused");
|
|
468
471
|
} else {
|
|
469
|
-
throw new RelayRefusal("refund-chain", `a refund is payable on "${refund.chainId}", neither the source nor the destination chain
|
|
472
|
+
throw new RelayRefusal("refund-chain", `a refund is payable on "${refund.chainId}", neither the source nor the destination chain`, "recipient_mismatch");
|
|
470
473
|
}
|
|
471
474
|
checkDeadline("refund-deadline", "a refund deadline", refund.deadline, nowS);
|
|
472
475
|
}
|
|
473
|
-
if (!originRefund) throw new RelayRefusal("refund-missing", "the order has no refund to the sender on the source chain");
|
|
476
|
+
if (!originRefund) throw new RelayRefusal("refund-missing", "the order has no refund to the sender on the source chain", "policy_refused");
|
|
474
477
|
const id = relayOrderId(order);
|
|
475
478
|
if (typeof protocol.orderId !== "string" || lower(protocol.orderId) !== id) {
|
|
476
|
-
throw new RelayRefusal("order-id-mismatch", `the quote names order ${String(protocol.orderId)}, the order data hashes to ${id}
|
|
479
|
+
throw new RelayRefusal("order-id-mismatch", `the quote names order ${String(protocol.orderId)}, the order data hashes to ${id}`, "recipient_unverifiable");
|
|
477
480
|
}
|
|
478
481
|
const signer = relayOrderSigner(id, protocol.orderSignature);
|
|
479
482
|
if (signer === null || signer !== order.solver) {
|
|
480
|
-
throw new RelayRefusal("signature-invalid", signer === null ? "the order signature is not a valid signature" : `the order is signed by ${signer}, not by its solver ${order.solver}
|
|
483
|
+
throw new RelayRefusal("signature-invalid", signer === null ? "the order signature is not a valid signature" : `the order is signed by ${signer}, not by its solver ${order.solver}`, "recipient_unverifiable");
|
|
481
484
|
}
|
|
482
485
|
const pd = protocol.paymentDetails;
|
|
483
|
-
if (pd === null || typeof pd !== "object") throw new RelayRefusal("payment-details", "the quote has no payment details");
|
|
486
|
+
if (pd === null || typeof pd !== "object") throw new RelayRefusal("payment-details", "the quote has no payment details", "upstream_unavailable");
|
|
484
487
|
if (pd.chainId !== source.slug || typeof pd.depository !== "string" || lower(pd.depository) !== source.depository || typeof pd.currency !== "string" || lower(pd.currency) !== input.payment.currency || typeof pd.amount !== "string" || pd.amount !== input.payment.amount.toString(10)) {
|
|
485
|
-
throw new RelayRefusal("payment-details", "the quote's payment details do not describe the order's input on the pinned depository");
|
|
488
|
+
throw new RelayRefusal("payment-details", "the quote's payment details do not describe the order's input on the pinned depository", "vault_mismatch");
|
|
486
489
|
}
|
|
487
490
|
const built = buildRelayDeposit(source, request.depositor, input.payment.currency, input.payment.amount, id);
|
|
488
491
|
if (deposit !== void 0) {
|
|
489
492
|
checkDepositTx(deposit, source, request, order, id);
|
|
490
493
|
if (lower(deposit.data) !== built.data || lower(deposit.to) !== built.to || deposit.value !== built.value) {
|
|
491
|
-
throw new RelayRefusal("tx-calldata", "the deposit is not the call this module builds for the order");
|
|
494
|
+
throw new RelayRefusal("tx-calldata", "the deposit is not the call this module builds for the order", "policy_refused");
|
|
492
495
|
}
|
|
493
496
|
}
|
|
494
497
|
return { order, id, deposit: built, expectedAmount: pay.expectedAmount, minimumAmount: pay.minimumAmount, source, dest };
|
|
@@ -498,22 +501,22 @@ function relayRefusalReason(err) {
|
|
|
498
501
|
throw err;
|
|
499
502
|
}
|
|
500
503
|
function relayRequestOf(params, opts = {}) {
|
|
501
|
-
const invalid = (what) => {
|
|
502
|
-
throw new RelayRefusal("request-invalid", what);
|
|
504
|
+
const invalid = (what, reason) => {
|
|
505
|
+
throw new RelayRefusal("request-invalid", what, reason);
|
|
503
506
|
};
|
|
504
|
-
if (params.flex) invalid("the amount is sealed into the order (no flexible deposits)");
|
|
505
|
-
if (!relayChain(params.sourceChain)) throw new RelayRefusal("chain-unsupported", `source chain ${params.sourceChain} is not a pinned Relay chain
|
|
506
|
-
if (!relayChain(params.destChain)) throw new RelayRefusal("chain-unsupported", `destination chain ${params.destChain} is not a pinned Relay chain
|
|
507
|
-
if (params.sourceChain === params.destChain) throw new RelayRefusal("chain-unsupported", "same-chain swaps are not served through the depository");
|
|
507
|
+
if (params.flex) invalid("the amount is sealed into the order (no flexible deposits)", "unsupported_pair");
|
|
508
|
+
if (!relayChain(params.sourceChain)) throw new RelayRefusal("chain-unsupported", `source chain ${params.sourceChain} is not a pinned Relay chain`, "unsupported_pair");
|
|
509
|
+
if (!relayChain(params.destChain)) throw new RelayRefusal("chain-unsupported", `destination chain ${params.destChain} is not a pinned Relay chain`, "unsupported_pair");
|
|
510
|
+
if (params.sourceChain === params.destChain) throw new RelayRefusal("chain-unsupported", "same-chain swaps are not served through the depository", "unsupported_pair");
|
|
508
511
|
let sourceToken;
|
|
509
512
|
if (typeof params.sourceToken === "string" && ADDRESS.test(params.sourceToken)) sourceToken = params.sourceToken;
|
|
510
513
|
else {
|
|
511
514
|
const asset = (0, import_util.sourceAssetOf)(params);
|
|
512
|
-
if (!asset) invalid(`source token ${String(params.sourceToken)} is not known on ${params.sourceChain}
|
|
515
|
+
if (!asset) invalid(`source token ${String(params.sourceToken)} is not known on ${params.sourceChain}`, "unsupported_pair");
|
|
513
516
|
sourceToken = asset.contract ?? RELAY_NATIVE;
|
|
514
|
-
if (!ADDRESS.test(sourceToken)) invalid(`source token ${String(params.sourceToken)} has no EVM contract
|
|
517
|
+
if (!ADDRESS.test(sourceToken)) invalid(`source token ${String(params.sourceToken)} has no EVM contract`, "unsupported_pair");
|
|
515
518
|
}
|
|
516
|
-
if (typeof params.destToken !== "string" || !ADDRESS.test(params.destToken)) invalid("the destination token must be an EVM address (zero for the native coin)");
|
|
519
|
+
if (typeof params.destToken !== "string" || !ADDRESS.test(params.destToken)) invalid("the destination token must be an EVM address (zero for the native coin)", "unsupported_pair");
|
|
517
520
|
if (typeof params.amountIn !== "string" || !/^[1-9]\d{0,77}$/.test(params.amountIn)) invalid("amount must be a positive base-unit integer");
|
|
518
521
|
if (params.minAmountOut !== void 0 && !/^(?:0|[1-9]\d{0,77})$/.test(params.minAmountOut)) invalid("the output floor must be a base-unit integer");
|
|
519
522
|
const recipient = params.destAddress || opts.placeholder || "";
|
|
@@ -549,57 +552,63 @@ function relayProtocolOf(quote) {
|
|
|
549
552
|
return { orderId: pd.orderId, hubType: pd.hubType, orderData, orderSignature: pd.orderSignature, paymentDetails };
|
|
550
553
|
}
|
|
551
554
|
function checkRelayQuote(request, quote, tx) {
|
|
552
|
-
if (quote === null || typeof quote !== "object" || quote.provider !== "relay") throw new RelayRefusal("quote-shape", "not a Relay quote");
|
|
555
|
+
if (quote === null || typeof quote !== "object" || quote.provider !== "relay") throw new RelayRefusal("quote-shape", "not a Relay quote", "policy_refused");
|
|
553
556
|
const t = tx ?? quote.txRequest;
|
|
554
|
-
if (!t) throw new RelayRefusal("quote-shape", "the quote has no transaction");
|
|
555
|
-
if (quote.depositAddress) throw new RelayRefusal("quote-shape", "a Relay quote pays the depository through its calldata, never a deposit address");
|
|
557
|
+
if (!t) throw new RelayRefusal("quote-shape", "the quote has no transaction", "policy_refused");
|
|
558
|
+
if (quote.depositAddress) throw new RelayRefusal("quote-shape", "a Relay quote pays the depository through its calldata, never a deposit address", "vault_mismatch");
|
|
556
559
|
if (quote.txRequest?.serializedTx !== void 0 || quote.txRequest?.nativeFee !== void 0) {
|
|
557
|
-
throw new RelayRefusal("quote-shape", "a Relay deposit carries no extra native fee and no serialized transaction");
|
|
560
|
+
throw new RelayRefusal("quote-shape", "a Relay deposit carries no extra native fee and no serialized transaction", "policy_refused");
|
|
558
561
|
}
|
|
559
562
|
const v = verifyRelayOrder(request, relayProtocolOf(quote), t);
|
|
560
563
|
const approval = t.approvalAddress;
|
|
561
564
|
if (v.deposit.approvalAddress === void 0 ? approval !== void 0 && approval !== "" : typeof approval !== "string" || lower(approval) !== v.deposit.approvalAddress) {
|
|
562
|
-
throw new RelayRefusal("quote-approval", `the quote approves ${String(approval)}, the order needs ${v.deposit.approvalAddress ?? "no approval"}
|
|
565
|
+
throw new RelayRefusal("quote-approval", `the quote approves ${String(approval)}, the order needs ${v.deposit.approvalAddress ?? "no approval"}`, "vault_mismatch");
|
|
563
566
|
}
|
|
564
567
|
if (quote.sourceAmount !== request.amount.toString(10) || quote.minDestAmount !== v.minimumAmount.toString(10) || quote.destAmount !== v.expectedAmount.toString(10)) {
|
|
565
|
-
throw new RelayRefusal("quote-amounts", "the amounts the quote shows are not the order's");
|
|
568
|
+
throw new RelayRefusal("quote-amounts", "the amounts the quote shows are not the order's", "price_check_failed");
|
|
566
569
|
}
|
|
567
570
|
const gas = t.gasLimit;
|
|
568
571
|
if (gas !== void 0) {
|
|
569
572
|
const floor = v.deposit.approvalAddress === void 0 ? RELAY_GAS_FLOOR_NATIVE : RELAY_GAS_FLOOR_ERC20;
|
|
570
573
|
if (typeof gas !== "string" || !/^[1-9]\d{0,10}$/.test(gas) || BigInt(gas) < floor || BigInt(gas) > RELAY_GAS_CAP) {
|
|
571
|
-
throw new RelayRefusal("quote-gas", `the gas limit ${String(gas).slice(0, 40)} is outside ${floor}\u2013${RELAY_GAS_CAP}
|
|
574
|
+
throw new RelayRefusal("quote-gas", `the gas limit ${String(gas).slice(0, 40)} is outside ${floor}\u2013${RELAY_GAS_CAP}`, "policy_refused");
|
|
572
575
|
}
|
|
573
576
|
}
|
|
574
577
|
const now = request.nowMs ?? Date.now();
|
|
575
578
|
if (typeof quote.validUntilMs !== "number" || !Number.isFinite(quote.validUntilMs) || quote.validUntilMs > now + RELAY_MAX_QUOTE_LIFE_MS) {
|
|
576
|
-
throw new RelayRefusal("quote-expiry", "the quote claims to live longer than a Relay quote may");
|
|
579
|
+
throw new RelayRefusal("quote-expiry", "the quote claims to live longer than a Relay quote may", "policy_refused");
|
|
577
580
|
}
|
|
578
581
|
if (typeof quote.intentId !== "string" || quote.intentId !== `relay:${String(quote.providerData?.requestId)}` || !/^relay:0x[0-9a-f]{64}$/.test(quote.intentId)) {
|
|
579
|
-
throw new RelayRefusal("quote-shape", "the quote's id is not its Relay request id");
|
|
582
|
+
throw new RelayRefusal("quote-shape", "the quote's id is not its Relay request id", "policy_refused");
|
|
580
583
|
}
|
|
581
584
|
return v;
|
|
582
585
|
}
|
|
586
|
+
var pinNotes = (0, import_errors2.refusalNotes)();
|
|
587
|
+
function notedReason(err) {
|
|
588
|
+
const text2 = relayRefusalReason(err);
|
|
589
|
+
const info = (0, import_errors2.refusalOf)(err);
|
|
590
|
+
return info ? pinNotes.note(text2, info) : text2;
|
|
591
|
+
}
|
|
583
592
|
function relayVerifyQuote(params, quote) {
|
|
584
593
|
try {
|
|
585
594
|
checkRelayQuote(relayRequestOf(params), quote);
|
|
586
595
|
return null;
|
|
587
596
|
} catch (err) {
|
|
588
|
-
return
|
|
597
|
+
return notedReason(err);
|
|
589
598
|
}
|
|
590
599
|
}
|
|
591
600
|
function relayVerifyBuild(quote, tx, params) {
|
|
592
601
|
try {
|
|
593
|
-
if (!params) throw new RelayRefusal("request-invalid", "the request this quote answered is not known on this side \u2014 quote again");
|
|
594
|
-
if (tx.chain !== params.sourceChain) throw new RelayRefusal("tx-chain", `the build is for ${tx.chain}, not ${params.sourceChain}
|
|
602
|
+
if (!params) throw new RelayRefusal("request-invalid", "the request this quote answered is not known on this side \u2014 quote again", "policy_refused");
|
|
603
|
+
if (tx.chain !== params.sourceChain) throw new RelayRefusal("tx-chain", `the build is for ${tx.chain}, not ${params.sourceChain}`, "vault_mismatch");
|
|
595
604
|
if (tx.serializedTx !== void 0 || tx.memo !== void 0 || tx.typedData !== void 0 || tx.bodyBoc !== void 0) {
|
|
596
|
-
throw new RelayRefusal("quote-shape", "a Relay deposit is one EVM call");
|
|
605
|
+
throw new RelayRefusal("quote-shape", "a Relay deposit is one EVM call", "policy_refused");
|
|
597
606
|
}
|
|
598
607
|
const v = checkRelayQuote(relayRequestOf(params), quote, tx);
|
|
599
608
|
relayClearOrder(v.id, "build");
|
|
600
609
|
return null;
|
|
601
610
|
} catch (err) {
|
|
602
|
-
return
|
|
611
|
+
return notedReason(err);
|
|
603
612
|
}
|
|
604
613
|
}
|
|
605
614
|
var relayPins = Object.freeze({
|
|
@@ -612,6 +621,7 @@ var relayPins = Object.freeze({
|
|
|
612
621
|
return c2 ? [c2.depository] : [];
|
|
613
622
|
},
|
|
614
623
|
verifyQuote: relayVerifyQuote,
|
|
615
|
-
verifyBuild: relayVerifyBuild
|
|
624
|
+
verifyBuild: relayVerifyBuild,
|
|
625
|
+
reasonOf: pinNotes.reasonOf
|
|
616
626
|
});
|
|
617
627
|
//# sourceMappingURL=verify.cjs.map
|