@hyperbridge/sdk 2.7.2 → 2.8.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.
@@ -1610,6 +1610,24 @@ var ABI2 = [
1610
1610
  internalType: "uint256"
1611
1611
  }
1612
1612
  ]
1613
+ },
1614
+ {
1615
+ name: "predispatchCall",
1616
+ type: "bytes",
1617
+ indexed: false,
1618
+ internalType: "bytes"
1619
+ },
1620
+ {
1621
+ name: "outputCall",
1622
+ type: "bytes",
1623
+ indexed: false,
1624
+ internalType: "bytes"
1625
+ },
1626
+ {
1627
+ name: "graffiti",
1628
+ type: "bytes32",
1629
+ indexed: false,
1630
+ internalType: "bytes32"
1613
1631
  }
1614
1632
  ],
1615
1633
  anonymous: false
@@ -2340,6 +2358,49 @@ async function rpcCall(url, payload) {
2340
2358
  throw lastErr;
2341
2359
  }
2342
2360
  var FILL_ORDER_ABI = IntentGatewayV2_default.ABI;
2361
+ var DECLARATION_VERSION = 1;
2362
+ var MAX_DECLARED_CHAINS = 255;
2363
+ function encodeAcceptedSourceChains(chains) {
2364
+ if (chains.length > MAX_DECLARED_CHAINS) {
2365
+ throw new Error(`Cannot declare more than ${MAX_DECLARED_CHAINS} source chains`);
2366
+ }
2367
+ const bytes = [DECLARATION_VERSION, chains.length];
2368
+ for (const chain of chains) {
2369
+ const encoded = util.stringToU8a(chain);
2370
+ if (encoded.length === 0 || encoded.length > 255) {
2371
+ throw new Error(`Invalid state machine id in source chain declaration: ${chain}`);
2372
+ }
2373
+ bytes.push(encoded.length, ...encoded);
2374
+ }
2375
+ return util.u8aToHex(new Uint8Array(bytes));
2376
+ }
2377
+ function decodeAcceptedSourceChains(paymasterAndData) {
2378
+ if (!paymasterAndData || !util.isHex(paymasterAndData)) return null;
2379
+ const bytes = util.hexToU8a(paymasterAndData);
2380
+ if (bytes.length < 2 || bytes[0] !== DECLARATION_VERSION) return null;
2381
+ const count = bytes[1];
2382
+ const chains = [];
2383
+ let offset = 2;
2384
+ for (let entry = 0; entry < count; entry++) {
2385
+ if (offset >= bytes.length) return null;
2386
+ const length = bytes[offset];
2387
+ offset += 1;
2388
+ if (length === 0 || offset + length > bytes.length) return null;
2389
+ chains.push(util.u8aToString(bytes.subarray(offset, offset + length)));
2390
+ offset += length;
2391
+ }
2392
+ if (offset !== bytes.length) return null;
2393
+ return chains;
2394
+ }
2395
+ function zipFillLegs(assets, outputs) {
2396
+ return assets.map((asset, index) => {
2397
+ const rawAmount = outputs[index]?.amount;
2398
+ return {
2399
+ outputToken: asset.token,
2400
+ solverAmount: rawAmount === void 0 || rawAmount === null ? 0n : BigInt(rawAmount.toString())
2401
+ };
2402
+ });
2403
+ }
2343
2404
  function weightedMedian(entries) {
2344
2405
  const sorted = [...entries].sort((a, b) => a.price < b.price ? -1 : a.price > b.price ? 1 : 0);
2345
2406
  const totalWeight = sorted.reduce((acc, e) => e.weight > 0n ? acc + e.weight : acc, 0n);
@@ -2365,10 +2426,10 @@ function extractFillData(callData, gatewayAddress) {
2365
2426
  if (decoded.functionName !== "fillOrder" || !decoded.args || decoded.args.length < 2) continue;
2366
2427
  const order = decoded.args[0];
2367
2428
  const options = decoded.args[1];
2368
- const outputToken = order?.output?.assets?.[0]?.token;
2429
+ const assets = order?.output?.assets;
2369
2430
  const outputs = options?.outputs;
2370
- if (!outputToken || !outputs?.length) continue;
2371
- return { order, options, outputToken, solverAmount: outputs[0].amount };
2431
+ if (!assets?.length || !outputs?.length) continue;
2432
+ return { order, options, legs: zipFillLegs(assets, outputs) };
2372
2433
  } catch {
2373
2434
  continue;
2374
2435
  }
@@ -2486,13 +2547,25 @@ async function getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVault
2486
2547
  );
2487
2548
  return vaultBalances.reduce((acc, b) => acc + b, raw);
2488
2549
  }
2489
- async function sweepSolverLiquidity(evmRpcUrls, yieldVaults, solver) {
2550
+ function memoizedSolverBalance(yieldVaults) {
2551
+ const cache = /* @__PURE__ */ new Map();
2552
+ return (evmRpcUrl, chain, token, solver) => {
2553
+ const key = `${chain}|${token.toLowerCase()}|${solver.toLowerCase()}`;
2554
+ let pending = cache.get(key);
2555
+ if (!pending) {
2556
+ pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults);
2557
+ cache.set(key, pending);
2558
+ }
2559
+ return pending;
2560
+ };
2561
+ }
2562
+ async function sweepSolverLiquidity(evmRpcUrls, yieldVaults, solver, getBalance) {
2490
2563
  const balances = [];
2491
2564
  for (const [chain, tokens] of Object.entries(yieldVaults)) {
2492
2565
  const url = evmRpcUrls[chain];
2493
2566
  if (!url) continue;
2494
2567
  for (const token of Object.keys(tokens)) {
2495
- const balance = await getTotalSolverBalance(url, chain, token, solver, yieldVaults);
2568
+ const balance = await getBalance(url, chain, token, solver);
2496
2569
  if (balance === 0n) continue;
2497
2570
  balances.push({ solver, chain, tokenAddress: token, balance });
2498
2571
  }
@@ -2519,7 +2592,8 @@ async function aggregatePhantomBids(params) {
2519
2592
  }
2520
2593
  const bids = await fetchBidsForOrder(nodeUrl, commitment);
2521
2594
  if (bids.length === 0) return null;
2522
- const quotes = [];
2595
+ const getBalance = params.getBalance ?? memoizedSolverBalance(yieldVaults);
2596
+ const quotesByLeg = /* @__PURE__ */ new Map();
2523
2597
  const lpBalances = [];
2524
2598
  const countedSolvers = /* @__PURE__ */ new Set();
2525
2599
  for (const bid of bids) {
@@ -2557,39 +2631,59 @@ async function aggregatePhantomBids(params) {
2557
2631
  continue;
2558
2632
  }
2559
2633
  countedSolvers.add(normalizedSolver);
2560
- const outputTokenAddress = toAddress(fillData.outputToken);
2561
- const weight = await getTotalSolverBalance(destUrl, chain, outputTokenAddress, solver, yieldVaults);
2562
- quotes.push({ price: fillData.solverAmount, weight });
2563
- lpBalances.push(...await sweepSolverLiquidity(evmRpcUrls, yieldVaults, solver));
2634
+ const acceptedSources = decodeAcceptedSourceChains(decoded.paymasterAndData);
2635
+ const quotedLegs = [...fillData.legs.entries()].filter(([, leg]) => leg.solverAmount !== 0n);
2636
+ const weights = await Promise.all(
2637
+ // Price influence: the solver's liquidity in THIS leg's output token on the destination
2638
+ // chain, so a leg is weighted by the inventory that actually backs it.
2639
+ quotedLegs.map(([, leg]) => getBalance(destUrl, chain, toAddress(leg.outputToken), solver))
2640
+ );
2641
+ for (const [position, [legIndex, leg]] of quotedLegs.entries()) {
2642
+ const weight = weights[position];
2643
+ const entry = quotesByLeg.get(legIndex) ?? { outputToken: leg.outputToken, quotes: [], bidders: [] };
2644
+ entry.quotes.push({ price: leg.solverAmount, weight });
2645
+ entry.bidders.push({ solver: normalizedSolver, weight, acceptedSources });
2646
+ quotesByLeg.set(legIndex, entry);
2647
+ }
2648
+ lpBalances.push(...await sweepSolverLiquidity(evmRpcUrls, yieldVaults, solver, getBalance));
2564
2649
  } catch (err) {
2565
2650
  logger?.warn({ err, filler: bid.filler }, "Failed to process bid for price snapshot");
2566
2651
  }
2567
2652
  }
2568
- if (quotes.length === 0) return null;
2569
- const medianPrice = weightedMedian(quotes);
2570
- return {
2571
- lowestPrice: medianPrice,
2572
- highestPrice: medianPrice,
2573
- medianPrice,
2574
- bidCount: quotes.length,
2575
- lpBalances
2576
- };
2653
+ if (quotesByLeg.size === 0) return null;
2654
+ const legs = [...quotesByLeg.entries()].sort(([a], [b]) => a - b).map(([legIndex, { outputToken, quotes, bidders }]) => {
2655
+ const medianPrice = weightedMedian(quotes);
2656
+ return {
2657
+ legIndex,
2658
+ outputToken,
2659
+ lowestPrice: medianPrice,
2660
+ highestPrice: medianPrice,
2661
+ medianPrice,
2662
+ bidCount: quotes.length,
2663
+ bidders
2664
+ };
2665
+ });
2666
+ return { legs, lpBalances };
2577
2667
  }
2578
2668
 
2579
2669
  exports.ENTRY_POINT_V08_ADDRESS = ENTRY_POINT_V08_ADDRESS;
2580
2670
  exports.FILL_ORDER_ABI = FILL_ORDER_ABI;
2581
2671
  exports.IntentGatewayV2 = IntentGatewayV2_default;
2582
2672
  exports.aggregatePhantomBids = aggregatePhantomBids;
2673
+ exports.decodeAcceptedSourceChains = decodeAcceptedSourceChains;
2583
2674
  exports.decodeERC7821ExecuteBatch = decodeERC7821ExecuteBatch;
2584
2675
  exports.decodeUserOpScale = decodeUserOpScale;
2676
+ exports.encodeAcceptedSourceChains = encodeAcceptedSourceChains;
2585
2677
  exports.encodeERC7821ExecuteBatch = encodeERC7821ExecuteBatch;
2586
2678
  exports.encodeUserOpScale = encodeUserOpScale;
2587
2679
  exports.extractFillData = extractFillData;
2588
2680
  exports.fetchBidsForOrder = fetchBidsForOrder;
2681
+ exports.memoizedSolverBalance = memoizedSolverBalance;
2589
2682
  exports.orderCommitmentFromDecoded = orderCommitmentFromDecoded;
2590
2683
  exports.recoverBidSignerViem = recoverBidSignerViem;
2591
2684
  exports.setAggregationFetch = setAggregationFetch;
2592
2685
  exports.splitBidSignature = splitBidSignature;
2593
2686
  exports.weightedMedian = weightedMedian;
2687
+ exports.zipFillLegs = zipFillLegs;
2594
2688
  //# sourceMappingURL=intents-helpers.cjs.map
2595
2689
  //# sourceMappingURL=intents-helpers.cjs.map