@hyperbridge/sdk 2.8.7 → 2.8.10

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.
@@ -3,7 +3,7 @@
3
3
  var viem = require('viem');
4
4
  require('@polkadot/api');
5
5
  var util = require('@polkadot/util');
6
- require('@polkadot/util-crypto');
6
+ var utilCrypto = require('@polkadot/util-crypto');
7
7
  var scaleTs = require('scale-ts');
8
8
  require('p-queue');
9
9
  var accounts = require('viem/accounts');
@@ -578,6 +578,11 @@ var ABI2 = [
578
578
  type: "uint256",
579
579
  internalType: "uint256"
580
580
  },
581
+ {
582
+ name: "validUntil",
583
+ type: "uint256",
584
+ internalType: "uint256"
585
+ },
581
586
  {
582
587
  name: "outputs",
583
588
  type: "tuple[]",
@@ -1888,6 +1893,7 @@ var ABI2 = [
1888
1893
  var IntentGatewayV2_default = { ABI: ABI2 };
1889
1894
 
1890
1895
  // src/chains/intentsCoprocessor.ts
1896
+ util.u8aToHex(util.u8aConcat(utilCrypto.xxhashAsU8a("System", 128), utilCrypto.xxhashAsU8a("Events", 128)));
1891
1897
  new TextEncoder().encode("intents::bid::");
1892
1898
  new TextEncoder().encode("intents::phantom::order::");
1893
1899
  scaleTs.Struct({ filler: scaleTs.Bytes(32), user_op: scaleTs.Vector(scaleTs.u8) });
@@ -1947,6 +1953,53 @@ function sortPoolSymbols(symbolA, symbolB) {
1947
1953
  function poolSlug(symbolA, symbolB) {
1948
1954
  return sortPoolSymbols(symbolA, symbolB).join("-");
1949
1955
  }
1956
+ var FILL_ORDER_V1_ABI = [
1957
+ {
1958
+ type: "function",
1959
+ name: "fillOrder",
1960
+ stateMutability: "payable",
1961
+ outputs: [],
1962
+ inputs: [
1963
+ ABI2.find((e) => e.type === "function" && e.name === "fillOrder").inputs[0],
1964
+ {
1965
+ name: "options",
1966
+ type: "tuple",
1967
+ internalType: "struct FillOptions",
1968
+ components: [
1969
+ { name: "relayerFee", type: "uint256", internalType: "uint256" },
1970
+ { name: "nativeDispatchFee", type: "uint256", internalType: "uint256" },
1971
+ {
1972
+ name: "outputs",
1973
+ type: "tuple[]",
1974
+ internalType: "struct TokenInfo[]",
1975
+ components: [
1976
+ { name: "token", type: "bytes32", internalType: "bytes32" },
1977
+ { name: "amount", type: "uint256", internalType: "uint256" }
1978
+ ]
1979
+ }
1980
+ ]
1981
+ }
1982
+ ]
1983
+ }
1984
+ ];
1985
+ function decodeFillOrder(data) {
1986
+ try {
1987
+ const decoded = viem.decodeFunctionData({ abi: ABI2, data });
1988
+ if (decoded.functionName === "fillOrder" && decoded.args && decoded.args.length >= 2) {
1989
+ return { order: decoded.args[0], options: decoded.args[1] };
1990
+ }
1991
+ } catch {
1992
+ }
1993
+ try {
1994
+ const decoded = viem.decodeFunctionData({ abi: FILL_ORDER_V1_ABI, data });
1995
+ if (decoded.functionName === "fillOrder" && decoded.args && decoded.args.length >= 2) {
1996
+ const legacy = decoded.args[1];
1997
+ return { order: decoded.args[0], options: { ...legacy, validUntil: 0n } };
1998
+ }
1999
+ } catch {
2000
+ }
2001
+ return null;
2002
+ }
1950
2003
  var SELECT_SOLVER_TYPEHASH = viem.keccak256(viem.toHex("SelectSolver(bytes32 commitment,address solver)"));
1951
2004
  var PACKED_USEROP_TYPEHASH = viem.keccak256(
1952
2005
  viem.toHex(
@@ -2593,6 +2646,17 @@ function zipFillLegs(assets, outputs) {
2593
2646
  };
2594
2647
  });
2595
2648
  }
2649
+ var UNISWAP_QUOTE_HAIRCUT_BPS = 10n;
2650
+ var PHANTOM_QUOTE_HAIRCUT_BPS = 5n;
2651
+ function haircut(amount, bps) {
2652
+ return amount * (10000n - bps) / 10000n;
2653
+ }
2654
+ function applyUniswapQuoteHaircut(amount) {
2655
+ return haircut(amount, UNISWAP_QUOTE_HAIRCUT_BPS);
2656
+ }
2657
+ function applyPhantomQuoteHaircut(amount) {
2658
+ return haircut(amount, PHANTOM_QUOTE_HAIRCUT_BPS);
2659
+ }
2596
2660
  function weightedMedian(entries) {
2597
2661
  const sorted = [...entries].sort((a, b) => a.price < b.price ? -1 : a.price > b.price ? 1 : 0);
2598
2662
  const totalWeight = sorted.reduce((acc, e) => e.weight > 0n ? acc + e.weight : acc, 0n);
@@ -2614,10 +2678,10 @@ function extractFillData(callData, gatewayAddress) {
2614
2678
  for (const call of calls) {
2615
2679
  if (call.target.toLowerCase() !== normalized) continue;
2616
2680
  try {
2617
- const decoded = viem.decodeFunctionData({ abi: FILL_ORDER_ABI, data: call.data });
2618
- if (decoded.functionName !== "fillOrder" || !decoded.args || decoded.args.length < 2) continue;
2619
- const order = decoded.args[0];
2620
- const options = decoded.args[1];
2681
+ const decoded = decodeFillOrder(call.data);
2682
+ if (!decoded) continue;
2683
+ const order = decoded.order;
2684
+ const options = decoded.options;
2621
2685
  const assets = order?.output?.assets;
2622
2686
  const outputs = options?.outputs;
2623
2687
  if (!assets?.length || !outputs?.length) continue;
@@ -2744,12 +2808,12 @@ async function fetchBidsForOrder(nodeUrl, commitment) {
2744
2808
  });
2745
2809
  return Array.isArray(data.result) ? data.result : [];
2746
2810
  }
2747
- async function ethCallUint(evmRpcUrl, to, data) {
2811
+ async function ethCallUint(evmRpcUrl, to, data, blockTag = "latest") {
2748
2812
  const result = await rpcCall(evmRpcUrl, {
2749
2813
  id: 1,
2750
2814
  jsonrpc: "2.0",
2751
2815
  method: "eth_call",
2752
- params: [{ to, data }, "latest"]
2816
+ params: [{ to, data }, blockTag]
2753
2817
  });
2754
2818
  if (result.result === "0x") return 0n;
2755
2819
  if (typeof result.result !== "string") {
@@ -2757,12 +2821,12 @@ async function ethCallUint(evmRpcUrl, to, data) {
2757
2821
  }
2758
2822
  return BigInt(result.result);
2759
2823
  }
2760
- async function getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults) {
2824
+ async function getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults, blockTag = "latest") {
2761
2825
  const padded = solver.replace("0x", "").padStart(64, "0");
2762
- const raw = await ethCallUint(evmRpcUrl, token, `0x70a08231${padded}`);
2826
+ const raw = await ethCallUint(evmRpcUrl, token, `0x70a08231${padded}`, blockTag);
2763
2827
  const vaults = yieldVaults[chain]?.[token.toLowerCase()] ?? [];
2764
2828
  const vaultBalances = await Promise.all(
2765
- vaults.map((v) => ethCallUint(evmRpcUrl, v, `0xce96cb77${padded}`))
2829
+ vaults.map((v) => ethCallUint(evmRpcUrl, v, `0xce96cb77${padded}`, blockTag))
2766
2830
  // maxWithdraw(address)
2767
2831
  );
2768
2832
  return vaultBalances.reduce((acc, b) => acc + b, raw);
@@ -2772,13 +2836,14 @@ var SELECTOR_POSITION_LIQUIDITY = "0x1efeed33";
2772
2836
  var SELECTOR_POOL_AND_POSITION_INFO = "0x7ba03aad";
2773
2837
  var SELECTOR_GET_SLOT0 = "0xc815641c";
2774
2838
  var uint256Arg = (value) => value.toString(16).padStart(64, "0");
2775
- async function readV4Position(evmRpcUrl, contracts, tokenId, keccak, logger) {
2839
+ async function readV4Position(params) {
2840
+ const { evmRpcUrl, contracts, tokenId, keccak, blockTag = "latest", logger } = params;
2776
2841
  const call = async (to, data) => {
2777
2842
  const result = await rpcCall(evmRpcUrl, {
2778
2843
  id: 1,
2779
2844
  jsonrpc: "2.0",
2780
2845
  method: "eth_call",
2781
- params: [{ to, data }, "latest"]
2846
+ params: [{ to, data }, blockTag]
2782
2847
  });
2783
2848
  if (result.result === "0x") return null;
2784
2849
  if (typeof result.result !== "string") {
@@ -2822,7 +2887,7 @@ function memoizedV4Position(keccak, logger) {
2822
2887
  const key = `${chain}|${tokenId}`;
2823
2888
  let pending = cache.get(key);
2824
2889
  if (!pending) {
2825
- pending = readV4Position(evmRpcUrl, contracts, tokenId, keccak, logger).catch((err) => {
2890
+ pending = readV4Position({ evmRpcUrl, contracts, tokenId, keccak, logger }).catch((err) => {
2826
2891
  cache.delete(key);
2827
2892
  throw err;
2828
2893
  });
@@ -2831,13 +2896,13 @@ function memoizedV4Position(keccak, logger) {
2831
2896
  return pending;
2832
2897
  };
2833
2898
  }
2834
- function memoizedSolverBalance(yieldVaults) {
2899
+ function memoizedSolverBalance(yieldVaults, blockTags = {}) {
2835
2900
  const cache = /* @__PURE__ */ new Map();
2836
2901
  return (evmRpcUrl, chain, token, solver) => {
2837
2902
  const key = `${chain}|${token.toLowerCase()}|${solver.toLowerCase()}`;
2838
2903
  let pending = cache.get(key);
2839
2904
  if (!pending) {
2840
- pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults).catch((err) => {
2905
+ pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults, blockTags[chain]).catch((err) => {
2841
2906
  cache.delete(key);
2842
2907
  throw err;
2843
2908
  });
@@ -2912,6 +2977,7 @@ async function runAggregation(params, isDelegated) {
2912
2977
  const getBalance = params.getBalance ?? memoizedSolverBalance(yieldVaults);
2913
2978
  const quotesByLeg = /* @__PURE__ */ new Map();
2914
2979
  const lpBalances = [];
2980
+ const verifiedPositions = [];
2915
2981
  const countedSolvers = /* @__PURE__ */ new Set();
2916
2982
  for (const bid of bids) {
2917
2983
  if (!bid.user_op) continue;
@@ -2951,21 +3017,33 @@ async function runAggregation(params, isDelegated) {
2951
3017
  countedSolvers.add(normalizedSolver);
2952
3018
  const declaration = decodePhantomBidDeclaration(decoded.paymasterAndData);
2953
3019
  const acceptedSources = declaration.acceptedSources;
2954
- const quotedLegs = [...fillData.legs.entries()].filter(([, leg]) => leg.solverAmount !== 0n);
3020
+ const poolPriced = declaration.uniswapV4Positions.length > 0;
3021
+ const applyHaircut = poolPriced ? applyUniswapQuoteHaircut : applyPhantomQuoteHaircut;
3022
+ const quotedLegs = [...fillData.legs.entries()].map(([legIndex, leg]) => [
3023
+ legIndex,
3024
+ { ...leg, solverAmount: applyHaircut(leg.solverAmount) }
3025
+ ]).filter(([, leg]) => leg.solverAmount !== 0n);
2955
3026
  const declaredPositions = v4Contracts ? declaration.uniswapV4Positions : [];
2956
- const positions = (await Promise.all(
2957
- declaredPositions.map((tokenId) => readPosition(destUrl, chain, v4Contracts, tokenId))
2958
- )).filter((state, index) => {
2959
- if (!state) return false;
2960
- if (state.owner !== normalizedSolver) {
3027
+ const ownedPositions = (await Promise.all(
3028
+ declaredPositions.map(async (tokenId) => ({
3029
+ tokenId,
3030
+ state: await readPosition(destUrl, chain, v4Contracts, tokenId)
3031
+ }))
3032
+ )).filter((entry) => {
3033
+ if (!entry.state) return false;
3034
+ if (entry.state.owner !== normalizedSolver) {
2961
3035
  logger?.warn(
2962
- { solver, commitment, tokenId: declaredPositions[index].toString(), owner: state.owner },
3036
+ { solver, commitment, tokenId: entry.tokenId.toString(), owner: entry.state.owner },
2963
3037
  "Ignoring declared Uniswap V4 position: not owned by the bidding solver"
2964
3038
  );
2965
3039
  return false;
2966
3040
  }
2967
3041
  return true;
2968
3042
  });
3043
+ const positions = ownedPositions.map((entry) => entry.state);
3044
+ for (const entry of ownedPositions) {
3045
+ verifiedPositions.push({ solver: normalizedSolver, chain, tokenId: entry.tokenId });
3046
+ }
2969
3047
  const weights = await Promise.all(
2970
3048
  // Price influence: the solver's liquidity in THIS leg's output token on the destination
2971
3049
  // chain, so a leg is weighted by the inventory that actually backs it.
@@ -3025,13 +3103,18 @@ async function runAggregation(params, isDelegated) {
3025
3103
  }
3026
3104
  ];
3027
3105
  });
3028
- return { legs, lpBalances };
3106
+ return { legs, lpBalances, positions: verifiedPositions, solvers: [...countedSolvers] };
3029
3107
  }
3030
3108
 
3031
3109
  exports.ENTRY_POINT_V08_ADDRESS = ENTRY_POINT_V08_ADDRESS;
3032
3110
  exports.FILL_ORDER_ABI = FILL_ORDER_ABI;
3111
+ exports.FILL_ORDER_V1_ABI = FILL_ORDER_V1_ABI;
3033
3112
  exports.IntentGatewayV2 = IntentGatewayV2_default;
3113
+ exports.PHANTOM_QUOTE_HAIRCUT_BPS = PHANTOM_QUOTE_HAIRCUT_BPS;
3114
+ exports.UNISWAP_QUOTE_HAIRCUT_BPS = UNISWAP_QUOTE_HAIRCUT_BPS;
3034
3115
  exports.aggregatePhantomBids = aggregatePhantomBids;
3116
+ exports.applyPhantomQuoteHaircut = applyPhantomQuoteHaircut;
3117
+ exports.applyUniswapQuoteHaircut = applyUniswapQuoteHaircut;
3035
3118
  exports.decodeAcceptedSourceChains = decodeAcceptedSourceChains;
3036
3119
  exports.decodeERC7821ExecuteBatch = decodeERC7821ExecuteBatch;
3037
3120
  exports.decodePhantomBidDeclaration = decodePhantomBidDeclaration;
@@ -3042,9 +3125,12 @@ exports.encodePhantomBidDeclaration = encodePhantomBidDeclaration;
3042
3125
  exports.encodeUserOpScale = encodeUserOpScale;
3043
3126
  exports.extractFillData = extractFillData;
3044
3127
  exports.fetchBidsForOrder = fetchBidsForOrder;
3128
+ exports.getTotalSolverBalance = getTotalSolverBalance;
3045
3129
  exports.memoizedSolverBalance = memoizedSolverBalance;
3046
3130
  exports.orderCommitmentFromDecoded = orderCommitmentFromDecoded;
3047
3131
  exports.poolSlug = poolSlug;
3132
+ exports.positionAmountOfToken = positionAmountOfToken;
3133
+ exports.readV4Position = readV4Position;
3048
3134
  exports.recoverBidSignerViem = recoverBidSignerViem;
3049
3135
  exports.setAggregationFetch = setAggregationFetch;
3050
3136
  exports.sortPoolSymbols = sortPoolSymbols;