@anywalletkit/protocol-swap2-omniston 0.2.8 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1
- package/dist/{chunk-KNT2XSQU.js → chunk-HOTFZYSW.js} +136 -9
- package/dist/chunk-HOTFZYSW.js.map +1 -0
- package/dist/{chunk-KVDPDEJB.js → chunk-RW4XZWNC.js} +2 -2
- package/dist/index.cjs +136 -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 +10 -4
- package/dist/protocol.cjs +52 -8
- 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 +2 -2
- package/dist/provider-BBG2zhpu.d.cts +772 -0
- package/dist/provider-BBG2zhpu.d.ts +772 -0
- package/dist/provider.cjs +136 -9
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +2 -590
- package/dist/provider.d.ts +2 -590
- package/dist/provider.js +9 -3
- package/dist/validators.cjs +144 -32
- package/dist/validators.cjs.map +1 -1
- package/dist/validators.d.cts +2 -93
- package/dist/validators.d.ts +2 -93
- package/dist/validators.js +144 -32
- package/dist/validators.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-KNT2XSQU.js.map +0 -1
- /package/dist/{chunk-KVDPDEJB.js.map → chunk-RW4XZWNC.js.map} +0 -0
package/dist/provider.cjs
CHANGED
|
@@ -36,8 +36,11 @@ __export(provider_exports, {
|
|
|
36
36
|
encodeTypedMessage: () => encodeTypedMessage,
|
|
37
37
|
inMemoryQuoteStore: () => inMemoryQuoteStore,
|
|
38
38
|
inMemorySecretStore: () => inMemorySecretStore,
|
|
39
|
+
omnistonPins: () => omnistonPins,
|
|
39
40
|
omnistonProvider: () => omnistonProvider,
|
|
40
|
-
|
|
41
|
+
omnistonVerifyBuild: () => omnistonVerifyBuild,
|
|
42
|
+
validateEvmToTonOrderExtension: () => validateEvmToTonOrderExtension,
|
|
43
|
+
validateEvmTypedOrder: () => validateEvmTypedOrder
|
|
41
44
|
});
|
|
42
45
|
module.exports = __toCommonJS(provider_exports);
|
|
43
46
|
var import_core3 = require("@ton/core");
|
|
@@ -456,7 +459,12 @@ function inMemoryQuoteStore() {
|
|
|
456
459
|
return {
|
|
457
460
|
save: (id, v) => void map.set(id, v),
|
|
458
461
|
load: (id) => map.get(id),
|
|
459
|
-
clear: (id) => void map.delete(id)
|
|
462
|
+
clear: (id) => void map.delete(id),
|
|
463
|
+
claim: (id, v) => {
|
|
464
|
+
if (map.has(id)) return false;
|
|
465
|
+
map.set(id, v);
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
460
468
|
};
|
|
461
469
|
}
|
|
462
470
|
function inMemorySecretStore() {
|
|
@@ -1030,6 +1038,13 @@ function validSwapSettlement(q) {
|
|
|
1030
1038
|
const v = q.settlementData.value;
|
|
1031
1039
|
return Array.isArray(v.routes) && v.routes.length > 0 && v.routes.every((route) => Array.isArray(route?.steps) && route.steps.length > 0 && route.steps.every((step) => Array.isArray(step?.chunks) && step.chunks.length > 0 && step.chunks.every((chunk) => typeof chunk?.protocol === "string" && chunk.protocol.length > 0 && isPositiveInteger(chunk.inputUnits) && isPositiveInteger(chunk.outputUnits)))) && isPositiveInteger(v.minOutputAmount) && BigInt(v.minOutputAmount) <= BigInt(q.outputUnits) && (v.recommendedMinOutputAmount === void 0 || isPositiveInteger(v.recommendedMinOutputAmount) && BigInt(v.recommendedMinOutputAmount) <= BigInt(q.outputUnits)) && (q.gasBudget === void 0 || isPositiveInteger(q.gasBudget));
|
|
1032
1040
|
}
|
|
1041
|
+
function swapSteps(v) {
|
|
1042
|
+
if (v.routes.length !== 1) return [{ protocol: `${v.routes.length}-routes`, inputJetton: void 0, outputJetton: void 0 }];
|
|
1043
|
+
return v.routes[0].steps.map((step) => {
|
|
1044
|
+
if (step.chunks.length !== 1) return { protocol: `split(${step.chunks.map((c) => c.protocol).join("|")})`, inputJetton: void 0, outputJetton: void 0 };
|
|
1045
|
+
return { protocol: step.chunks[0].protocol, inputJetton: stepJetton(step.inputAsset), outputJetton: stepJetton(step.outputAsset) };
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1033
1048
|
function swapProtocols(v) {
|
|
1034
1049
|
const names = /* @__PURE__ */ new Set();
|
|
1035
1050
|
for (const route of v.routes) for (const step of route.steps) for (const chunk of step.chunks) names.add(chunk.protocol);
|
|
@@ -1206,6 +1221,86 @@ function mapOrderStatus(order) {
|
|
|
1206
1221
|
return { state: "pending", depositReceived };
|
|
1207
1222
|
}
|
|
1208
1223
|
}
|
|
1224
|
+
function omnistonPins(trustedEvmOrderProtocols) {
|
|
1225
|
+
const byChain = new Map(Object.entries(trustedEvmOrderProtocols).map(([chain, list]) => [chain, list.map((a) => (0, import_viem.getAddress)(a))]));
|
|
1226
|
+
return Object.freeze({ callTargets: () => [], spenders: (chain) => byChain.get(chain) ?? [] });
|
|
1227
|
+
}
|
|
1228
|
+
function omnistonVerifyBuild(hooks) {
|
|
1229
|
+
return async (quote, tx, params) => {
|
|
1230
|
+
if (tx.bodyBoc === void 0) return null;
|
|
1231
|
+
if (!params) return "the request this quote answered is unknown";
|
|
1232
|
+
if (quote.providerData?.settlement !== "swap") {
|
|
1233
|
+
if (params.sourceChain.startsWith("ton:") && params.destChain.startsWith("eip155:")) {
|
|
1234
|
+
if (!hooks.verifyTonEscrowBuild) return "a TON \u2192 EVM escrow body needs verifyTonEscrowBuild (createOmnistonTonValidators)";
|
|
1235
|
+
if (!params.refundAddress) return "the trader's TON address (refundAddress) is unknown";
|
|
1236
|
+
const floor = [quote.minDestAmount, params.minAmountOut ?? "0"].filter((v) => /^\d{1,80}$/.test(v)).map((v) => BigInt(v)).reduce((a, b) => a > b ? a : b, 0n);
|
|
1237
|
+
try {
|
|
1238
|
+
return await hooks.verifyTonEscrowBuild({
|
|
1239
|
+
payloadBocHex: import_buffer2.Buffer.from(tx.bodyBoc, "base64").toString("hex"),
|
|
1240
|
+
ownerAddress: params.refundAddress,
|
|
1241
|
+
inputUnits: quote.sourceAmount,
|
|
1242
|
+
destinationChain: params.destChain,
|
|
1243
|
+
destinationAddress: params.destAddress,
|
|
1244
|
+
outputTokenAddress: params.destToken,
|
|
1245
|
+
minResolverSendsUnits: floor.toString()
|
|
1246
|
+
});
|
|
1247
|
+
} catch {
|
|
1248
|
+
return "the escrow body could not be checked";
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
return "only TON swap and TON \u2192 EVM escrow bodies can be checked on the client";
|
|
1252
|
+
}
|
|
1253
|
+
let steps;
|
|
1254
|
+
try {
|
|
1255
|
+
steps = JSON.parse(quote.providerData.routeSteps ?? "");
|
|
1256
|
+
} catch {
|
|
1257
|
+
return "the quote carries no route steps";
|
|
1258
|
+
}
|
|
1259
|
+
if (!Array.isArray(steps) || steps.length === 0) return "the quote carries no route steps";
|
|
1260
|
+
const source = (0, import_swap2_assets.ccAsset)(params.sourceChain, params.sourceToken);
|
|
1261
|
+
const dest = (0, import_swap2_assets.ccAssetByToken)(params.destChain, params.destToken);
|
|
1262
|
+
if (!source || !dest) return "unknown source or destination token";
|
|
1263
|
+
const protocols = (quote.providerData.protocols ?? "").split(",").filter(Boolean);
|
|
1264
|
+
let checked;
|
|
1265
|
+
try {
|
|
1266
|
+
checked = checkTonSwapPayload({
|
|
1267
|
+
payloadHex: import_buffer2.Buffer.from(tx.bodyBoc, "base64").toString("hex"),
|
|
1268
|
+
targetAddress: tx.to,
|
|
1269
|
+
sendAmount: BigInt(tx.value),
|
|
1270
|
+
trader: params.refundAddress ?? "",
|
|
1271
|
+
dest: params.destAddress,
|
|
1272
|
+
inputUnits: quote.sourceAmount,
|
|
1273
|
+
minOutputAmount: quote.minDestAmount,
|
|
1274
|
+
inputJetton: source.contract ?? null,
|
|
1275
|
+
outputJetton: dest.contract ?? null,
|
|
1276
|
+
steps: steps.map((st) => ({ protocol: String(st.protocol), inputJetton: st.inputJetton, outputJetton: st.outputJetton })),
|
|
1277
|
+
integratorAddress: hooks.integratorAddress ?? null
|
|
1278
|
+
});
|
|
1279
|
+
} catch (e) {
|
|
1280
|
+
return e instanceof Error ? e.message.replace(/^omniston: /, "") : String(e);
|
|
1281
|
+
}
|
|
1282
|
+
const payload = parseSwapPayload(import_buffer2.Buffer.from(tx.bodyBoc, "base64").toString("hex"));
|
|
1283
|
+
const target = source.contract ? payload.jettonTransfer?.destination : tx.to;
|
|
1284
|
+
if (!target) return "the body names no swap destination";
|
|
1285
|
+
try {
|
|
1286
|
+
if (!await hooks.validateTonSwapTarget({ address: target, protocols })) return `${target} is not a recognized DEX contract for ${protocols.join("+")}`;
|
|
1287
|
+
} catch {
|
|
1288
|
+
return "the swap target could not be checked";
|
|
1289
|
+
}
|
|
1290
|
+
if (hooks.validateTonSwapLeg) {
|
|
1291
|
+
for (const leg of checked.legs) {
|
|
1292
|
+
let ok = false;
|
|
1293
|
+
try {
|
|
1294
|
+
ok = await hooks.validateTonSwapLeg(leg);
|
|
1295
|
+
} catch {
|
|
1296
|
+
ok = false;
|
|
1297
|
+
}
|
|
1298
|
+
if (!ok) return `${leg.kind} v${leg.version} leg not verified`;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return null;
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1209
1304
|
function omnistonProvider(opts = {}) {
|
|
1210
1305
|
opts = Object.freeze({ ...opts });
|
|
1211
1306
|
const apiUrl = opts.apiUrl ?? "wss://omni-ws.ston.fi";
|
|
@@ -1323,6 +1418,26 @@ function omnistonProvider(opts = {}) {
|
|
|
1323
1418
|
async function saveBuilt(quoteId, entry) {
|
|
1324
1419
|
await quotes.save(quoteId, JSON.stringify(entry));
|
|
1325
1420
|
}
|
|
1421
|
+
async function claimBuilt(quoteId, entry) {
|
|
1422
|
+
const json = JSON.stringify(entry);
|
|
1423
|
+
if (typeof quotes.claim === "function") {
|
|
1424
|
+
if (await quotes.claim(quoteId, json)) return true;
|
|
1425
|
+
} else if (!await quotes.load(quoteId)) {
|
|
1426
|
+
await quotes.save(quoteId, json);
|
|
1427
|
+
return true;
|
|
1428
|
+
}
|
|
1429
|
+
const existing = await loadBuilt(quoteId);
|
|
1430
|
+
if (!existing) {
|
|
1431
|
+
if (typeof quotes.claim === "function") return await quotes.claim(quoteId, json);
|
|
1432
|
+
await quotes.save(quoteId, json);
|
|
1433
|
+
return true;
|
|
1434
|
+
}
|
|
1435
|
+
const a = existing.bound, b = entry.bound;
|
|
1436
|
+
const same = !!a && !!b && a.kind === b.kind && a.srcChain === b.srcChain && sameIntentAddress(a.trader, b.trader) && sameIntentAddress(a.dest, b.dest);
|
|
1437
|
+
if (!same) return false;
|
|
1438
|
+
await quotes.save(quoteId, json);
|
|
1439
|
+
return true;
|
|
1440
|
+
}
|
|
1326
1441
|
async function loadBuilt(quoteId) {
|
|
1327
1442
|
const raw2 = await quotes.load(quoteId);
|
|
1328
1443
|
if (!raw2) return void 0;
|
|
@@ -1489,7 +1604,10 @@ function omnistonProvider(opts = {}) {
|
|
|
1489
1604
|
if (BigInt(swap.minOutputAmount) < requiredMin(q.outputUnits)) return null;
|
|
1490
1605
|
if (q.gasBudget !== void 0 && BigInt(q.gasBudget) > BigInt(maxTonExecutionNano)) return null;
|
|
1491
1606
|
const minOut = swap.minOutputAmount;
|
|
1492
|
-
await
|
|
1607
|
+
if (!await claimBuilt(q.quoteId, { quote: q, at: Date.now(), bound: { trader, dest: params.destAddress, srcChain: params.sourceChain, kind: "swap" } })) {
|
|
1608
|
+
traceFor(q.quoteId)("quote-id-reused", { kind: "swap" });
|
|
1609
|
+
return null;
|
|
1610
|
+
}
|
|
1493
1611
|
const feeUnits = Number(q.protocolFeeUnits || "0") + Number(q.integratorFeeUnits || "0");
|
|
1494
1612
|
const stableOut = /^(USDT|USDC|USD₮|jUSDT)$/.test(dest.symbol);
|
|
1495
1613
|
const feeUsd = stableOut ? feeUnits / 10 ** dest.decimals : 0;
|
|
@@ -1516,6 +1634,8 @@ function omnistonProvider(opts = {}) {
|
|
|
1516
1634
|
providerData: {
|
|
1517
1635
|
settlement: "swap",
|
|
1518
1636
|
protocols: swapProtocols(swap).join(","),
|
|
1637
|
+
// For the app's own check of a remote build (omnistonVerifyBuild): the route the body must follow.
|
|
1638
|
+
routeSteps: JSON.stringify(swapSteps(swap)),
|
|
1519
1639
|
...q.gasBudget ? { gasBudget: q.gasBudget } : {},
|
|
1520
1640
|
...q.estimatedGasConsumption ? { gasEstimate: q.estimatedGasConsumption } : {}
|
|
1521
1641
|
}
|
|
@@ -1616,10 +1736,7 @@ function omnistonProvider(opts = {}) {
|
|
|
1616
1736
|
minOutputAmount: swap.minOutputAmount,
|
|
1617
1737
|
inputJetton,
|
|
1618
1738
|
outputJetton: assetContract(q.outputAsset),
|
|
1619
|
-
steps: swap
|
|
1620
|
-
if (step.chunks.length !== 1) return { protocol: `split(${step.chunks.map((c) => c.protocol).join("|")})`, inputJetton: void 0, outputJetton: void 0 };
|
|
1621
|
-
return { protocol: step.chunks[0].protocol, inputJetton: stepJetton(step.inputAsset), outputJetton: stepJetton(step.outputAsset) };
|
|
1622
|
-
}) : [{ protocol: `${swap.routes.length}-routes`, inputJetton: void 0, outputJetton: void 0 }],
|
|
1739
|
+
steps: swapSteps(swap),
|
|
1623
1740
|
integratorAddress: q.integratorAddress?.chain.$case === "ton" ? q.integratorAddress.chain.value : null
|
|
1624
1741
|
});
|
|
1625
1742
|
} catch (error) {
|
|
@@ -1907,7 +2024,9 @@ function omnistonProvider(opts = {}) {
|
|
|
1907
2024
|
const outputScaled = BigInt(q.outputUnits) * 10n ** BigInt(source.decimals);
|
|
1908
2025
|
if (outputScaled * 2n < inputScaled || outputScaled > inputScaled * 2n) return refuse2("quoted output is outside 0.5x\u20132x of the input");
|
|
1909
2026
|
if (await quoteIdInUse(q.quoteId)) return refuse2("the platform reused a quote id that already belongs to an order");
|
|
1910
|
-
await
|
|
2027
|
+
if (!await claimBuilt(q.quoteId, { quote: q, at: Date.now(), bound: { trader, dest: params.destAddress, srcChain: params.sourceChain, kind: "order" } })) {
|
|
2028
|
+
return refuse2("the platform reused a quote id that already holds another user's quote");
|
|
2029
|
+
}
|
|
1911
2030
|
const feeUnits = Number(q.protocolFeeUnits || "0") + Number(q.integratorFeeUnits || "0");
|
|
1912
2031
|
const feeUsd = feeUnits / 10 ** dest.decimals;
|
|
1913
2032
|
return {
|
|
@@ -2039,6 +2158,7 @@ function omnistonProvider(opts = {}) {
|
|
|
2039
2158
|
await forget();
|
|
2040
2159
|
throw error;
|
|
2041
2160
|
}
|
|
2161
|
+
await saveBuilt(ref.quoteId, { quote: q, at: Date.now(), ...cached.bound ? { bound: cached.bound } : {} });
|
|
2042
2162
|
return {
|
|
2043
2163
|
chain: srcChain,
|
|
2044
2164
|
to: message.targetAddress,
|
|
@@ -2082,8 +2202,15 @@ function omnistonProvider(opts = {}) {
|
|
|
2082
2202
|
})
|
|
2083
2203
|
);
|
|
2084
2204
|
if (!order) return { state: "pending" };
|
|
2085
|
-
|
|
2205
|
+
let secretsHex = await store.load(decoded.quoteId);
|
|
2086
2206
|
if (!secretsHex || cached?.quote.settlementData.$case !== "order") trace("disclosure-skipped", { gate: "context", secrets: !!secretsHex, cached: !!cached, feedStatus: order.status });
|
|
2207
|
+
if (secretsHex && cached?.quote.settlementData.$case === "order") {
|
|
2208
|
+
const [lockedTo] = await store.load(bindKey(decoded.quoteId)) ?? [];
|
|
2209
|
+
if (lockedTo !== orderBinding(bound, cached.quote)) {
|
|
2210
|
+
trace("disclosure-skipped", { gate: "binding", bound: lockedTo !== void 0, feedStatus: order.status });
|
|
2211
|
+
secretsHex = void 0;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2087
2214
|
if (secretsHex && cached?.quote.settlementData.$case === "order") {
|
|
2088
2215
|
const q = cached.quote;
|
|
2089
2216
|
const settlement = q.settlementData.value;
|