@hyperbridge/sdk 2.8.8 → 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,9 +2646,16 @@ function zipFillLegs(assets, outputs) {
2593
2646
  };
2594
2647
  });
2595
2648
  }
2596
- var UNISWAP_QUOTE_HAIRCUT_BPS = 30n;
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
+ }
2597
2654
  function applyUniswapQuoteHaircut(amount) {
2598
- return amount * (10000n - UNISWAP_QUOTE_HAIRCUT_BPS) / 10000n;
2655
+ return haircut(amount, UNISWAP_QUOTE_HAIRCUT_BPS);
2656
+ }
2657
+ function applyPhantomQuoteHaircut(amount) {
2658
+ return haircut(amount, PHANTOM_QUOTE_HAIRCUT_BPS);
2599
2659
  }
2600
2660
  function weightedMedian(entries) {
2601
2661
  const sorted = [...entries].sort((a, b) => a.price < b.price ? -1 : a.price > b.price ? 1 : 0);
@@ -2618,10 +2678,10 @@ function extractFillData(callData, gatewayAddress) {
2618
2678
  for (const call of calls) {
2619
2679
  if (call.target.toLowerCase() !== normalized) continue;
2620
2680
  try {
2621
- const decoded = viem.decodeFunctionData({ abi: FILL_ORDER_ABI, data: call.data });
2622
- if (decoded.functionName !== "fillOrder" || !decoded.args || decoded.args.length < 2) continue;
2623
- const order = decoded.args[0];
2624
- 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;
2625
2685
  const assets = order?.output?.assets;
2626
2686
  const outputs = options?.outputs;
2627
2687
  if (!assets?.length || !outputs?.length) continue;
@@ -2748,12 +2808,12 @@ async function fetchBidsForOrder(nodeUrl, commitment) {
2748
2808
  });
2749
2809
  return Array.isArray(data.result) ? data.result : [];
2750
2810
  }
2751
- async function ethCallUint(evmRpcUrl, to, data) {
2811
+ async function ethCallUint(evmRpcUrl, to, data, blockTag = "latest") {
2752
2812
  const result = await rpcCall(evmRpcUrl, {
2753
2813
  id: 1,
2754
2814
  jsonrpc: "2.0",
2755
2815
  method: "eth_call",
2756
- params: [{ to, data }, "latest"]
2816
+ params: [{ to, data }, blockTag]
2757
2817
  });
2758
2818
  if (result.result === "0x") return 0n;
2759
2819
  if (typeof result.result !== "string") {
@@ -2761,12 +2821,12 @@ async function ethCallUint(evmRpcUrl, to, data) {
2761
2821
  }
2762
2822
  return BigInt(result.result);
2763
2823
  }
2764
- async function getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults) {
2824
+ async function getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults, blockTag = "latest") {
2765
2825
  const padded = solver.replace("0x", "").padStart(64, "0");
2766
- const raw = await ethCallUint(evmRpcUrl, token, `0x70a08231${padded}`);
2826
+ const raw = await ethCallUint(evmRpcUrl, token, `0x70a08231${padded}`, blockTag);
2767
2827
  const vaults = yieldVaults[chain]?.[token.toLowerCase()] ?? [];
2768
2828
  const vaultBalances = await Promise.all(
2769
- vaults.map((v) => ethCallUint(evmRpcUrl, v, `0xce96cb77${padded}`))
2829
+ vaults.map((v) => ethCallUint(evmRpcUrl, v, `0xce96cb77${padded}`, blockTag))
2770
2830
  // maxWithdraw(address)
2771
2831
  );
2772
2832
  return vaultBalances.reduce((acc, b) => acc + b, raw);
@@ -2776,13 +2836,14 @@ var SELECTOR_POSITION_LIQUIDITY = "0x1efeed33";
2776
2836
  var SELECTOR_POOL_AND_POSITION_INFO = "0x7ba03aad";
2777
2837
  var SELECTOR_GET_SLOT0 = "0xc815641c";
2778
2838
  var uint256Arg = (value) => value.toString(16).padStart(64, "0");
2779
- async function readV4Position(evmRpcUrl, contracts, tokenId, keccak, logger) {
2839
+ async function readV4Position(params) {
2840
+ const { evmRpcUrl, contracts, tokenId, keccak, blockTag = "latest", logger } = params;
2780
2841
  const call = async (to, data) => {
2781
2842
  const result = await rpcCall(evmRpcUrl, {
2782
2843
  id: 1,
2783
2844
  jsonrpc: "2.0",
2784
2845
  method: "eth_call",
2785
- params: [{ to, data }, "latest"]
2846
+ params: [{ to, data }, blockTag]
2786
2847
  });
2787
2848
  if (result.result === "0x") return null;
2788
2849
  if (typeof result.result !== "string") {
@@ -2826,7 +2887,7 @@ function memoizedV4Position(keccak, logger) {
2826
2887
  const key = `${chain}|${tokenId}`;
2827
2888
  let pending = cache.get(key);
2828
2889
  if (!pending) {
2829
- pending = readV4Position(evmRpcUrl, contracts, tokenId, keccak, logger).catch((err) => {
2890
+ pending = readV4Position({ evmRpcUrl, contracts, tokenId, keccak, logger }).catch((err) => {
2830
2891
  cache.delete(key);
2831
2892
  throw err;
2832
2893
  });
@@ -2835,13 +2896,13 @@ function memoizedV4Position(keccak, logger) {
2835
2896
  return pending;
2836
2897
  };
2837
2898
  }
2838
- function memoizedSolverBalance(yieldVaults) {
2899
+ function memoizedSolverBalance(yieldVaults, blockTags = {}) {
2839
2900
  const cache = /* @__PURE__ */ new Map();
2840
2901
  return (evmRpcUrl, chain, token, solver) => {
2841
2902
  const key = `${chain}|${token.toLowerCase()}|${solver.toLowerCase()}`;
2842
2903
  let pending = cache.get(key);
2843
2904
  if (!pending) {
2844
- pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults).catch((err) => {
2905
+ pending = getTotalSolverBalance(evmRpcUrl, chain, token, solver, yieldVaults, blockTags[chain]).catch((err) => {
2845
2906
  cache.delete(key);
2846
2907
  throw err;
2847
2908
  });
@@ -2916,6 +2977,7 @@ async function runAggregation(params, isDelegated) {
2916
2977
  const getBalance = params.getBalance ?? memoizedSolverBalance(yieldVaults);
2917
2978
  const quotesByLeg = /* @__PURE__ */ new Map();
2918
2979
  const lpBalances = [];
2980
+ const verifiedPositions = [];
2919
2981
  const countedSolvers = /* @__PURE__ */ new Set();
2920
2982
  for (const bid of bids) {
2921
2983
  if (!bid.user_op) continue;
@@ -2956,23 +3018,32 @@ async function runAggregation(params, isDelegated) {
2956
3018
  const declaration = decodePhantomBidDeclaration(decoded.paymasterAndData);
2957
3019
  const acceptedSources = declaration.acceptedSources;
2958
3020
  const poolPriced = declaration.uniswapV4Positions.length > 0;
2959
- const quotedLegs = [...fillData.legs.entries()].map(
2960
- ([legIndex, leg]) => poolPriced ? [legIndex, { ...leg, solverAmount: applyUniswapQuoteHaircut(leg.solverAmount) }] : [legIndex, leg]
2961
- ).filter(([, leg]) => leg.solverAmount !== 0n);
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);
2962
3026
  const declaredPositions = v4Contracts ? declaration.uniswapV4Positions : [];
2963
- const positions = (await Promise.all(
2964
- declaredPositions.map((tokenId) => readPosition(destUrl, chain, v4Contracts, tokenId))
2965
- )).filter((state, index) => {
2966
- if (!state) return false;
2967
- 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) {
2968
3035
  logger?.warn(
2969
- { solver, commitment, tokenId: declaredPositions[index].toString(), owner: state.owner },
3036
+ { solver, commitment, tokenId: entry.tokenId.toString(), owner: entry.state.owner },
2970
3037
  "Ignoring declared Uniswap V4 position: not owned by the bidding solver"
2971
3038
  );
2972
3039
  return false;
2973
3040
  }
2974
3041
  return true;
2975
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
+ }
2976
3047
  const weights = await Promise.all(
2977
3048
  // Price influence: the solver's liquidity in THIS leg's output token on the destination
2978
3049
  // chain, so a leg is weighted by the inventory that actually backs it.
@@ -3032,14 +3103,17 @@ async function runAggregation(params, isDelegated) {
3032
3103
  }
3033
3104
  ];
3034
3105
  });
3035
- return { legs, lpBalances };
3106
+ return { legs, lpBalances, positions: verifiedPositions, solvers: [...countedSolvers] };
3036
3107
  }
3037
3108
 
3038
3109
  exports.ENTRY_POINT_V08_ADDRESS = ENTRY_POINT_V08_ADDRESS;
3039
3110
  exports.FILL_ORDER_ABI = FILL_ORDER_ABI;
3111
+ exports.FILL_ORDER_V1_ABI = FILL_ORDER_V1_ABI;
3040
3112
  exports.IntentGatewayV2 = IntentGatewayV2_default;
3113
+ exports.PHANTOM_QUOTE_HAIRCUT_BPS = PHANTOM_QUOTE_HAIRCUT_BPS;
3041
3114
  exports.UNISWAP_QUOTE_HAIRCUT_BPS = UNISWAP_QUOTE_HAIRCUT_BPS;
3042
3115
  exports.aggregatePhantomBids = aggregatePhantomBids;
3116
+ exports.applyPhantomQuoteHaircut = applyPhantomQuoteHaircut;
3043
3117
  exports.applyUniswapQuoteHaircut = applyUniswapQuoteHaircut;
3044
3118
  exports.decodeAcceptedSourceChains = decodeAcceptedSourceChains;
3045
3119
  exports.decodeERC7821ExecuteBatch = decodeERC7821ExecuteBatch;
@@ -3051,9 +3125,12 @@ exports.encodePhantomBidDeclaration = encodePhantomBidDeclaration;
3051
3125
  exports.encodeUserOpScale = encodeUserOpScale;
3052
3126
  exports.extractFillData = extractFillData;
3053
3127
  exports.fetchBidsForOrder = fetchBidsForOrder;
3128
+ exports.getTotalSolverBalance = getTotalSolverBalance;
3054
3129
  exports.memoizedSolverBalance = memoizedSolverBalance;
3055
3130
  exports.orderCommitmentFromDecoded = orderCommitmentFromDecoded;
3056
3131
  exports.poolSlug = poolSlug;
3132
+ exports.positionAmountOfToken = positionAmountOfToken;
3133
+ exports.readV4Position = readV4Position;
3057
3134
  exports.recoverBidSignerViem = recoverBidSignerViem;
3058
3135
  exports.setAggregationFetch = setAggregationFetch;
3059
3136
  exports.sortPoolSymbols = sortPoolSymbols;