@depthhq/maker-sdk 0.1.18 → 0.1.20
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/bot/bot.d.ts +1 -0
- package/dist/bot/policy.d.ts +1 -0
- package/dist/node.js +50 -18
- package/package.json +2 -2
package/dist/bot/bot.d.ts
CHANGED
package/dist/bot/policy.d.ts
CHANGED
|
@@ -43,3 +43,4 @@ export declare function executionCosts(policy: BotPolicy, pricing?: Pick<BotPric
|
|
|
43
43
|
export declare function validateBotPolicy(policy: BotPolicy): void;
|
|
44
44
|
export declare function quoteHealth(market: BotMarket, now: number): string | undefined;
|
|
45
45
|
export declare function botQuote(policy: BotPolicy, market: BotMarket, position: PositionSnapshot, nonce: bigint, now: number, pricing?: BotPricing, reservationCredit?: bigint): QuoteInput | undefined;
|
|
46
|
+
export declare function quotePrices(policy: BotPolicy, market: BotMarket, position: bigint, sizes: readonly bigint[], now: number, pricing?: BotPricing): QuoteInput["tiers"];
|
package/dist/node.js
CHANGED
|
@@ -335,6 +335,17 @@ function botQuote(policy, market, position, nonce, now, pricing, reservationCred
|
|
|
335
335
|
const tiers = quoteSizes(market.config.quoteTiers.map((value) => BigInt(value.toString())), capacity);
|
|
336
336
|
if (!tiers.length)
|
|
337
337
|
return;
|
|
338
|
+
const quotes = quotePrices(policy, market, position.position, tiers, now, pricing);
|
|
339
|
+
const duration = Math.min(policy.lifetimeSeconds, market.config.maxQuoteLifetimeSeconds);
|
|
340
|
+
return {
|
|
341
|
+
tiers: quotes,
|
|
342
|
+
maxCapacity: capacity,
|
|
343
|
+
expiresAt: now + duration,
|
|
344
|
+
clientNonce: nonce
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function quotePrices(policy, market, position, sizes, now, pricing) {
|
|
348
|
+
const price = BigInt(market.oraclePriceE8.toString());
|
|
338
349
|
const half = Math.ceil(policy.spreadBps / 2);
|
|
339
350
|
const preparation = quoteBounds(market.config.maxQuoteDeviationBps).preparationBps;
|
|
340
351
|
if (half > preparation)
|
|
@@ -343,7 +354,7 @@ function botQuote(policy, market, position, nonce, now, pricing, reservationCred
|
|
|
343
354
|
validateBook(pricing.book, now * 1000, pricing.maxPriceAgeMs);
|
|
344
355
|
if (pricing && (!Number.isFinite(pricing.takerFeeBps) || pricing.takerFeeBps < 0 || !Number.isFinite(pricing.hourlyFundingBps)))
|
|
345
356
|
throw new Error("External execution costs are invalid");
|
|
346
|
-
const netPosition = position
|
|
357
|
+
const netPosition = position + (pricing?.externalPosition ?? 0n);
|
|
347
358
|
const netExposure = notional(netPosition, price);
|
|
348
359
|
const skewBps = netExposure * BigInt(policy.inventorySkewBps ?? 0) / policy.maxInventoryNotional;
|
|
349
360
|
const boundedSkew = skewBps < BigInt(policy.inventorySkewBps ?? 0) ? skewBps : BigInt(policy.inventorySkewBps ?? 0);
|
|
@@ -352,7 +363,7 @@ function botQuote(policy, market, position, nonce, now, pricing, reservationCred
|
|
|
352
363
|
const execution = executionCosts(policy, pricing);
|
|
353
364
|
const bidCosts = costs + BigInt(execution.bid);
|
|
354
365
|
const askCosts = costs + BigInt(execution.ask);
|
|
355
|
-
|
|
366
|
+
return sizes.map((size) => {
|
|
356
367
|
const units = (size * 100000000000n + price - 1n) / price;
|
|
357
368
|
const sell = pricing ? executionPrice(pricing.book.bids, units) : price;
|
|
358
369
|
const buy = pricing ? executionPrice(pricing.book.asks, units) : price;
|
|
@@ -363,13 +374,6 @@ function botQuote(policy, market, position, nonce, now, pricing, reservationCred
|
|
|
363
374
|
throw new Error("Executable maker prices exceed oracle deviation bounds");
|
|
364
375
|
return { size, bidE8, askE8 };
|
|
365
376
|
});
|
|
366
|
-
const duration = Math.min(policy.lifetimeSeconds, market.config.maxQuoteLifetimeSeconds);
|
|
367
|
-
return {
|
|
368
|
-
tiers: quotes,
|
|
369
|
-
maxCapacity: capacity,
|
|
370
|
-
expiresAt: now + duration,
|
|
371
|
-
clientNonce: nonce
|
|
372
|
-
};
|
|
373
377
|
}
|
|
374
378
|
|
|
375
379
|
// src/chain/clock.ts
|
|
@@ -841,6 +845,13 @@ class MakerBot {
|
|
|
841
845
|
}
|
|
842
846
|
const prior = this.maker.quote.get(new PublicKey2(replacement.prior));
|
|
843
847
|
const previous = await prior.status();
|
|
848
|
+
if (snapshot.status === "validated" && this.pricesChanged(replacement.request, market, now)) {
|
|
849
|
+
await flow.discard();
|
|
850
|
+
state.replacement = undefined;
|
|
851
|
+
this.reservationView = undefined;
|
|
852
|
+
await this.store.save(state);
|
|
853
|
+
return this.snapshot("pending", "successor prices changed");
|
|
854
|
+
}
|
|
844
855
|
if (previous.status === "active" && ["validated", "reserving"].includes(snapshot.status)) {
|
|
845
856
|
const price = BigInt(market.oraclePriceE8.toString());
|
|
846
857
|
const size = this.position.position;
|
|
@@ -916,8 +927,6 @@ class MakerBot {
|
|
|
916
927
|
await this.hedge.tick(state.hedge, () => this.saveHedge(), undefined);
|
|
917
928
|
return this.snapshot(stopped && !state.hedge?.pending ? "stopped" : "pending", reason);
|
|
918
929
|
}
|
|
919
|
-
if (state.quote)
|
|
920
|
-
await this.renew(market, now);
|
|
921
930
|
await this.fills();
|
|
922
931
|
const hedgeReason = await this.hedgeTick();
|
|
923
932
|
if (hedgeReason)
|
|
@@ -977,8 +986,19 @@ class MakerBot {
|
|
|
977
986
|
const reference = BigInt(current.oracleReferenceE8.toString());
|
|
978
987
|
const drift = price > reference ? price - reference : reference - price;
|
|
979
988
|
const compatible = current.marketRevision.eq(market.revision) && drift * 10000n <= reference * BigInt(Math.min(Math.floor(market.config.maxQuoteDeviationBps / 4), 25));
|
|
980
|
-
if (!this.dirty && !this.pricingDirty && compatible && current.expiry.toNumber() > now && difference !== undefined && difference < BigInt(this.policy.repriceBps) * state.referencePrice)
|
|
981
|
-
|
|
989
|
+
if (!this.dirty && !this.pricingDirty && compatible && current.expiry.toNumber() > now && difference !== undefined && difference < BigInt(this.policy.repriceBps) * state.referencePrice && state.request !== undefined && !this.pricesChanged(state.request, market, now)) {
|
|
990
|
+
if (await this.renew(market, now))
|
|
991
|
+
return this.snapshot("active");
|
|
992
|
+
market = await this.maker.read("Market", this.maker.marketAddress);
|
|
993
|
+
now = await chainTime(this.maker.options.connection);
|
|
994
|
+
const changed = quoteHealth(market, now);
|
|
995
|
+
if (changed) {
|
|
996
|
+
const stopped = await this.cancel();
|
|
997
|
+
return this.snapshot(stopped ? "stopped" : "pending", changed);
|
|
998
|
+
}
|
|
999
|
+
if ((await handle2.status()).status !== "active")
|
|
1000
|
+
return this.snapshot("pending", "quote changed during renewal");
|
|
1001
|
+
}
|
|
982
1002
|
state.replacement = { prior: state.quote, nonce: nonce() };
|
|
983
1003
|
this.pricingDirty = false;
|
|
984
1004
|
await this.store.save(state);
|
|
@@ -1034,22 +1054,33 @@ class MakerBot {
|
|
|
1034
1054
|
this.busy = false;
|
|
1035
1055
|
}
|
|
1036
1056
|
}
|
|
1057
|
+
pricesChanged(request, market, now) {
|
|
1058
|
+
if (this.position?.position === undefined)
|
|
1059
|
+
return true;
|
|
1060
|
+
const prices = quotePrices(this.policy, market, this.position.position, request.tiers.map((tier) => tier.size), now, this.pricing);
|
|
1061
|
+
return request.tiers.some((tier, index) => ["bidE8", "askE8"].some((side) => {
|
|
1062
|
+
const before = tier[side];
|
|
1063
|
+
const after = prices[index][side];
|
|
1064
|
+
const change = after > before ? after - before : before - after;
|
|
1065
|
+
return change * 10000n >= before * BigInt(this.policy.repriceBps);
|
|
1066
|
+
}));
|
|
1067
|
+
}
|
|
1037
1068
|
async renew(market, now) {
|
|
1038
1069
|
const state = this.state;
|
|
1039
1070
|
if (this.hedge && (state.hedge?.pending || state.inventoryPendingSince !== undefined && Date.now() - state.inventoryPendingSince >= this.hedge.policy.maxUnhedgedMs))
|
|
1040
|
-
return;
|
|
1071
|
+
return false;
|
|
1041
1072
|
const handle = this.maker.quote.get(new PublicKey2(state.quote));
|
|
1042
1073
|
const quote = await this.maker.quoteState(handle.id);
|
|
1043
1074
|
if (!("active" in quote.status) || quote.expiry.toNumber() <= now)
|
|
1044
|
-
return;
|
|
1075
|
+
return false;
|
|
1045
1076
|
const duration = Math.min(this.policy.lifetimeSeconds, market.config.maxQuoteLifetimeSeconds);
|
|
1046
1077
|
if (quote.expiry.toNumber() - now > Math.max(this.policy.refreshSeconds, duration - this.policy.refreshSeconds))
|
|
1047
|
-
return;
|
|
1078
|
+
return true;
|
|
1048
1079
|
const price = BigInt(market.oraclePriceE8.toString());
|
|
1049
1080
|
const reference = BigInt(quote.oracleReferenceE8.toString());
|
|
1050
1081
|
const drift = price > reference ? price - reference : reference - price;
|
|
1051
1082
|
if (!quote.marketRevision.eq(market.revision) || reference <= 0n || drift * 10000n > reference * BigInt(Math.min(Math.floor(market.config.maxQuoteDeviationBps / 4), 25)))
|
|
1052
|
-
return;
|
|
1083
|
+
return false;
|
|
1053
1084
|
let renewed;
|
|
1054
1085
|
try {
|
|
1055
1086
|
renewed = await handle.renew({ validForSeconds: duration });
|
|
@@ -1065,12 +1096,13 @@ class MakerBot {
|
|
|
1065
1096
|
const quotedPrice = BigInt(current.oracleReferenceE8.toString());
|
|
1066
1097
|
const moved = currentPrice > quotedPrice ? currentPrice - quotedPrice : quotedPrice - currentPrice;
|
|
1067
1098
|
if (!("active" in current.status) || current.expiry.toNumber() <= Math.floor(Date.now() / 1000) || !current.marketRevision.eq(latest.revision) || quoteHealth(latest, Math.floor(Date.now() / 1000)) || moved * 10000n > quotedPrice * BigInt(Math.min(Math.floor(latest.config.maxQuoteDeviationBps / 4), 25)))
|
|
1068
|
-
return;
|
|
1099
|
+
return false;
|
|
1069
1100
|
throw error;
|
|
1070
1101
|
}
|
|
1071
1102
|
if (state.request)
|
|
1072
1103
|
state.request.expiresAt = renewed.expiresAt;
|
|
1073
1104
|
await this.store.save(state);
|
|
1105
|
+
return true;
|
|
1074
1106
|
}
|
|
1075
1107
|
quotePolicy(market) {
|
|
1076
1108
|
if (!this.hedge || !this.pricing || this.position?.position === undefined)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depthhq/maker-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"buffer": "6.0.3",
|
|
31
31
|
"viem": "2.38.0",
|
|
32
32
|
"@depthhq/bindings": "0.1.5",
|
|
33
|
-
"@depthhq/sdk": "0.1.
|
|
33
|
+
"@depthhq/sdk": "0.1.12"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "node ../../scripts/build-package.mjs maker-sdk",
|