@anywalletkit/protocol-swap2-omniston 0.5.2 → 0.5.4

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.
@@ -34,7 +34,10 @@ __export(validators_exports, {
34
34
  createOmnistonEvmOutputValidator: () => createOmnistonEvmOutputValidator,
35
35
  createOmnistonTonDeliveryLocator: () => createOmnistonTonDeliveryLocator,
36
36
  createOmnistonTonValidators: () => createOmnistonTonValidators,
37
- omnistonEvmRpcRequest: () => omnistonEvmRpcRequest
37
+ omnistonEvmRpcRequest: () => omnistonEvmRpcRequest,
38
+ omnistonQuorumValidator: () => omnistonQuorumValidator,
39
+ omnistonRpcOperator: () => omnistonRpcOperator,
40
+ omnistonRpcOperatorGroups: () => omnistonRpcOperatorGroups
38
41
  });
39
42
  module.exports = __toCommonJS(validators_exports);
40
43
 
@@ -179,6 +182,9 @@ function decodeFeeParameters(parameters) {
179
182
  async function omnistonEvmRpcRequest(chain, method, params, rpcUrls) {
180
183
  const urls = [...rpcUrls?.[chain] ?? [], ...DEFAULT_RPC_URLS[chain] ?? []].filter((url) => !!url);
181
184
  if (!urls.length) throw new Error(`omniston: no RPC configured for ${chain}`);
185
+ return await rpcOver(urls, chain, method, params);
186
+ }
187
+ async function rpcOver(urls, chain, method, params) {
182
188
  let lastError;
183
189
  for (const url of urls) {
184
190
  try {
@@ -198,6 +204,62 @@ async function omnistonEvmRpcRequest(chain, method, params, rpcUrls) {
198
204
  }
199
205
  throw lastError instanceof Error ? lastError : new Error(`omniston: RPC failed for ${chain}`);
200
206
  }
207
+ function omnistonRpcOperator(url) {
208
+ const host = new URL(url).hostname.toLowerCase().replace(/\.$/, "");
209
+ if (/^[\d.]+$/.test(host) || host.includes(":") || host.startsWith("[")) return host;
210
+ return host.split(".").slice(-2).join(".");
211
+ }
212
+ function omnistonRpcOperatorGroups(chain, rpcUrls, operatorOf = omnistonRpcOperator) {
213
+ const groups = [];
214
+ const seen = /* @__PURE__ */ new Set();
215
+ for (const url of [...rpcUrls?.[chain] ?? [], ...DEFAULT_RPC_URLS[chain] ?? []]) {
216
+ if (!url || seen.has(url)) continue;
217
+ seen.add(url);
218
+ let operator;
219
+ try {
220
+ operator = operatorOf(url);
221
+ } catch {
222
+ continue;
223
+ }
224
+ const group = groups.find((g) => g.operator === operator);
225
+ if (group) group.urls.push(url);
226
+ else groups.push({ operator, urls: [url] });
227
+ }
228
+ return groups;
229
+ }
230
+ function pinnedStateRequest(request) {
231
+ let pinned = null;
232
+ return async (chain, method, params) => {
233
+ if (method === "eth_blockNumber") {
234
+ const head = await request(chain, method, params);
235
+ const latest = BigInt(head);
236
+ const confirmations = OMNISTON_EVM_MIN_CONFIRMATIONS[chain] ?? 20n;
237
+ pinned = quantity(latest >= confirmations ? latest - confirmations : 0n);
238
+ return head;
239
+ }
240
+ if (pinned && (method === "eth_call" || method === "eth_getCode" || method === "eth_getBalance") && params.at(-1) === "latest") {
241
+ return await request(chain, method, [...params.slice(0, -1), pinned]);
242
+ }
243
+ return await request(chain, method, params);
244
+ };
245
+ }
246
+ function omnistonQuorumValidator(options, refuse, once) {
247
+ const quorum = options.quorum ?? 1;
248
+ if (!Number.isSafeInteger(quorum) || quorum < 1) throw new Error("omniston: quorum must be a positive integer");
249
+ if (quorum === 1) {
250
+ const request = options.request ?? ((chain, method, params) => omnistonEvmRpcRequest(chain, method, params, options.rpcUrls));
251
+ return (input) => once(request, input, refuse);
252
+ }
253
+ if (options.request) throw new Error("omniston: an RPC quorum needs rpcUrls (one request per operator), not a single request");
254
+ return async (input) => {
255
+ const groups = omnistonRpcOperatorGroups(input.chain, options.rpcUrls, options.operatorOf);
256
+ const operators = groups.map((g) => g.operator);
257
+ if (groups.length < quorum) return refuse("rpc-quorum-unavailable", { chain: input.chain, operators, quorum });
258
+ const results = await Promise.all(groups.map((g) => once(pinnedStateRequest((chain, method, params) => rpcOver(g.urls, chain, method, params)), input, (reason, details) => refuse(reason, { ...details, operator: g.operator })).catch(() => false)));
259
+ const agreed = operators.filter((_, i) => results[i]);
260
+ return agreed.length >= quorum || refuse("rpc-quorum-not-met", { chain: input.chain, agreed, operators, quorum });
261
+ };
262
+ }
201
263
  async function ethCall(request, chain, to, data) {
202
264
  return await request(chain, "eth_call", [{ to, data }, "latest"]);
203
265
  }
@@ -231,16 +293,15 @@ function locateImmutables(input, secretHash) {
231
293
  }
232
294
  }
233
295
  function createOmnistonEvmOutputValidator(options = {}) {
234
- const refuse = (reason, details) => {
296
+ const report = (reason, details) => {
235
297
  try {
236
298
  options.onRefusal?.(reason, details);
237
299
  } catch {
238
300
  }
239
301
  return false;
240
302
  };
241
- const request = options.request ?? ((chain, method, params) => omnistonEvmRpcRequest(chain, method, params, options.rpcUrls));
242
303
  const now = options.now ?? Date.now;
243
- return async (input) => {
304
+ return omnistonQuorumValidator(options, report, async (request, input, refuse) => {
244
305
  try {
245
306
  if (!OMNISTON_EVM_LOOKBACK_BLOCKS[input.chain] || input.executionIndex !== 0 || !(0, import_viem.isAddress)(input.positionAddress) || !(0, import_viem.isAddress)(input.factoryAddress) || !(0, import_viem.isAddress)(input.recipientAddress) || !(0, import_viem.isAddress)(input.outputTokenAddress) || !Number.isInteger(input.quoteTimestamp) || input.quoteTimestamp * 1e3 > now() + 12e4 || now() - input.quoteTimestamp * 1e3 > 6 * 60 * 60 * 1e3) return refuse("input-shape");
246
307
  const position = (0, import_viem.getAddress)(input.positionAddress);
@@ -337,7 +398,7 @@ function createOmnistonEvmOutputValidator(options = {}) {
337
398
  } catch (error) {
338
399
  return refuse("error", { message: error instanceof Error ? error.message : String(error) });
339
400
  }
340
- };
401
+ });
341
402
  }
342
403
  var TRANSFER_TOPIC = (0, import_viem.keccak256)((0, import_viem.stringToHex)("Transfer(address,address,uint256)"));
343
404
  var topicAddress = (address) => `0x${(0, import_viem.getAddress)(address).slice(2).toLowerCase().padStart(64, "0")}`;
@@ -440,16 +501,15 @@ async function ethCall2(request, chain, to, data) {
440
501
  return await request(chain, "eth_call", [{ to, data }, "latest"]);
441
502
  }
442
503
  function createOmnistonEvmInputValidator(options = {}) {
443
- const refuse = (reason, details) => {
504
+ const report = (reason, details) => {
444
505
  try {
445
506
  options.onRefusal?.(reason, details);
446
507
  } catch {
447
508
  }
448
509
  return false;
449
510
  };
450
- const request = options.request ?? ((chain, method, params) => omnistonEvmRpcRequest(chain, method, params, options.rpcUrls));
451
511
  const now = options.now ?? Date.now;
452
- return async (input) => {
512
+ return omnistonQuorumValidator(options, report, async (request, input, refuse) => {
453
513
  try {
454
514
  if (!OMNISTON_EVM_LOOKBACK_BLOCKS[input.chain] || !(0, import_viem2.isAddress)(input.positionAddress) || !(0, import_viem2.isAddress)(input.factoryAddress) || !(0, import_viem2.isAddress)(input.orderProtocolAddress) || !(0, import_viem2.isAddress)(input.ownerAddress) || !(0, import_viem2.isAddress)(input.resolverAddress) || !(0, import_viem2.isAddress)(input.inputTokenAddress) || !Number.isInteger(input.quoteTimestamp) || input.quoteTimestamp * 1e3 > now() + 12e4 || now() - input.quoteTimestamp * 1e3 > 6 * 60 * 60 * 1e3 || input.secretHash.length !== 32) return refuse("input-shape");
455
515
  const position = (0, import_viem2.getAddress)(input.positionAddress);
@@ -524,7 +584,7 @@ function createOmnistonEvmInputValidator(options = {}) {
524
584
  } catch (error) {
525
585
  return refuse("error", { message: error instanceof Error ? error.message : String(error) });
526
586
  }
527
- };
587
+ });
528
588
  }
529
589
 
530
590
  // src/validators/ton.ts