@anywalletkit/protocol-swap2-omniston 0.3.1 → 0.5.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 +20 -4
- package/dist/{chunk-HOTFZYSW.js → chunk-2DGCZD5K.js} +214 -62
- package/dist/chunk-2DGCZD5K.js.map +1 -0
- package/dist/{chunk-RW4XZWNC.js → chunk-4MKR2SUZ.js} +2 -2
- package/dist/chunk-JWYDIW4V.js +37 -0
- package/dist/chunk-JWYDIW4V.js.map +1 -0
- package/dist/index.cjs +241 -61
- 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 +3 -2
- package/dist/protocol.cjs +108 -52
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +3 -2
- package/dist/{provider-BBG2zhpu.d.cts → provider-CcCZB-Cj.d.cts} +15 -5
- package/dist/{provider-BBG2zhpu.d.ts → provider-CcCZB-Cj.d.ts} +15 -5
- package/dist/provider.cjs +241 -61
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +1 -1
- package/dist/provider.d.ts +1 -1
- package/dist/provider.js +2 -1
- package/dist/validators.d.cts +1 -1
- package/dist/validators.d.ts +1 -1
- package/dist/validators.js +5 -34
- package/dist/validators.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-HOTFZYSW.js.map +0 -1
- /package/dist/{chunk-RW4XZWNC.js.map → chunk-4MKR2SUZ.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { omniston } from './config.cjs';
|
|
2
|
-
export { A as AssetId, C as ChainAddress, E as EscrowMessage, H as HtlcSecretStore, O as ObservableLike, a as OmnistonClientLike, b as OmnistonProviderOptions, c as OmnistonQuote, d as OmnistonQuoteStore, e as OrderEvent, f as OrderExecution, g as OrderSettlement, h as OrderSnapshot, Q as QuoteRequest, R as RfqEvent, S as SwapSettlement, i as SwapTrackEvent, T as TON_SWAP_PROTOCOL_LAYOUTS, j as TonSwapCheckInput, k as TonSwapCheckResult, l as TonSwapLeg, m as TonSwapPayloadError, n as checkTonSwapPayload, o as encodeTypedMessage, p as inMemoryQuoteStore, q as inMemorySecretStore, r as omnistonPins, s as omnistonProvider, t as omnistonVerifyBuild, v as validateEvmToTonOrderExtension, u as validateEvmTypedOrder } from './provider-
|
|
2
|
+
export { A as AssetId, C as ChainAddress, E as EscrowMessage, H as HtlcSecretStore, O as ObservableLike, a as OmnistonClientLike, b as OmnistonProviderOptions, c as OmnistonQuote, d as OmnistonQuoteStore, e as OrderEvent, f as OrderExecution, g as OrderSettlement, h as OrderSnapshot, Q as QuoteRequest, R as RfqEvent, S as SwapSettlement, i as SwapTrackEvent, T as TON_SWAP_PROTOCOL_LAYOUTS, j as TonSwapCheckInput, k as TonSwapCheckResult, l as TonSwapLeg, m as TonSwapPayloadError, n as checkTonSwapPayload, o as encodeTypedMessage, p as inMemoryQuoteStore, q as inMemorySecretStore, r as omnistonPins, s as omnistonProvider, t as omnistonVerifyBuild, v as validateEvmToTonOrderExtension, u as validateEvmTypedOrder } from './provider-CcCZB-Cj.cjs';
|
|
3
3
|
export { OmnistonSwap2Config, OmnistonSwap2Protocol, OmnistonSwap2Protocol as default } from './protocol.cjs';
|
|
4
4
|
export { OMNISTON_ESCROWS, OMNISTON_MODULE, STONFI_ROUTERS, describeOmnistonActivity } from './activity.cjs';
|
|
5
5
|
import '@anywalletkit/protocol-swap2-core/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { omniston } from './config.js';
|
|
2
|
-
export { A as AssetId, C as ChainAddress, E as EscrowMessage, H as HtlcSecretStore, O as ObservableLike, a as OmnistonClientLike, b as OmnistonProviderOptions, c as OmnistonQuote, d as OmnistonQuoteStore, e as OrderEvent, f as OrderExecution, g as OrderSettlement, h as OrderSnapshot, Q as QuoteRequest, R as RfqEvent, S as SwapSettlement, i as SwapTrackEvent, T as TON_SWAP_PROTOCOL_LAYOUTS, j as TonSwapCheckInput, k as TonSwapCheckResult, l as TonSwapLeg, m as TonSwapPayloadError, n as checkTonSwapPayload, o as encodeTypedMessage, p as inMemoryQuoteStore, q as inMemorySecretStore, r as omnistonPins, s as omnistonProvider, t as omnistonVerifyBuild, v as validateEvmToTonOrderExtension, u as validateEvmTypedOrder } from './provider-
|
|
2
|
+
export { A as AssetId, C as ChainAddress, E as EscrowMessage, H as HtlcSecretStore, O as ObservableLike, a as OmnistonClientLike, b as OmnistonProviderOptions, c as OmnistonQuote, d as OmnistonQuoteStore, e as OrderEvent, f as OrderExecution, g as OrderSettlement, h as OrderSnapshot, Q as QuoteRequest, R as RfqEvent, S as SwapSettlement, i as SwapTrackEvent, T as TON_SWAP_PROTOCOL_LAYOUTS, j as TonSwapCheckInput, k as TonSwapCheckResult, l as TonSwapLeg, m as TonSwapPayloadError, n as checkTonSwapPayload, o as encodeTypedMessage, p as inMemoryQuoteStore, q as inMemorySecretStore, r as omnistonPins, s as omnistonProvider, t as omnistonVerifyBuild, v as validateEvmToTonOrderExtension, u as validateEvmTypedOrder } from './provider-CcCZB-Cj.js';
|
|
3
3
|
export { OmnistonSwap2Config, OmnistonSwap2Protocol, OmnistonSwap2Protocol as default } from './protocol.js';
|
|
4
4
|
export { OMNISTON_ESCROWS, OMNISTON_MODULE, STONFI_ROUTERS, describeOmnistonActivity } from './activity.js';
|
|
5
5
|
import '@anywalletkit/protocol-swap2-core/types';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OmnistonSwap2Protocol
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4MKR2SUZ.js";
|
|
4
4
|
import {
|
|
5
5
|
TON_SWAP_PROTOCOL_LAYOUTS,
|
|
6
6
|
TonSwapPayloadError,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
omnistonVerifyBuild,
|
|
14
14
|
validateEvmToTonOrderExtension,
|
|
15
15
|
validateEvmTypedOrder
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2DGCZD5K.js";
|
|
17
17
|
import {
|
|
18
18
|
omniston
|
|
19
19
|
} from "./chunk-QDXFC6BC.js";
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
STONFI_ROUTERS,
|
|
24
24
|
describeOmnistonActivity
|
|
25
25
|
} from "./chunk-AIWAM7BS.js";
|
|
26
|
+
import "./chunk-JWYDIW4V.js";
|
|
26
27
|
export {
|
|
27
28
|
OMNISTON_ESCROWS,
|
|
28
29
|
OMNISTON_MODULE,
|
package/dist/protocol.cjs
CHANGED
|
@@ -500,18 +500,36 @@ function toChainAddress(caip2, address) {
|
|
|
500
500
|
if (!$case) return null;
|
|
501
501
|
return { chain: { $case, value: (0, import_viem.getAddress)(address) } };
|
|
502
502
|
}
|
|
503
|
-
|
|
504
|
-
|
|
503
|
+
var QUOTE_DIGEST_SKIP = /* @__PURE__ */ new Set(["rfqId", "resolverName", "estimatedSettlementDuration", "estimatedGasConsumption"]);
|
|
504
|
+
function canonicalJson(value) {
|
|
505
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
506
|
+
if (value && typeof value === "object") {
|
|
507
|
+
return `{${Object.keys(value).sort().map((k) => `${JSON.stringify(k)}:${canonicalJson(value[k])}`).join(",")}}`;
|
|
508
|
+
}
|
|
509
|
+
return JSON.stringify(value) ?? "null";
|
|
510
|
+
}
|
|
511
|
+
function quoteDigest(q) {
|
|
512
|
+
const terms = JSON.parse(JSON.stringify(q));
|
|
513
|
+
for (const key of QUOTE_DIGEST_SKIP) delete terms[key];
|
|
514
|
+
return (0, import_viem.sha256)(new TextEncoder().encode(canonicalJson(terms))).slice(2, 34);
|
|
515
|
+
}
|
|
516
|
+
var QUOTE_DIGEST = /^[0-9a-f]{32}$/;
|
|
517
|
+
function encodeIntent(quoteId, trader, dest, srcChain, kind, digest) {
|
|
518
|
+
return [INTENT_PREFIX, quoteId, trader, `${dest}#${digest}`, srcChain, ...kind === "swap" ? ["swap"] : []].map(encodeURIComponent).join("|");
|
|
505
519
|
}
|
|
506
520
|
var QUOTE_ID = /^[0-9a-fA-F]{48,64}$/;
|
|
507
521
|
function decodeIntent(intentId) {
|
|
508
522
|
try {
|
|
509
523
|
const parts = intentId.split("|");
|
|
510
524
|
if (parts.length !== 5 && parts.length !== 6 || parts[0] !== INTENT_PREFIX) return null;
|
|
511
|
-
const [, quoteId = "", trader = "",
|
|
525
|
+
const [, quoteId = "", trader = "", destPart = "", srcChain = "", kindPart = ""] = parts.map(decodeURIComponent);
|
|
526
|
+
const mark = destPart.lastIndexOf("#");
|
|
527
|
+
const dest = mark < 0 ? destPart : destPart.slice(0, mark);
|
|
528
|
+
const digest = mark < 0 ? void 0 : destPart.slice(mark + 1);
|
|
529
|
+
if (digest !== void 0 && !QUOTE_DIGEST.test(digest)) return null;
|
|
512
530
|
if (!QUOTE_ID.test(quoteId) || !trader || !dest || !srcChain) return null;
|
|
513
531
|
if (parts.length === 6 && kindPart !== "swap") return null;
|
|
514
|
-
return { quoteId, trader, dest, srcChain, kind: parts.length === 6 ? "swap" : "order" };
|
|
532
|
+
return { quoteId, trader, dest, srcChain, kind: parts.length === 6 ? "swap" : "order", ...digest ? { digest } : {} };
|
|
515
533
|
} catch {
|
|
516
534
|
return null;
|
|
517
535
|
}
|
|
@@ -632,9 +650,9 @@ function validEvmAddress(value) {
|
|
|
632
650
|
}
|
|
633
651
|
}
|
|
634
652
|
var EVM_DEST_PROTOCOL_FEE_RECIPIENTS = /* @__PURE__ */ new Set(["0x076268146b4ec6d21fc49c27586cfa91b9079a00"]);
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
653
|
+
var EVM_AUCTION_POINTS = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
|
|
654
|
+
var EVM_TIMELOCKS = [1n, 120n, 240n, 300n, 1n, 120n, 180n, 0n].reduce((packed, value, index) => packed | value << BigInt(index * 32), 0n);
|
|
655
|
+
function readEvmOrderExtension(extension) {
|
|
638
656
|
if (extension.length < 32) throw new Error("omniston: malformed EVM order extension");
|
|
639
657
|
const view = new DataView(extension.buffer, extension.byteOffset, extension.byteLength);
|
|
640
658
|
const fields = [];
|
|
@@ -654,54 +672,48 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
654
672
|
}
|
|
655
673
|
let target;
|
|
656
674
|
for (const index of [2, 3, 7]) {
|
|
657
|
-
const
|
|
658
|
-
if (
|
|
659
|
-
const address = (0, import_viem.getAddress)(`0x${bytesToHex(
|
|
660
|
-
if (
|
|
675
|
+
const field2 = fields[index];
|
|
676
|
+
if (field2.length <= 20) throw new Error("omniston: incomplete EVM order extension program");
|
|
677
|
+
const address = (0, import_viem.getAddress)(`0x${bytesToHex(field2.slice(0, 20))}`);
|
|
678
|
+
if (target !== void 0 && (0, import_viem.getAddress)(target) !== address) {
|
|
661
679
|
throw new Error("omniston: EVM order extension target is not independently trusted");
|
|
662
680
|
}
|
|
663
681
|
target = address;
|
|
664
682
|
}
|
|
665
|
-
const
|
|
683
|
+
const field = fields[2];
|
|
666
684
|
let cursor = 20;
|
|
667
|
-
const gasBump = readBigEndian(
|
|
685
|
+
const gasBump = readBigEndian(field, cursor, 3);
|
|
668
686
|
cursor += 3;
|
|
669
|
-
const gasPrice = readBigEndian(
|
|
687
|
+
const gasPrice = readBigEndian(field, cursor, 4);
|
|
670
688
|
cursor += 4;
|
|
671
|
-
const auctionStart = readBigEndian(
|
|
689
|
+
const auctionStart = readBigEndian(field, cursor, 4);
|
|
672
690
|
cursor += 4;
|
|
673
|
-
const duration = readBigEndian(
|
|
691
|
+
const duration = readBigEndian(field, cursor, 3);
|
|
674
692
|
cursor += 3;
|
|
675
|
-
const initialRateBump = readBigEndian(
|
|
693
|
+
const initialRateBump = readBigEndian(field, cursor, 3);
|
|
676
694
|
cursor += 3;
|
|
677
|
-
const pointCount = (0, import_core4.bigintToNumber)(readBigEndian(
|
|
695
|
+
const pointCount = (0, import_core4.bigintToNumber)(readBigEndian(field, cursor, 1));
|
|
678
696
|
cursor += 1;
|
|
679
697
|
if (pointCount !== 5) throw new Error("omniston: unsupported EVM auction profile");
|
|
680
698
|
const points = [];
|
|
681
699
|
for (let index = 0; index < pointCount; index++) {
|
|
682
|
-
points.push([readBigEndian(
|
|
700
|
+
points.push([readBigEndian(field, cursor, 3), readBigEndian(field, cursor + 3, 2)]);
|
|
683
701
|
cursor += 5;
|
|
684
702
|
}
|
|
685
|
-
const integratorFee = readBigEndian(
|
|
703
|
+
const integratorFee = readBigEndian(field, cursor, 2);
|
|
686
704
|
cursor += 2;
|
|
687
|
-
const integratorShare = readBigEndian(
|
|
705
|
+
const integratorShare = readBigEndian(field, cursor, 1);
|
|
688
706
|
cursor += 1;
|
|
689
|
-
const resolverFee = readBigEndian(
|
|
707
|
+
const resolverFee = readBigEndian(field, cursor, 2);
|
|
690
708
|
cursor += 2;
|
|
691
|
-
const whitelistDiscount = readBigEndian(
|
|
709
|
+
const whitelistDiscount = readBigEndian(field, cursor, 1);
|
|
692
710
|
cursor += 1;
|
|
693
|
-
const getterWhitelistCount = (0, import_core4.bigintToNumber)(readBigEndian(
|
|
711
|
+
const getterWhitelistCount = (0, import_core4.bigintToNumber)(readBigEndian(field, cursor, 1));
|
|
694
712
|
cursor += 1;
|
|
695
|
-
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !==
|
|
713
|
+
if (getterWhitelistCount !== 1 || cursor + getterWhitelistCount * 10 !== field.length) {
|
|
696
714
|
throw new Error("omniston: malformed EVM amount-getter whitelist");
|
|
697
715
|
}
|
|
698
|
-
const
|
|
699
|
-
const expectedPoints = [[800000n, 100n], [700000n, 100n], [600000n, 100n], [500000n, 100n], [400000n, 100n]];
|
|
700
|
-
const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
|
|
701
|
-
const resolverLow80 = BigInt((0, import_viem.getAddress)(expected.initialResolverAddress)) & (1n << 80n) - 1n;
|
|
702
|
-
if (gasBump !== 0n || gasPrice !== 0n || !within(auctionStart, expected.quoteTimestamp, 5, 5) || duration !== 1800n || initialRateBump !== 900000n || points.some((point, index) => point[0] !== expectedPoints[index][0] || point[1] !== expectedPoints[index][1]) || expected.integratorFeePips !== 0 || integratorFee !== 0n || integratorShare !== 100n || quoteResolverFee < 0n || resolverFee !== quoteResolverFee || whitelistDiscount !== 50n || getterResolver !== resolverLow80) {
|
|
703
|
-
throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
|
|
704
|
-
}
|
|
716
|
+
const getter = { gasBump, gasPrice, auctionStart, duration, initialRateBump, points, integratorFee, integratorShare, resolverFee, whitelistDiscount, resolver: readBigEndian(field, cursor, 10) };
|
|
705
717
|
const post = fields[7];
|
|
706
718
|
cursor = 20;
|
|
707
719
|
const integratorRecipient = post.slice(cursor, cursor + 20);
|
|
@@ -727,28 +739,51 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
727
739
|
cursor += 10;
|
|
728
740
|
const resolverTimeDelta = readBigEndian(post, cursor, 2);
|
|
729
741
|
cursor += 2;
|
|
730
|
-
if (!zeroBytes(integratorRecipient) || !(zeroBytes(protocolRecipient) || evmDest && EVM_DEST_PROTOCOL_FEE_RECIPIENTS.has(`0x${bytesToHex(protocolRecipient)}`)) || postIntegratorFee !== 0n || postIntegratorShare !== 100n || postResolverFee !== quoteResolverFee || postDiscount !== 50n || !within(allowedTime, expected.quoteTimestamp, 60, 5) || postResolver !== resolverLow80 || resolverTimeDelta !== 0n) {
|
|
731
|
-
throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
|
|
732
|
-
}
|
|
733
742
|
const extra = Array.from({ length: 5 }, () => {
|
|
734
743
|
const value = readBigEndian(post, cursor, 32);
|
|
735
744
|
cursor += 32;
|
|
736
745
|
return value;
|
|
737
746
|
});
|
|
747
|
+
const customData = extension.slice(32 + begin);
|
|
748
|
+
if (customData.length !== 131) throw new Error("omniston: malformed EVM order extension custom data");
|
|
749
|
+
return {
|
|
750
|
+
target,
|
|
751
|
+
getter,
|
|
752
|
+
post: { integratorRecipient, protocolRecipient, integratorFee: postIntegratorFee, integratorShare: postIntegratorShare, resolverFee: postResolverFee, discount: postDiscount, allowedTime, resolver: postResolver, resolverTimeDelta },
|
|
753
|
+
extra,
|
|
754
|
+
customData
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
async function validateEvmToTonOrderExtension(extension, expected) {
|
|
758
|
+
const evmDest = expected.dstChainId !== void 0;
|
|
759
|
+
if (evmDest && (!Number.isSafeInteger(expected.dstChainId) || expected.dstChainId <= 0)) throw new Error("omniston: invalid EVM destination chain id");
|
|
760
|
+
const { target, getter, post, extra, customData } = readEvmOrderExtension(extension);
|
|
761
|
+
if (!expected.trustedTarget(target)) throw new Error("omniston: EVM order extension target is not independently trusted");
|
|
762
|
+
const quoteResolverFee = expected.protocolFeePips % 10 === 0 ? BigInt(expected.protocolFeePips / 10) : -1n;
|
|
763
|
+
const resolverLow80 = BigInt((0, import_viem.getAddress)(expected.initialResolverAddress)) & (1n << 80n) - 1n;
|
|
764
|
+
if (getter.gasBump !== 0n || getter.gasPrice !== 0n || !within(getter.auctionStart, expected.quoteTimestamp, 5, 5) || getter.duration !== 1800n || getter.initialRateBump !== 900000n || getter.points.some((point, index) => point[0] !== EVM_AUCTION_POINTS[index][0] || point[1] !== EVM_AUCTION_POINTS[index][1]) || expected.integratorFeePips !== 0 || getter.integratorFee !== 0n || getter.integratorShare !== 100n || quoteResolverFee < 0n || getter.resolverFee !== quoteResolverFee || getter.whitelistDiscount !== 50n || getter.resolver !== resolverLow80) {
|
|
765
|
+
throw new Error("omniston: EVM amount-getter terms do not match the pinned v1beta8 profile");
|
|
766
|
+
}
|
|
767
|
+
if (!zeroBytes(post.integratorRecipient) || !(zeroBytes(post.protocolRecipient) || evmDest && EVM_DEST_PROTOCOL_FEE_RECIPIENTS.has(`0x${bytesToHex(post.protocolRecipient)}`)) || post.integratorFee !== 0n || post.integratorShare !== 100n || post.resolverFee !== quoteResolverFee || post.discount !== 50n || !within(post.allowedTime, expected.quoteTimestamp, 60, 5) || post.resolver !== resolverLow80 || post.resolverTimeDelta !== 0n) {
|
|
768
|
+
throw new Error("omniston: EVM post-interaction terms do not match the pinned v1beta8 profile");
|
|
769
|
+
}
|
|
738
770
|
const hashlock2 = readBigEndian(expected.secretHash, 0, expected.secretHash.length);
|
|
739
771
|
const dstToken = evmDest ? BigInt((0, import_viem.getAddress)(expected.outputTokenAddress)) : BigInt((0, import_viem.getAddress)(expected.takerAsset));
|
|
740
772
|
const deposits = BigInt(expected.srcSecurityDepositUnits) << 128n | BigInt(expected.dstSecurityDepositUnits);
|
|
741
|
-
|
|
742
|
-
if (expected.secretHash.length !== 32 || extra[0] !== hashlock2 || extra[1] !== (evmDest ? BigInt(expected.dstChainId) : 0n) || extra[2] !== dstToken || extra[3] !== deposits || extra[4] !== timelocks) {
|
|
773
|
+
if (expected.secretHash.length !== 32 || extra[0] !== hashlock2 || extra[1] !== (evmDest ? BigInt(expected.dstChainId) : 0n) || extra[2] !== dstToken || extra[3] !== deposits || extra[4] !== EVM_TIMELOCKS) {
|
|
743
774
|
throw new Error("omniston: signed EVM HTLC terms do not match the validated order details");
|
|
744
775
|
}
|
|
745
|
-
|
|
746
|
-
if (
|
|
747
|
-
|
|
776
|
+
await checkOrderCustomData(customData, { evmDest, outputToken: expected.outputTokenAddress, traderDst: expected.traderDstAddress, quoteId: expected.quoteId });
|
|
777
|
+
if (expected.tradeStartDeadline < expected.quoteTimestamp) {
|
|
778
|
+
throw new Error("omniston: invalid EVM order quote deadline");
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
async function checkOrderCustomData(customData, expected) {
|
|
782
|
+
if (expected.evmDest) {
|
|
748
783
|
if (!zeroBytes(customData.slice(0, 66))) throw new Error("omniston: unexpected TON addresses in an EVM-destination order");
|
|
749
784
|
} else {
|
|
750
785
|
const { Address: Address3 } = await import("@ton/core");
|
|
751
|
-
const expectedTon = [expected.
|
|
786
|
+
const expectedTon = [expected.outputToken, expected.traderDst].map((value) => Address3.parse(value));
|
|
752
787
|
for (let index = 0; index < expectedTon.length; index++) {
|
|
753
788
|
const offset = index * 33;
|
|
754
789
|
const workchain = customData[offset] === 255 ? -1 : customData[offset];
|
|
@@ -764,9 +799,6 @@ async function validateEvmToTonOrderExtension(extension, expected) {
|
|
|
764
799
|
if (!QUOTE_ID.test(quoteId) || !sliceEqual(customData.slice(99), hexToBytes(quoteId.padStart(64, "0")))) {
|
|
765
800
|
throw new Error("omniston: EVM order extension custom data is not bound to the quote id");
|
|
766
801
|
}
|
|
767
|
-
if (expected.tradeStartDeadline < expected.quoteTimestamp) {
|
|
768
|
-
throw new Error("omniston: invalid EVM order quote deadline");
|
|
769
|
-
}
|
|
770
802
|
}
|
|
771
803
|
function validateEvmTypedOrder(td, expected) {
|
|
772
804
|
const value = td;
|
|
@@ -1346,7 +1378,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1346
1378
|
return true;
|
|
1347
1379
|
}
|
|
1348
1380
|
const a = existing.bound, b = entry.bound;
|
|
1349
|
-
const same = !!a && !!b && a.kind === b.kind && a.srcChain === b.srcChain && sameIntentAddress(a.trader, b.trader) && sameIntentAddress(a.dest, b.dest);
|
|
1381
|
+
const same = !!a && !!b && a.kind === b.kind && a.srcChain === b.srcChain && sameIntentAddress(a.trader, b.trader) && sameIntentAddress(a.dest, b.dest) && quoteDigest(existing.quote) === quoteDigest(entry.quote);
|
|
1350
1382
|
if (!same) return false;
|
|
1351
1383
|
await quotes.save(quoteId, json);
|
|
1352
1384
|
return true;
|
|
@@ -1399,10 +1431,19 @@ function omnistonProvider(opts = {}) {
|
|
|
1399
1431
|
throw new Error(`omniston: intent id does not match the quote it was issued for (${bound.field})`);
|
|
1400
1432
|
}
|
|
1401
1433
|
if (bound.legacy) trace("legacy-intent", { where });
|
|
1434
|
+
if (!decoded.digest) {
|
|
1435
|
+
trace("intent-mismatch", { where, field: "digest-missing" });
|
|
1436
|
+
throw new Error("omniston: this quote was issued before an update \u2014 request a fresh quote");
|
|
1437
|
+
}
|
|
1438
|
+
if (decoded.digest !== quoteDigest(entry.quote)) {
|
|
1439
|
+
trace("intent-mismatch", { where, field: "digest" });
|
|
1440
|
+
throw new Error("omniston: quote was replaced \u2014 request a fresh quote");
|
|
1441
|
+
}
|
|
1402
1442
|
return bound.ref;
|
|
1403
1443
|
}
|
|
1404
1444
|
const bindKey = (quoteId) => `${quoteId}#bind`;
|
|
1405
1445
|
const disclosedKey = (quoteId) => `${quoteId}#disclosed`;
|
|
1446
|
+
const disclosedIndicesKey = (quoteId) => `${quoteId}#disclosed-indices`;
|
|
1406
1447
|
function orderBinding(ref, q) {
|
|
1407
1448
|
return (0, import_viem.sha256)(new TextEncoder().encode(JSON.stringify([
|
|
1408
1449
|
ref.quoteId,
|
|
@@ -1419,6 +1460,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1419
1460
|
await store.clear(quoteId);
|
|
1420
1461
|
await store.clear(bindKey(quoteId));
|
|
1421
1462
|
await store.clear(disclosedKey(quoteId));
|
|
1463
|
+
await store.clear(disclosedIndicesKey(quoteId));
|
|
1422
1464
|
}
|
|
1423
1465
|
async function secretsFor(ref, q, count) {
|
|
1424
1466
|
const quoteId = ref.quoteId;
|
|
@@ -1447,7 +1489,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1447
1489
|
return !!existing && existing.length > 0;
|
|
1448
1490
|
}
|
|
1449
1491
|
const SWAP_SLIPPAGE_PIPS_DEFAULT = 5e3;
|
|
1450
|
-
const sameChainTonReady = () => typeof opts.validateTonJettonWallet === "function" && typeof opts.validateTonSwapTarget === "function";
|
|
1492
|
+
const sameChainTonReady = () => typeof opts.validateTonJettonWallet === "function" && typeof opts.validateTonSwapTarget === "function" && (typeof opts.validateTonSwapLeg === "function" || opts.tonSwapPayloadCheck === "report");
|
|
1451
1493
|
const tonSourceReady = (from, to) => omniston.supports(from, to) && trustedContracts.has(from) && trustedContracts.has(to) && typeof opts.validateTonJettonWallet === "function" && typeof opts.validateTonEscrowPayload === "function" && typeof opts.validateEvmOutputPosition === "function";
|
|
1452
1494
|
const evmSourceReady = (from, to) => omniston.supports(from, to) && trustedOrderProtocols.has(from) && trustedContracts.has(from) && trustedContracts.has(to) && typeof opts.validateEvmInputPosition === "function" && typeof opts.validateTonOutputPosition === "function";
|
|
1453
1495
|
const evmToEvmReady = (from, to) => omniston.supports(from, to) && trustedOrderProtocols.has(from) && trustedContracts.has(from) && trustedContracts.has(to) && typeof opts.validateEvmInputPosition === "function" && typeof opts.validateEvmOutputPosition === "function";
|
|
@@ -1526,7 +1568,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1526
1568
|
const feeUsd = stableOut ? feeUnits / 10 ** dest.decimals : 0;
|
|
1527
1569
|
return {
|
|
1528
1570
|
provider: "omniston",
|
|
1529
|
-
intentId: encodeIntent(q.quoteId, trader, params.destAddress, params.sourceChain, "swap"),
|
|
1571
|
+
intentId: encodeIntent(q.quoteId, trader, params.destAddress, params.sourceChain, "swap", quoteDigest(q)),
|
|
1530
1572
|
depositAddress: "",
|
|
1531
1573
|
// swap settlement — the built message pays the DEX directly
|
|
1532
1574
|
depositMemo: null,
|
|
@@ -1559,7 +1601,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1559
1601
|
if (!isTon(ref.srcChain) || q.inputAsset.chain.$case !== "ton" || q.outputAsset.chain.$case !== "ton") {
|
|
1560
1602
|
throw new Error("omniston: swap quote is not a TON same-chain swap");
|
|
1561
1603
|
}
|
|
1562
|
-
if (!sameChainTonReady()) throw new Error("omniston: TON same-chain swaps need independent jetton-wallet and swap-
|
|
1604
|
+
if (!sameChainTonReady()) throw new Error("omniston: TON same-chain swaps need independent jetton-wallet, swap-target and swap-leg validators");
|
|
1563
1605
|
const owner = { chain: { $case: "ton", value: ref.trader } };
|
|
1564
1606
|
const receiver = { chain: { $case: "ton", value: ref.dest } };
|
|
1565
1607
|
const omni = await getClient();
|
|
@@ -1658,7 +1700,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1658
1700
|
}
|
|
1659
1701
|
if (checked) {
|
|
1660
1702
|
if (typeof opts.validateTonSwapLeg !== "function") {
|
|
1661
|
-
|
|
1703
|
+
payloadRefusal("legs-unverified", `no validateTonSwapLeg hook for ${checked.legs.length} leg(s)`);
|
|
1662
1704
|
} else {
|
|
1663
1705
|
for (const leg of checked.legs) {
|
|
1664
1706
|
let ok = false;
|
|
@@ -1829,7 +1871,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1829
1871
|
}
|
|
1830
1872
|
});
|
|
1831
1873
|
const orderProtocol = (0, import_viem.getAddress)(protocol.chain.value);
|
|
1832
|
-
return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData };
|
|
1874
|
+
return { chain: srcChain, to: orderProtocol, value: "0", chainId, approvalAddress: orderProtocol, typedData, orderExtension: `0x${bytesToHex(payload.orderExtension)}` };
|
|
1833
1875
|
}
|
|
1834
1876
|
return {
|
|
1835
1877
|
name: "omniston",
|
|
@@ -1938,13 +1980,13 @@ function omnistonProvider(opts = {}) {
|
|
|
1938
1980
|
if (outputScaled * 2n < inputScaled || outputScaled > inputScaled * 2n) return refuse2("quoted output is outside 0.5x\u20132x of the input");
|
|
1939
1981
|
if (await quoteIdInUse(q.quoteId)) return refuse2("the platform reused a quote id that already belongs to an order");
|
|
1940
1982
|
if (!await claimBuilt(q.quoteId, { quote: q, at: Date.now(), bound: { trader, dest: params.destAddress, srcChain: params.sourceChain, kind: "order" } })) {
|
|
1941
|
-
return refuse2("the platform reused a quote id that already holds another
|
|
1983
|
+
return refuse2("the platform reused a quote id that already holds another quote");
|
|
1942
1984
|
}
|
|
1943
1985
|
const feeUnits = Number(q.protocolFeeUnits || "0") + Number(q.integratorFeeUnits || "0");
|
|
1944
1986
|
const feeUsd = feeUnits / 10 ** dest.decimals;
|
|
1945
1987
|
return {
|
|
1946
1988
|
provider: "omniston",
|
|
1947
|
-
intentId: encodeIntent(q.quoteId, trader, params.destAddress, params.sourceChain),
|
|
1989
|
+
intentId: encodeIntent(q.quoteId, trader, params.destAddress, params.sourceChain, "order", quoteDigest(q)),
|
|
1948
1990
|
depositAddress: "",
|
|
1949
1991
|
// order settlement — no static deposit address
|
|
1950
1992
|
depositMemo: null,
|
|
@@ -2116,6 +2158,7 @@ function omnistonProvider(opts = {}) {
|
|
|
2116
2158
|
);
|
|
2117
2159
|
if (!order) return { state: "pending" };
|
|
2118
2160
|
let secretsHex = await store.load(decoded.quoteId);
|
|
2161
|
+
const storedSecrets = secretsHex?.length ?? 0;
|
|
2119
2162
|
if (!secretsHex || cached?.quote.settlementData.$case !== "order") trace("disclosure-skipped", { gate: "context", secrets: !!secretsHex, cached: !!cached, feedStatus: order.status });
|
|
2120
2163
|
if (secretsHex && cached?.quote.settlementData.$case === "order") {
|
|
2121
2164
|
const [lockedTo] = await store.load(bindKey(decoded.quoteId)) ?? [];
|
|
@@ -2124,6 +2167,7 @@ function omnistonProvider(opts = {}) {
|
|
|
2124
2167
|
secretsHex = void 0;
|
|
2125
2168
|
}
|
|
2126
2169
|
}
|
|
2170
|
+
const disclosedNow = /* @__PURE__ */ new Set();
|
|
2127
2171
|
if (secretsHex && cached?.quote.settlementData.$case === "order") {
|
|
2128
2172
|
const q = cached.quote;
|
|
2129
2173
|
const settlement = q.settlementData.value;
|
|
@@ -2222,11 +2266,15 @@ function omnistonProvider(opts = {}) {
|
|
|
2222
2266
|
}
|
|
2223
2267
|
await omni.orderDiscloseHtlcSecret({ quoteId: decoded.quoteId, executionIndex: i, secret: secretBytes }).then(async () => {
|
|
2224
2268
|
trace("secret-disclosed", { index: i });
|
|
2269
|
+
disclosedNow.add(i);
|
|
2225
2270
|
await store.save(disclosedKey(decoded.quoteId), ["1"]);
|
|
2226
2271
|
}, (error) => trace("disclose-failed", { index: i, error: error instanceof Error ? error.message : String(error) }));
|
|
2227
2272
|
})
|
|
2228
2273
|
);
|
|
2229
2274
|
}
|
|
2275
|
+
const disclosedBefore = (await store.load(disclosedIndicesKey(decoded.quoteId)) ?? []).map(Number).filter(Number.isSafeInteger);
|
|
2276
|
+
const disclosedAll = /* @__PURE__ */ new Set([...disclosedBefore, ...disclosedNow]);
|
|
2277
|
+
if (disclosedNow.size > 0) await store.save(disclosedIndicesKey(decoded.quoteId), [...disclosedAll].sort((a, b) => a - b).map(String));
|
|
2230
2278
|
const status = mapOrderStatus(order);
|
|
2231
2279
|
const delivered = order.executions[0]?.outputPositionAddress;
|
|
2232
2280
|
const outCase = cached?.quote.outputAsset.chain.$case;
|
|
@@ -2251,6 +2299,14 @@ function omnistonProvider(opts = {}) {
|
|
|
2251
2299
|
}).catch(() => null);
|
|
2252
2300
|
if (hash) status.destTxHash = hash;
|
|
2253
2301
|
}
|
|
2302
|
+
if (status.state === "completed" && storedSecrets > 0 && !status.destTxHash) {
|
|
2303
|
+
const legacyDisclosed = disclosedBefore.length === 0 && storedSecrets === 1 && (await store.load(disclosedKey(decoded.quoteId)) ?? []).length > 0;
|
|
2304
|
+
const allDisclosed = legacyDisclosed || (order.executions.length > 0 ? order.executions.every((execution) => disclosedAll.has(execution.index)) : disclosedAll.size > 0);
|
|
2305
|
+
if (!allDisclosed) {
|
|
2306
|
+
trace("completion-unproven", { feedStatus: order.status, executions: order.executions.length, disclosed: disclosedAll.size });
|
|
2307
|
+
return { state: "pending", depositReceived: order.executions.length > 0 || disclosedAll.size > 0 };
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2254
2310
|
if (status.state === "completed") {
|
|
2255
2311
|
await clearSecrets(decoded.quoteId);
|
|
2256
2312
|
await quotes.clear(decoded.quoteId);
|