@drift-labs/sdk 2.97.0-beta.5 → 2.97.0-beta.7
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/VERSION +1 -1
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +5 -1
- package/lib/adminClient.d.ts +6 -0
- package/lib/adminClient.js +53 -0
- package/lib/config.d.ts +1 -1
- package/lib/config.js +5 -3
- package/lib/driftClient.d.ts +4 -0
- package/lib/driftClient.js +30 -0
- package/lib/math/margin.d.ts +2 -2
- package/lib/math/margin.js +4 -4
- package/lib/math/market.d.ts +1 -1
- package/lib/math/market.js +15 -3
- package/lib/types.d.ts +11 -0
- package/lib/types.js +6 -1
- package/lib/user.d.ts +1 -0
- package/lib/user.js +12 -8
- package/package.json +1 -1
- package/src/addresses/pda.ts +9 -0
- package/src/adminClient.ts +114 -0
- package/src/config.ts +12 -3
- package/src/driftClient.ts +68 -0
- package/src/math/margin.ts +8 -4
- package/src/math/market.ts +19 -3
- package/src/types.ts +9 -0
- package/src/user.ts +21 -8
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.97.0-beta.
|
|
1
|
+
2.97.0-beta.7
|
package/lib/addresses/pda.d.ts
CHANGED
|
@@ -26,3 +26,4 @@ export declare function getProtocolIfSharesTransferConfigPublicKey(programId: Pu
|
|
|
26
26
|
export declare function getPrelaunchOraclePublicKey(programId: PublicKey, marketIndex: number): PublicKey;
|
|
27
27
|
export declare function getPythPullOraclePublicKey(progarmId: PublicKey, feedId: Uint8Array): PublicKey;
|
|
28
28
|
export declare function getTokenProgramForSpotMarket(spotMarketAccount: SpotMarketAccount): PublicKey;
|
|
29
|
+
export declare function getHighLeverageModeConfigPublicKey(programId: PublicKey): PublicKey;
|
package/lib/addresses/pda.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.getTokenProgramForSpotMarket = exports.getPythPullOraclePublicKey = exports.getPrelaunchOraclePublicKey = exports.getProtocolIfSharesTransferConfigPublicKey = exports.getReferrerNamePublicKeySync = exports.getOpenbookV2FulfillmentConfigPublicKey = exports.getPhoenixFulfillmentConfigPublicKey = exports.getSerumFulfillmentConfigPublicKey = exports.getSerumSignerPublicKey = exports.getSerumOpenOrdersPublicKey = exports.getDriftSignerPublicKey = exports.getInsuranceFundStakeAccountPublicKey = exports.getInsuranceFundVaultPublicKey = exports.getSpotMarketVaultPublicKey = exports.getSpotMarketPublicKeySync = exports.getSpotMarketPublicKey = exports.getPerpMarketPublicKeySync = exports.getPerpMarketPublicKey = exports.getUserStatsAccountPublicKey = exports.getUserAccountPublicKeySync = exports.getUserAccountPublicKey = exports.getUserAccountPublicKeyAndNonce = exports.getDriftStateAccountPublicKey = exports.getDriftStateAccountPublicKeyAndNonce = void 0;
|
|
26
|
+
exports.getHighLeverageModeConfigPublicKey = exports.getTokenProgramForSpotMarket = exports.getPythPullOraclePublicKey = exports.getPrelaunchOraclePublicKey = exports.getProtocolIfSharesTransferConfigPublicKey = exports.getReferrerNamePublicKeySync = exports.getOpenbookV2FulfillmentConfigPublicKey = exports.getPhoenixFulfillmentConfigPublicKey = exports.getSerumFulfillmentConfigPublicKey = exports.getSerumSignerPublicKey = exports.getSerumOpenOrdersPublicKey = exports.getDriftSignerPublicKey = exports.getInsuranceFundStakeAccountPublicKey = exports.getInsuranceFundVaultPublicKey = exports.getSpotMarketVaultPublicKey = exports.getSpotMarketPublicKeySync = exports.getSpotMarketPublicKey = exports.getPerpMarketPublicKeySync = exports.getPerpMarketPublicKey = exports.getUserStatsAccountPublicKey = exports.getUserAccountPublicKeySync = exports.getUserAccountPublicKey = exports.getUserAccountPublicKeyAndNonce = exports.getDriftStateAccountPublicKey = exports.getDriftStateAccountPublicKeyAndNonce = void 0;
|
|
27
27
|
const web3_js_1 = require("@solana/web3.js");
|
|
28
28
|
const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
29
29
|
const spl_token_1 = require("@solana/spl-token");
|
|
@@ -180,3 +180,7 @@ function getTokenProgramForSpotMarket(spotMarketAccount) {
|
|
|
180
180
|
return spl_token_1.TOKEN_PROGRAM_ID;
|
|
181
181
|
}
|
|
182
182
|
exports.getTokenProgramForSpotMarket = getTokenProgramForSpotMarket;
|
|
183
|
+
function getHighLeverageModeConfigPublicKey(programId) {
|
|
184
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(anchor.utils.bytes.utf8.encode('high_leverage_mode_config'))], programId)[0];
|
|
185
|
+
}
|
|
186
|
+
exports.getHighLeverageModeConfigPublicKey = getHighLeverageModeConfigPublicKey;
|
package/lib/adminClient.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export declare class AdminClient extends DriftClient {
|
|
|
55
55
|
getUpdatePerpMarketTargetBaseAssetAmountPerLpIx(perpMarketIndex: number, targetBaseAssetAmountPerLP: number): Promise<TransactionInstruction>;
|
|
56
56
|
updatePerpMarketMarginRatio(perpMarketIndex: number, marginRatioInitial: number, marginRatioMaintenance: number): Promise<TransactionSignature>;
|
|
57
57
|
getUpdatePerpMarketMarginRatioIx(perpMarketIndex: number, marginRatioInitial: number, marginRatioMaintenance: number): Promise<TransactionInstruction>;
|
|
58
|
+
updatePerpMarketHighLeverageMarginRatio(perpMarketIndex: number, marginRatioInitial: number, marginRatioMaintenance: number): Promise<TransactionSignature>;
|
|
59
|
+
getUpdatePerpMarketHighLeverageMarginRatioIx(perpMarketIndex: number, marginRatioInitial: number, marginRatioMaintenance: number): Promise<TransactionInstruction>;
|
|
58
60
|
updatePerpMarketImfFactor(perpMarketIndex: number, imfFactor: number, unrealizedPnlImfFactor: number): Promise<TransactionSignature>;
|
|
59
61
|
getUpdatePerpMarketImfFactorIx(perpMarketIndex: number, imfFactor: number, unrealizedPnlImfFactor: number): Promise<TransactionInstruction>;
|
|
60
62
|
updatePerpMarketBaseSpread(perpMarketIndex: number, baseSpread: number): Promise<TransactionSignature>;
|
|
@@ -193,4 +195,8 @@ export declare class AdminClient extends DriftClient {
|
|
|
193
195
|
getInitUserFuelIx(user: PublicKey, authority: PublicKey, fuelBonusDeposits?: number, fuelBonusBorrows?: number, fuelBonusTaker?: number, fuelBonusMaker?: number, fuelBonusInsurance?: number): Promise<TransactionInstruction>;
|
|
194
196
|
initializePythPullOracle(feedId: string): Promise<TransactionSignature>;
|
|
195
197
|
getInitializePythPullOracleIx(feedId: string): Promise<TransactionInstruction>;
|
|
198
|
+
initializeHighLeverageModeConfig(maxUsers: number): Promise<TransactionSignature>;
|
|
199
|
+
getInitializeHighLeverageModeConfigIx(maxUsers: number): Promise<TransactionInstruction>;
|
|
200
|
+
updateUpdateHighLeverageModeConfig(maxUsers: number, reduceOnly: boolean): Promise<TransactionSignature>;
|
|
201
|
+
getUpdateHighLeverageModeConfigIx(maxUsers: number, reduceOnly: boolean): Promise<TransactionInstruction>;
|
|
196
202
|
}
|
package/lib/adminClient.js
CHANGED
|
@@ -561,6 +561,23 @@ class AdminClient extends driftClient_1.DriftClient {
|
|
|
561
561
|
},
|
|
562
562
|
});
|
|
563
563
|
}
|
|
564
|
+
async updatePerpMarketHighLeverageMarginRatio(perpMarketIndex, marginRatioInitial, marginRatioMaintenance) {
|
|
565
|
+
const updatePerpMarketHighLeverageMarginRatioIx = await this.getUpdatePerpMarketHighLeverageMarginRatioIx(perpMarketIndex, marginRatioInitial, marginRatioMaintenance);
|
|
566
|
+
const tx = await this.buildTransaction(updatePerpMarketHighLeverageMarginRatioIx);
|
|
567
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
568
|
+
return txSig;
|
|
569
|
+
}
|
|
570
|
+
async getUpdatePerpMarketHighLeverageMarginRatioIx(perpMarketIndex, marginRatioInitial, marginRatioMaintenance) {
|
|
571
|
+
return await this.program.instruction.updatePerpMarketHighLeverageMarginRatio(marginRatioInitial, marginRatioMaintenance, {
|
|
572
|
+
accounts: {
|
|
573
|
+
admin: this.isSubscribed
|
|
574
|
+
? this.getStateAccount().admin
|
|
575
|
+
: this.wallet.publicKey,
|
|
576
|
+
state: await this.getStatePublicKey(),
|
|
577
|
+
perpMarket: await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, perpMarketIndex),
|
|
578
|
+
},
|
|
579
|
+
});
|
|
580
|
+
}
|
|
564
581
|
async updatePerpMarketImfFactor(perpMarketIndex, imfFactor, unrealizedPnlImfFactor) {
|
|
565
582
|
const updatePerpMarketImfFactorIx = await this.getUpdatePerpMarketImfFactorIx(perpMarketIndex, imfFactor, unrealizedPnlImfFactor);
|
|
566
583
|
const tx = await this.buildTransaction(updatePerpMarketImfFactorIx);
|
|
@@ -1769,5 +1786,41 @@ class AdminClient extends driftClient_1.DriftClient {
|
|
|
1769
1786
|
},
|
|
1770
1787
|
});
|
|
1771
1788
|
}
|
|
1789
|
+
async initializeHighLeverageModeConfig(maxUsers) {
|
|
1790
|
+
const initializeHighLeverageModeConfigIx = await this.getInitializeHighLeverageModeConfigIx(maxUsers);
|
|
1791
|
+
const tx = await this.buildTransaction(initializeHighLeverageModeConfigIx);
|
|
1792
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1793
|
+
return txSig;
|
|
1794
|
+
}
|
|
1795
|
+
async getInitializeHighLeverageModeConfigIx(maxUsers) {
|
|
1796
|
+
return await this.program.instruction.initializeHighLeverageModeConfig(maxUsers, {
|
|
1797
|
+
accounts: {
|
|
1798
|
+
admin: this.isSubscribed
|
|
1799
|
+
? this.getStateAccount().admin
|
|
1800
|
+
: this.wallet.publicKey,
|
|
1801
|
+
state: await this.getStatePublicKey(),
|
|
1802
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
1803
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
1804
|
+
highLeverageModeConfig: (0, pda_1.getHighLeverageModeConfigPublicKey)(this.program.programId),
|
|
1805
|
+
},
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
async updateUpdateHighLeverageModeConfig(maxUsers, reduceOnly) {
|
|
1809
|
+
const updateHighLeverageModeConfigIx = await this.getUpdateHighLeverageModeConfigIx(maxUsers, reduceOnly);
|
|
1810
|
+
const tx = await this.buildTransaction(updateHighLeverageModeConfigIx);
|
|
1811
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1812
|
+
return txSig;
|
|
1813
|
+
}
|
|
1814
|
+
async getUpdateHighLeverageModeConfigIx(maxUsers, reduceOnly) {
|
|
1815
|
+
return await this.program.instruction.updateHighLeverageModeConfig(maxUsers, reduceOnly, {
|
|
1816
|
+
accounts: {
|
|
1817
|
+
admin: this.isSubscribed
|
|
1818
|
+
? this.getStateAccount().admin
|
|
1819
|
+
: this.wallet.publicKey,
|
|
1820
|
+
state: await this.getStatePublicKey(),
|
|
1821
|
+
highLeverageModeConfig: (0, pda_1.getHighLeverageModeConfigPublicKey)(this.program.programId),
|
|
1822
|
+
},
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1772
1825
|
}
|
|
1773
1826
|
exports.AdminClient = AdminClient;
|
package/lib/config.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare const initialize: (props: {
|
|
|
43
43
|
env: DriftEnv;
|
|
44
44
|
overrideEnv?: Partial<DriftConfig>;
|
|
45
45
|
}) => DriftConfig;
|
|
46
|
-
export declare function getMarketsAndOraclesForSubscription(env: DriftEnv): {
|
|
46
|
+
export declare function getMarketsAndOraclesForSubscription(env: DriftEnv, perpMarkets?: PerpMarketConfig[], spotMarkets?: SpotMarketConfig[]): {
|
|
47
47
|
perpMarketIndexes: number[];
|
|
48
48
|
spotMarketIndexes: number[];
|
|
49
49
|
oracleInfos: OracleInfo[];
|
package/lib/config.js
CHANGED
|
@@ -66,18 +66,20 @@ const initialize = (props) => {
|
|
|
66
66
|
return currentConfig;
|
|
67
67
|
};
|
|
68
68
|
exports.initialize = initialize;
|
|
69
|
-
function getMarketsAndOraclesForSubscription(env) {
|
|
69
|
+
function getMarketsAndOraclesForSubscription(env, perpMarkets, spotMarkets) {
|
|
70
|
+
const perpMarketsToUse = (perpMarkets === null || perpMarkets === void 0 ? void 0 : perpMarkets.length) > 0 ? perpMarkets : perpMarkets_1.PerpMarkets[env];
|
|
71
|
+
const spotMarketsToUse = (spotMarkets === null || spotMarkets === void 0 ? void 0 : spotMarkets.length) > 0 ? spotMarkets : spotMarkets_1.SpotMarkets[env];
|
|
70
72
|
const perpMarketIndexes = [];
|
|
71
73
|
const spotMarketIndexes = [];
|
|
72
74
|
const oracleInfos = new Map();
|
|
73
|
-
for (const market of
|
|
75
|
+
for (const market of perpMarketsToUse) {
|
|
74
76
|
perpMarketIndexes.push(market.marketIndex);
|
|
75
77
|
oracleInfos.set(market.oracle.toString(), {
|
|
76
78
|
publicKey: market.oracle,
|
|
77
79
|
source: market.oracleSource,
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
|
-
for (const spotMarket of
|
|
82
|
+
for (const spotMarket of spotMarketsToUse) {
|
|
81
83
|
spotMarketIndexes.push(spotMarket.marketIndex);
|
|
82
84
|
oracleInfos.set(spotMarket.oracle.toString(), {
|
|
83
85
|
publicKey: spotMarket.oracle,
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -789,6 +789,10 @@ export declare class DriftClient {
|
|
|
789
789
|
getPostSwitchboardOnDemandUpdateAtomicIx(feed: PublicKey, numSignatures?: number): Promise<TransactionInstruction | undefined>;
|
|
790
790
|
postSwitchboardOnDemandUpdate(feed: PublicKey, numSignatures?: number): Promise<TransactionSignature>;
|
|
791
791
|
private getBuildEncodedVaaIxs;
|
|
792
|
+
enableUserHighLeverageMode(subAccountId: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
793
|
+
getEnableHighLeverageModeIx(subAccountId: number): Promise<anchor.web3.TransactionInstruction>;
|
|
794
|
+
disableUserHighLeverageMode(user: PublicKey, txParams?: TxParams): Promise<TransactionSignature>;
|
|
795
|
+
getDisableHighLeverageModeIx(user: PublicKey): Promise<anchor.web3.TransactionInstruction>;
|
|
792
796
|
private handleSignedTransaction;
|
|
793
797
|
private handlePreSignedTransaction;
|
|
794
798
|
private isVersionedTransaction;
|
package/lib/driftClient.js
CHANGED
|
@@ -4254,6 +4254,36 @@ class DriftClient {
|
|
|
4254
4254
|
.instruction());
|
|
4255
4255
|
return [postIxs, encodedVaaKeypair];
|
|
4256
4256
|
}
|
|
4257
|
+
async enableUserHighLeverageMode(subAccountId, txParams) {
|
|
4258
|
+
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getEnableHighLeverageModeIx(subAccountId), txParams), [], this.opts);
|
|
4259
|
+
return txSig;
|
|
4260
|
+
}
|
|
4261
|
+
async getEnableHighLeverageModeIx(subAccountId) {
|
|
4262
|
+
const ix = await this.program.instruction.enableHighLeverageMode(subAccountId, {
|
|
4263
|
+
accounts: {
|
|
4264
|
+
state: await this.getStatePublicKey(),
|
|
4265
|
+
user: (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId),
|
|
4266
|
+
authority: this.wallet.publicKey,
|
|
4267
|
+
highLeverageModeConfig: (0, pda_1.getHighLeverageModeConfigPublicKey)(this.program.programId),
|
|
4268
|
+
},
|
|
4269
|
+
});
|
|
4270
|
+
return ix;
|
|
4271
|
+
}
|
|
4272
|
+
async disableUserHighLeverageMode(user, txParams) {
|
|
4273
|
+
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getDisableHighLeverageModeIx(user), txParams), [], this.opts);
|
|
4274
|
+
return txSig;
|
|
4275
|
+
}
|
|
4276
|
+
async getDisableHighLeverageModeIx(user) {
|
|
4277
|
+
const ix = await this.program.instruction.disableHighLeverageMode({
|
|
4278
|
+
accounts: {
|
|
4279
|
+
state: await this.getStatePublicKey(),
|
|
4280
|
+
user,
|
|
4281
|
+
authority: this.wallet.publicKey,
|
|
4282
|
+
highLeverageModeConfig: (0, pda_1.getHighLeverageModeConfigPublicKey)(this.program.programId),
|
|
4283
|
+
},
|
|
4284
|
+
});
|
|
4285
|
+
return ix;
|
|
4286
|
+
}
|
|
4257
4287
|
handleSignedTransaction(signedTxs) {
|
|
4258
4288
|
if (this.enableMetricsEvents && this.metricsEventEmitter) {
|
|
4259
4289
|
this.metricsEventEmitter.emit('txSigned', signedTxs);
|
package/lib/math/margin.d.ts
CHANGED
|
@@ -28,12 +28,12 @@ export declare function calculatePerpLiabilityValue(baseAssetAmount: BN, oracleP
|
|
|
28
28
|
* @param baseSize
|
|
29
29
|
* @returns
|
|
30
30
|
*/
|
|
31
|
-
export declare function calculateMarginUSDCRequiredForTrade(driftClient: DriftClient, targetMarketIndex: number, baseSize: BN, userMaxMarginRatio?: number): BN;
|
|
31
|
+
export declare function calculateMarginUSDCRequiredForTrade(driftClient: DriftClient, targetMarketIndex: number, baseSize: BN, userMaxMarginRatio?: number, userHighLeverageMode?: boolean): BN;
|
|
32
32
|
/**
|
|
33
33
|
* Similar to calculatetMarginUSDCRequiredForTrade, but calculates how much of a given collateral is required to cover the margin requirements for a given trade. Basically does the same thing as getMarginUSDCRequiredForTrade but also accounts for asset weight of the selected collateral.
|
|
34
34
|
*
|
|
35
35
|
* Returns collateral required in the precision of the target collateral market.
|
|
36
36
|
*/
|
|
37
|
-
export declare function calculateCollateralDepositRequiredForTrade(driftClient: DriftClient, targetMarketIndex: number, baseSize: BN, collateralIndex: number, userMaxMarginRatio?: number): BN;
|
|
37
|
+
export declare function calculateCollateralDepositRequiredForTrade(driftClient: DriftClient, targetMarketIndex: number, baseSize: BN, collateralIndex: number, userMaxMarginRatio?: number, userHighLeverageMode?: boolean): BN;
|
|
38
38
|
export declare function calculateCollateralValueOfDeposit(driftClient: DriftClient, collateralIndex: number, baseSize: BN): BN;
|
|
39
39
|
export declare function calculateLiquidationPrice(freeCollateral: BN, freeCollateralDelta: BN, oraclePrice: BN): BN;
|
package/lib/math/margin.js
CHANGED
|
@@ -123,11 +123,11 @@ exports.calculatePerpLiabilityValue = calculatePerpLiabilityValue;
|
|
|
123
123
|
* @param baseSize
|
|
124
124
|
* @returns
|
|
125
125
|
*/
|
|
126
|
-
function calculateMarginUSDCRequiredForTrade(driftClient, targetMarketIndex, baseSize, userMaxMarginRatio) {
|
|
126
|
+
function calculateMarginUSDCRequiredForTrade(driftClient, targetMarketIndex, baseSize, userMaxMarginRatio, userHighLeverageMode) {
|
|
127
127
|
const targetMarket = driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
128
128
|
const oracleData = driftClient.getOracleDataForPerpMarket(targetMarket.marketIndex);
|
|
129
129
|
const perpLiabilityValue = calculatePerpLiabilityValue(baseSize, oracleData.price, (0, types_1.isVariant)(targetMarket.contractType, 'prediction'));
|
|
130
|
-
const marginRequired = new anchor_1.BN((0, __1.calculateMarketMarginRatio)(targetMarket, baseSize.abs(), 'Initial', userMaxMarginRatio))
|
|
130
|
+
const marginRequired = new anchor_1.BN((0, __1.calculateMarketMarginRatio)(targetMarket, baseSize.abs(), 'Initial', userMaxMarginRatio, userHighLeverageMode))
|
|
131
131
|
.mul(perpLiabilityValue)
|
|
132
132
|
.div(numericConstants_1.MARGIN_PRECISION);
|
|
133
133
|
return marginRequired;
|
|
@@ -138,8 +138,8 @@ exports.calculateMarginUSDCRequiredForTrade = calculateMarginUSDCRequiredForTrad
|
|
|
138
138
|
*
|
|
139
139
|
* Returns collateral required in the precision of the target collateral market.
|
|
140
140
|
*/
|
|
141
|
-
function calculateCollateralDepositRequiredForTrade(driftClient, targetMarketIndex, baseSize, collateralIndex, userMaxMarginRatio) {
|
|
142
|
-
const marginRequiredUsdc = calculateMarginUSDCRequiredForTrade(driftClient, targetMarketIndex, baseSize, userMaxMarginRatio);
|
|
141
|
+
function calculateCollateralDepositRequiredForTrade(driftClient, targetMarketIndex, baseSize, collateralIndex, userMaxMarginRatio, userHighLeverageMode) {
|
|
142
|
+
const marginRequiredUsdc = calculateMarginUSDCRequiredForTrade(driftClient, targetMarketIndex, baseSize, userMaxMarginRatio, userHighLeverageMode);
|
|
143
143
|
const collateralMarket = driftClient.getSpotMarketAccount(collateralIndex);
|
|
144
144
|
const collateralOracleData = driftClient.getOracleDataForSpotMarket(collateralIndex);
|
|
145
145
|
const scaledAssetWeight = (0, __1.calculateScaledInitialAssetWeight)(collateralMarket, collateralOracleData.price);
|
package/lib/math/market.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare function calculateAskPrice(market: PerpMarketAccount, oraclePrice
|
|
|
27
27
|
export declare function calculateNewMarketAfterTrade(baseAssetAmount: BN, direction: PositionDirection, market: PerpMarketAccount): PerpMarketAccount;
|
|
28
28
|
export declare function calculateOracleReserveSpread(market: PerpMarketAccount, oraclePriceData: OraclePriceData): BN;
|
|
29
29
|
export declare function calculateOracleSpread(price: BN, oraclePriceData: OraclePriceData): BN;
|
|
30
|
-
export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory, customMarginRatio?: number): number;
|
|
30
|
+
export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory, customMarginRatio?: number, userHighLeverageMode?: boolean): number;
|
|
31
31
|
export declare function calculateUnrealizedAssetWeight(market: PerpMarketAccount, quoteSpotMarket: SpotMarketAccount, unrealizedPnl: BN, marginCategory: MarginCategory, oraclePriceData: OraclePriceData): BN;
|
|
32
32
|
export declare function calculateMarketAvailablePNL(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
|
|
33
33
|
export declare function calculateMarketMaxAvailableInsurance(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
|
package/lib/math/market.js
CHANGED
|
@@ -60,16 +60,28 @@ function calculateOracleSpread(price, oraclePriceData) {
|
|
|
60
60
|
return price.sub(oraclePriceData.price);
|
|
61
61
|
}
|
|
62
62
|
exports.calculateOracleSpread = calculateOracleSpread;
|
|
63
|
-
function calculateMarketMarginRatio(market, size, marginCategory, customMarginRatio = 0) {
|
|
63
|
+
function calculateMarketMarginRatio(market, size, marginCategory, customMarginRatio = 0, userHighLeverageMode = false) {
|
|
64
|
+
let marginRationInitial;
|
|
65
|
+
let marginRatioMaintenance;
|
|
66
|
+
if (userHighLeverageMode &&
|
|
67
|
+
market.highLeverageMarginRatioInitial > 0 &&
|
|
68
|
+
market.highLeverageMarginRatioMaintenance) {
|
|
69
|
+
marginRationInitial = market.highLeverageMarginRatioInitial;
|
|
70
|
+
marginRatioMaintenance = market.highLeverageMarginRatioMaintenance;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
marginRationInitial = market.marginRatioInitial;
|
|
74
|
+
marginRatioMaintenance = market.marginRatioMaintenance;
|
|
75
|
+
}
|
|
64
76
|
let marginRatio;
|
|
65
77
|
switch (marginCategory) {
|
|
66
78
|
case 'Initial': {
|
|
67
79
|
// use lowest leverage between max allowed and optional user custom max
|
|
68
|
-
marginRatio = Math.max((0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(
|
|
80
|
+
marginRatio = Math.max((0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(marginRationInitial), numericConstants_1.MARGIN_PRECISION).toNumber(), customMarginRatio);
|
|
69
81
|
break;
|
|
70
82
|
}
|
|
71
83
|
case 'Maintenance': {
|
|
72
|
-
marginRatio = (0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(
|
|
84
|
+
marginRatio = (0, margin_1.calculateSizePremiumLiabilityWeight)(size, new anchor_1.BN(market.imfFactor), new anchor_1.BN(marginRatioMaintenance), numericConstants_1.MARGIN_PRECISION).toNumber();
|
|
73
85
|
break;
|
|
74
86
|
}
|
|
75
87
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -71,6 +71,14 @@ export declare enum UserStatus {
|
|
|
71
71
|
REDUCE_ONLY = 4,
|
|
72
72
|
ADVANCED_LP = 8
|
|
73
73
|
}
|
|
74
|
+
export declare class MarginMode {
|
|
75
|
+
static readonly DEFAULT: {
|
|
76
|
+
default: {};
|
|
77
|
+
};
|
|
78
|
+
static readonly HIGH_LEVERAGE: {
|
|
79
|
+
highLeverage: {};
|
|
80
|
+
};
|
|
81
|
+
}
|
|
74
82
|
export declare class ContractType {
|
|
75
83
|
static readonly PERPETUAL: {
|
|
76
84
|
perpetual: {};
|
|
@@ -753,6 +761,8 @@ export type PerpMarketAccount = {
|
|
|
753
761
|
fuelBoostTaker: number;
|
|
754
762
|
fuelBoostMaker: number;
|
|
755
763
|
fuelBoostPosition: number;
|
|
764
|
+
highLeverageMarginRatioInitial: number;
|
|
765
|
+
highLeverageMarginRatioMaintenance: number;
|
|
756
766
|
};
|
|
757
767
|
export type HistoricalOracleData = {
|
|
758
768
|
lastOraclePrice: BN;
|
|
@@ -1004,6 +1014,7 @@ export type UserAccount = {
|
|
|
1004
1014
|
openAuctions: number;
|
|
1005
1015
|
hasOpenAuction: boolean;
|
|
1006
1016
|
lastFuelBonusUpdateTs: number;
|
|
1017
|
+
marginMode: MarginMode;
|
|
1007
1018
|
};
|
|
1008
1019
|
export type SpotPosition = {
|
|
1009
1020
|
marketIndex: number;
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
3
|
+
exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.MarginMode = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
// # Utility Types / Enums / Constants
|
|
6
6
|
var ExchangeStatus;
|
|
@@ -58,6 +58,11 @@ var UserStatus;
|
|
|
58
58
|
UserStatus[UserStatus["REDUCE_ONLY"] = 4] = "REDUCE_ONLY";
|
|
59
59
|
UserStatus[UserStatus["ADVANCED_LP"] = 8] = "ADVANCED_LP";
|
|
60
60
|
})(UserStatus = exports.UserStatus || (exports.UserStatus = {}));
|
|
61
|
+
class MarginMode {
|
|
62
|
+
}
|
|
63
|
+
exports.MarginMode = MarginMode;
|
|
64
|
+
MarginMode.DEFAULT = { default: {} };
|
|
65
|
+
MarginMode.HIGH_LEVERAGE = { highLeverage: {} };
|
|
61
66
|
class ContractType {
|
|
62
67
|
}
|
|
63
68
|
exports.ContractType = ContractType;
|
package/lib/user.d.ts
CHANGED
|
@@ -247,6 +247,7 @@ export declare class User {
|
|
|
247
247
|
isBeingLiquidated(): boolean;
|
|
248
248
|
hasStatus(status: UserStatus): boolean;
|
|
249
249
|
isBankrupt(): boolean;
|
|
250
|
+
isHighLeverageMode(): boolean;
|
|
250
251
|
/**
|
|
251
252
|
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
252
253
|
* @returns
|
package/lib/user.js
CHANGED
|
@@ -420,7 +420,7 @@ class User {
|
|
|
420
420
|
return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
|
|
421
421
|
}
|
|
422
422
|
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
|
|
423
|
-
const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial', this.getUserAccount().maxMarginRatio);
|
|
423
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial', this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
424
424
|
return freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio));
|
|
425
425
|
}
|
|
426
426
|
/**
|
|
@@ -787,7 +787,7 @@ class User {
|
|
|
787
787
|
liabilityValue = (0, _1.calculatePerpLiabilityValue)(baseAssetAmount, valuationPrice, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
788
788
|
}
|
|
789
789
|
if (marginCategory) {
|
|
790
|
-
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio));
|
|
790
|
+
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode()));
|
|
791
791
|
if (liquidationBuffer !== undefined) {
|
|
792
792
|
marginRatio = marginRatio.add(liquidationBuffer);
|
|
793
793
|
}
|
|
@@ -1032,7 +1032,7 @@ class User {
|
|
|
1032
1032
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1033
1033
|
.div(marketPrice));
|
|
1034
1034
|
// margin ratio incorporting upper bound on size
|
|
1035
|
-
let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
1035
|
+
let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1036
1036
|
// use more fesible size since imf factor activated
|
|
1037
1037
|
let attempts = 0;
|
|
1038
1038
|
while (marginRatio > rawMarginRatio + 1e-4 && attempts < 10) {
|
|
@@ -1043,7 +1043,7 @@ class User {
|
|
|
1043
1043
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1044
1044
|
.div(marketPrice));
|
|
1045
1045
|
// margin ratio incorporting more fesible target size
|
|
1046
|
-
marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
1046
|
+
marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1047
1047
|
attempts += 1;
|
|
1048
1048
|
}
|
|
1049
1049
|
// how much more liabilities can be opened w remaining free collateral
|
|
@@ -1133,6 +1133,9 @@ class User {
|
|
|
1133
1133
|
isBankrupt() {
|
|
1134
1134
|
return (this.getUserAccount().status & types_1.UserStatus.BANKRUPT) > 0;
|
|
1135
1135
|
}
|
|
1136
|
+
isHighLeverageMode() {
|
|
1137
|
+
return (0, types_1.isVariant)(this.getUserAccount().marginMode, 'highLeverage');
|
|
1138
|
+
}
|
|
1136
1139
|
/**
|
|
1137
1140
|
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
1138
1141
|
* @returns
|
|
@@ -1279,7 +1282,7 @@ class User {
|
|
|
1279
1282
|
baseAssetAmount = perpPosition.baseAssetAmount;
|
|
1280
1283
|
liabilityValue = (0, _1.calculatePerpLiabilityValue)(baseAssetAmount, oraclePrice, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
1281
1284
|
}
|
|
1282
|
-
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), 'Maintenance');
|
|
1285
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), 'Maintenance', this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1283
1286
|
return liabilityValue.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION);
|
|
1284
1287
|
};
|
|
1285
1288
|
const freeCollateralConsumptionBefore = calculateMarginRequirement(perpPosition);
|
|
@@ -1295,7 +1298,7 @@ class User {
|
|
|
1295
1298
|
// zero if include orders == false
|
|
1296
1299
|
const orderBaseAssetAmount = baseAssetAmount.sub(perpPosition.baseAssetAmount);
|
|
1297
1300
|
const proposedBaseAssetAmount = baseAssetAmount.add(positionBaseSizeChange);
|
|
1298
|
-
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, proposedBaseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio);
|
|
1301
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, proposedBaseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1299
1302
|
const marginRatioQuotePrecision = new _1.BN(marginRatio)
|
|
1300
1303
|
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1301
1304
|
.div(numericConstants_1.MARGIN_PRECISION);
|
|
@@ -1372,7 +1375,8 @@ class User {
|
|
|
1372
1375
|
return (0, margin_1.calculateMarginUSDCRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, this.getUserAccount().maxMarginRatio);
|
|
1373
1376
|
}
|
|
1374
1377
|
getCollateralDepositRequiredForTrade(targetMarketIndex, baseSize, collateralIndex) {
|
|
1375
|
-
return (0, margin_1.calculateCollateralDepositRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, collateralIndex, this.getUserAccount().maxMarginRatio
|
|
1378
|
+
return (0, margin_1.calculateCollateralDepositRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, collateralIndex, this.getUserAccount().maxMarginRatio, false // assume user cant be high leverage if they havent created user account ?
|
|
1379
|
+
);
|
|
1376
1380
|
}
|
|
1377
1381
|
/**
|
|
1378
1382
|
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
@@ -2002,7 +2006,7 @@ class User {
|
|
|
2002
2006
|
this.driftClient.getOracleDataForPerpMarket(perpMarket.marketIndex);
|
|
2003
2007
|
const oraclePrice = _oraclePriceData.price;
|
|
2004
2008
|
const { worstCaseBaseAssetAmount: worstCaseBaseAmount, worstCaseLiabilityValue, } = (0, _1.calculateWorstCasePerpLiabilityValue)(settledLpPosition, perpMarket, oraclePrice);
|
|
2005
|
-
const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio));
|
|
2009
|
+
const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode()));
|
|
2006
2010
|
const _quoteOraclePriceData = quoteOraclePriceData ||
|
|
2007
2011
|
this.driftClient.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
2008
2012
|
let marginRequirement = worstCaseLiabilityValue
|
package/package.json
CHANGED
package/src/addresses/pda.ts
CHANGED
|
@@ -300,3 +300,12 @@ export function getTokenProgramForSpotMarket(
|
|
|
300
300
|
}
|
|
301
301
|
return TOKEN_PROGRAM_ID;
|
|
302
302
|
}
|
|
303
|
+
|
|
304
|
+
export function getHighLeverageModeConfigPublicKey(
|
|
305
|
+
programId: PublicKey
|
|
306
|
+
): PublicKey {
|
|
307
|
+
return PublicKey.findProgramAddressSync(
|
|
308
|
+
[Buffer.from(anchor.utils.bytes.utf8.encode('high_leverage_mode_config'))],
|
|
309
|
+
programId
|
|
310
|
+
)[0];
|
|
311
|
+
}
|
package/src/adminClient.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
getOpenbookV2FulfillmentConfigPublicKey,
|
|
33
33
|
getPythPullOraclePublicKey,
|
|
34
34
|
getUserStatsAccountPublicKey,
|
|
35
|
+
getHighLeverageModeConfigPublicKey,
|
|
35
36
|
} from './addresses/pda';
|
|
36
37
|
import { squareRootBN } from './math/utils';
|
|
37
38
|
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
@@ -1268,6 +1269,50 @@ export class AdminClient extends DriftClient {
|
|
|
1268
1269
|
);
|
|
1269
1270
|
}
|
|
1270
1271
|
|
|
1272
|
+
public async updatePerpMarketHighLeverageMarginRatio(
|
|
1273
|
+
perpMarketIndex: number,
|
|
1274
|
+
marginRatioInitial: number,
|
|
1275
|
+
marginRatioMaintenance: number
|
|
1276
|
+
): Promise<TransactionSignature> {
|
|
1277
|
+
const updatePerpMarketHighLeverageMarginRatioIx =
|
|
1278
|
+
await this.getUpdatePerpMarketHighLeverageMarginRatioIx(
|
|
1279
|
+
perpMarketIndex,
|
|
1280
|
+
marginRatioInitial,
|
|
1281
|
+
marginRatioMaintenance
|
|
1282
|
+
);
|
|
1283
|
+
|
|
1284
|
+
const tx = await this.buildTransaction(
|
|
1285
|
+
updatePerpMarketHighLeverageMarginRatioIx
|
|
1286
|
+
);
|
|
1287
|
+
|
|
1288
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1289
|
+
|
|
1290
|
+
return txSig;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
public async getUpdatePerpMarketHighLeverageMarginRatioIx(
|
|
1294
|
+
perpMarketIndex: number,
|
|
1295
|
+
marginRatioInitial: number,
|
|
1296
|
+
marginRatioMaintenance: number
|
|
1297
|
+
): Promise<TransactionInstruction> {
|
|
1298
|
+
return await this.program.instruction.updatePerpMarketHighLeverageMarginRatio(
|
|
1299
|
+
marginRatioInitial,
|
|
1300
|
+
marginRatioMaintenance,
|
|
1301
|
+
{
|
|
1302
|
+
accounts: {
|
|
1303
|
+
admin: this.isSubscribed
|
|
1304
|
+
? this.getStateAccount().admin
|
|
1305
|
+
: this.wallet.publicKey,
|
|
1306
|
+
state: await this.getStatePublicKey(),
|
|
1307
|
+
perpMarket: await getPerpMarketPublicKey(
|
|
1308
|
+
this.program.programId,
|
|
1309
|
+
perpMarketIndex
|
|
1310
|
+
),
|
|
1311
|
+
},
|
|
1312
|
+
}
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1271
1316
|
public async updatePerpMarketImfFactor(
|
|
1272
1317
|
perpMarketIndex: number,
|
|
1273
1318
|
imfFactor: number,
|
|
@@ -3847,4 +3892,73 @@ export class AdminClient extends DriftClient {
|
|
|
3847
3892
|
}
|
|
3848
3893
|
);
|
|
3849
3894
|
}
|
|
3895
|
+
|
|
3896
|
+
public async initializeHighLeverageModeConfig(
|
|
3897
|
+
maxUsers: number
|
|
3898
|
+
): Promise<TransactionSignature> {
|
|
3899
|
+
const initializeHighLeverageModeConfigIx =
|
|
3900
|
+
await this.getInitializeHighLeverageModeConfigIx(maxUsers);
|
|
3901
|
+
|
|
3902
|
+
const tx = await this.buildTransaction(initializeHighLeverageModeConfigIx);
|
|
3903
|
+
|
|
3904
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
3905
|
+
|
|
3906
|
+
return txSig;
|
|
3907
|
+
}
|
|
3908
|
+
|
|
3909
|
+
public async getInitializeHighLeverageModeConfigIx(
|
|
3910
|
+
maxUsers: number
|
|
3911
|
+
): Promise<TransactionInstruction> {
|
|
3912
|
+
return await this.program.instruction.initializeHighLeverageModeConfig(
|
|
3913
|
+
maxUsers,
|
|
3914
|
+
{
|
|
3915
|
+
accounts: {
|
|
3916
|
+
admin: this.isSubscribed
|
|
3917
|
+
? this.getStateAccount().admin
|
|
3918
|
+
: this.wallet.publicKey,
|
|
3919
|
+
state: await this.getStatePublicKey(),
|
|
3920
|
+
rent: SYSVAR_RENT_PUBKEY,
|
|
3921
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
3922
|
+
highLeverageModeConfig: getHighLeverageModeConfigPublicKey(
|
|
3923
|
+
this.program.programId
|
|
3924
|
+
),
|
|
3925
|
+
},
|
|
3926
|
+
}
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
public async updateUpdateHighLeverageModeConfig(
|
|
3931
|
+
maxUsers: number,
|
|
3932
|
+
reduceOnly: boolean
|
|
3933
|
+
): Promise<TransactionSignature> {
|
|
3934
|
+
const updateHighLeverageModeConfigIx =
|
|
3935
|
+
await this.getUpdateHighLeverageModeConfigIx(maxUsers, reduceOnly);
|
|
3936
|
+
|
|
3937
|
+
const tx = await this.buildTransaction(updateHighLeverageModeConfigIx);
|
|
3938
|
+
|
|
3939
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
3940
|
+
|
|
3941
|
+
return txSig;
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
public async getUpdateHighLeverageModeConfigIx(
|
|
3945
|
+
maxUsers: number,
|
|
3946
|
+
reduceOnly: boolean
|
|
3947
|
+
): Promise<TransactionInstruction> {
|
|
3948
|
+
return await this.program.instruction.updateHighLeverageModeConfig(
|
|
3949
|
+
maxUsers,
|
|
3950
|
+
reduceOnly,
|
|
3951
|
+
{
|
|
3952
|
+
accounts: {
|
|
3953
|
+
admin: this.isSubscribed
|
|
3954
|
+
? this.getStateAccount().admin
|
|
3955
|
+
: this.wallet.publicKey,
|
|
3956
|
+
state: await this.getStatePublicKey(),
|
|
3957
|
+
highLeverageModeConfig: getHighLeverageModeConfigPublicKey(
|
|
3958
|
+
this.program.programId
|
|
3959
|
+
),
|
|
3960
|
+
},
|
|
3961
|
+
}
|
|
3962
|
+
);
|
|
3963
|
+
}
|
|
3850
3964
|
}
|
package/src/config.ts
CHANGED
|
@@ -114,16 +114,25 @@ export const initialize = (props: {
|
|
|
114
114
|
return currentConfig;
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
-
export function getMarketsAndOraclesForSubscription(
|
|
117
|
+
export function getMarketsAndOraclesForSubscription(
|
|
118
|
+
env: DriftEnv,
|
|
119
|
+
perpMarkets?: PerpMarketConfig[],
|
|
120
|
+
spotMarkets?: SpotMarketConfig[]
|
|
121
|
+
): {
|
|
118
122
|
perpMarketIndexes: number[];
|
|
119
123
|
spotMarketIndexes: number[];
|
|
120
124
|
oracleInfos: OracleInfo[];
|
|
121
125
|
} {
|
|
126
|
+
const perpMarketsToUse =
|
|
127
|
+
perpMarkets?.length > 0 ? perpMarkets : PerpMarkets[env];
|
|
128
|
+
const spotMarketsToUse =
|
|
129
|
+
spotMarkets?.length > 0 ? spotMarkets : SpotMarkets[env];
|
|
130
|
+
|
|
122
131
|
const perpMarketIndexes = [];
|
|
123
132
|
const spotMarketIndexes = [];
|
|
124
133
|
const oracleInfos = new Map<string, OracleInfo>();
|
|
125
134
|
|
|
126
|
-
for (const market of
|
|
135
|
+
for (const market of perpMarketsToUse) {
|
|
127
136
|
perpMarketIndexes.push(market.marketIndex);
|
|
128
137
|
oracleInfos.set(market.oracle.toString(), {
|
|
129
138
|
publicKey: market.oracle,
|
|
@@ -131,7 +140,7 @@ export function getMarketsAndOraclesForSubscription(env: DriftEnv): {
|
|
|
131
140
|
});
|
|
132
141
|
}
|
|
133
142
|
|
|
134
|
-
for (const spotMarket of
|
|
143
|
+
for (const spotMarket of spotMarketsToUse) {
|
|
135
144
|
spotMarketIndexes.push(spotMarket.marketIndex);
|
|
136
145
|
oracleInfos.set(spotMarket.oracle.toString(), {
|
|
137
146
|
publicKey: spotMarket.oracle,
|
package/src/driftClient.ts
CHANGED
|
@@ -82,6 +82,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
82
82
|
import {
|
|
83
83
|
getDriftSignerPublicKey,
|
|
84
84
|
getDriftStateAccountPublicKey,
|
|
85
|
+
getHighLeverageModeConfigPublicKey,
|
|
85
86
|
getInsuranceFundStakeAccountPublicKey,
|
|
86
87
|
getOpenbookV2FulfillmentConfigPublicKey,
|
|
87
88
|
getPerpMarketPublicKey,
|
|
@@ -8102,6 +8103,73 @@ export class DriftClient {
|
|
|
8102
8103
|
return [postIxs, encodedVaaKeypair];
|
|
8103
8104
|
}
|
|
8104
8105
|
|
|
8106
|
+
public async enableUserHighLeverageMode(
|
|
8107
|
+
subAccountId: number,
|
|
8108
|
+
txParams?: TxParams
|
|
8109
|
+
): Promise<TransactionSignature> {
|
|
8110
|
+
const { txSig } = await this.sendTransaction(
|
|
8111
|
+
await this.buildTransaction(
|
|
8112
|
+
await this.getEnableHighLeverageModeIx(subAccountId),
|
|
8113
|
+
txParams
|
|
8114
|
+
),
|
|
8115
|
+
[],
|
|
8116
|
+
this.opts
|
|
8117
|
+
);
|
|
8118
|
+
return txSig;
|
|
8119
|
+
}
|
|
8120
|
+
|
|
8121
|
+
public async getEnableHighLeverageModeIx(subAccountId: number) {
|
|
8122
|
+
const ix = await this.program.instruction.enableHighLeverageMode(
|
|
8123
|
+
subAccountId,
|
|
8124
|
+
{
|
|
8125
|
+
accounts: {
|
|
8126
|
+
state: await this.getStatePublicKey(),
|
|
8127
|
+
user: getUserAccountPublicKeySync(
|
|
8128
|
+
this.program.programId,
|
|
8129
|
+
this.wallet.publicKey,
|
|
8130
|
+
subAccountId
|
|
8131
|
+
),
|
|
8132
|
+
authority: this.wallet.publicKey,
|
|
8133
|
+
highLeverageModeConfig: getHighLeverageModeConfigPublicKey(
|
|
8134
|
+
this.program.programId
|
|
8135
|
+
),
|
|
8136
|
+
},
|
|
8137
|
+
}
|
|
8138
|
+
);
|
|
8139
|
+
|
|
8140
|
+
return ix;
|
|
8141
|
+
}
|
|
8142
|
+
|
|
8143
|
+
public async disableUserHighLeverageMode(
|
|
8144
|
+
user: PublicKey,
|
|
8145
|
+
txParams?: TxParams
|
|
8146
|
+
): Promise<TransactionSignature> {
|
|
8147
|
+
const { txSig } = await this.sendTransaction(
|
|
8148
|
+
await this.buildTransaction(
|
|
8149
|
+
await this.getDisableHighLeverageModeIx(user),
|
|
8150
|
+
txParams
|
|
8151
|
+
),
|
|
8152
|
+
[],
|
|
8153
|
+
this.opts
|
|
8154
|
+
);
|
|
8155
|
+
return txSig;
|
|
8156
|
+
}
|
|
8157
|
+
|
|
8158
|
+
public async getDisableHighLeverageModeIx(user: PublicKey) {
|
|
8159
|
+
const ix = await this.program.instruction.disableHighLeverageMode({
|
|
8160
|
+
accounts: {
|
|
8161
|
+
state: await this.getStatePublicKey(),
|
|
8162
|
+
user,
|
|
8163
|
+
authority: this.wallet.publicKey,
|
|
8164
|
+
highLeverageModeConfig: getHighLeverageModeConfigPublicKey(
|
|
8165
|
+
this.program.programId
|
|
8166
|
+
),
|
|
8167
|
+
},
|
|
8168
|
+
});
|
|
8169
|
+
|
|
8170
|
+
return ix;
|
|
8171
|
+
}
|
|
8172
|
+
|
|
8105
8173
|
private handleSignedTransaction(signedTxs: SignedTxData[]) {
|
|
8106
8174
|
if (this.enableMetricsEvents && this.metricsEventEmitter) {
|
|
8107
8175
|
this.metricsEventEmitter.emit('txSigned', signedTxs);
|
package/src/math/margin.ts
CHANGED
|
@@ -214,7 +214,8 @@ export function calculateMarginUSDCRequiredForTrade(
|
|
|
214
214
|
driftClient: DriftClient,
|
|
215
215
|
targetMarketIndex: number,
|
|
216
216
|
baseSize: BN,
|
|
217
|
-
userMaxMarginRatio?: number
|
|
217
|
+
userMaxMarginRatio?: number,
|
|
218
|
+
userHighLeverageMode?: boolean
|
|
218
219
|
): BN {
|
|
219
220
|
const targetMarket = driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
220
221
|
const oracleData = driftClient.getOracleDataForPerpMarket(
|
|
@@ -232,7 +233,8 @@ export function calculateMarginUSDCRequiredForTrade(
|
|
|
232
233
|
targetMarket,
|
|
233
234
|
baseSize.abs(),
|
|
234
235
|
'Initial',
|
|
235
|
-
userMaxMarginRatio
|
|
236
|
+
userMaxMarginRatio,
|
|
237
|
+
userHighLeverageMode
|
|
236
238
|
)
|
|
237
239
|
)
|
|
238
240
|
.mul(perpLiabilityValue)
|
|
@@ -251,13 +253,15 @@ export function calculateCollateralDepositRequiredForTrade(
|
|
|
251
253
|
targetMarketIndex: number,
|
|
252
254
|
baseSize: BN,
|
|
253
255
|
collateralIndex: number,
|
|
254
|
-
userMaxMarginRatio?: number
|
|
256
|
+
userMaxMarginRatio?: number,
|
|
257
|
+
userHighLeverageMode?: boolean
|
|
255
258
|
): BN {
|
|
256
259
|
const marginRequiredUsdc = calculateMarginUSDCRequiredForTrade(
|
|
257
260
|
driftClient,
|
|
258
261
|
targetMarketIndex,
|
|
259
262
|
baseSize,
|
|
260
|
-
userMaxMarginRatio
|
|
263
|
+
userMaxMarginRatio,
|
|
264
|
+
userHighLeverageMode
|
|
261
265
|
);
|
|
262
266
|
|
|
263
267
|
const collateralMarket = driftClient.getSpotMarketAccount(collateralIndex);
|
package/src/math/market.ts
CHANGED
|
@@ -130,8 +130,24 @@ export function calculateMarketMarginRatio(
|
|
|
130
130
|
market: PerpMarketAccount,
|
|
131
131
|
size: BN,
|
|
132
132
|
marginCategory: MarginCategory,
|
|
133
|
-
customMarginRatio = 0
|
|
133
|
+
customMarginRatio = 0,
|
|
134
|
+
userHighLeverageMode = false
|
|
134
135
|
): number {
|
|
136
|
+
let marginRationInitial;
|
|
137
|
+
let marginRatioMaintenance;
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
userHighLeverageMode &&
|
|
141
|
+
market.highLeverageMarginRatioInitial > 0 &&
|
|
142
|
+
market.highLeverageMarginRatioMaintenance
|
|
143
|
+
) {
|
|
144
|
+
marginRationInitial = market.highLeverageMarginRatioInitial;
|
|
145
|
+
marginRatioMaintenance = market.highLeverageMarginRatioMaintenance;
|
|
146
|
+
} else {
|
|
147
|
+
marginRationInitial = market.marginRatioInitial;
|
|
148
|
+
marginRatioMaintenance = market.marginRatioMaintenance;
|
|
149
|
+
}
|
|
150
|
+
|
|
135
151
|
let marginRatio;
|
|
136
152
|
switch (marginCategory) {
|
|
137
153
|
case 'Initial': {
|
|
@@ -140,7 +156,7 @@ export function calculateMarketMarginRatio(
|
|
|
140
156
|
calculateSizePremiumLiabilityWeight(
|
|
141
157
|
size,
|
|
142
158
|
new BN(market.imfFactor),
|
|
143
|
-
new BN(
|
|
159
|
+
new BN(marginRationInitial),
|
|
144
160
|
MARGIN_PRECISION
|
|
145
161
|
).toNumber(),
|
|
146
162
|
customMarginRatio
|
|
@@ -151,7 +167,7 @@ export function calculateMarketMarginRatio(
|
|
|
151
167
|
marginRatio = calculateSizePremiumLiabilityWeight(
|
|
152
168
|
size,
|
|
153
169
|
new BN(market.imfFactor),
|
|
154
|
-
new BN(
|
|
170
|
+
new BN(marginRatioMaintenance),
|
|
155
171
|
MARGIN_PRECISION
|
|
156
172
|
).toNumber();
|
|
157
173
|
break;
|
package/src/types.ts
CHANGED
|
@@ -68,6 +68,11 @@ export enum UserStatus {
|
|
|
68
68
|
ADVANCED_LP = 8,
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
export class MarginMode {
|
|
72
|
+
static readonly DEFAULT = { default: {} };
|
|
73
|
+
static readonly HIGH_LEVERAGE = { highLeverage: {} };
|
|
74
|
+
}
|
|
75
|
+
|
|
71
76
|
export class ContractType {
|
|
72
77
|
static readonly PERPETUAL = { perpetual: {} };
|
|
73
78
|
static readonly FUTURE = { future: {} };
|
|
@@ -661,6 +666,9 @@ export type PerpMarketAccount = {
|
|
|
661
666
|
fuelBoostTaker: number;
|
|
662
667
|
fuelBoostMaker: number;
|
|
663
668
|
fuelBoostPosition: number;
|
|
669
|
+
|
|
670
|
+
highLeverageMarginRatioInitial: number;
|
|
671
|
+
highLeverageMarginRatioMaintenance: number;
|
|
664
672
|
};
|
|
665
673
|
|
|
666
674
|
export type HistoricalOracleData = {
|
|
@@ -950,6 +958,7 @@ export type UserAccount = {
|
|
|
950
958
|
openAuctions: number;
|
|
951
959
|
hasOpenAuction: boolean;
|
|
952
960
|
lastFuelBonusUpdateTs: number;
|
|
961
|
+
marginMode: MarginMode;
|
|
953
962
|
};
|
|
954
963
|
|
|
955
964
|
export type SpotPosition = {
|
package/src/user.ts
CHANGED
|
@@ -676,7 +676,8 @@ export class User {
|
|
|
676
676
|
this.driftClient.getPerpMarketAccount(marketIndex),
|
|
677
677
|
baseAssetAmount,
|
|
678
678
|
'Initial',
|
|
679
|
-
this.getUserAccount().maxMarginRatio
|
|
679
|
+
this.getUserAccount().maxMarginRatio,
|
|
680
|
+
this.isHighLeverageMode()
|
|
680
681
|
);
|
|
681
682
|
|
|
682
683
|
return freeCollateral.mul(MARGIN_PRECISION).div(new BN(marginRatio));
|
|
@@ -1507,7 +1508,8 @@ export class User {
|
|
|
1507
1508
|
market,
|
|
1508
1509
|
baseAssetAmount.abs(),
|
|
1509
1510
|
marginCategory,
|
|
1510
|
-
this.getUserAccount().maxMarginRatio
|
|
1511
|
+
this.getUserAccount().maxMarginRatio,
|
|
1512
|
+
this.isHighLeverageMode()
|
|
1511
1513
|
)
|
|
1512
1514
|
);
|
|
1513
1515
|
|
|
@@ -1972,7 +1974,8 @@ export class User {
|
|
|
1972
1974
|
market,
|
|
1973
1975
|
maxSize,
|
|
1974
1976
|
marginCategory,
|
|
1975
|
-
this.getUserAccount().maxMarginRatio
|
|
1977
|
+
this.getUserAccount().maxMarginRatio,
|
|
1978
|
+
this.isHighLeverageMode()
|
|
1976
1979
|
);
|
|
1977
1980
|
|
|
1978
1981
|
// use more fesible size since imf factor activated
|
|
@@ -1993,7 +1996,8 @@ export class User {
|
|
|
1993
1996
|
market,
|
|
1994
1997
|
targetSize,
|
|
1995
1998
|
marginCategory,
|
|
1996
|
-
this.getUserAccount().maxMarginRatio
|
|
1999
|
+
this.getUserAccount().maxMarginRatio,
|
|
2000
|
+
this.isHighLeverageMode()
|
|
1997
2001
|
);
|
|
1998
2002
|
attempts += 1;
|
|
1999
2003
|
}
|
|
@@ -2154,6 +2158,10 @@ export class User {
|
|
|
2154
2158
|
return (this.getUserAccount().status & UserStatus.BANKRUPT) > 0;
|
|
2155
2159
|
}
|
|
2156
2160
|
|
|
2161
|
+
public isHighLeverageMode(): boolean {
|
|
2162
|
+
return isVariant(this.getUserAccount().marginMode, 'highLeverage');
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2157
2165
|
/**
|
|
2158
2166
|
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
2159
2167
|
* @returns
|
|
@@ -2443,7 +2451,9 @@ export class User {
|
|
|
2443
2451
|
const marginRatio = calculateMarketMarginRatio(
|
|
2444
2452
|
market,
|
|
2445
2453
|
baseAssetAmount.abs(),
|
|
2446
|
-
'Maintenance'
|
|
2454
|
+
'Maintenance',
|
|
2455
|
+
this.getUserAccount().maxMarginRatio,
|
|
2456
|
+
this.isHighLeverageMode()
|
|
2447
2457
|
);
|
|
2448
2458
|
|
|
2449
2459
|
return liabilityValue.mul(new BN(marginRatio)).div(MARGIN_PRECISION);
|
|
@@ -2488,7 +2498,8 @@ export class User {
|
|
|
2488
2498
|
market,
|
|
2489
2499
|
proposedBaseAssetAmount.abs(),
|
|
2490
2500
|
marginCategory,
|
|
2491
|
-
this.getUserAccount().maxMarginRatio
|
|
2501
|
+
this.getUserAccount().maxMarginRatio,
|
|
2502
|
+
this.isHighLeverageMode()
|
|
2492
2503
|
);
|
|
2493
2504
|
const marginRatioQuotePrecision = new BN(marginRatio)
|
|
2494
2505
|
.mul(QUOTE_PRECISION)
|
|
@@ -2622,7 +2633,8 @@ export class User {
|
|
|
2622
2633
|
targetMarketIndex,
|
|
2623
2634
|
baseSize,
|
|
2624
2635
|
collateralIndex,
|
|
2625
|
-
this.getUserAccount().maxMarginRatio
|
|
2636
|
+
this.getUserAccount().maxMarginRatio,
|
|
2637
|
+
false // assume user cant be high leverage if they havent created user account ?
|
|
2626
2638
|
);
|
|
2627
2639
|
}
|
|
2628
2640
|
|
|
@@ -3771,7 +3783,8 @@ export class User {
|
|
|
3771
3783
|
perpMarket,
|
|
3772
3784
|
worstCaseBaseAmount.abs(),
|
|
3773
3785
|
marginCategory,
|
|
3774
|
-
this.getUserAccount().maxMarginRatio
|
|
3786
|
+
this.getUserAccount().maxMarginRatio,
|
|
3787
|
+
this.isHighLeverageMode()
|
|
3775
3788
|
)
|
|
3776
3789
|
);
|
|
3777
3790
|
|