@hyperbridge/sdk 2.8.16 → 2.8.17
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/dist/browser/index.d.ts +130 -44
- package/dist/browser/index.js +145 -68
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +145 -68
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +130 -44
- package/dist/node/index.d.ts +130 -44
- package/dist/node/index.js +145 -68
- package/dist/node/index.js.map +1 -1
- package/package.json +1 -1
package/dist/node/index.cjs
CHANGED
|
@@ -18788,20 +18788,27 @@ var ROUTE_LIQUIDITY_QUERY = `
|
|
|
18788
18788
|
query RouteLiquidity($route: RouteInput!) {
|
|
18789
18789
|
books { id base quote }
|
|
18790
18790
|
routeLiquidity(route: $route) {
|
|
18791
|
-
route bestRate depthIn depthOut availableLiquidity maxFillableIn orderCount solverCount
|
|
18791
|
+
route bestRate slippageBps depthIn depthOut availableLiquidity maxFillableIn orderCount solverCount
|
|
18792
18792
|
}
|
|
18793
18793
|
}`;
|
|
18794
18794
|
var QUOTE_QUERY = `
|
|
18795
18795
|
query Quote($route: RouteInput!, $amountIn: BigInt!) {
|
|
18796
18796
|
quote(route: $route, amountIn: $amountIn) {
|
|
18797
|
-
route side amountIn
|
|
18798
|
-
fills { orderRate amountOut
|
|
18797
|
+
route side amountIn slippageBps fillable maxFillableIn
|
|
18798
|
+
fills { advertisedSize orderRate amountIn amountOut }
|
|
18799
|
+
}
|
|
18800
|
+
}`;
|
|
18801
|
+
var QUOTE_PESSIMISTIC_QUERY = `
|
|
18802
|
+
query QuotePessimistic($route: RouteInput!, $amountIn: BigInt!) {
|
|
18803
|
+
quotePessimistic(route: $route, amountIn: $amountIn) {
|
|
18804
|
+
route side amountIn amountOut rate priceBucket slippageBps fillable maxFillableIn
|
|
18799
18805
|
}
|
|
18800
18806
|
}`;
|
|
18801
18807
|
var ORDERBOOK_QUERIES = {
|
|
18802
18808
|
topOfBook: TOP_OF_BOOK_QUERY,
|
|
18803
18809
|
routeLiquidity: ROUTE_LIQUIDITY_QUERY,
|
|
18804
|
-
quote: QUOTE_QUERY
|
|
18810
|
+
quote: QUOTE_QUERY,
|
|
18811
|
+
quotePessimistic: QUOTE_PESSIMISTIC_QUERY
|
|
18805
18812
|
};
|
|
18806
18813
|
var HyperFxOrderbook = class {
|
|
18807
18814
|
client;
|
|
@@ -18830,8 +18837,9 @@ var HyperFxOrderbook = class {
|
|
|
18830
18837
|
return {
|
|
18831
18838
|
route: raw.route,
|
|
18832
18839
|
book,
|
|
18833
|
-
side: book.base
|
|
18834
|
-
bestRate:
|
|
18840
|
+
side: sameSymbol(book.base, route.tokenIn) ? "BID" : "ASK",
|
|
18841
|
+
bestRate: optionalBigInt(raw.bestRate),
|
|
18842
|
+
slippageBps: raw.slippageBps,
|
|
18835
18843
|
depthIn: BigInt(raw.depthIn),
|
|
18836
18844
|
depthOut: BigInt(raw.depthOut),
|
|
18837
18845
|
availableLiquidity: BigInt(raw.availableLiquidity),
|
|
@@ -18840,7 +18848,10 @@ var HyperFxOrderbook = class {
|
|
|
18840
18848
|
solverCount: raw.solverCount
|
|
18841
18849
|
};
|
|
18842
18850
|
}
|
|
18843
|
-
/**
|
|
18851
|
+
/**
|
|
18852
|
+
* The optimistic quote for `amountIn` (1e18 tokenIn) on a route: the route's orders, best price
|
|
18853
|
+
* first, each taking what it can at its own price. The fills' `amountOut`s sum to the output.
|
|
18854
|
+
*/
|
|
18844
18855
|
async quote(route, amountIn) {
|
|
18845
18856
|
const { quote: raw } = await this.request(QUOTE_QUERY, {
|
|
18846
18857
|
route,
|
|
@@ -18850,18 +18861,39 @@ var HyperFxOrderbook = class {
|
|
|
18850
18861
|
route: raw.route,
|
|
18851
18862
|
side: raw.side,
|
|
18852
18863
|
amountIn: BigInt(raw.amountIn),
|
|
18853
|
-
|
|
18854
|
-
rate: raw.rate === null ? null : BigInt(raw.rate),
|
|
18864
|
+
slippageBps: raw.slippageBps,
|
|
18855
18865
|
fillable: raw.fillable,
|
|
18856
|
-
depth: BigInt(raw.depth),
|
|
18857
18866
|
maxFillableIn: BigInt(raw.maxFillableIn),
|
|
18858
18867
|
fills: raw.fills.map((fill) => ({
|
|
18868
|
+
advertisedSize: BigInt(fill.advertisedSize),
|
|
18859
18869
|
orderRate: BigInt(fill.orderRate),
|
|
18860
|
-
|
|
18861
|
-
|
|
18870
|
+
amountIn: BigInt(fill.amountIn),
|
|
18871
|
+
amountOut: BigInt(fill.amountOut)
|
|
18862
18872
|
}))
|
|
18863
18873
|
};
|
|
18864
18874
|
}
|
|
18875
|
+
/**
|
|
18876
|
+
* The pessimistic quote for `amountIn` (1e18 tokenIn) on a route: one price, from the first level
|
|
18877
|
+
* deep enough to fill the whole trade by itself, at which every order in it fills; the route's
|
|
18878
|
+
* worst price when no one level can but its levels together can.
|
|
18879
|
+
*/
|
|
18880
|
+
async quotePessimistic(route, amountIn) {
|
|
18881
|
+
const { quotePessimistic: raw } = await this.request(
|
|
18882
|
+
QUOTE_PESSIMISTIC_QUERY,
|
|
18883
|
+
{ route, amountIn: amountIn.toString() }
|
|
18884
|
+
);
|
|
18885
|
+
return {
|
|
18886
|
+
route: raw.route,
|
|
18887
|
+
side: raw.side,
|
|
18888
|
+
amountIn: BigInt(raw.amountIn),
|
|
18889
|
+
amountOut: BigInt(raw.amountOut),
|
|
18890
|
+
rate: optionalBigInt(raw.rate),
|
|
18891
|
+
priceBucket: optionalBigInt(raw.priceBucket),
|
|
18892
|
+
slippageBps: raw.slippageBps,
|
|
18893
|
+
fillable: raw.fillable,
|
|
18894
|
+
maxFillableIn: BigInt(raw.maxFillableIn)
|
|
18895
|
+
};
|
|
18896
|
+
}
|
|
18865
18897
|
async request(query, variables) {
|
|
18866
18898
|
try {
|
|
18867
18899
|
return await this.client.request(query, variables);
|
|
@@ -18875,13 +18907,19 @@ function describeError(error) {
|
|
|
18875
18907
|
if (graphqlErrors?.length) return graphqlErrors.map((e) => e.message).join("; ");
|
|
18876
18908
|
return error instanceof Error ? error.message : String(error);
|
|
18877
18909
|
}
|
|
18910
|
+
function sameSymbol(a, b) {
|
|
18911
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
18912
|
+
}
|
|
18878
18913
|
function findBook(books, tokenA, tokenB) {
|
|
18879
18914
|
const book = books.find(
|
|
18880
|
-
(b) => b.base
|
|
18915
|
+
(b) => sameSymbol(b.base, tokenA) && sameSymbol(b.quote, tokenB) || sameSymbol(b.base, tokenB) && sameSymbol(b.quote, tokenA)
|
|
18881
18916
|
);
|
|
18882
18917
|
if (!book) throw new OrderbookRequestError(`no book trades ${tokenA} for ${tokenB}`);
|
|
18883
18918
|
return book;
|
|
18884
18919
|
}
|
|
18920
|
+
function optionalBigInt(value) {
|
|
18921
|
+
return value === null ? null : BigInt(value);
|
|
18922
|
+
}
|
|
18885
18923
|
function parseRate(raw) {
|
|
18886
18924
|
return {
|
|
18887
18925
|
side: raw.side,
|
|
@@ -18946,26 +18984,69 @@ var OrderbookMarket = class {
|
|
|
18946
18984
|
configService;
|
|
18947
18985
|
orderbook;
|
|
18948
18986
|
async quoteIntent(params, sourceChain, destinationChain) {
|
|
18987
|
+
const orderbook = this.orderbook();
|
|
18988
|
+
if (!params.optimistic) {
|
|
18989
|
+
const { quote: quote2, tokenIn: tokenIn2, tokenOut: tokenOut2 } = await this.priceIntent(
|
|
18990
|
+
params,
|
|
18991
|
+
sourceChain,
|
|
18992
|
+
destinationChain,
|
|
18993
|
+
(route, amountIn) => orderbook.quotePessimistic(route, amountIn),
|
|
18994
|
+
levelQuoteTotals
|
|
18995
|
+
);
|
|
18996
|
+
return {
|
|
18997
|
+
route: quote2.route,
|
|
18998
|
+
side: quote2.side,
|
|
18999
|
+
amountIn: fromOrderbookAmount(quote2.amountIn, tokenIn2.decimals),
|
|
19000
|
+
amountOut: fromOrderbookAmount(quote2.amountOut, tokenOut2.decimals),
|
|
19001
|
+
rate: quote2.rate,
|
|
19002
|
+
priceBucket: quote2.priceBucket,
|
|
19003
|
+
slippageBps: quote2.slippageBps,
|
|
19004
|
+
fillable: quote2.fillable,
|
|
19005
|
+
maxFillableIn: fromOrderbookAmount(quote2.maxFillableIn, tokenIn2.decimals)
|
|
19006
|
+
};
|
|
19007
|
+
}
|
|
19008
|
+
const { quote, tokenIn, tokenOut } = await this.priceIntent(
|
|
19009
|
+
params,
|
|
19010
|
+
sourceChain,
|
|
19011
|
+
destinationChain,
|
|
19012
|
+
(route, amountIn) => orderbook.quote(route, amountIn),
|
|
19013
|
+
swapQuoteTotals
|
|
19014
|
+
);
|
|
19015
|
+
return {
|
|
19016
|
+
route: quote.route,
|
|
19017
|
+
side: quote.side,
|
|
19018
|
+
amountIn: fromOrderbookAmount(quote.amountIn, tokenIn.decimals),
|
|
19019
|
+
slippageBps: quote.slippageBps,
|
|
19020
|
+
fillable: quote.fillable,
|
|
19021
|
+
maxFillableIn: fromOrderbookAmount(quote.maxFillableIn, tokenIn.decimals),
|
|
19022
|
+
legs: quote.fills.map((fill) => ({
|
|
19023
|
+
advertisedSize: fromOrderbookAmount(fill.advertisedSize, tokenOut.decimals),
|
|
19024
|
+
orderRate: fill.orderRate,
|
|
19025
|
+
amountIn: fromOrderbookAmount(fill.amountIn, tokenIn.decimals),
|
|
19026
|
+
amountOut: fromOrderbookAmount(fill.amountOut, tokenOut.decimals)
|
|
19027
|
+
}))
|
|
19028
|
+
};
|
|
19029
|
+
}
|
|
19030
|
+
/**
|
|
19031
|
+
* The fillable quote for an exact input, or for the input found to deliver an
|
|
19032
|
+
* exact output, with the assets it trades.
|
|
19033
|
+
*/
|
|
19034
|
+
async priceIntent(params, sourceChain, destinationChain, price, totals) {
|
|
18949
19035
|
validateQuoteParams(params);
|
|
18950
19036
|
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
18951
19037
|
const tokenOut = this.assetByAddress(destinationChain, params.tokenOut);
|
|
18952
19038
|
const route = toRoute(tokenIn, tokenOut);
|
|
18953
19039
|
if (params.amountIn !== void 0) {
|
|
18954
|
-
const quote2 = await
|
|
18955
|
-
const
|
|
18956
|
-
if (
|
|
18957
|
-
|
|
19040
|
+
const quote2 = await price(route, toOrderbookAmount(params.amountIn, tokenIn.decimals));
|
|
19041
|
+
const { fillable, amountOut, maxFillableIn } = totals(quote2);
|
|
19042
|
+
if (!fillable || fromOrderbookAmount(amountOut, tokenOut.decimals) === 0n) {
|
|
19043
|
+
throw this.insufficient(route, maxFillableIn, tokenIn);
|
|
19044
|
+
}
|
|
19045
|
+
return { quote: quote2, tokenIn, tokenOut };
|
|
18958
19046
|
}
|
|
18959
|
-
const
|
|
18960
|
-
const quote = await this.quoteExactOutput(route,
|
|
18961
|
-
return
|
|
18962
|
-
"EXACT_OUTPUT",
|
|
18963
|
-
fromOrderbookAmount(quote.amountIn, tokenIn.decimals),
|
|
18964
|
-
amountOut,
|
|
18965
|
-
quote,
|
|
18966
|
-
tokenIn,
|
|
18967
|
-
tokenOut
|
|
18968
|
-
);
|
|
19047
|
+
const targetOut = toOrderbookAmount(params.amountOut, tokenOut.decimals);
|
|
19048
|
+
const quote = await this.quoteExactOutput(route, targetOut, tokenIn, price, totals);
|
|
19049
|
+
return { quote, tokenIn, tokenOut };
|
|
18969
19050
|
}
|
|
18970
19051
|
async availableLiquidity(params, sourceChain, destinationChain) {
|
|
18971
19052
|
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
@@ -19018,22 +19099,26 @@ var OrderbookMarket = class {
|
|
|
19018
19099
|
}
|
|
19019
19100
|
/**
|
|
19020
19101
|
* The orderbook only quotes an input amount, so an output is priced by
|
|
19021
|
-
* guessing the input from the best rate
|
|
19022
|
-
*
|
|
19102
|
+
* guessing the input from the best rate, then keeping the part of each quote
|
|
19103
|
+
* filled better than its worst rate and re-pricing the rest of `targetOut` at
|
|
19104
|
+
* the input-to-output ratio that part filled at, until a quote delivers it.
|
|
19105
|
+
* That ratio is the orderbook's own, with the protocol fee already taken off.
|
|
19023
19106
|
*/
|
|
19024
|
-
async quoteExactOutput(route, targetOut, tokenIn) {
|
|
19025
|
-
const
|
|
19026
|
-
const liquidity = await orderbook.routeLiquidity(route);
|
|
19107
|
+
async quoteExactOutput(route, targetOut, tokenIn, price, totals) {
|
|
19108
|
+
const liquidity = await this.orderbook().routeLiquidity(route);
|
|
19027
19109
|
if (liquidity.bestRate === null) throw this.insufficient(route, 0n, tokenIn);
|
|
19028
19110
|
const inputUnit = toOrderbookAmount(1n, tokenIn.decimals);
|
|
19029
19111
|
let amountIn = roundUpTo(requiredInput(liquidity.side, targetOut, liquidity.bestRate), inputUnit);
|
|
19030
19112
|
let lastAmountIn = amountIn;
|
|
19031
19113
|
for (let round = 0; round < MAX_EXACT_OUTPUT_ROUNDS; round++) {
|
|
19032
19114
|
if (amountIn > liquidity.maxFillableIn) throw this.insufficient(route, liquidity.maxFillableIn, tokenIn);
|
|
19033
|
-
const
|
|
19034
|
-
|
|
19115
|
+
const served = await price(route, amountIn);
|
|
19116
|
+
const quote = totals(served);
|
|
19117
|
+
if (quote.fillable && quote.amountOut >= targetOut) return served;
|
|
19035
19118
|
lastAmountIn = amountIn;
|
|
19036
|
-
const
|
|
19119
|
+
const betterIn = quote.amountIn - quote.worstIn;
|
|
19120
|
+
const betterOut = quote.amountOut - quote.worstOut;
|
|
19121
|
+
const next = quote.fillable && quote.worstOut > 0n ? betterIn + roundUpTo(divCeil((targetOut - betterOut) * quote.worstIn, quote.worstOut), inputUnit) : amountIn;
|
|
19037
19122
|
amountIn = next > amountIn ? next : amountIn + inputUnit;
|
|
19038
19123
|
}
|
|
19039
19124
|
throw new OrderbookQuoteNotConvergedError(
|
|
@@ -19089,24 +19174,32 @@ function toRoute(tokenIn, tokenOut) {
|
|
|
19089
19174
|
function requiredInput(side, amountOut, rate) {
|
|
19090
19175
|
return side === "BID" ? divCeil(amountOut * ORDERBOOK_SCALE, rate) : divCeil(amountOut * rate, ORDERBOOK_SCALE);
|
|
19091
19176
|
}
|
|
19092
|
-
function
|
|
19093
|
-
|
|
19094
|
-
|
|
19177
|
+
function swapQuoteTotals(quote) {
|
|
19178
|
+
const worstFill = quote.fills.at(-1);
|
|
19179
|
+
if (quote.fillable && !worstFill)
|
|
19180
|
+
throw new OrderbookRequestError("the orderbook served a fillable quote with no fills");
|
|
19095
19181
|
return {
|
|
19096
|
-
|
|
19097
|
-
amountIn,
|
|
19098
|
-
amountOut,
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19106
|
-
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19182
|
+
side: quote.side,
|
|
19183
|
+
amountIn: quote.amountIn,
|
|
19184
|
+
amountOut: quote.fills.reduce((total, fill) => total + fill.amountOut, 0n),
|
|
19185
|
+
fillable: quote.fillable,
|
|
19186
|
+
maxFillableIn: quote.maxFillableIn,
|
|
19187
|
+
worstIn: worstFill?.amountIn ?? 0n,
|
|
19188
|
+
worstOut: worstFill?.amountOut ?? 0n
|
|
19189
|
+
};
|
|
19190
|
+
}
|
|
19191
|
+
function levelQuoteTotals(quote) {
|
|
19192
|
+
if (quote.fillable && quote.rate === null) {
|
|
19193
|
+
throw new OrderbookRequestError("the orderbook served a fillable quote with no rate");
|
|
19194
|
+
}
|
|
19195
|
+
return {
|
|
19196
|
+
side: quote.side,
|
|
19197
|
+
amountIn: quote.amountIn,
|
|
19198
|
+
amountOut: quote.amountOut,
|
|
19199
|
+
fillable: quote.fillable,
|
|
19200
|
+
maxFillableIn: quote.maxFillableIn,
|
|
19201
|
+
worstIn: quote.amountIn,
|
|
19202
|
+
worstOut: quote.amountOut
|
|
19110
19203
|
};
|
|
19111
19204
|
}
|
|
19112
19205
|
function toOrderbookAmount(amount, decimals) {
|
|
@@ -19270,22 +19363,6 @@ var IntentGateway = class _IntentGateway {
|
|
|
19270
19363
|
this.orderbook = typeof orderbook === "string" ? new HyperFxOrderbook(orderbook) : orderbook;
|
|
19271
19364
|
return this;
|
|
19272
19365
|
}
|
|
19273
|
-
/**
|
|
19274
|
-
* Quotes an intent between this gateway's source and destination chains from
|
|
19275
|
-
* the HyperFX orderbook. Provide exactly one of `amountIn` or `amountOut`, in
|
|
19276
|
-
* raw token units.
|
|
19277
|
-
*
|
|
19278
|
-
* An exact-input quote is the orderbook's clearing price for `amountIn`,
|
|
19279
|
-
* which may combine several solvers' orders. An exact-output quote finds the
|
|
19280
|
-
* smallest input whose clearing price delivers `amountOut`. A cross-chain
|
|
19281
|
-
* route only counts orders whose solvers accept the source chain.
|
|
19282
|
-
*
|
|
19283
|
-
* The orderbook's rates already carry the gateway protocol fee, so the
|
|
19284
|
-
* returned amounts can be placed as the order's inputs and outputs directly.
|
|
19285
|
-
*
|
|
19286
|
-
* @throws {InsufficientOrderbookLiquidityError} When the route cannot fill the amount.
|
|
19287
|
-
* @throws {OrderbookRequestError} When the orderbook is unreachable or trades no book for the pair.
|
|
19288
|
-
*/
|
|
19289
19366
|
async quoteIntent(params) {
|
|
19290
19367
|
return this.market.quoteIntent(params, this.source.config.stateMachineId, this.dest.config.stateMachineId);
|
|
19291
19368
|
}
|