@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.js
CHANGED
|
@@ -18777,20 +18777,27 @@ var ROUTE_LIQUIDITY_QUERY = `
|
|
|
18777
18777
|
query RouteLiquidity($route: RouteInput!) {
|
|
18778
18778
|
books { id base quote }
|
|
18779
18779
|
routeLiquidity(route: $route) {
|
|
18780
|
-
route bestRate depthIn depthOut availableLiquidity maxFillableIn orderCount solverCount
|
|
18780
|
+
route bestRate slippageBps depthIn depthOut availableLiquidity maxFillableIn orderCount solverCount
|
|
18781
18781
|
}
|
|
18782
18782
|
}`;
|
|
18783
18783
|
var QUOTE_QUERY = `
|
|
18784
18784
|
query Quote($route: RouteInput!, $amountIn: BigInt!) {
|
|
18785
18785
|
quote(route: $route, amountIn: $amountIn) {
|
|
18786
|
-
route side amountIn
|
|
18787
|
-
fills { orderRate amountOut
|
|
18786
|
+
route side amountIn slippageBps fillable maxFillableIn
|
|
18787
|
+
fills { advertisedSize orderRate amountIn amountOut }
|
|
18788
|
+
}
|
|
18789
|
+
}`;
|
|
18790
|
+
var QUOTE_PESSIMISTIC_QUERY = `
|
|
18791
|
+
query QuotePessimistic($route: RouteInput!, $amountIn: BigInt!) {
|
|
18792
|
+
quotePessimistic(route: $route, amountIn: $amountIn) {
|
|
18793
|
+
route side amountIn amountOut rate priceBucket slippageBps fillable maxFillableIn
|
|
18788
18794
|
}
|
|
18789
18795
|
}`;
|
|
18790
18796
|
var ORDERBOOK_QUERIES = {
|
|
18791
18797
|
topOfBook: TOP_OF_BOOK_QUERY,
|
|
18792
18798
|
routeLiquidity: ROUTE_LIQUIDITY_QUERY,
|
|
18793
|
-
quote: QUOTE_QUERY
|
|
18799
|
+
quote: QUOTE_QUERY,
|
|
18800
|
+
quotePessimistic: QUOTE_PESSIMISTIC_QUERY
|
|
18794
18801
|
};
|
|
18795
18802
|
var HyperFxOrderbook = class {
|
|
18796
18803
|
client;
|
|
@@ -18819,8 +18826,9 @@ var HyperFxOrderbook = class {
|
|
|
18819
18826
|
return {
|
|
18820
18827
|
route: raw.route,
|
|
18821
18828
|
book,
|
|
18822
|
-
side: book.base
|
|
18823
|
-
bestRate:
|
|
18829
|
+
side: sameSymbol(book.base, route.tokenIn) ? "BID" : "ASK",
|
|
18830
|
+
bestRate: optionalBigInt(raw.bestRate),
|
|
18831
|
+
slippageBps: raw.slippageBps,
|
|
18824
18832
|
depthIn: BigInt(raw.depthIn),
|
|
18825
18833
|
depthOut: BigInt(raw.depthOut),
|
|
18826
18834
|
availableLiquidity: BigInt(raw.availableLiquidity),
|
|
@@ -18829,7 +18837,10 @@ var HyperFxOrderbook = class {
|
|
|
18829
18837
|
solverCount: raw.solverCount
|
|
18830
18838
|
};
|
|
18831
18839
|
}
|
|
18832
|
-
/**
|
|
18840
|
+
/**
|
|
18841
|
+
* The optimistic quote for `amountIn` (1e18 tokenIn) on a route: the route's orders, best price
|
|
18842
|
+
* first, each taking what it can at its own price. The fills' `amountOut`s sum to the output.
|
|
18843
|
+
*/
|
|
18833
18844
|
async quote(route, amountIn) {
|
|
18834
18845
|
const { quote: raw } = await this.request(QUOTE_QUERY, {
|
|
18835
18846
|
route,
|
|
@@ -18839,18 +18850,39 @@ var HyperFxOrderbook = class {
|
|
|
18839
18850
|
route: raw.route,
|
|
18840
18851
|
side: raw.side,
|
|
18841
18852
|
amountIn: BigInt(raw.amountIn),
|
|
18842
|
-
|
|
18843
|
-
rate: raw.rate === null ? null : BigInt(raw.rate),
|
|
18853
|
+
slippageBps: raw.slippageBps,
|
|
18844
18854
|
fillable: raw.fillable,
|
|
18845
|
-
depth: BigInt(raw.depth),
|
|
18846
18855
|
maxFillableIn: BigInt(raw.maxFillableIn),
|
|
18847
18856
|
fills: raw.fills.map((fill) => ({
|
|
18857
|
+
advertisedSize: BigInt(fill.advertisedSize),
|
|
18848
18858
|
orderRate: BigInt(fill.orderRate),
|
|
18849
|
-
|
|
18850
|
-
|
|
18859
|
+
amountIn: BigInt(fill.amountIn),
|
|
18860
|
+
amountOut: BigInt(fill.amountOut)
|
|
18851
18861
|
}))
|
|
18852
18862
|
};
|
|
18853
18863
|
}
|
|
18864
|
+
/**
|
|
18865
|
+
* The pessimistic quote for `amountIn` (1e18 tokenIn) on a route: one price, from the first level
|
|
18866
|
+
* deep enough to fill the whole trade by itself, at which every order in it fills; the route's
|
|
18867
|
+
* worst price when no one level can but its levels together can.
|
|
18868
|
+
*/
|
|
18869
|
+
async quotePessimistic(route, amountIn) {
|
|
18870
|
+
const { quotePessimistic: raw } = await this.request(
|
|
18871
|
+
QUOTE_PESSIMISTIC_QUERY,
|
|
18872
|
+
{ route, amountIn: amountIn.toString() }
|
|
18873
|
+
);
|
|
18874
|
+
return {
|
|
18875
|
+
route: raw.route,
|
|
18876
|
+
side: raw.side,
|
|
18877
|
+
amountIn: BigInt(raw.amountIn),
|
|
18878
|
+
amountOut: BigInt(raw.amountOut),
|
|
18879
|
+
rate: optionalBigInt(raw.rate),
|
|
18880
|
+
priceBucket: optionalBigInt(raw.priceBucket),
|
|
18881
|
+
slippageBps: raw.slippageBps,
|
|
18882
|
+
fillable: raw.fillable,
|
|
18883
|
+
maxFillableIn: BigInt(raw.maxFillableIn)
|
|
18884
|
+
};
|
|
18885
|
+
}
|
|
18854
18886
|
async request(query, variables) {
|
|
18855
18887
|
try {
|
|
18856
18888
|
return await this.client.request(query, variables);
|
|
@@ -18864,13 +18896,19 @@ function describeError(error) {
|
|
|
18864
18896
|
if (graphqlErrors?.length) return graphqlErrors.map((e) => e.message).join("; ");
|
|
18865
18897
|
return error instanceof Error ? error.message : String(error);
|
|
18866
18898
|
}
|
|
18899
|
+
function sameSymbol(a, b) {
|
|
18900
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
18901
|
+
}
|
|
18867
18902
|
function findBook(books, tokenA, tokenB) {
|
|
18868
18903
|
const book = books.find(
|
|
18869
|
-
(b) => b.base
|
|
18904
|
+
(b) => sameSymbol(b.base, tokenA) && sameSymbol(b.quote, tokenB) || sameSymbol(b.base, tokenB) && sameSymbol(b.quote, tokenA)
|
|
18870
18905
|
);
|
|
18871
18906
|
if (!book) throw new OrderbookRequestError(`no book trades ${tokenA} for ${tokenB}`);
|
|
18872
18907
|
return book;
|
|
18873
18908
|
}
|
|
18909
|
+
function optionalBigInt(value) {
|
|
18910
|
+
return value === null ? null : BigInt(value);
|
|
18911
|
+
}
|
|
18874
18912
|
function parseRate(raw) {
|
|
18875
18913
|
return {
|
|
18876
18914
|
side: raw.side,
|
|
@@ -18935,26 +18973,69 @@ var OrderbookMarket = class {
|
|
|
18935
18973
|
configService;
|
|
18936
18974
|
orderbook;
|
|
18937
18975
|
async quoteIntent(params, sourceChain, destinationChain) {
|
|
18976
|
+
const orderbook = this.orderbook();
|
|
18977
|
+
if (!params.optimistic) {
|
|
18978
|
+
const { quote: quote2, tokenIn: tokenIn2, tokenOut: tokenOut2 } = await this.priceIntent(
|
|
18979
|
+
params,
|
|
18980
|
+
sourceChain,
|
|
18981
|
+
destinationChain,
|
|
18982
|
+
(route, amountIn) => orderbook.quotePessimistic(route, amountIn),
|
|
18983
|
+
levelQuoteTotals
|
|
18984
|
+
);
|
|
18985
|
+
return {
|
|
18986
|
+
route: quote2.route,
|
|
18987
|
+
side: quote2.side,
|
|
18988
|
+
amountIn: fromOrderbookAmount(quote2.amountIn, tokenIn2.decimals),
|
|
18989
|
+
amountOut: fromOrderbookAmount(quote2.amountOut, tokenOut2.decimals),
|
|
18990
|
+
rate: quote2.rate,
|
|
18991
|
+
priceBucket: quote2.priceBucket,
|
|
18992
|
+
slippageBps: quote2.slippageBps,
|
|
18993
|
+
fillable: quote2.fillable,
|
|
18994
|
+
maxFillableIn: fromOrderbookAmount(quote2.maxFillableIn, tokenIn2.decimals)
|
|
18995
|
+
};
|
|
18996
|
+
}
|
|
18997
|
+
const { quote, tokenIn, tokenOut } = await this.priceIntent(
|
|
18998
|
+
params,
|
|
18999
|
+
sourceChain,
|
|
19000
|
+
destinationChain,
|
|
19001
|
+
(route, amountIn) => orderbook.quote(route, amountIn),
|
|
19002
|
+
swapQuoteTotals
|
|
19003
|
+
);
|
|
19004
|
+
return {
|
|
19005
|
+
route: quote.route,
|
|
19006
|
+
side: quote.side,
|
|
19007
|
+
amountIn: fromOrderbookAmount(quote.amountIn, tokenIn.decimals),
|
|
19008
|
+
slippageBps: quote.slippageBps,
|
|
19009
|
+
fillable: quote.fillable,
|
|
19010
|
+
maxFillableIn: fromOrderbookAmount(quote.maxFillableIn, tokenIn.decimals),
|
|
19011
|
+
legs: quote.fills.map((fill) => ({
|
|
19012
|
+
advertisedSize: fromOrderbookAmount(fill.advertisedSize, tokenOut.decimals),
|
|
19013
|
+
orderRate: fill.orderRate,
|
|
19014
|
+
amountIn: fromOrderbookAmount(fill.amountIn, tokenIn.decimals),
|
|
19015
|
+
amountOut: fromOrderbookAmount(fill.amountOut, tokenOut.decimals)
|
|
19016
|
+
}))
|
|
19017
|
+
};
|
|
19018
|
+
}
|
|
19019
|
+
/**
|
|
19020
|
+
* The fillable quote for an exact input, or for the input found to deliver an
|
|
19021
|
+
* exact output, with the assets it trades.
|
|
19022
|
+
*/
|
|
19023
|
+
async priceIntent(params, sourceChain, destinationChain, price, totals) {
|
|
18938
19024
|
validateQuoteParams(params);
|
|
18939
19025
|
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
18940
19026
|
const tokenOut = this.assetByAddress(destinationChain, params.tokenOut);
|
|
18941
19027
|
const route = toRoute(tokenIn, tokenOut);
|
|
18942
19028
|
if (params.amountIn !== void 0) {
|
|
18943
|
-
const quote2 = await
|
|
18944
|
-
const
|
|
18945
|
-
if (
|
|
18946
|
-
|
|
19029
|
+
const quote2 = await price(route, toOrderbookAmount(params.amountIn, tokenIn.decimals));
|
|
19030
|
+
const { fillable, amountOut, maxFillableIn } = totals(quote2);
|
|
19031
|
+
if (!fillable || fromOrderbookAmount(amountOut, tokenOut.decimals) === 0n) {
|
|
19032
|
+
throw this.insufficient(route, maxFillableIn, tokenIn);
|
|
19033
|
+
}
|
|
19034
|
+
return { quote: quote2, tokenIn, tokenOut };
|
|
18947
19035
|
}
|
|
18948
|
-
const
|
|
18949
|
-
const quote = await this.quoteExactOutput(route,
|
|
18950
|
-
return
|
|
18951
|
-
"EXACT_OUTPUT",
|
|
18952
|
-
fromOrderbookAmount(quote.amountIn, tokenIn.decimals),
|
|
18953
|
-
amountOut,
|
|
18954
|
-
quote,
|
|
18955
|
-
tokenIn,
|
|
18956
|
-
tokenOut
|
|
18957
|
-
);
|
|
19036
|
+
const targetOut = toOrderbookAmount(params.amountOut, tokenOut.decimals);
|
|
19037
|
+
const quote = await this.quoteExactOutput(route, targetOut, tokenIn, price, totals);
|
|
19038
|
+
return { quote, tokenIn, tokenOut };
|
|
18958
19039
|
}
|
|
18959
19040
|
async availableLiquidity(params, sourceChain, destinationChain) {
|
|
18960
19041
|
const tokenIn = this.assetByAddress(sourceChain, params.tokenIn);
|
|
@@ -19007,22 +19088,26 @@ var OrderbookMarket = class {
|
|
|
19007
19088
|
}
|
|
19008
19089
|
/**
|
|
19009
19090
|
* The orderbook only quotes an input amount, so an output is priced by
|
|
19010
|
-
* guessing the input from the best rate
|
|
19011
|
-
*
|
|
19091
|
+
* guessing the input from the best rate, then keeping the part of each quote
|
|
19092
|
+
* filled better than its worst rate and re-pricing the rest of `targetOut` at
|
|
19093
|
+
* the input-to-output ratio that part filled at, until a quote delivers it.
|
|
19094
|
+
* That ratio is the orderbook's own, with the protocol fee already taken off.
|
|
19012
19095
|
*/
|
|
19013
|
-
async quoteExactOutput(route, targetOut, tokenIn) {
|
|
19014
|
-
const
|
|
19015
|
-
const liquidity = await orderbook.routeLiquidity(route);
|
|
19096
|
+
async quoteExactOutput(route, targetOut, tokenIn, price, totals) {
|
|
19097
|
+
const liquidity = await this.orderbook().routeLiquidity(route);
|
|
19016
19098
|
if (liquidity.bestRate === null) throw this.insufficient(route, 0n, tokenIn);
|
|
19017
19099
|
const inputUnit = toOrderbookAmount(1n, tokenIn.decimals);
|
|
19018
19100
|
let amountIn = roundUpTo(requiredInput(liquidity.side, targetOut, liquidity.bestRate), inputUnit);
|
|
19019
19101
|
let lastAmountIn = amountIn;
|
|
19020
19102
|
for (let round = 0; round < MAX_EXACT_OUTPUT_ROUNDS; round++) {
|
|
19021
19103
|
if (amountIn > liquidity.maxFillableIn) throw this.insufficient(route, liquidity.maxFillableIn, tokenIn);
|
|
19022
|
-
const
|
|
19023
|
-
|
|
19104
|
+
const served = await price(route, amountIn);
|
|
19105
|
+
const quote = totals(served);
|
|
19106
|
+
if (quote.fillable && quote.amountOut >= targetOut) return served;
|
|
19024
19107
|
lastAmountIn = amountIn;
|
|
19025
|
-
const
|
|
19108
|
+
const betterIn = quote.amountIn - quote.worstIn;
|
|
19109
|
+
const betterOut = quote.amountOut - quote.worstOut;
|
|
19110
|
+
const next = quote.fillable && quote.worstOut > 0n ? betterIn + roundUpTo(divCeil((targetOut - betterOut) * quote.worstIn, quote.worstOut), inputUnit) : amountIn;
|
|
19026
19111
|
amountIn = next > amountIn ? next : amountIn + inputUnit;
|
|
19027
19112
|
}
|
|
19028
19113
|
throw new OrderbookQuoteNotConvergedError(
|
|
@@ -19078,24 +19163,32 @@ function toRoute(tokenIn, tokenOut) {
|
|
|
19078
19163
|
function requiredInput(side, amountOut, rate) {
|
|
19079
19164
|
return side === "BID" ? divCeil(amountOut * ORDERBOOK_SCALE, rate) : divCeil(amountOut * rate, ORDERBOOK_SCALE);
|
|
19080
19165
|
}
|
|
19081
|
-
function
|
|
19082
|
-
|
|
19083
|
-
|
|
19166
|
+
function swapQuoteTotals(quote) {
|
|
19167
|
+
const worstFill = quote.fills.at(-1);
|
|
19168
|
+
if (quote.fillable && !worstFill)
|
|
19169
|
+
throw new OrderbookRequestError("the orderbook served a fillable quote with no fills");
|
|
19084
19170
|
return {
|
|
19085
|
-
|
|
19086
|
-
amountIn,
|
|
19087
|
-
amountOut,
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
19093
|
-
|
|
19094
|
-
|
|
19095
|
-
|
|
19096
|
-
|
|
19097
|
-
|
|
19098
|
-
|
|
19171
|
+
side: quote.side,
|
|
19172
|
+
amountIn: quote.amountIn,
|
|
19173
|
+
amountOut: quote.fills.reduce((total, fill) => total + fill.amountOut, 0n),
|
|
19174
|
+
fillable: quote.fillable,
|
|
19175
|
+
maxFillableIn: quote.maxFillableIn,
|
|
19176
|
+
worstIn: worstFill?.amountIn ?? 0n,
|
|
19177
|
+
worstOut: worstFill?.amountOut ?? 0n
|
|
19178
|
+
};
|
|
19179
|
+
}
|
|
19180
|
+
function levelQuoteTotals(quote) {
|
|
19181
|
+
if (quote.fillable && quote.rate === null) {
|
|
19182
|
+
throw new OrderbookRequestError("the orderbook served a fillable quote with no rate");
|
|
19183
|
+
}
|
|
19184
|
+
return {
|
|
19185
|
+
side: quote.side,
|
|
19186
|
+
amountIn: quote.amountIn,
|
|
19187
|
+
amountOut: quote.amountOut,
|
|
19188
|
+
fillable: quote.fillable,
|
|
19189
|
+
maxFillableIn: quote.maxFillableIn,
|
|
19190
|
+
worstIn: quote.amountIn,
|
|
19191
|
+
worstOut: quote.amountOut
|
|
19099
19192
|
};
|
|
19100
19193
|
}
|
|
19101
19194
|
function toOrderbookAmount(amount, decimals) {
|
|
@@ -19259,22 +19352,6 @@ var IntentGateway = class _IntentGateway {
|
|
|
19259
19352
|
this.orderbook = typeof orderbook === "string" ? new HyperFxOrderbook(orderbook) : orderbook;
|
|
19260
19353
|
return this;
|
|
19261
19354
|
}
|
|
19262
|
-
/**
|
|
19263
|
-
* Quotes an intent between this gateway's source and destination chains from
|
|
19264
|
-
* the HyperFX orderbook. Provide exactly one of `amountIn` or `amountOut`, in
|
|
19265
|
-
* raw token units.
|
|
19266
|
-
*
|
|
19267
|
-
* An exact-input quote is the orderbook's clearing price for `amountIn`,
|
|
19268
|
-
* which may combine several solvers' orders. An exact-output quote finds the
|
|
19269
|
-
* smallest input whose clearing price delivers `amountOut`. A cross-chain
|
|
19270
|
-
* route only counts orders whose solvers accept the source chain.
|
|
19271
|
-
*
|
|
19272
|
-
* The orderbook's rates already carry the gateway protocol fee, so the
|
|
19273
|
-
* returned amounts can be placed as the order's inputs and outputs directly.
|
|
19274
|
-
*
|
|
19275
|
-
* @throws {InsufficientOrderbookLiquidityError} When the route cannot fill the amount.
|
|
19276
|
-
* @throws {OrderbookRequestError} When the orderbook is unreachable or trades no book for the pair.
|
|
19277
|
-
*/
|
|
19278
19355
|
async quoteIntent(params) {
|
|
19279
19356
|
return this.market.quoteIntent(params, this.source.config.stateMachineId, this.dest.config.stateMachineId);
|
|
19280
19357
|
}
|