@drift-labs/sdk 2.30.0-beta.0 → 2.30.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/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +5 -2
- package/lib/accounts/types.d.ts +3 -3
- package/lib/constants/spotMarkets.js +10 -0
- package/lib/dlob/DLOB.d.ts +20 -1
- package/lib/dlob/DLOB.js +39 -0
- package/lib/driftClient.d.ts +51 -2
- package/lib/driftClient.js +162 -13
- package/lib/events/types.d.ts +3 -2
- package/lib/events/types.js +1 -0
- package/lib/examples/makeTradeExample.js +1 -1
- package/lib/idl/drift.json +279 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/jupiter/jupiterClient.d.ts +86 -0
- package/lib/jupiter/jupiterClient.js +109 -0
- package/lib/math/spotBalance.d.ts +41 -0
- package/lib/math/spotBalance.js +41 -0
- package/lib/token/index.d.ts +3 -2
- package/lib/token/index.js +9 -32
- package/lib/tokenFaucet.d.ts +3 -3
- package/lib/tokenFaucet.js +4 -9
- package/lib/tx/retryTxSender.js +3 -0
- package/lib/types.d.ts +29 -1
- package/lib/types.js +6 -1
- package/lib/wallet.d.ts +5 -3
- package/lib/wallet.js +19 -7
- package/package.json +2 -2
- package/src/accounts/pollingTokenAccountSubscriber.ts +8 -5
- package/src/accounts/types.ts +3 -3
- package/src/assert/assert.js +9 -0
- package/src/constants/spotMarkets.ts +11 -0
- package/src/dlob/DLOB.ts +75 -0
- package/src/driftClient.ts +288 -37
- package/src/events/types.ts +5 -1
- package/src/examples/makeTradeExample.ts +2 -4
- package/src/idl/drift.json +279 -2
- package/src/index.ts +1 -0
- package/src/jupiter/jupiterClient.ts +214 -0
- package/src/math/spotBalance.ts +41 -0
- package/src/token/index.js +38 -0
- package/src/token/index.ts +12 -36
- package/src/tokenFaucet.ts +15 -34
- package/src/tx/retryTxSender.ts +4 -0
- package/src/types.ts +32 -1
- package/src/util/computeUnits.js +27 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.ts +34 -12
- package/tests/dlob/helpers.ts +9 -0
- package/tests/dlob/test.ts +218 -40
- package/dlob_read.ts +0 -155
- package/lib/util/getTokenAddress.d.ts +0 -2
- package/lib/util/getTokenAddress.js +0 -9
- package/src/util/getTokenAddress.ts +0 -18
package/lib/token/index.js
CHANGED
|
@@ -2,37 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseTokenAccount = void 0;
|
|
4
4
|
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const accountInfo =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(Buffer.from('0'));
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
|
|
18
|
-
accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
|
|
19
|
-
}
|
|
20
|
-
accountInfo.isInitialized = accountInfo.state !== 0;
|
|
21
|
-
accountInfo.isFrozen = accountInfo.state === 2;
|
|
22
|
-
if (accountInfo.isNativeOption === 1) {
|
|
23
|
-
accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
|
|
24
|
-
accountInfo.isNative = true;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
accountInfo.rentExemptReserve = null;
|
|
28
|
-
accountInfo.isNative = false;
|
|
29
|
-
}
|
|
30
|
-
if (accountInfo.closeAuthorityOption === 0) {
|
|
31
|
-
accountInfo.closeAuthority = null;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
|
|
35
|
-
}
|
|
36
|
-
return accountInfo;
|
|
5
|
+
function parseTokenAccount(data, pubkey) {
|
|
6
|
+
// mock AccountInfo so unpackAccount can be used
|
|
7
|
+
const accountInfo = {
|
|
8
|
+
data,
|
|
9
|
+
owner: spl_token_1.TOKEN_PROGRAM_ID,
|
|
10
|
+
executable: false,
|
|
11
|
+
lamports: 0,
|
|
12
|
+
};
|
|
13
|
+
return (0, spl_token_1.unpackAccount)(pubkey, accountInfo, spl_token_1.TOKEN_PROGRAM_ID);
|
|
37
14
|
}
|
|
38
15
|
exports.parseTokenAccount = parseTokenAccount;
|
package/lib/tokenFaucet.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as anchor from '@coral-xyz/anchor';
|
|
2
2
|
import { AnchorProvider, Program } from '@coral-xyz/anchor';
|
|
3
|
-
import {
|
|
3
|
+
import { Account } from '@solana/spl-token';
|
|
4
4
|
import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
|
|
5
5
|
import { BN } from '.';
|
|
6
6
|
import { IWallet } from './types';
|
|
@@ -30,9 +30,9 @@ export declare class TokenFaucet {
|
|
|
30
30
|
}): Promise<anchor.web3.PublicKey>;
|
|
31
31
|
getTokenAccountInfo(props: {
|
|
32
32
|
userPubKey: PublicKey;
|
|
33
|
-
}): Promise<
|
|
33
|
+
}): Promise<Account>;
|
|
34
34
|
subscribeToTokenAccount(props: {
|
|
35
35
|
userPubKey: PublicKey;
|
|
36
|
-
callback: (accountInfo:
|
|
36
|
+
callback: (accountInfo: Account) => void;
|
|
37
37
|
}): Promise<boolean>;
|
|
38
38
|
}
|
package/lib/tokenFaucet.js
CHANGED
|
@@ -123,22 +123,17 @@ class TokenFaucet {
|
|
|
123
123
|
async createAssociatedTokenAccountAndMintToInstructions(userPublicKey, amount) {
|
|
124
124
|
const state = await this.fetchState();
|
|
125
125
|
const associateTokenPublicKey = await this.getAssosciatedMockUSDMintAddress({ userPubKey: userPublicKey });
|
|
126
|
-
const createAssociatedAccountIx = spl_token_1.
|
|
126
|
+
const createAssociatedAccountIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associateTokenPublicKey, userPublicKey, state.mint);
|
|
127
127
|
const mintToIx = await this.mintToUserIx(associateTokenPublicKey, amount);
|
|
128
128
|
return [associateTokenPublicKey, createAssociatedAccountIx, mintToIx];
|
|
129
129
|
}
|
|
130
130
|
async getAssosciatedMockUSDMintAddress(props) {
|
|
131
131
|
const state = await this.fetchState();
|
|
132
|
-
return
|
|
132
|
+
return (0, spl_token_1.getAssociatedTokenAddress)(state.mint, props.userPubKey);
|
|
133
133
|
}
|
|
134
134
|
async getTokenAccountInfo(props) {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
const token = new spl_token_1.Token(this.connection, state.mint, spl_token_1.TOKEN_PROGRAM_ID,
|
|
138
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
139
|
-
// @ts-ignore
|
|
140
|
-
this.provider.payer);
|
|
141
|
-
return await token.getAccountInfo(assosciatedKey);
|
|
135
|
+
const associatedKey = await this.getAssosciatedMockUSDMintAddress(props);
|
|
136
|
+
return await (0, spl_token_1.getAccount)(this.connection, associatedKey);
|
|
142
137
|
}
|
|
143
138
|
async subscribeToTokenAccount(props) {
|
|
144
139
|
try {
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -57,6 +57,9 @@ class RetryTxSender {
|
|
|
57
57
|
async sendVersionedTransaction(tx, additionalSigners, opts) {
|
|
58
58
|
// @ts-ignore
|
|
59
59
|
tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.provider.wallet.payer));
|
|
60
|
+
if (opts === undefined) {
|
|
61
|
+
opts = this.provider.opts;
|
|
62
|
+
}
|
|
60
63
|
return this.sendRawTransaction(tx.serialize(), opts);
|
|
61
64
|
}
|
|
62
65
|
async sendRawTransaction(rawTransaction, opts) {
|
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PublicKey, Transaction } from '@solana/web3.js';
|
|
1
|
+
import { PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
2
|
import { BN } from '.';
|
|
3
3
|
export declare enum ExchangeStatus {
|
|
4
4
|
ACTIVE = 0,
|
|
@@ -584,6 +584,17 @@ export type OrderActionRecord = {
|
|
|
584
584
|
makerOrderCumulativeQuoteAssetAmountFilled: BN | null;
|
|
585
585
|
oraclePrice: BN;
|
|
586
586
|
};
|
|
587
|
+
export type SwapRecord = {
|
|
588
|
+
ts: BN;
|
|
589
|
+
user: PublicKey;
|
|
590
|
+
amountOut: BN;
|
|
591
|
+
amountIn: BN;
|
|
592
|
+
outMarketIndex: number;
|
|
593
|
+
inMarketIndex: number;
|
|
594
|
+
outOraclePrice: BN;
|
|
595
|
+
inOraclePrice: BN;
|
|
596
|
+
fee: BN;
|
|
597
|
+
};
|
|
587
598
|
export type StateAccount = {
|
|
588
599
|
admin: PublicKey;
|
|
589
600
|
exchangeStatus: number;
|
|
@@ -711,6 +722,9 @@ export type SpotMarketAccount = {
|
|
|
711
722
|
nextFillRecordId: BN;
|
|
712
723
|
spotFeePool: PoolBalance;
|
|
713
724
|
totalSpotFee: BN;
|
|
725
|
+
totalSwapFee: BN;
|
|
726
|
+
flashLoanAmount: BN;
|
|
727
|
+
flashLoanInitialTokenAmount: BN;
|
|
714
728
|
ordersEnabled: boolean;
|
|
715
729
|
};
|
|
716
730
|
export type PoolBalance = {
|
|
@@ -851,6 +865,7 @@ export type UserAccount = {
|
|
|
851
865
|
totalWithdraws: BN;
|
|
852
866
|
totalSocialLoss: BN;
|
|
853
867
|
cumulativePerpFunding: BN;
|
|
868
|
+
cumulativeSpotFees: BN;
|
|
854
869
|
liquidationMarginFreed: BN;
|
|
855
870
|
lastActiveSlot: BN;
|
|
856
871
|
isMarginTradingEnabled: boolean;
|
|
@@ -964,11 +979,24 @@ export type TxParams = {
|
|
|
964
979
|
computeUnits?: number;
|
|
965
980
|
computeUnitsPrice?: number;
|
|
966
981
|
};
|
|
982
|
+
export declare class SwapReduceOnly {
|
|
983
|
+
static readonly In: {
|
|
984
|
+
in: {};
|
|
985
|
+
};
|
|
986
|
+
static readonly Out: {
|
|
987
|
+
out: {};
|
|
988
|
+
};
|
|
989
|
+
}
|
|
967
990
|
export interface IWallet {
|
|
968
991
|
signTransaction(tx: Transaction): Promise<Transaction>;
|
|
969
992
|
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
|
|
970
993
|
publicKey: PublicKey;
|
|
971
994
|
}
|
|
995
|
+
export interface IVersionedWallet {
|
|
996
|
+
signVersionedTransaction(tx: VersionedTransaction): Promise<VersionedTransaction>;
|
|
997
|
+
signAllVersionedTransactions(txs: VersionedTransaction[]): Promise<VersionedTransaction[]>;
|
|
998
|
+
publicKey: PublicKey;
|
|
999
|
+
}
|
|
972
1000
|
export type FeeStructure = {
|
|
973
1001
|
feeTiers: FeeTier[];
|
|
974
1002
|
makerRebateNumerator: BN;
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = 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.MarketStatus = exports.ExchangeStatus = void 0;
|
|
3
|
+
exports.SwapReduceOnly = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = 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.MarketStatus = exports.ExchangeStatus = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
// # Utility Types / Enums / Constants
|
|
6
6
|
var ExchangeStatus;
|
|
@@ -266,3 +266,8 @@ exports.DefaultOrderParams = {
|
|
|
266
266
|
auctionStartPrice: null,
|
|
267
267
|
auctionEndPrice: null,
|
|
268
268
|
};
|
|
269
|
+
class SwapReduceOnly {
|
|
270
|
+
}
|
|
271
|
+
exports.SwapReduceOnly = SwapReduceOnly;
|
|
272
|
+
SwapReduceOnly.In = { in: {} };
|
|
273
|
+
SwapReduceOnly.Out = { out: {} };
|
package/lib/wallet.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { Keypair, PublicKey, Transaction } from '@solana/web3.js';
|
|
2
|
-
import { IWallet } from './types';
|
|
3
|
-
export declare class Wallet implements IWallet {
|
|
1
|
+
import { Keypair, PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
|
+
import { IWallet, IVersionedWallet } from './types';
|
|
3
|
+
export declare class Wallet implements IWallet, IVersionedWallet {
|
|
4
4
|
readonly payer: Keypair;
|
|
5
5
|
constructor(payer: Keypair);
|
|
6
6
|
signTransaction(tx: Transaction): Promise<Transaction>;
|
|
7
|
+
signVersionedTransaction(tx: VersionedTransaction): Promise<VersionedTransaction>;
|
|
7
8
|
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
|
|
9
|
+
signAllVersionedTransactions(txs: VersionedTransaction[]): Promise<VersionedTransaction[]>;
|
|
8
10
|
get publicKey(): PublicKey;
|
|
9
11
|
}
|
|
10
12
|
export declare function loadKeypair(privateKey: string): Keypair;
|
package/lib/wallet.js
CHANGED
|
@@ -15,12 +15,22 @@ class Wallet {
|
|
|
15
15
|
tx.partialSign(this.payer);
|
|
16
16
|
return tx;
|
|
17
17
|
}
|
|
18
|
+
async signVersionedTransaction(tx) {
|
|
19
|
+
tx.sign([this.payer]);
|
|
20
|
+
return tx;
|
|
21
|
+
}
|
|
18
22
|
async signAllTransactions(txs) {
|
|
19
23
|
return txs.map((t) => {
|
|
20
24
|
t.partialSign(this.payer);
|
|
21
25
|
return t;
|
|
22
26
|
});
|
|
23
27
|
}
|
|
28
|
+
async signAllVersionedTransactions(txs) {
|
|
29
|
+
return txs.map((t) => {
|
|
30
|
+
t.sign([this.payer]);
|
|
31
|
+
return t;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
24
34
|
get publicKey() {
|
|
25
35
|
return this.payer.publicKey;
|
|
26
36
|
}
|
|
@@ -30,15 +40,17 @@ function loadKeypair(privateKey) {
|
|
|
30
40
|
// try to load privateKey as a filepath
|
|
31
41
|
let loadedKey;
|
|
32
42
|
if (fs_1.default.existsSync(privateKey)) {
|
|
33
|
-
|
|
43
|
+
privateKey = fs_1.default.readFileSync(privateKey).toString();
|
|
44
|
+
}
|
|
45
|
+
if (privateKey.includes('[') && privateKey.includes(']')) {
|
|
46
|
+
loadedKey = Uint8Array.from(JSON.parse(privateKey));
|
|
47
|
+
}
|
|
48
|
+
else if (privateKey.includes(',')) {
|
|
49
|
+
loadedKey = Uint8Array.from(privateKey.split(',').map((val) => Number(val)));
|
|
34
50
|
}
|
|
35
51
|
else {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
loadedKey = new Uint8Array(bs58_1.default.decode(privateKey));
|
|
41
|
-
}
|
|
52
|
+
privateKey = privateKey.replace(/\s/g, '');
|
|
53
|
+
loadedKey = new Uint8Array(bs58_1.default.decode(privateKey));
|
|
42
54
|
}
|
|
43
55
|
return web3_js_1.Keypair.fromSecretKey(Uint8Array.from(loadedKey));
|
|
44
56
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.30.0
|
|
3
|
+
"version": "2.30.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@ellipsis-labs/phoenix-sdk": "^1.4.2",
|
|
38
38
|
"@project-serum/serum": "^0.13.38",
|
|
39
39
|
"@pythnetwork/client": "2.5.3",
|
|
40
|
-
"@solana/spl-token": "^0.
|
|
40
|
+
"@solana/spl-token": "^0.3.7",
|
|
41
41
|
"@solana/web3.js": "1.73.2",
|
|
42
42
|
"strict-event-emitter-types": "^2.0.0",
|
|
43
43
|
"uuid": "^8.3.2"
|
|
@@ -9,7 +9,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
9
9
|
import { EventEmitter } from 'events';
|
|
10
10
|
import { PublicKey } from '@solana/web3.js';
|
|
11
11
|
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
12
|
-
import {
|
|
12
|
+
import { Account } from '@solana/spl-token';
|
|
13
13
|
import { parseTokenAccount } from '../token';
|
|
14
14
|
|
|
15
15
|
export class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
@@ -22,7 +22,7 @@ export class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
|
22
22
|
callbackId?: string;
|
|
23
23
|
errorCallbackId?: string;
|
|
24
24
|
|
|
25
|
-
tokenAccountAndSlot?: DataAndSlot<
|
|
25
|
+
tokenAccountAndSlot?: DataAndSlot<Account>;
|
|
26
26
|
|
|
27
27
|
public constructor(publicKey: PublicKey, accountLoader: BulkAccountLoader) {
|
|
28
28
|
this.isSubscribed = false;
|
|
@@ -61,7 +61,7 @@ export class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
|
61
61
|
this.callbackId = await this.accountLoader.addAccount(
|
|
62
62
|
this.publicKey,
|
|
63
63
|
(buffer, slot: number) => {
|
|
64
|
-
const tokenAccount = parseTokenAccount(buffer);
|
|
64
|
+
const tokenAccount = parseTokenAccount(buffer, this.publicKey);
|
|
65
65
|
this.tokenAccountAndSlot = { data: tokenAccount, slot };
|
|
66
66
|
// @ts-ignore
|
|
67
67
|
this.eventEmitter.emit('tokenAccountUpdate', tokenAccount);
|
|
@@ -79,7 +79,10 @@ export class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
|
79
79
|
const { buffer, slot } = this.accountLoader.getBufferAndSlot(
|
|
80
80
|
this.publicKey
|
|
81
81
|
);
|
|
82
|
-
this.tokenAccountAndSlot = {
|
|
82
|
+
this.tokenAccountAndSlot = {
|
|
83
|
+
data: parseTokenAccount(buffer, this.publicKey),
|
|
84
|
+
slot,
|
|
85
|
+
};
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
async unsubscribe(): Promise<void> {
|
|
@@ -104,7 +107,7 @@ export class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
public getTokenAccountAndSlot(): DataAndSlot<
|
|
110
|
+
public getTokenAccountAndSlot(): DataAndSlot<Account> {
|
|
108
111
|
this.assertIsSubscribed();
|
|
109
112
|
return this.tokenAccountAndSlot;
|
|
110
113
|
}
|
package/src/accounts/types.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
10
10
|
import { EventEmitter } from 'events';
|
|
11
11
|
import { PublicKey } from '@solana/web3.js';
|
|
12
|
-
import {
|
|
12
|
+
import { Account } from '@solana/spl-token';
|
|
13
13
|
import { OracleInfo, OraclePriceData } from '..';
|
|
14
14
|
|
|
15
15
|
export interface AccountSubscriber<T> {
|
|
@@ -82,7 +82,7 @@ export interface UserAccountSubscriber {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export interface TokenAccountEvents {
|
|
85
|
-
tokenAccountUpdate: (payload:
|
|
85
|
+
tokenAccountUpdate: (payload: Account) => void;
|
|
86
86
|
update: void;
|
|
87
87
|
error: (e: Error) => void;
|
|
88
88
|
}
|
|
@@ -95,7 +95,7 @@ export interface TokenAccountSubscriber {
|
|
|
95
95
|
fetch(): Promise<void>;
|
|
96
96
|
unsubscribe(): Promise<void>;
|
|
97
97
|
|
|
98
|
-
getTokenAccountAndSlot(): DataAndSlot<
|
|
98
|
+
getTokenAccountAndSlot(): DataAndSlot<Account>;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export interface OracleEvents {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
LAMPORTS_EXP,
|
|
7
7
|
LAMPORTS_PRECISION,
|
|
8
8
|
SIX,
|
|
9
|
+
NINE,
|
|
9
10
|
} from './numericConstants';
|
|
10
11
|
|
|
11
12
|
export type SpotMarketConfig = {
|
|
@@ -82,6 +83,16 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
82
83
|
'4DoNfFBfF7UokCC2FQzriy7yHK6DY6NVdYpuekQ5pRgg'
|
|
83
84
|
),
|
|
84
85
|
},
|
|
86
|
+
{
|
|
87
|
+
symbol: 'mSOL',
|
|
88
|
+
marketIndex: 2,
|
|
89
|
+
oracle: new PublicKey('E4v1BBgoso9s64TQvmyownAVJbhbEPGyzA3qn4n46qj9'),
|
|
90
|
+
oracleSource: OracleSource.PYTH,
|
|
91
|
+
mint: new PublicKey('mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So'),
|
|
92
|
+
precision: new BN(10).pow(NINE),
|
|
93
|
+
precisionExp: NINE,
|
|
94
|
+
serumMarket: new PublicKey('9Lyhks5bQQxb9EyyX55NtgKQzpM4WK7JCmeaWuQ5MoXD'),
|
|
95
|
+
},
|
|
85
96
|
];
|
|
86
97
|
|
|
87
98
|
export const SpotMarkets: { [key in DriftEnv]: SpotMarketConfig[] } = {
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getOrderSignature, getVammNodeGenerator, NodeList } from './NodeList';
|
|
2
2
|
import {
|
|
3
|
+
BASE_PRECISION,
|
|
3
4
|
BN,
|
|
4
5
|
calculateAskPrice,
|
|
5
6
|
calculateBidPrice,
|
|
@@ -24,12 +25,15 @@ import {
|
|
|
24
25
|
OrderActionRecord,
|
|
25
26
|
OrderRecord,
|
|
26
27
|
PerpMarketAccount,
|
|
28
|
+
PositionDirection,
|
|
27
29
|
PRICE_PRECISION,
|
|
30
|
+
QUOTE_PRECISION,
|
|
28
31
|
SlotSubscriber,
|
|
29
32
|
SpotMarketAccount,
|
|
30
33
|
StateAccount,
|
|
31
34
|
TriggerOrderNode,
|
|
32
35
|
UserMap,
|
|
36
|
+
ZERO,
|
|
33
37
|
} from '..';
|
|
34
38
|
import { PublicKey } from '@solana/web3.js';
|
|
35
39
|
import { ammPaused, exchangePaused, fillPaused } from '../math/exchangeStatus';
|
|
@@ -1849,4 +1853,75 @@ export class DLOB {
|
|
|
1849
1853
|
asks,
|
|
1850
1854
|
};
|
|
1851
1855
|
}
|
|
1856
|
+
|
|
1857
|
+
private estimateFillExactBaseAmountInForSide(
|
|
1858
|
+
baseAmountIn: BN,
|
|
1859
|
+
oraclePriceData: OraclePriceData,
|
|
1860
|
+
slot: number,
|
|
1861
|
+
dlobSide: Generator<DLOBNode>
|
|
1862
|
+
): BN {
|
|
1863
|
+
let runningSumQuote = ZERO;
|
|
1864
|
+
let runningSumBase = ZERO;
|
|
1865
|
+
for (const side of dlobSide) {
|
|
1866
|
+
const price = side.getPrice(oraclePriceData, slot); //side.order.quoteAssetAmount.div(side.order.baseAssetAmount);
|
|
1867
|
+
const baseAmountRemaining = side.order.baseAssetAmount.sub(
|
|
1868
|
+
side.order.baseAssetAmountFilled
|
|
1869
|
+
);
|
|
1870
|
+
if (runningSumBase.add(baseAmountRemaining).gt(baseAmountIn)) {
|
|
1871
|
+
const remainingBase = baseAmountIn.sub(runningSumBase);
|
|
1872
|
+
runningSumBase = runningSumBase.add(remainingBase);
|
|
1873
|
+
runningSumQuote = runningSumQuote.add(remainingBase.mul(price));
|
|
1874
|
+
break;
|
|
1875
|
+
} else {
|
|
1876
|
+
runningSumBase = runningSumBase.add(baseAmountRemaining);
|
|
1877
|
+
runningSumQuote = runningSumQuote.add(baseAmountRemaining.mul(price));
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
return runningSumQuote
|
|
1882
|
+
.mul(QUOTE_PRECISION)
|
|
1883
|
+
.div(BASE_PRECISION.mul(PRICE_PRECISION));
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
/**
|
|
1887
|
+
*
|
|
1888
|
+
* @param param.marketIndex the index of the market
|
|
1889
|
+
* @param param.marketType the type of the market
|
|
1890
|
+
* @param param.baseAmount the base amount in to estimate
|
|
1891
|
+
* @param param.orderDirection the direction of the trade
|
|
1892
|
+
* @param param.slot current slot for estimating dlob node price
|
|
1893
|
+
* @param param.oraclePriceData the oracle price data
|
|
1894
|
+
* @returns the estimated quote amount filled: QUOTE_PRECISION
|
|
1895
|
+
*/
|
|
1896
|
+
public estimateFillWithExactBaseAmount({
|
|
1897
|
+
marketIndex,
|
|
1898
|
+
marketType,
|
|
1899
|
+
baseAmount,
|
|
1900
|
+
orderDirection,
|
|
1901
|
+
slot,
|
|
1902
|
+
oraclePriceData,
|
|
1903
|
+
}: {
|
|
1904
|
+
marketIndex: number;
|
|
1905
|
+
marketType: MarketType;
|
|
1906
|
+
baseAmount: BN;
|
|
1907
|
+
orderDirection: PositionDirection;
|
|
1908
|
+
slot: number;
|
|
1909
|
+
oraclePriceData: OraclePriceData;
|
|
1910
|
+
}): BN {
|
|
1911
|
+
if (isVariant(orderDirection, 'long')) {
|
|
1912
|
+
return this.estimateFillExactBaseAmountInForSide(
|
|
1913
|
+
baseAmount,
|
|
1914
|
+
oraclePriceData,
|
|
1915
|
+
slot,
|
|
1916
|
+
this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)
|
|
1917
|
+
);
|
|
1918
|
+
} else if (isVariant(orderDirection, 'short')) {
|
|
1919
|
+
return this.estimateFillExactBaseAmountInForSide(
|
|
1920
|
+
baseAmount,
|
|
1921
|
+
oraclePriceData,
|
|
1922
|
+
slot,
|
|
1923
|
+
this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData)
|
|
1924
|
+
);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1852
1927
|
}
|