@drift-labs/sdk 2.42.0-beta.8 → 2.43.0-beta.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/VERSION +1 -1
- package/bun.lockb +0 -0
- package/lib/accounts/bulkAccountLoader.d.ts +1 -2
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/adminClient.d.ts +1 -0
- package/lib/config.d.ts +1 -0
- package/lib/config.js +1 -0
- package/lib/constants/numericConstants.d.ts +62 -60
- package/lib/constants/perpMarkets.js +42 -2
- package/lib/constants/spotMarkets.d.ts +1 -0
- package/lib/dlob/DLOB.d.ts +10 -16
- package/lib/dlob/DLOB.js +9 -39
- package/lib/dlob/DLOBNode.d.ts +1 -0
- package/lib/dlob/NodeList.d.ts +1 -0
- package/lib/dlob/orderBookLevels.d.ts +2 -1
- package/lib/driftClient.d.ts +10 -2
- package/lib/driftClient.js +20 -18
- package/lib/events/fetchLogs.js +2 -0
- package/lib/factory/bigNum.d.ts +8 -7
- package/lib/idl/drift.json +251 -239
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/jupiter/jupiterClient.d.ts +1 -0
- package/lib/marinade/index.d.ts +1 -0
- package/lib/math/amm.d.ts +2 -1
- package/lib/math/auction.d.ts +1 -0
- package/lib/math/conversion.d.ts +2 -1
- package/lib/math/funding.d.ts +1 -0
- package/lib/math/funding.js +1 -1
- package/lib/math/insurance.d.ts +1 -0
- package/lib/math/margin.d.ts +1 -0
- package/lib/math/market.d.ts +1 -0
- package/lib/math/oracles.d.ts +1 -0
- package/lib/math/orders.d.ts +1 -0
- package/lib/math/position.d.ts +1 -0
- package/lib/math/repeg.d.ts +1 -0
- package/lib/math/spotBalance.d.ts +3 -2
- package/lib/math/spotMarket.d.ts +1 -0
- package/lib/math/spotPosition.d.ts +1 -0
- package/lib/math/superStake.d.ts +1 -0
- package/lib/math/trade.d.ts +1 -0
- package/lib/math/utils.d.ts +1 -0
- package/lib/oracles/pythClient.d.ts +2 -1
- package/lib/oracles/strictOraclePrice.d.ts +1 -0
- package/lib/oracles/types.d.ts +1 -0
- package/lib/orderParams.d.ts +1 -0
- package/lib/orderSubscriber/PollingSubscription.d.ts +1 -2
- package/lib/phoenix/phoenixSubscriber.d.ts +1 -0
- package/lib/priorityFee/priorityFeeSubscriber.d.ts +1 -2
- package/lib/serum/serumSubscriber.d.ts +1 -0
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/types.d.ts +6 -14
- package/lib/types.js +6 -7
- package/lib/user.d.ts +6 -5
- package/lib/user.js +17 -11
- package/package.json +2 -1
- package/src/accounts/bulkAccountLoader.ts +1 -1
- package/src/config.ts +2 -0
- package/src/constants/perpMarkets.ts +42 -2
- package/src/dlob/DLOB.ts +23 -67
- package/src/driftClient.ts +41 -27
- package/src/events/fetchLogs.ts +3 -0
- package/src/events/pollingLogProvider.ts +1 -1
- package/src/idl/drift.json +251 -239
- package/src/index.ts +3 -0
- package/src/math/funding.ts +1 -1
- package/src/orderSubscriber/PollingSubscription.ts +1 -1
- package/src/priorityFee/priorityFeeSubscriber.ts +1 -1
- package/src/types.ts +5 -6
- package/src/user.ts +49 -42
- package/tests/user/helpers.ts +1 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
|
|
2
3
|
import { BN } from '@coral-xyz/anchor';
|
|
3
4
|
import { OraclePriceData } from '../oracles/types';
|
|
@@ -50,7 +51,7 @@ export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, ora
|
|
|
50
51
|
export declare function calculateAssetWeight(balanceAmount: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
|
|
51
52
|
export declare function calculateScaledInitialAssetWeight(spotMarket: SpotMarketAccount, oraclePrice: BN): BN;
|
|
52
53
|
export declare function calculateLiabilityWeight(size: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
|
|
53
|
-
export declare function calculateUtilization(bank: SpotMarketAccount, delta?:
|
|
54
|
+
export declare function calculateUtilization(bank: SpotMarketAccount, delta?: BN): BN;
|
|
54
55
|
/**
|
|
55
56
|
* calculates max borrow amount where rate would stay below targetBorrowRate
|
|
56
57
|
* @param spotMarketAccount
|
|
@@ -61,7 +62,7 @@ export declare function calculateSpotMarketBorrowCapacity(spotMarketAccount: Spo
|
|
|
61
62
|
totalCapacity: BN;
|
|
62
63
|
remainingCapacity: BN;
|
|
63
64
|
};
|
|
64
|
-
export declare function calculateInterestRate(bank: SpotMarketAccount, delta?:
|
|
65
|
+
export declare function calculateInterestRate(bank: SpotMarketAccount, delta?: BN): BN;
|
|
65
66
|
export declare function calculateDepositRate(bank: SpotMarketAccount): BN;
|
|
66
67
|
export declare function calculateBorrowRate(bank: SpotMarketAccount): BN;
|
|
67
68
|
export declare function calculateInterestAccumulated(bank: SpotMarketAccount, now: BN): {
|
package/lib/math/spotMarket.d.ts
CHANGED
package/lib/math/superStake.d.ts
CHANGED
package/lib/math/trade.d.ts
CHANGED
package/lib/math/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
/// <reference types="node" />
|
|
2
3
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
4
|
import { OracleClient, OraclePriceData } from './types';
|
|
@@ -6,7 +7,7 @@ export declare class PythClient implements OracleClient {
|
|
|
6
7
|
private connection;
|
|
7
8
|
private multiple;
|
|
8
9
|
private stableCoin;
|
|
9
|
-
constructor(connection: Connection, multiple?:
|
|
10
|
+
constructor(connection: Connection, multiple?: BN, stableCoin?: boolean);
|
|
10
11
|
getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
|
|
11
12
|
getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData;
|
|
12
13
|
}
|
package/lib/oracles/types.d.ts
CHANGED
package/lib/orderParams.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { OrderSubscriber } from './OrderSubscriber';
|
|
3
2
|
export declare class PollingSubscription {
|
|
4
3
|
private orderSubscriber;
|
|
5
4
|
private frequency;
|
|
6
|
-
intervalId?:
|
|
5
|
+
intervalId?: ReturnType<typeof setTimeout>;
|
|
7
6
|
constructor({ orderSubscriber, frequency, }: {
|
|
8
7
|
orderSubscriber: OrderSubscriber;
|
|
9
8
|
frequency: number;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
2
|
export declare class PriorityFeeSubscriber {
|
|
4
3
|
connection: Connection;
|
|
5
4
|
frequencyMs: number;
|
|
6
5
|
addresses: PublicKey[];
|
|
7
6
|
slotsToCheck: number;
|
|
8
|
-
intervalId?:
|
|
7
|
+
intervalId?: ReturnType<typeof setTimeout>;
|
|
9
8
|
latestPriorityFee: number;
|
|
10
9
|
avgPriorityFee: number;
|
|
11
10
|
maxPriorityFee: number;
|
package/lib/tokenFaucet.d.ts
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
3
|
import { BN } from '.';
|
|
3
4
|
export declare enum ExchangeStatus {
|
|
@@ -40,19 +41,10 @@ export declare class MarketStatus {
|
|
|
40
41
|
delisted: {};
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
|
-
export declare
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
static readonly BEING_LIQUIDATED: {
|
|
48
|
-
beingLiquidated: {};
|
|
49
|
-
};
|
|
50
|
-
static readonly BANKRUPT: {
|
|
51
|
-
bankrupt: {};
|
|
52
|
-
};
|
|
53
|
-
static readonly REDUCE_ONLY: {
|
|
54
|
-
reduceOnly: {};
|
|
55
|
-
};
|
|
44
|
+
export declare enum UserStatus {
|
|
45
|
+
BEING_LIQUIDATED = 1,
|
|
46
|
+
BANKRUPT = 2,
|
|
47
|
+
REDUCE_ONLY = 4
|
|
56
48
|
}
|
|
57
49
|
export declare class ContractType {
|
|
58
50
|
static readonly PERPETUAL: {
|
|
@@ -881,7 +873,7 @@ export type UserAccount = {
|
|
|
881
873
|
spotPositions: SpotPosition[];
|
|
882
874
|
perpPositions: PerpPosition[];
|
|
883
875
|
orders: Order[];
|
|
884
|
-
status:
|
|
876
|
+
status: number;
|
|
885
877
|
nextLiquidationId: number;
|
|
886
878
|
nextOrderId: number;
|
|
887
879
|
maxMarginRatio: number;
|
package/lib/types.js
CHANGED
|
@@ -27,13 +27,12 @@ MarketStatus.WITHDRAW_PAUSED = { withdrawPaused: {} };
|
|
|
27
27
|
MarketStatus.REDUCE_ONLY = { reduceOnly: {} };
|
|
28
28
|
MarketStatus.SETTLEMENT = { settlement: {} };
|
|
29
29
|
MarketStatus.DELISTED = { delisted: {} };
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
UserStatus
|
|
34
|
-
UserStatus
|
|
35
|
-
UserStatus
|
|
36
|
-
UserStatus.REDUCE_ONLY = { reduceOnly: {} };
|
|
30
|
+
var UserStatus;
|
|
31
|
+
(function (UserStatus) {
|
|
32
|
+
UserStatus[UserStatus["BEING_LIQUIDATED"] = 1] = "BEING_LIQUIDATED";
|
|
33
|
+
UserStatus[UserStatus["BANKRUPT"] = 2] = "BANKRUPT";
|
|
34
|
+
UserStatus[UserStatus["REDUCE_ONLY"] = 4] = "REDUCE_ONLY";
|
|
35
|
+
})(UserStatus = exports.UserStatus || (exports.UserStatus = {}));
|
|
37
36
|
class ContractType {
|
|
38
37
|
}
|
|
39
38
|
exports.ContractType = ContractType;
|
package/lib/user.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="bn.js" />
|
|
2
3
|
import { PublicKey } from '@solana/web3.js';
|
|
3
4
|
import { EventEmitter } from 'events';
|
|
4
5
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
6
|
import { DriftClient } from './driftClient';
|
|
6
|
-
import { MarginCategory, Order,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { HealthComponents, MarginCategory, Order, PerpMarketAccount, PerpPosition, SpotPosition, UserAccount } from './types';
|
|
8
|
+
import { DataAndSlot, UserAccountEvents, UserAccountSubscriber } from './accounts/types';
|
|
9
|
+
import { BN, MarketType, PositionDirection, SpotMarketAccount } from '.';
|
|
9
10
|
import { OraclePriceData } from './oracles/types';
|
|
10
11
|
import { UserConfig } from './userConfig';
|
|
11
12
|
import { StrictOraclePrice } from './oracles/strictOraclePrice';
|
|
@@ -99,7 +100,7 @@ export declare class User {
|
|
|
99
100
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
100
101
|
* @returns : Precision QUOTE_PRECISION
|
|
101
102
|
*/
|
|
102
|
-
getPerpBuyingPower(marketIndex: number, collateralBuffer?:
|
|
103
|
+
getPerpBuyingPower(marketIndex: number, collateralBuffer?: BN): BN;
|
|
103
104
|
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex: number, freeCollateral: BN, baseAssetAmount: BN): BN;
|
|
104
105
|
/**
|
|
105
106
|
* calculates Free Collateral = Total collateral - margin requirement
|
|
@@ -365,7 +366,7 @@ export declare class User {
|
|
|
365
366
|
depositAmount: BN;
|
|
366
367
|
maxDepositAmount: BN;
|
|
367
368
|
};
|
|
368
|
-
canMakeIdle(slot: BN
|
|
369
|
+
canMakeIdle(slot: BN): boolean;
|
|
369
370
|
getSafestTiers(): {
|
|
370
371
|
perpTier: number;
|
|
371
372
|
spotTier: number;
|
package/lib/user.js
CHANGED
|
@@ -670,9 +670,7 @@ class User {
|
|
|
670
670
|
* @returns : number (value from [0, 100])
|
|
671
671
|
*/
|
|
672
672
|
getHealth() {
|
|
673
|
-
|
|
674
|
-
if ((0, types_1.isVariant)(userAccount.status, 'beingLiquidated') ||
|
|
675
|
-
(0, types_1.isVariant)(userAccount.status, 'bankrupt')) {
|
|
673
|
+
if (this.isBeingLiquidated()) {
|
|
676
674
|
return 0;
|
|
677
675
|
}
|
|
678
676
|
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
@@ -1004,13 +1002,12 @@ class User {
|
|
|
1004
1002
|
};
|
|
1005
1003
|
}
|
|
1006
1004
|
isBeingLiquidated() {
|
|
1007
|
-
return (
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
]);
|
|
1005
|
+
return ((this.getUserAccount().status &
|
|
1006
|
+
(types_1.UserStatus.BEING_LIQUIDATED | types_1.UserStatus.BANKRUPT)) >
|
|
1007
|
+
0);
|
|
1011
1008
|
}
|
|
1012
1009
|
isBankrupt() {
|
|
1013
|
-
return (
|
|
1010
|
+
return (this.getUserAccount().status & types_1.UserStatus.BANKRUPT) > 0;
|
|
1014
1011
|
}
|
|
1015
1012
|
/**
|
|
1016
1013
|
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
@@ -1335,7 +1332,7 @@ class User {
|
|
|
1335
1332
|
const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
|
|
1336
1333
|
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1337
1334
|
const initialContribution = inContributionInitial.add(outContributionInitial);
|
|
1338
|
-
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents(
|
|
1335
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1339
1336
|
if (!calculateSwap) {
|
|
1340
1337
|
calculateSwap = (inSwap) => {
|
|
1341
1338
|
return inSwap
|
|
@@ -1490,7 +1487,7 @@ class User {
|
|
|
1490
1487
|
this.getEmptySpotPosition(outMarketIndex);
|
|
1491
1488
|
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
|
|
1492
1489
|
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1493
|
-
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents(
|
|
1490
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1494
1491
|
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
|
|
1495
1492
|
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
|
|
1496
1493
|
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
|
|
@@ -1741,11 +1738,20 @@ class User {
|
|
|
1741
1738
|
depositAmount,
|
|
1742
1739
|
};
|
|
1743
1740
|
}
|
|
1744
|
-
canMakeIdle(slot
|
|
1741
|
+
canMakeIdle(slot) {
|
|
1745
1742
|
const userAccount = this.getUserAccount();
|
|
1746
1743
|
if (userAccount.idle) {
|
|
1747
1744
|
return false;
|
|
1748
1745
|
}
|
|
1746
|
+
const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue();
|
|
1747
|
+
const equity = totalAssetValue.sub(totalLiabilityValue);
|
|
1748
|
+
let slotsBeforeIdle;
|
|
1749
|
+
if (equity.lt(numericConstants_1.QUOTE_PRECISION)) {
|
|
1750
|
+
slotsBeforeIdle = new _1.BN(9000); // 1 hour
|
|
1751
|
+
}
|
|
1752
|
+
else {
|
|
1753
|
+
slotsBeforeIdle = new _1.BN(1512000); // 1 week
|
|
1754
|
+
}
|
|
1749
1755
|
const userLastActiveSlot = userAccount.lastActiveSlot;
|
|
1750
1756
|
const slotsSinceLastActive = slot.sub(userLastActiveSlot);
|
|
1751
1757
|
if (slotsSinceLastActive.lt(slotsBeforeIdle)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.43.0-beta.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/big.js": "^6.2.0",
|
|
48
|
+
"@types/bn.js": "^5.1.3",
|
|
48
49
|
"@types/chai": "^4.3.1",
|
|
49
50
|
"@types/jest": "^28.1.3",
|
|
50
51
|
"@types/mocha": "^9.1.1",
|
|
@@ -19,7 +19,7 @@ export class BulkAccountLoader {
|
|
|
19
19
|
accountsToLoad = new Map<string, AccountToLoad>();
|
|
20
20
|
bufferAndSlotMap = new Map<string, BufferAndSlot>();
|
|
21
21
|
errorCallbacks = new Map<string, (e) => void>();
|
|
22
|
-
intervalId?:
|
|
22
|
+
intervalId?: ReturnType<typeof setTimeout>;
|
|
23
23
|
// to handle clients spamming load
|
|
24
24
|
loadPromise?: Promise<void>;
|
|
25
25
|
loadPromiseResolver: () => void;
|
package/src/config.ts
CHANGED
|
@@ -26,6 +26,7 @@ type DriftConfig = {
|
|
|
26
26
|
PERP_MARKETS: PerpMarketConfig[];
|
|
27
27
|
SPOT_MARKETS: SpotMarketConfig[];
|
|
28
28
|
MARKET_LOOKUP_TABLE: string;
|
|
29
|
+
SERUM_LOOKUP_TABLE?: string;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
export type DriftEnv = 'devnet' | 'mainnet-beta';
|
|
@@ -60,6 +61,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
60
61
|
PERP_MARKETS: MainnetPerpMarkets,
|
|
61
62
|
SPOT_MARKETS: MainnetSpotMarkets,
|
|
62
63
|
MARKET_LOOKUP_TABLE: 'D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c',
|
|
64
|
+
SERUM_LOOKUP_TABLE: 'GPZkp76cJtNL2mphCvT6FXkJCVPpouidnacckR6rzKDN',
|
|
63
65
|
},
|
|
64
66
|
};
|
|
65
67
|
|
|
@@ -161,7 +161,27 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
161
161
|
baseAssetSymbol: 'HNT',
|
|
162
162
|
marketIndex: 14,
|
|
163
163
|
oracle: new PublicKey('6Eg8YdfFJQF2HHonzPUBSCCmyUEhrStg9VBLK957sBe6'),
|
|
164
|
-
launchTs:
|
|
164
|
+
launchTs: 1692294955000,
|
|
165
|
+
oracleSource: OracleSource.PYTH,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
fullName: 'INJ',
|
|
169
|
+
category: ['L1', 'Exchange'],
|
|
170
|
+
symbol: 'INJ-PERP',
|
|
171
|
+
baseAssetSymbol: 'INJ',
|
|
172
|
+
marketIndex: 15,
|
|
173
|
+
oracle: new PublicKey('44uRsNnT35kjkscSu59MxRr9CfkLZWf6gny8bWqUbVxE'),
|
|
174
|
+
launchTs: 1698074659000,
|
|
175
|
+
oracleSource: OracleSource.PYTH,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
fullName: 'LINK',
|
|
179
|
+
category: ['Oracle'],
|
|
180
|
+
symbol: 'LINK-PERP',
|
|
181
|
+
baseAssetSymbol: 'LINK',
|
|
182
|
+
marketIndex: 16,
|
|
183
|
+
oracle: new PublicKey('9sGidS4qUXS2WvHZFhzw4df1jNd5TvUGZXZVsSjXo7UF'),
|
|
184
|
+
launchTs: 1698074659000,
|
|
165
185
|
oracleSource: OracleSource.PYTH,
|
|
166
186
|
},
|
|
167
187
|
];
|
|
@@ -314,7 +334,27 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
314
334
|
baseAssetSymbol: 'HNT',
|
|
315
335
|
marketIndex: 14,
|
|
316
336
|
oracle: new PublicKey('7moA1i5vQUpfDwSpK6Pw9s56ahB7WFGidtbL2ujWrVvm'),
|
|
317
|
-
launchTs:
|
|
337
|
+
launchTs: 1692294955000,
|
|
338
|
+
oracleSource: OracleSource.PYTH,
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
fullName: 'INJ',
|
|
342
|
+
category: ['L1', 'Exchange'],
|
|
343
|
+
symbol: 'INJ-PERP',
|
|
344
|
+
baseAssetSymbol: 'INJ',
|
|
345
|
+
marketIndex: 15,
|
|
346
|
+
oracle: new PublicKey('9EdtbaivHQYA4Nh3XzGR6DwRaoorqXYnmpfsnFhvwuVj'),
|
|
347
|
+
launchTs: 1698074659000,
|
|
348
|
+
oracleSource: OracleSource.PYTH,
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
fullName: 'LINK',
|
|
352
|
+
category: ['Oracle'],
|
|
353
|
+
symbol: 'LINK-PERP',
|
|
354
|
+
baseAssetSymbol: 'LINK',
|
|
355
|
+
marketIndex: 16,
|
|
356
|
+
oracle: new PublicKey('ALdkqQDMfHNg77oCNskfX751kHys4KE7SFuZzuKaN536'),
|
|
357
|
+
launchTs: 1698074659000,
|
|
318
358
|
oracleSource: OracleSource.PYTH,
|
|
319
359
|
},
|
|
320
360
|
];
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -73,6 +73,14 @@ export type MarketNodeLists = {
|
|
|
73
73
|
|
|
74
74
|
type OrderBookCallback = () => void;
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Receives a DLOBNode and is expected to return true if the node should
|
|
78
|
+
* be taken into account when generating, or false otherwise.
|
|
79
|
+
*
|
|
80
|
+
* Currently used in getRestingLimitBids and getRestingLimitAsks.
|
|
81
|
+
*/
|
|
82
|
+
export type DLOBFilterFcn = (node: DLOBNode) => boolean;
|
|
83
|
+
|
|
76
84
|
export type NodeToFill = {
|
|
77
85
|
node: DLOBNode;
|
|
78
86
|
makerNodes: DLOBNode[];
|
|
@@ -1065,7 +1073,8 @@ export class DLOB {
|
|
|
1065
1073
|
currentDLOBNode: DLOBNode,
|
|
1066
1074
|
slot: number,
|
|
1067
1075
|
oraclePriceData: OraclePriceData
|
|
1068
|
-
) => boolean
|
|
1076
|
+
) => boolean,
|
|
1077
|
+
filterFcn?: DLOBFilterFcn
|
|
1069
1078
|
): Generator<DLOBNode> {
|
|
1070
1079
|
const generators = generatorList.map((generator) => {
|
|
1071
1080
|
return {
|
|
@@ -1102,6 +1111,11 @@ export class DLOB {
|
|
|
1102
1111
|
continue;
|
|
1103
1112
|
}
|
|
1104
1113
|
|
|
1114
|
+
if (filterFcn && filterFcn(bestGenerator.next.value)) {
|
|
1115
|
+
bestGenerator.next = bestGenerator.generator.next();
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1105
1119
|
yield bestGenerator.next.value;
|
|
1106
1120
|
bestGenerator.next = bestGenerator.generator.next();
|
|
1107
1121
|
} else {
|
|
@@ -1114,7 +1128,8 @@ export class DLOB {
|
|
|
1114
1128
|
marketIndex: number,
|
|
1115
1129
|
slot: number,
|
|
1116
1130
|
marketType: MarketType,
|
|
1117
|
-
oraclePriceData: OraclePriceData
|
|
1131
|
+
oraclePriceData: OraclePriceData,
|
|
1132
|
+
filterFcn?: DLOBFilterFcn
|
|
1118
1133
|
): Generator<DLOBNode> {
|
|
1119
1134
|
if (isVariant(marketType, 'spot') && !oraclePriceData) {
|
|
1120
1135
|
throw new Error('Must provide OraclePriceData to get spot asks');
|
|
@@ -1142,46 +1157,17 @@ export class DLOB {
|
|
|
1142
1157
|
return bestNode
|
|
1143
1158
|
.getPrice(oraclePriceData, slot)
|
|
1144
1159
|
.lt(currentNode.getPrice(oraclePriceData, slot));
|
|
1145
|
-
}
|
|
1160
|
+
},
|
|
1161
|
+
filterFcn
|
|
1146
1162
|
);
|
|
1147
1163
|
}
|
|
1148
1164
|
|
|
1149
|
-
/**
|
|
1150
|
-
* Filters the limit asks that are resting and do not cross fallback bid
|
|
1151
|
-
* Taking orders can only fill against orders that meet this criteria
|
|
1152
|
-
*
|
|
1153
|
-
* @returns
|
|
1154
|
-
*/
|
|
1155
|
-
*getMakerLimitAsks(
|
|
1156
|
-
marketIndex: number,
|
|
1157
|
-
slot: number,
|
|
1158
|
-
marketType: MarketType,
|
|
1159
|
-
oraclePriceData: OraclePriceData,
|
|
1160
|
-
fallbackBid?: BN
|
|
1161
|
-
): Generator<DLOBNode> {
|
|
1162
|
-
const isPerpMarket = isVariant(marketType, 'perp');
|
|
1163
|
-
for (const node of this.getRestingLimitAsks(
|
|
1164
|
-
marketIndex,
|
|
1165
|
-
slot,
|
|
1166
|
-
marketType,
|
|
1167
|
-
oraclePriceData
|
|
1168
|
-
)) {
|
|
1169
|
-
if (
|
|
1170
|
-
isPerpMarket &&
|
|
1171
|
-
fallbackBid &&
|
|
1172
|
-
node.getPrice(oraclePriceData, slot).lte(fallbackBid)
|
|
1173
|
-
) {
|
|
1174
|
-
continue;
|
|
1175
|
-
}
|
|
1176
|
-
yield node;
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
1165
|
*getRestingLimitBids(
|
|
1181
1166
|
marketIndex: number,
|
|
1182
1167
|
slot: number,
|
|
1183
1168
|
marketType: MarketType,
|
|
1184
|
-
oraclePriceData: OraclePriceData
|
|
1169
|
+
oraclePriceData: OraclePriceData,
|
|
1170
|
+
filterFcn?: DLOBFilterFcn
|
|
1185
1171
|
): Generator<DLOBNode> {
|
|
1186
1172
|
if (isVariant(marketType, 'spot') && !oraclePriceData) {
|
|
1187
1173
|
throw new Error('Must provide OraclePriceData to get spot bids');
|
|
@@ -1209,41 +1195,11 @@ export class DLOB {
|
|
|
1209
1195
|
return bestNode
|
|
1210
1196
|
.getPrice(oraclePriceData, slot)
|
|
1211
1197
|
.gt(currentNode.getPrice(oraclePriceData, slot));
|
|
1212
|
-
}
|
|
1198
|
+
},
|
|
1199
|
+
filterFcn
|
|
1213
1200
|
);
|
|
1214
1201
|
}
|
|
1215
1202
|
|
|
1216
|
-
/**
|
|
1217
|
-
* Filters the limit bids that are post only, have been place for sufficiently long or are below the fallback ask
|
|
1218
|
-
* Market orders can only fill against orders that meet this criteria
|
|
1219
|
-
*
|
|
1220
|
-
* @returns
|
|
1221
|
-
*/
|
|
1222
|
-
*getMakerLimitBids(
|
|
1223
|
-
marketIndex: number,
|
|
1224
|
-
slot: number,
|
|
1225
|
-
marketType: MarketType,
|
|
1226
|
-
oraclePriceData: OraclePriceData,
|
|
1227
|
-
fallbackAsk?: BN
|
|
1228
|
-
): Generator<DLOBNode> {
|
|
1229
|
-
const isPerpMarket = isVariant(marketType, 'perp');
|
|
1230
|
-
for (const node of this.getRestingLimitBids(
|
|
1231
|
-
marketIndex,
|
|
1232
|
-
slot,
|
|
1233
|
-
marketType,
|
|
1234
|
-
oraclePriceData
|
|
1235
|
-
)) {
|
|
1236
|
-
if (
|
|
1237
|
-
isPerpMarket &&
|
|
1238
|
-
fallbackAsk &&
|
|
1239
|
-
node.getPrice(oraclePriceData, slot).gte(fallbackAsk)
|
|
1240
|
-
) {
|
|
1241
|
-
continue;
|
|
1242
|
-
}
|
|
1243
|
-
yield node;
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
1203
|
*getAsks(
|
|
1248
1204
|
marketIndex: number,
|
|
1249
1205
|
fallbackAsk: BN | undefined,
|
package/src/driftClient.ts
CHANGED
|
@@ -875,21 +875,48 @@ export class DriftClient {
|
|
|
875
875
|
}
|
|
876
876
|
|
|
877
877
|
public async updateUserCustomMarginRatio(
|
|
878
|
+
updates: { marginRatio: number; subAccountId: number }[]
|
|
879
|
+
): Promise<TransactionSignature> {
|
|
880
|
+
const ixs = await Promise.all(
|
|
881
|
+
updates.map(async ({ marginRatio, subAccountId }) => {
|
|
882
|
+
const ix = await this.getUpdateUserCustomMarginRatioIx(
|
|
883
|
+
marginRatio,
|
|
884
|
+
subAccountId
|
|
885
|
+
);
|
|
886
|
+
return ix;
|
|
887
|
+
})
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
const tx = await this.buildTransaction(ixs, this.txParams);
|
|
891
|
+
|
|
892
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
893
|
+
return txSig;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
public async getUpdateUserCustomMarginRatioIx(
|
|
878
897
|
marginRatio: number,
|
|
879
898
|
subAccountId = 0
|
|
880
|
-
): Promise<
|
|
881
|
-
const
|
|
899
|
+
): Promise<TransactionInstruction> {
|
|
900
|
+
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
901
|
+
this.program.programId,
|
|
902
|
+
this.wallet.publicKey,
|
|
903
|
+
subAccountId
|
|
904
|
+
);
|
|
905
|
+
|
|
906
|
+
await this.addUser(subAccountId, this.wallet.publicKey);
|
|
907
|
+
|
|
908
|
+
const ix = this.program.instruction.updateUserCustomMarginRatio(
|
|
882
909
|
subAccountId,
|
|
883
910
|
marginRatio,
|
|
884
911
|
{
|
|
885
912
|
accounts: {
|
|
886
|
-
user:
|
|
913
|
+
user: userAccountPublicKey,
|
|
887
914
|
authority: this.wallet.publicKey,
|
|
888
915
|
},
|
|
889
916
|
}
|
|
890
917
|
);
|
|
891
|
-
|
|
892
|
-
return
|
|
918
|
+
|
|
919
|
+
return ix;
|
|
893
920
|
}
|
|
894
921
|
|
|
895
922
|
public async getUpdateUserMarginTradingEnabledIx(
|
|
@@ -930,31 +957,18 @@ export class DriftClient {
|
|
|
930
957
|
}
|
|
931
958
|
|
|
932
959
|
public async updateUserMarginTradingEnabled(
|
|
933
|
-
marginTradingEnabled: boolean
|
|
934
|
-
subAccountId = 0
|
|
960
|
+
updates: { marginTradingEnabled: boolean; subAccountId: number }[]
|
|
935
961
|
): Promise<TransactionSignature> {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
962
|
+
const ixs = await Promise.all(
|
|
963
|
+
updates.map(async ({ marginTradingEnabled, subAccountId }) => {
|
|
964
|
+
return await this.getUpdateUserMarginTradingEnabledIx(
|
|
965
|
+
marginTradingEnabled,
|
|
966
|
+
subAccountId
|
|
967
|
+
);
|
|
968
|
+
})
|
|
940
969
|
);
|
|
941
970
|
|
|
942
|
-
await this.
|
|
943
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
944
|
-
userAccounts: [this.getUserAccount(subAccountId)],
|
|
945
|
-
});
|
|
946
|
-
|
|
947
|
-
const tx = await this.program.transaction.updateUserMarginTradingEnabled(
|
|
948
|
-
subAccountId,
|
|
949
|
-
marginTradingEnabled,
|
|
950
|
-
{
|
|
951
|
-
accounts: {
|
|
952
|
-
user: userAccountPublicKey,
|
|
953
|
-
authority: this.wallet.publicKey,
|
|
954
|
-
},
|
|
955
|
-
remainingAccounts,
|
|
956
|
-
}
|
|
957
|
-
);
|
|
971
|
+
const tx = await this.buildTransaction(ixs, this.txParams);
|
|
958
972
|
|
|
959
973
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
960
974
|
return txSig;
|
package/src/events/fetchLogs.ts
CHANGED
|
@@ -150,6 +150,9 @@ export class LogParser {
|
|
|
150
150
|
|
|
151
151
|
public parseEventsFromLogs(event: Log): WrappedEvents {
|
|
152
152
|
const records: WrappedEvents = [];
|
|
153
|
+
|
|
154
|
+
if (!event.logs) return records;
|
|
155
|
+
|
|
153
156
|
// @ts-ignore
|
|
154
157
|
const eventGenerator = this.program._events._eventParser.parseLogs(
|
|
155
158
|
event.logs,
|
|
@@ -10,7 +10,7 @@ import { fetchLogs } from './fetchLogs';
|
|
|
10
10
|
|
|
11
11
|
export class PollingLogProvider implements LogProvider {
|
|
12
12
|
private finality: Finality;
|
|
13
|
-
private intervalId:
|
|
13
|
+
private intervalId: ReturnType<typeof setTimeout>;
|
|
14
14
|
private mostRecentSeenTx?: TransactionSignature;
|
|
15
15
|
private mutex: number;
|
|
16
16
|
private firstFetch = true;
|