@kamino-finance/klend-sdk 5.12.8 → 5.13.0
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/classes/action.d.ts +2 -2
- package/dist/classes/action.d.ts.map +1 -1
- package/dist/classes/action.js +5 -3
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/market.d.ts +10 -0
- package/dist/classes/market.d.ts.map +1 -1
- package/dist/classes/market.js +17 -10
- package/dist/classes/market.js.map +1 -1
- package/dist/classes/obligation.d.ts +2 -2
- package/dist/classes/obligation.js +1 -1
- package/dist/classes/obligationOrder.d.ts +30 -7
- package/dist/classes/obligationOrder.d.ts.map +1 -1
- package/dist/classes/obligationOrder.js +47 -12
- package/dist/classes/obligationOrder.js.map +1 -1
- package/dist/classes/utils.d.ts +0 -1
- package/dist/classes/utils.d.ts.map +1 -1
- package/dist/classes/utils.js +0 -7
- package/dist/classes/utils.js.map +1 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +1 -0
- package/dist/lib.js.map +1 -1
- package/dist/obligation_orders/common.d.ts +62 -0
- package/dist/obligation_orders/common.d.ts.map +1 -0
- package/dist/obligation_orders/common.js +20 -0
- package/dist/obligation_orders/common.js.map +1 -0
- package/dist/obligation_orders/index.d.ts +4 -0
- package/dist/obligation_orders/index.d.ts.map +1 -0
- package/dist/obligation_orders/index.js +20 -0
- package/dist/obligation_orders/index.js.map +1 -0
- package/dist/obligation_orders/internal.d.ts +6 -0
- package/dist/obligation_orders/internal.d.ts.map +1 -0
- package/dist/obligation_orders/internal.js +72 -0
- package/dist/obligation_orders/internal.js.map +1 -0
- package/dist/obligation_orders/ltv_based.d.ts +51 -0
- package/dist/obligation_orders/ltv_based.d.ts.map +1 -0
- package/dist/obligation_orders/ltv_based.js +107 -0
- package/dist/obligation_orders/ltv_based.js.map +1 -0
- package/dist/obligation_orders/price_based.d.ts +81 -0
- package/dist/obligation_orders/price_based.d.ts.map +1 -0
- package/dist/obligation_orders/price_based.js +167 -0
- package/dist/obligation_orders/price_based.js.map +1 -0
- package/dist/utils/validations.d.ts +5 -0
- package/dist/utils/validations.d.ts.map +1 -0
- package/dist/utils/validations.js +36 -0
- package/dist/utils/validations.js.map +1 -0
- package/package.json +1 -1
- package/src/classes/action.ts +6 -4
- package/src/classes/manager.ts +1 -4
- package/src/classes/market.ts +21 -11
- package/src/classes/obligation.ts +2 -2
- package/src/classes/obligationOrder.ts +57 -20
- package/src/classes/utils.ts +0 -7
- package/src/lib.ts +1 -0
- package/src/obligation_orders/common.ts +70 -0
- package/src/obligation_orders/index.ts +3 -0
- package/src/obligation_orders/internal.ts +92 -0
- package/src/obligation_orders/ltv_based.ts +143 -0
- package/src/obligation_orders/price_based.ts +256 -0
- package/src/utils/validations.ts +31 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LtvBasedOrderTriggerType = void 0;
|
|
7
|
+
exports.createLtvBasedOrder = createLtvBasedOrder;
|
|
8
|
+
exports.readLtvBasedOrder = readLtvBasedOrder;
|
|
9
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
10
|
+
const obligationOrder_1 = require("../classes/obligationOrder");
|
|
11
|
+
const validations_1 = require("../utils/validations");
|
|
12
|
+
const common_1 = require("./common");
|
|
13
|
+
const internal_1 = require("./internal");
|
|
14
|
+
/**
|
|
15
|
+
* Creates an LTV-based {@link ObligationOrderAtIndex} based on the given stop-loss or take-profit specification.
|
|
16
|
+
*
|
|
17
|
+
* The returned object can then be passed directly to {@link KaminoAction.buildSetObligationOrderIxn()} to build an
|
|
18
|
+
* instruction which replaces (or cancels, if the specification is `null`) the given obligation's stop-loss or
|
|
19
|
+
* take-profit order on-chain.
|
|
20
|
+
*
|
|
21
|
+
* The given obligation cannot use 0-LTV collaterals (see {@link checkObligationCompatible()} for rationale).
|
|
22
|
+
*/
|
|
23
|
+
function createLtvBasedOrder(context, orderType, specification) {
|
|
24
|
+
checkObligationCompatible(context);
|
|
25
|
+
const index = (0, internal_1.toOrderIndex)(orderType);
|
|
26
|
+
if (specification === null) {
|
|
27
|
+
return obligationOrder_1.ObligationOrderAtIndex.empty(index);
|
|
28
|
+
}
|
|
29
|
+
const condition = toOrderCondition(orderType, specification.trigger);
|
|
30
|
+
(0, validations_1.checkThat)(condition.threshold().gte(MIN_LTV_THRESHOLD) && condition.threshold().lte(MAX_LTV_THRESHOLD), `LTV-based trigger outside valid range [${MIN_LTV_THRESHOLD}%; ${MAX_LTV_THRESHOLD}%]: ${condition.threshold()}%`);
|
|
31
|
+
return (0, internal_1.createConditionBasedOrder)(context, condition, specification).atIndex(index);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parses an {@link OrderSpecification} from the selected stop-loss or take-profit order of the given obligation.
|
|
35
|
+
*
|
|
36
|
+
* The given obligation cannot use 0-LTV collaterals (see {@link checkObligationCompatible()} for rationale).
|
|
37
|
+
*
|
|
38
|
+
* The selected order is expected to be of matching type (i.e. as if it was created using the
|
|
39
|
+
* {@link createLtvBasedOrder()}).
|
|
40
|
+
*/
|
|
41
|
+
function readLtvBasedOrder(context, orderType) {
|
|
42
|
+
checkObligationCompatible(context);
|
|
43
|
+
const kaminoOrder = context.kaminoObligation.getOrders()[(0, internal_1.toOrderIndex)(orderType)];
|
|
44
|
+
if (kaminoOrder === null) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const trigger = toTrigger(kaminoOrder.condition, orderType);
|
|
48
|
+
return (0, internal_1.readTriggerBasedOrder)(kaminoOrder, trigger);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A discriminator enum for {@link LtvBasedOrderTrigger};
|
|
52
|
+
*/
|
|
53
|
+
var LtvBasedOrderTriggerType;
|
|
54
|
+
(function (LtvBasedOrderTriggerType) {
|
|
55
|
+
LtvBasedOrderTriggerType["StopLoss"] = "StopLoss";
|
|
56
|
+
LtvBasedOrderTriggerType["TakeProfit"] = "TakeProfit";
|
|
57
|
+
})(LtvBasedOrderTriggerType || (exports.LtvBasedOrderTriggerType = LtvBasedOrderTriggerType = {}));
|
|
58
|
+
// Only internals below:
|
|
59
|
+
const FULL_PCT = 100;
|
|
60
|
+
const MIN_LTV_THRESHOLD = 0.01;
|
|
61
|
+
const MAX_LTV_THRESHOLD = 0.99;
|
|
62
|
+
function checkObligationCompatible({ kaminoMarket, kaminoObligation }) {
|
|
63
|
+
for (const depositReserveAddress of kaminoObligation.deposits.keys()) {
|
|
64
|
+
const depositReserve = kaminoMarket.getExistingReserveByAddress(depositReserveAddress);
|
|
65
|
+
// Note: the seemingly over-cautious requirement below ensures that the user-facing LTV calculation gives the same
|
|
66
|
+
// result as on the Klend SC side (they differ in the handling of 0-LTV collaterals; see
|
|
67
|
+
// `KaminoObligation.loanToValue()` doc for details). We may unify the 0-LTV handling some day and remove this.
|
|
68
|
+
(0, validations_1.checkThat)(depositReserve.state.config.loanToValuePct !== 0, `LTV-based orders cannot be used with a 0-LTV collateral: ${depositReserve.symbol}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function toOrderCondition(orderType, trigger) {
|
|
72
|
+
switch (orderType) {
|
|
73
|
+
case common_1.OrderType.StopLoss:
|
|
74
|
+
if (trigger.type === LtvBasedOrderTriggerType.StopLoss) {
|
|
75
|
+
return new obligationOrder_1.UserLtvAbove(new decimal_js_1.default(trigger.whenLtvPctAbove).div(FULL_PCT));
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case common_1.OrderType.TakeProfit:
|
|
79
|
+
if (trigger.type === LtvBasedOrderTriggerType.TakeProfit) {
|
|
80
|
+
return new obligationOrder_1.UserLtvBelow(new decimal_js_1.default(trigger.whenLtvPctBelow).div(FULL_PCT));
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`an LTV-based ${orderType} order cannot use ${trigger.type} condition`);
|
|
85
|
+
}
|
|
86
|
+
function toTrigger(condition, orderType) {
|
|
87
|
+
switch (orderType) {
|
|
88
|
+
case common_1.OrderType.StopLoss:
|
|
89
|
+
if (condition instanceof obligationOrder_1.UserLtvAbove) {
|
|
90
|
+
return {
|
|
91
|
+
type: LtvBasedOrderTriggerType.StopLoss,
|
|
92
|
+
whenLtvPctAbove: condition.minUserLtvExclusive.mul(FULL_PCT).toNumber(),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case common_1.OrderType.TakeProfit:
|
|
97
|
+
if (condition instanceof obligationOrder_1.UserLtvBelow) {
|
|
98
|
+
return {
|
|
99
|
+
type: LtvBasedOrderTriggerType.TakeProfit,
|
|
100
|
+
whenLtvPctBelow: condition.maxUserLtvExclusive.mul(FULL_PCT).toNumber(),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
throw new Error(`an LTV-based ${orderType} order has an incompatible on-chain condition ${condition.constructor.name}`);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=ltv_based.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ltv_based.js","sourceRoot":"","sources":["../../src/obligation_orders/ltv_based.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
import { ObligationOrderAtIndex } from '../classes/obligationOrder';
|
|
3
|
+
import { PublicKey } from '@solana/web3.js';
|
|
4
|
+
import { OrderContext, OrderSpecification, OrderType } from './common';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a price-based {@link ObligationOrderAtIndex} based on the given stop-loss or take-profit specification.
|
|
7
|
+
*
|
|
8
|
+
* The returned object can then be passed directly to {@link KaminoAction.buildSetObligationOrderIxn()} to build an
|
|
9
|
+
* instruction which replaces (or cancels, if the specification is `null`) the given obligation's stop-loss or
|
|
10
|
+
* take-profit order on-chain.
|
|
11
|
+
*
|
|
12
|
+
* The given obligation is expected to be a "price-based position" - a single-debt, single-coll obligation which either
|
|
13
|
+
* deposits or borrows a stablecoin (i.e. a long or short position of some token against a stablecoin).
|
|
14
|
+
*/
|
|
15
|
+
export declare function createPriceBasedOrder(context: PriceBasedOrderContext, orderType: OrderType, specification: PriceBasedOrderSpecification | null): ObligationOrderAtIndex;
|
|
16
|
+
/**
|
|
17
|
+
* Parses an {@link PriceBasedOrderSpecification} from the selected stop-loss or take-profit order of the given obligation.
|
|
18
|
+
*
|
|
19
|
+
* The given obligation is expected to be a "price-based position" - a single-debt, single-coll obligation which either
|
|
20
|
+
* deposits or borrows a stablecoin (i.e. a long or short position of some token against a stablecoin).
|
|
21
|
+
*
|
|
22
|
+
* The selected order is expected to be of matching type (i.e. as if it was created using the
|
|
23
|
+
* {@link createPriceBasedOrder()}).
|
|
24
|
+
*/
|
|
25
|
+
export declare function readPriceBasedOrder(context: PriceBasedOrderContext, orderType: OrderType): PriceBasedOrderSpecification | null;
|
|
26
|
+
/**
|
|
27
|
+
* An extended {@link OrderContext} needed to interpret orders on "price-based position" obligations.
|
|
28
|
+
*/
|
|
29
|
+
export type PriceBasedOrderContext = OrderContext & {
|
|
30
|
+
stablecoins: SymbolOrMintAddress[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A convenient multi-way of specifying a token.
|
|
34
|
+
*/
|
|
35
|
+
export type SymbolOrMintAddress = string | PublicKey;
|
|
36
|
+
/**
|
|
37
|
+
* A high-level specification of a price-based order.
|
|
38
|
+
*/
|
|
39
|
+
export type PriceBasedOrderSpecification = OrderSpecification<PriceBasedOrderTrigger>;
|
|
40
|
+
/**
|
|
41
|
+
* A discriminator enum for {@link PriceBasedOrderTrigger};
|
|
42
|
+
*/
|
|
43
|
+
export declare enum PriceBasedOrderTriggerType {
|
|
44
|
+
LongStopLoss = "LongStopLoss",
|
|
45
|
+
LongTakeProfit = "LongTakeProfit",
|
|
46
|
+
ShortStopLoss = "ShortStopLoss",
|
|
47
|
+
ShortTakeProfit = "ShortTakeProfit"
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One of possible triggers depending on the obligation's type and the price bracket's side.
|
|
51
|
+
*/
|
|
52
|
+
export type PriceBasedOrderTrigger = LongStopLoss | LongTakeProfit | ShortStopLoss | ShortTakeProfit;
|
|
53
|
+
/**
|
|
54
|
+
* A trigger for a stop-loss on a long position.
|
|
55
|
+
*/
|
|
56
|
+
export type LongStopLoss = {
|
|
57
|
+
type: PriceBasedOrderTriggerType.LongStopLoss;
|
|
58
|
+
whenCollateralPriceBelow: Decimal;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* A trigger for a take-profit on a long position.
|
|
62
|
+
*/
|
|
63
|
+
export type LongTakeProfit = {
|
|
64
|
+
type: PriceBasedOrderTriggerType.LongTakeProfit;
|
|
65
|
+
whenCollateralPriceAbove: Decimal;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* A trigger for a stop-loss on a short position.
|
|
69
|
+
*/
|
|
70
|
+
export type ShortStopLoss = {
|
|
71
|
+
type: PriceBasedOrderTriggerType.ShortStopLoss;
|
|
72
|
+
whenDebtPriceAbove: Decimal;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A trigger for a take-profit on a short position.
|
|
76
|
+
*/
|
|
77
|
+
export type ShortTakeProfit = {
|
|
78
|
+
type: PriceBasedOrderTriggerType.ShortTakeProfit;
|
|
79
|
+
whenDebtPriceBelow: Decimal;
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=price_based.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price_based.d.ts","sourceRoot":"","sources":["../../src/obligation_orders/price_based.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,EAGL,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGvE;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,4BAA4B,GAAG,IAAI,GACjD,sBAAsB,CAQxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,EAAE,SAAS,GACnB,4BAA4B,GAAG,IAAI,CAQrC;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG;IAClD,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,kBAAkB,CAAC,sBAAsB,CAAC,CAAC;AAEtF;;GAEG;AACH,oBAAY,0BAA0B;IACpC,YAAY,iBAAiB;IAC7B,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,eAAe,oBAAoB;CACpC;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC;AAErG;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,0BAA0B,CAAC,YAAY,CAAC;IAC9C,wBAAwB,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,0BAA0B,CAAC,cAAc,CAAC;IAChD,wBAAwB,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,0BAA0B,CAAC,aAAa,CAAC;IAC/C,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,0BAA0B,CAAC,eAAe,CAAC;IACjD,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PriceBasedOrderTriggerType = void 0;
|
|
7
|
+
exports.createPriceBasedOrder = createPriceBasedOrder;
|
|
8
|
+
exports.readPriceBasedOrder = readPriceBasedOrder;
|
|
9
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
10
|
+
const obligationOrder_1 = require("../classes/obligationOrder");
|
|
11
|
+
const utils_1 = require("../utils");
|
|
12
|
+
const validations_1 = require("../utils/validations");
|
|
13
|
+
const common_1 = require("./common");
|
|
14
|
+
const internal_1 = require("./internal");
|
|
15
|
+
/**
|
|
16
|
+
* Creates a price-based {@link ObligationOrderAtIndex} based on the given stop-loss or take-profit specification.
|
|
17
|
+
*
|
|
18
|
+
* The returned object can then be passed directly to {@link KaminoAction.buildSetObligationOrderIxn()} to build an
|
|
19
|
+
* instruction which replaces (or cancels, if the specification is `null`) the given obligation's stop-loss or
|
|
20
|
+
* take-profit order on-chain.
|
|
21
|
+
*
|
|
22
|
+
* The given obligation is expected to be a "price-based position" - a single-debt, single-coll obligation which either
|
|
23
|
+
* deposits or borrows a stablecoin (i.e. a long or short position of some token against a stablecoin).
|
|
24
|
+
*/
|
|
25
|
+
function createPriceBasedOrder(context, orderType, specification) {
|
|
26
|
+
const positionType = resolvePositionType(context); // resolving this first has an intentional side effect of validating the obligation being compatible
|
|
27
|
+
const index = (0, internal_1.toOrderIndex)(orderType);
|
|
28
|
+
if (specification === null) {
|
|
29
|
+
return obligationOrder_1.ObligationOrderAtIndex.empty(index);
|
|
30
|
+
}
|
|
31
|
+
const condition = toOrderCondition(positionType, orderType, specification.trigger);
|
|
32
|
+
return (0, internal_1.createConditionBasedOrder)(context, condition, specification).atIndex(index);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parses an {@link PriceBasedOrderSpecification} from the selected stop-loss or take-profit order of the given obligation.
|
|
36
|
+
*
|
|
37
|
+
* The given obligation is expected to be a "price-based position" - a single-debt, single-coll obligation which either
|
|
38
|
+
* deposits or borrows a stablecoin (i.e. a long or short position of some token against a stablecoin).
|
|
39
|
+
*
|
|
40
|
+
* The selected order is expected to be of matching type (i.e. as if it was created using the
|
|
41
|
+
* {@link createPriceBasedOrder()}).
|
|
42
|
+
*/
|
|
43
|
+
function readPriceBasedOrder(context, orderType) {
|
|
44
|
+
const positionType = resolvePositionType(context); // resolving this first has an intentional side effect of validating the obligation being compatible
|
|
45
|
+
const kaminoOrder = context.kaminoObligation.getOrders()[(0, internal_1.toOrderIndex)(orderType)];
|
|
46
|
+
if (kaminoOrder === null) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const trigger = toTrigger(positionType, kaminoOrder.condition, orderType);
|
|
50
|
+
return (0, internal_1.readTriggerBasedOrder)(kaminoOrder, trigger);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A discriminator enum for {@link PriceBasedOrderTrigger};
|
|
54
|
+
*/
|
|
55
|
+
var PriceBasedOrderTriggerType;
|
|
56
|
+
(function (PriceBasedOrderTriggerType) {
|
|
57
|
+
PriceBasedOrderTriggerType["LongStopLoss"] = "LongStopLoss";
|
|
58
|
+
PriceBasedOrderTriggerType["LongTakeProfit"] = "LongTakeProfit";
|
|
59
|
+
PriceBasedOrderTriggerType["ShortStopLoss"] = "ShortStopLoss";
|
|
60
|
+
PriceBasedOrderTriggerType["ShortTakeProfit"] = "ShortTakeProfit";
|
|
61
|
+
})(PriceBasedOrderTriggerType || (exports.PriceBasedOrderTriggerType = PriceBasedOrderTriggerType = {}));
|
|
62
|
+
// Only internals below:
|
|
63
|
+
function toOrderCondition(positionType, orderType, trigger) {
|
|
64
|
+
switch (positionType) {
|
|
65
|
+
case PositionType.Long:
|
|
66
|
+
switch (orderType) {
|
|
67
|
+
case common_1.OrderType.StopLoss:
|
|
68
|
+
if (trigger.type === PriceBasedOrderTriggerType.LongStopLoss) {
|
|
69
|
+
return new obligationOrder_1.DebtCollPriceRatioAbove(invertPriceRatio(trigger.whenCollateralPriceBelow));
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case common_1.OrderType.TakeProfit:
|
|
73
|
+
if (trigger.type === PriceBasedOrderTriggerType.LongTakeProfit) {
|
|
74
|
+
return new obligationOrder_1.DebtCollPriceRatioBelow(invertPriceRatio(trigger.whenCollateralPriceAbove));
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
case PositionType.Short:
|
|
80
|
+
switch (orderType) {
|
|
81
|
+
case common_1.OrderType.StopLoss:
|
|
82
|
+
if (trigger.type === PriceBasedOrderTriggerType.ShortStopLoss) {
|
|
83
|
+
return new obligationOrder_1.DebtCollPriceRatioAbove(trigger.whenDebtPriceAbove);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
case common_1.OrderType.TakeProfit:
|
|
87
|
+
if (trigger.type === PriceBasedOrderTriggerType.ShortTakeProfit) {
|
|
88
|
+
return new obligationOrder_1.DebtCollPriceRatioBelow(trigger.whenDebtPriceBelow);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`a ${orderType} order on a ${positionType} position cannot use ${trigger.type} condition`);
|
|
95
|
+
}
|
|
96
|
+
function toTrigger(positionType, condition, orderType) {
|
|
97
|
+
switch (positionType) {
|
|
98
|
+
case PositionType.Long:
|
|
99
|
+
switch (orderType) {
|
|
100
|
+
case common_1.OrderType.StopLoss:
|
|
101
|
+
if (condition instanceof obligationOrder_1.DebtCollPriceRatioAbove) {
|
|
102
|
+
return {
|
|
103
|
+
type: PriceBasedOrderTriggerType.LongStopLoss,
|
|
104
|
+
whenCollateralPriceBelow: invertPriceRatio(condition.minDebtCollPriceRatioExclusive),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case common_1.OrderType.TakeProfit:
|
|
109
|
+
if (condition instanceof obligationOrder_1.DebtCollPriceRatioBelow) {
|
|
110
|
+
return {
|
|
111
|
+
type: PriceBasedOrderTriggerType.LongTakeProfit,
|
|
112
|
+
whenCollateralPriceAbove: invertPriceRatio(condition.maxDebtCollPriceRatioExclusive),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
case PositionType.Short:
|
|
119
|
+
switch (orderType) {
|
|
120
|
+
case common_1.OrderType.StopLoss:
|
|
121
|
+
if (condition instanceof obligationOrder_1.DebtCollPriceRatioAbove) {
|
|
122
|
+
return {
|
|
123
|
+
type: PriceBasedOrderTriggerType.ShortStopLoss,
|
|
124
|
+
whenDebtPriceAbove: condition.minDebtCollPriceRatioExclusive,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case common_1.OrderType.TakeProfit:
|
|
129
|
+
if (condition instanceof obligationOrder_1.DebtCollPriceRatioBelow) {
|
|
130
|
+
return {
|
|
131
|
+
type: PriceBasedOrderTriggerType.ShortTakeProfit,
|
|
132
|
+
whenDebtPriceBelow: condition.maxDebtCollPriceRatioExclusive,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
throw new Error(`a ${orderType} order on a ${positionType} position has an incompatible on-chain condition ${condition.constructor.name}`);
|
|
140
|
+
}
|
|
141
|
+
function invertPriceRatio(priceRatio) {
|
|
142
|
+
return new decimal_js_1.default(1).div(priceRatio);
|
|
143
|
+
}
|
|
144
|
+
var PositionType;
|
|
145
|
+
(function (PositionType) {
|
|
146
|
+
PositionType["Long"] = "Long";
|
|
147
|
+
PositionType["Short"] = "Short";
|
|
148
|
+
})(PositionType || (PositionType = {}));
|
|
149
|
+
function resolvePositionType(context) {
|
|
150
|
+
const collateralReserveAddress = (0, validations_1.getSingleElement)(context.kaminoObligation.deposits.keys(), 'deposit');
|
|
151
|
+
const debtReserveAddress = (0, validations_1.getSingleElement)(context.kaminoObligation.borrows.keys(), 'borrow');
|
|
152
|
+
const stablecoinReserveAddresses = collectReserveAddresses(context.kaminoMarket, context.stablecoins);
|
|
153
|
+
if (stablecoinReserveAddresses.contains(collateralReserveAddress)) {
|
|
154
|
+
(0, validations_1.checkThat)(!stablecoinReserveAddresses.contains(debtReserveAddress), 'cannot resolve long vs short position from all-stablecoins obligation');
|
|
155
|
+
return PositionType.Short;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
(0, validations_1.checkThat)(stablecoinReserveAddresses.contains(debtReserveAddress), 'cannot resolve long vs short position from no-stablecoins obligation');
|
|
159
|
+
return PositionType.Long;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function collectReserveAddresses(kaminoMarket, symbolOrMintAddresses) {
|
|
163
|
+
return new utils_1.PublicKeySet(symbolOrMintAddresses.map((symbolOrMintAddress) => typeof symbolOrMintAddress === 'string'
|
|
164
|
+
? kaminoMarket.getExistingReserveBySymbol(symbolOrMintAddress).address
|
|
165
|
+
: kaminoMarket.getExistingReserveByMint(symbolOrMintAddress).address));
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=price_based.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price_based.js","sourceRoot":"","sources":["../../src/obligation_orders/price_based.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function checkThat(evaluationResult: boolean, message?: string): void;
|
|
2
|
+
export declare function checkDefined<T>(value: T | undefined, message?: string): T;
|
|
3
|
+
export declare function checkNotNull<T>(value: T | null, message?: string): T;
|
|
4
|
+
export declare function getSingleElement<T>(iterable: Iterable<T>, nameWithinMessage?: string): T;
|
|
5
|
+
//# sourceMappingURL=validations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validations.d.ts","sourceRoot":"","sources":["../../src/utils/validations.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAE,MAA8B,GAAG,IAAI,CAIlG;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,EAAE,OAAO,GAAE,MAA0B,GAAG,CAAC,CAG5F;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,GAAE,MAAqB,GAAG,CAAC,CAGlF;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,iBAAiB,GAAE,MAAkB,GAAG,CAAC,CAcnG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkThat = checkThat;
|
|
4
|
+
exports.checkDefined = checkDefined;
|
|
5
|
+
exports.checkNotNull = checkNotNull;
|
|
6
|
+
exports.getSingleElement = getSingleElement;
|
|
7
|
+
function checkThat(evaluationResult, message = 'precondition failed') {
|
|
8
|
+
if (!evaluationResult) {
|
|
9
|
+
throw new Error(message);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function checkDefined(value, message = 'value undefined') {
|
|
13
|
+
checkThat(value !== undefined, message);
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function checkNotNull(value, message = 'value null') {
|
|
17
|
+
checkThat(value !== null, message);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
function getSingleElement(iterable, nameWithinMessage = 'element') {
|
|
21
|
+
const nothingReturnedMarker = {};
|
|
22
|
+
let single = nothingReturnedMarker;
|
|
23
|
+
for (const element of iterable) {
|
|
24
|
+
if (single === nothingReturnedMarker) {
|
|
25
|
+
single = element;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw new Error(`exactly one ${nameWithinMessage} expected, but multiple found`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (single === nothingReturnedMarker) {
|
|
32
|
+
throw new Error(`exactly one ${nameWithinMessage} expected, but none found`);
|
|
33
|
+
}
|
|
34
|
+
return single;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=validations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validations.js","sourceRoot":"","sources":["../../src/utils/validations.ts"],"names":[],"mappings":";;AAAA,8BAIC;AAED,oCAGC;AAED,oCAGC;AAED,4CAcC;AA9BD,SAAgB,SAAS,CAAC,gBAAyB,EAAE,UAAkB,qBAAqB;IAC1F,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAI,KAAoB,EAAE,UAAkB,iBAAiB;IACvF,SAAS,CAAC,KAAK,KAAK,SAAS,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,KAAU,CAAC;AACpB,CAAC;AAED,SAAgB,YAAY,CAAI,KAAe,EAAE,UAAkB,YAAY;IAC7E,SAAS,CAAC,KAAK,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,KAAU,CAAC;AACpB,CAAC;AAED,SAAgB,gBAAgB,CAAI,QAAqB,EAAE,oBAA4B,SAAS;IAC9F,MAAM,qBAAqB,GAAG,EAAE,CAAC;IACjC,IAAI,MAAM,GAAW,qBAAqB,CAAC;IAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,qBAAqB,EAAE,CAAC;YACrC,MAAM,GAAG,OAAO,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,eAAe,iBAAiB,+BAA+B,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,qBAAqB,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,eAAe,iBAAiB,2BAA2B,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC"}
|
package/package.json
CHANGED
package/src/classes/action.ts
CHANGED
|
@@ -78,7 +78,7 @@ import { Reserve } from '../idl_codegen/accounts';
|
|
|
78
78
|
import { VanillaObligation } from '../utils/ObligationType';
|
|
79
79
|
import { PROGRAM_ID } from '../lib';
|
|
80
80
|
import { Scope } from '@kamino-finance/scope-sdk';
|
|
81
|
-
import {
|
|
81
|
+
import { ObligationOrderAtIndex } from './obligationOrder';
|
|
82
82
|
|
|
83
83
|
export type ActionType =
|
|
84
84
|
| 'deposit'
|
|
@@ -1165,11 +1165,13 @@ export class KaminoAction {
|
|
|
1165
1165
|
static buildSetObligationOrderIxn(
|
|
1166
1166
|
kaminoMarket: KaminoMarket,
|
|
1167
1167
|
obligation: KaminoObligation,
|
|
1168
|
-
|
|
1169
|
-
order: KaminoObligationOrder | null
|
|
1168
|
+
orderAtIndex: ObligationOrderAtIndex
|
|
1170
1169
|
): TransactionInstruction {
|
|
1171
1170
|
return setObligationOrder(
|
|
1172
|
-
{
|
|
1171
|
+
{
|
|
1172
|
+
index: orderAtIndex.index,
|
|
1173
|
+
order: orderAtIndex.orderState(),
|
|
1174
|
+
},
|
|
1173
1175
|
{
|
|
1174
1176
|
lendingMarket: kaminoMarket.getAddress(),
|
|
1175
1177
|
obligation: obligation.obligationAddress,
|
package/src/classes/manager.ts
CHANGED
|
@@ -629,10 +629,7 @@ export class KaminoManager {
|
|
|
629
629
|
const switchboardV2 = await SwitchboardProgram.loadMainnet(this.getConnection());
|
|
630
630
|
|
|
631
631
|
// Group reserves by market
|
|
632
|
-
const marketToReserve = new PubkeyHashMap<
|
|
633
|
-
PublicKey,
|
|
634
|
-
[PublicKey, Reserve, AccountInfo<Buffer>][]
|
|
635
|
-
>();
|
|
632
|
+
const marketToReserve = new PubkeyHashMap<PublicKey, [PublicKey, Reserve, AccountInfo<Buffer>][]>();
|
|
636
633
|
for (const [reserveAddress, reserveState, buffer] of reservePairs) {
|
|
637
634
|
const marketAddress = reserveState.lendingMarket;
|
|
638
635
|
if (!marketToReserve.has(marketAddress)) {
|
package/src/classes/market.ts
CHANGED
|
@@ -36,6 +36,7 @@ import { parseTokenSymbol, parseZeroPaddedUtf8 } from './utils';
|
|
|
36
36
|
import SwitchboardProgram from '@switchboard-xyz/sbv2-lite';
|
|
37
37
|
import { ObligationZP } from '../idl_codegen/zero_padding';
|
|
38
38
|
import { getProgramAccounts } from '../utils';
|
|
39
|
+
import { checkDefined } from '../utils/validations';
|
|
39
40
|
|
|
40
41
|
export interface ReserveRewardInfo {
|
|
41
42
|
rewardsPerSecond: Decimal; // not lamport
|
|
@@ -175,13 +176,10 @@ export class KaminoMarket {
|
|
|
175
176
|
if (elevationGroupId === 0) {
|
|
176
177
|
return null;
|
|
177
178
|
}
|
|
178
|
-
|
|
179
|
-
(candidate) => candidate.elevationGroup === elevationGroupId
|
|
179
|
+
return checkDefined(
|
|
180
|
+
this.getMarketElevationGroupDescriptions().find((candidate) => candidate.elevationGroup === elevationGroupId),
|
|
181
|
+
`${description} elevation group ${elevationGroupId} not found`
|
|
180
182
|
);
|
|
181
|
-
if (elevationGroup === undefined) {
|
|
182
|
-
throw new Error(`${description} elevation group ${elevationGroupId} not found in market ${this.getAddress()}`);
|
|
183
|
-
}
|
|
184
|
-
return elevationGroup;
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
getMinNetValueObligation(): Decimal {
|
|
@@ -420,6 +418,14 @@ export class KaminoMarket {
|
|
|
420
418
|
return this.reserves.get(address);
|
|
421
419
|
}
|
|
422
420
|
|
|
421
|
+
/**
|
|
422
|
+
* Returns this market's reserve of the given address, or throws an error (including the given description) if such
|
|
423
|
+
* reserve does not exist.
|
|
424
|
+
*/
|
|
425
|
+
getExistingReserveByAddress(address: PublicKey, description: string = 'Requested'): KaminoReserve {
|
|
426
|
+
return checkDefined(this.getReserveByAddress(address), `${description} reserve ${address} not found`);
|
|
427
|
+
}
|
|
428
|
+
|
|
423
429
|
getReserveByMint(address: PublicKey): KaminoReserve | undefined {
|
|
424
430
|
for (const reserve of this.reserves.values()) {
|
|
425
431
|
if (reserve.getLiquidityMint().equals(address)) {
|
|
@@ -434,11 +440,7 @@ export class KaminoMarket {
|
|
|
434
440
|
* such reserve does not exist.
|
|
435
441
|
*/
|
|
436
442
|
getExistingReserveByMint(address: PublicKey, description: string = 'Requested'): KaminoReserve {
|
|
437
|
-
|
|
438
|
-
if (!reserve) {
|
|
439
|
-
throw new Error(`${description} reserve with mint ${address} not found in market ${this.getAddress()}`);
|
|
440
|
-
}
|
|
441
|
-
return reserve;
|
|
443
|
+
return checkDefined(this.getReserveByMint(address), `${description} reserve with mint ${address} not found`);
|
|
442
444
|
}
|
|
443
445
|
|
|
444
446
|
getReserveBySymbol(symbol: string) {
|
|
@@ -450,6 +452,14 @@ export class KaminoMarket {
|
|
|
450
452
|
return undefined;
|
|
451
453
|
}
|
|
452
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Returns this market's reserve of the given symbol, or throws an error (including the given description) if
|
|
457
|
+
* such reserve does not exist.
|
|
458
|
+
*/
|
|
459
|
+
getExistingReserveBySymbol(symbol: string, description: string = 'Requested'): KaminoReserve {
|
|
460
|
+
return checkDefined(this.getReserveBySymbol(symbol), `${description} reserve with symbol ${symbol} not found`);
|
|
461
|
+
}
|
|
462
|
+
|
|
453
463
|
getReserveMintBySymbol(symbol: string) {
|
|
454
464
|
return this.getReserveBySymbol(symbol)?.getLiquidityMint();
|
|
455
465
|
}
|
|
@@ -67,7 +67,7 @@ export type ObligationStats = {
|
|
|
67
67
|
* The LTV at which the obligation becomes subject to liquidation, *suitable for UI display*.
|
|
68
68
|
*
|
|
69
69
|
* Technically, this is a ratio:
|
|
70
|
-
* - of a sum of all
|
|
70
|
+
* - of a sum of values of all deposits multiplied by reserves' liquidationLtv (i.e. `borrowLiquidationLimit`)
|
|
71
71
|
* - to a sum of values of all deposits having reserve's liquidationLtv > 0 (i.e. `userTotalLiquidatableDeposit`)
|
|
72
72
|
*
|
|
73
73
|
* Please note that this is different from the smart contract's definition of liquidation LTV (which divides by a sum
|
|
@@ -271,7 +271,7 @@ export class KaminoObligation {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
/**
|
|
274
|
-
* Returns obligation orders (including the null ones, i.e. non-active
|
|
274
|
+
* Returns obligation orders (including the null ones, i.e. non-active positions in the orders' array).
|
|
275
275
|
*/
|
|
276
276
|
getOrders(): Array<KaminoObligationOrder | null> {
|
|
277
277
|
return this.state.orders.map((order) => KaminoObligationOrder.fromState(order));
|