@drift-labs/sdk 0.1.18-orders.3 → 0.1.18-orders.4
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/bulkAccountLoader.d.ts +3 -4
- package/lib/accounts/bulkAccountLoader.js +23 -4
- package/lib/accounts/types.d.ts +4 -0
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -2
- package/lib/accounts/webSocketAccountSubscriber.js +43 -12
- package/lib/clearingHouse.d.ts +4 -0
- package/lib/clearingHouse.js +40 -0
- package/lib/clearingHouseUser.d.ts +3 -3
- package/lib/clearingHouseUser.js +16 -20
- package/lib/config.js +1 -1
- package/lib/constants/markets.d.ts +2 -1
- package/lib/constants/markets.js +20 -15
- package/lib/constants/numericConstants.d.ts +3 -1
- package/lib/constants/numericConstants.js +15 -17
- package/lib/examples/makeTradeExample.js +1 -1
- package/lib/idl/clearing_house.json +6 -2
- package/lib/math/conversion.d.ts +1 -1
- package/lib/math/insuranceFund.d.ts +2 -1
- package/lib/math/insuranceFund.js +3 -6
- package/lib/math/position.d.ts +2 -1
- package/lib/math/position.js +2 -5
- package/lib/math/utils.d.ts +2 -1
- package/lib/math/utils.js +3 -6
- package/lib/mockUSDCFaucet.d.ts +2 -1
- package/lib/orderParams.d.ts +2 -2
- package/lib/orderParams.js +7 -7
- package/lib/orders.d.ts +2 -1
- package/lib/types.d.ts +7 -5
- package/lib/types.js +2 -2
- package/package.json +9 -1
- package/src/accounts/bulkAccountLoader.ts +35 -15
- package/src/accounts/types.ts +5 -0
- package/src/accounts/webSocketAccountSubscriber.ts +67 -17
- package/src/clearingHouse.ts +56 -0
- package/src/clearingHouseUser.ts +2 -2
- package/src/config.ts +1 -1
- package/src/constants/markets.ts +9 -1
- package/src/constants/numericConstants.ts +2 -1
- package/src/examples/makeTradeExample.ts +4 -1
- package/src/idl/clearing_house.json +6 -2
- package/src/math/conversion.ts +1 -1
- package/src/math/insuranceFund.ts +1 -1
- package/src/math/position.ts +1 -1
- package/src/math/utils.ts +1 -1
- package/src/mockUSDCFaucet.ts +1 -1
- package/src/orderParams.ts +4 -4
- package/src/orders.ts +1 -1
- package/src/types.ts +4 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { MarketsAccount, StateAccount } from '../types';
|
|
2
|
-
import BN from '
|
|
3
|
+
import { BN } from '../';
|
|
3
4
|
import { Connection } from '@solana/web3.js';
|
|
4
5
|
/**
|
|
5
6
|
* In the case of a levered loss, the exchange first pays out undistributed fees and then the insurance fund.
|
|
@@ -8,12 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
12
|
exports.calculateInsuranceFundSize = void 0;
|
|
16
|
-
const
|
|
13
|
+
const __1 = require("../");
|
|
17
14
|
/**
|
|
18
15
|
* In the case of a levered loss, the exchange first pays out undistributed fees and then the insurance fund.
|
|
19
16
|
* Thus the de facto size of the insurance fund is the amount in the insurance vault plus the sum of each markets
|
|
@@ -27,9 +24,9 @@ const bn_js_1 = __importDefault(require("bn.js"));
|
|
|
27
24
|
function calculateInsuranceFundSize(connection, state, marketsAccount) {
|
|
28
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
26
|
const insuranceVaultPublicKey = state.insuranceVault;
|
|
30
|
-
const insuranceVaultAmount = new
|
|
27
|
+
const insuranceVaultAmount = new __1.BN((yield connection.getTokenAccountBalance(insuranceVaultPublicKey)).value.amount);
|
|
31
28
|
return marketsAccount.markets.reduce((insuranceVaultAmount, market) => {
|
|
32
|
-
return insuranceVaultAmount.add(market.amm.totalFee.div(new
|
|
29
|
+
return insuranceVaultAmount.add(market.amm.totalFee.div(new __1.BN(2)));
|
|
33
30
|
}, insuranceVaultAmount);
|
|
34
31
|
});
|
|
35
32
|
}
|
package/lib/math/position.d.ts
CHANGED
package/lib/math/position.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
7
|
-
const
|
|
4
|
+
const __1 = require("../");
|
|
8
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
9
6
|
const types_1 = require("../types");
|
|
10
7
|
const amm_1 = require("./amm");
|
|
@@ -84,7 +81,7 @@ function calculatePositionFundingPNL(market, marketPosition) {
|
|
|
84
81
|
.mul(marketPosition.baseAssetAmount)
|
|
85
82
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
86
83
|
.div(numericConstants_1.FUNDING_PAYMENT_PRECISION)
|
|
87
|
-
.mul(new
|
|
84
|
+
.mul(new __1.BN(-1));
|
|
88
85
|
return perPositionFundingRate;
|
|
89
86
|
}
|
|
90
87
|
exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
|
package/lib/math/utils.d.ts
CHANGED
package/lib/math/utils.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.squareRootBN = void 0;
|
|
7
|
-
const
|
|
8
|
-
const squareRootBN = (n, closeness = new
|
|
4
|
+
const __1 = require("../");
|
|
5
|
+
const squareRootBN = (n, closeness = new __1.BN(1)) => {
|
|
9
6
|
// Assuming the sqrt of n as n only
|
|
10
7
|
let x = n;
|
|
11
8
|
// The closed guess will be stored in the root
|
|
12
9
|
let root;
|
|
13
10
|
// To count the number of iterations
|
|
14
11
|
let count = 0;
|
|
15
|
-
const TWO = new
|
|
12
|
+
const TWO = new __1.BN(2);
|
|
16
13
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
17
14
|
while (count < Number.MAX_SAFE_INTEGER) {
|
|
18
15
|
count++;
|
package/lib/mockUSDCFaucet.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import * as anchor from '@project-serum/anchor';
|
|
2
3
|
import { Program, Provider } from '@project-serum/anchor';
|
|
3
4
|
import { AccountInfo } from '@solana/spl-token';
|
|
4
5
|
import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
|
|
5
|
-
import BN from '
|
|
6
|
+
import { BN } from '.';
|
|
6
7
|
import { IWallet } from './types';
|
|
7
8
|
export declare class MockUSDCFaucet {
|
|
8
9
|
connection: Connection;
|
package/lib/orderParams.d.ts
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
import { OrderParams, OrderTriggerCondition, PositionDirection } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
4
|
export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
5
|
+
export declare function getTriggerMarketOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
6
|
+
export declare function getTriggerLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
7
7
|
export declare function getMarketOrderParams(marketIndex: BN, direction: PositionDirection, quoteAssetAmount: BN, baseAssetAmount: BN, reduceOnly: boolean, price?: BN, discountToken?: boolean, referrer?: boolean): OrderParams;
|
package/lib/orderParams.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getMarketOrderParams = exports.
|
|
3
|
+
exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
5
|
const numericConstants_1 = require("./constants/numericConstants");
|
|
6
6
|
function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
|
|
@@ -28,9 +28,9 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
exports.getLimitOrderParams = getLimitOrderParams;
|
|
31
|
-
function
|
|
31
|
+
function getTriggerMarketOrderParams(marketIndex, direction, baseAssetAmount, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
|
|
32
32
|
return {
|
|
33
|
-
orderType: types_1.OrderType.
|
|
33
|
+
orderType: types_1.OrderType.TRIGGER_MARKET,
|
|
34
34
|
userOrderId,
|
|
35
35
|
marketIndex,
|
|
36
36
|
direction,
|
|
@@ -52,10 +52,10 @@ function getStopOrderParams(marketIndex, direction, baseAssetAmount, triggerPric
|
|
|
52
52
|
oraclePriceOffset: numericConstants_1.ZERO,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
-
exports.
|
|
56
|
-
function
|
|
55
|
+
exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
|
|
56
|
+
function getTriggerLimitOrderParams(marketIndex, direction, baseAssetAmount, price, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
|
|
57
57
|
return {
|
|
58
|
-
orderType: types_1.OrderType.
|
|
58
|
+
orderType: types_1.OrderType.TRIGGER_LIMIT,
|
|
59
59
|
userOrderId,
|
|
60
60
|
marketIndex,
|
|
61
61
|
direction,
|
|
@@ -77,7 +77,7 @@ function getStopLimitOrderParams(marketIndex, direction, baseAssetAmount, price,
|
|
|
77
77
|
oraclePriceOffset: numericConstants_1.ZERO,
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
-
exports.
|
|
80
|
+
exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
|
|
81
81
|
function getMarketOrderParams(marketIndex, direction, quoteAssetAmount, baseAssetAmount, reduceOnly, price = numericConstants_1.ZERO, discountToken = false, referrer = false) {
|
|
82
82
|
if (baseAssetAmount.eq(numericConstants_1.ZERO) && quoteAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
83
83
|
throw Error('baseAssetAmount or quoteAssetAmount must be zero');
|
package/lib/orders.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { Market, Order, UserAccount, UserPosition } from './types';
|
|
2
|
-
import BN from '
|
|
3
|
+
import { BN } from '.';
|
|
3
4
|
export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: Market, order: Order): [UserAccount, UserPosition, Market] | null;
|
|
4
5
|
export declare function calculateAmountToTradeForLimit(market: Market, order: Order): BN;
|
|
5
6
|
export declare function calculateAmountToTradeForStopLimit(market: Market, order: Order): BN;
|
package/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
1
2
|
import { PublicKey, Transaction } from '@solana/web3.js';
|
|
2
|
-
import BN from '
|
|
3
|
+
import { BN } from '.';
|
|
3
4
|
export declare class SwapDirection {
|
|
4
5
|
static readonly ADD: {
|
|
5
6
|
add: {};
|
|
@@ -28,11 +29,11 @@ export declare class OrderType {
|
|
|
28
29
|
static readonly LIMIT: {
|
|
29
30
|
limit: {};
|
|
30
31
|
};
|
|
31
|
-
static readonly
|
|
32
|
-
|
|
32
|
+
static readonly TRIGGER_MARKET: {
|
|
33
|
+
triggerMarket: {};
|
|
33
34
|
};
|
|
34
|
-
static readonly
|
|
35
|
-
|
|
35
|
+
static readonly TRIGGER_LIMIT: {
|
|
36
|
+
triggerLimit: {};
|
|
36
37
|
};
|
|
37
38
|
static readonly MARKET: {
|
|
38
39
|
market: {};
|
|
@@ -341,6 +342,7 @@ export declare type Order = {
|
|
|
341
342
|
userOrderId: number;
|
|
342
343
|
marketIndex: BN;
|
|
343
344
|
price: BN;
|
|
345
|
+
userBaseAssetAmount: BN;
|
|
344
346
|
baseAssetAmount: BN;
|
|
345
347
|
baseAssetAmountFilled: BN;
|
|
346
348
|
quoteAssetAmount: BN;
|
package/lib/types.js
CHANGED
|
@@ -21,8 +21,8 @@ class OrderType {
|
|
|
21
21
|
}
|
|
22
22
|
exports.OrderType = OrderType;
|
|
23
23
|
OrderType.LIMIT = { limit: {} };
|
|
24
|
-
OrderType.
|
|
25
|
-
OrderType.
|
|
24
|
+
OrderType.TRIGGER_MARKET = { triggerMarket: {} };
|
|
25
|
+
OrderType.TRIGGER_LIMIT = { triggerLimit: {} };
|
|
26
26
|
OrderType.MARKET = { market: {} };
|
|
27
27
|
class OrderStatus {
|
|
28
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "0.1.18-orders.
|
|
3
|
+
"version": "0.1.18-orders.4",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"url": "git@github.com:drift-labs/protocol-v1.git"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
+
"lint": "eslint './**/*.{ts,tsx}' --quiet",
|
|
13
14
|
"build": "yarn clean && tsc",
|
|
14
15
|
"clean": "rm -rf lib",
|
|
15
16
|
"patch-and-pub": "npm version patch --force && npm publish"
|
|
@@ -34,6 +35,13 @@
|
|
|
34
35
|
"strict-event-emitter-types": "^2.0.0",
|
|
35
36
|
"uuid": "^8.3.2"
|
|
36
37
|
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
|
40
|
+
"@typescript-eslint/parser": "^4.28.0",
|
|
41
|
+
"eslint": "^7.29.0",
|
|
42
|
+
"eslint-config-prettier": "^8.3.0",
|
|
43
|
+
"eslint-plugin-prettier": "^3.4.0"
|
|
44
|
+
},
|
|
37
45
|
"description": "SDK for Drift Protocol v1",
|
|
38
46
|
"engines": {
|
|
39
47
|
"node": ">=12"
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { Commitment, Connection, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { AccountData } from './types';
|
|
3
4
|
|
|
4
5
|
type AccountToLoad = {
|
|
5
6
|
publicKey: PublicKey;
|
|
6
7
|
callbacks: Map<string, (buffer: Buffer) => void>;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
|
-
type AccountData = {
|
|
10
|
-
slot: number;
|
|
11
|
-
buffer: Buffer | undefined;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
10
|
const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
|
|
15
11
|
|
|
16
12
|
export class BulkAccountLoader {
|
|
@@ -21,6 +17,9 @@ export class BulkAccountLoader {
|
|
|
21
17
|
accountData = new Map<string, AccountData>();
|
|
22
18
|
errorCallbacks = new Map<string, (e) => void>();
|
|
23
19
|
intervalId?: NodeJS.Timer;
|
|
20
|
+
// to handle clients spamming load
|
|
21
|
+
loadPromise?: Promise<void>;
|
|
22
|
+
loadPromiseResolver: () => void;
|
|
24
23
|
|
|
25
24
|
public constructor(
|
|
26
25
|
connection: Connection,
|
|
@@ -56,6 +55,9 @@ export class BulkAccountLoader {
|
|
|
56
55
|
this.startPolling();
|
|
57
56
|
}
|
|
58
57
|
|
|
58
|
+
// if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
|
|
59
|
+
this.loadPromise = undefined;
|
|
60
|
+
|
|
59
61
|
return callbackId;
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -91,16 +93,34 @@ export class BulkAccountLoader {
|
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
public async load(): Promise<void> {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
if (this.loadPromise) {
|
|
97
|
+
return this.loadPromise;
|
|
98
|
+
}
|
|
99
|
+
this.loadPromise = new Promise((resolver) => {
|
|
100
|
+
this.loadPromiseResolver = resolver;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const chunks = this.chunks(
|
|
105
|
+
Array.from(this.accountsToLoad.values()),
|
|
106
|
+
GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
await Promise.all(
|
|
110
|
+
chunks.map((chunk) => {
|
|
111
|
+
return this.loadChunk(chunk);
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.error(`Error in bulkAccountLoader.load()`);
|
|
116
|
+
console.error(e);
|
|
117
|
+
for (const [_, callback] of this.errorCallbacks) {
|
|
118
|
+
callback(e);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.loadPromiseResolver();
|
|
123
|
+
this.loadPromise = undefined;
|
|
104
124
|
}
|
|
105
125
|
|
|
106
126
|
async loadChunk(accountsToLoad: AccountToLoad[]): Promise<void> {
|
package/src/accounts/types.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { AccountSubscriber } from './types';
|
|
1
|
+
import { AccountData, AccountSubscriber } from './types';
|
|
2
2
|
import { Program } from '@project-serum/anchor';
|
|
3
|
-
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { AccountInfo, Context, PublicKey } from '@solana/web3.js';
|
|
4
|
+
import { capitalize } from './utils';
|
|
5
|
+
import * as Buffer from 'buffer';
|
|
4
6
|
|
|
5
7
|
export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
|
|
6
8
|
data?: T;
|
|
9
|
+
accountData?: AccountData;
|
|
7
10
|
accountName: string;
|
|
8
11
|
program: Program;
|
|
9
12
|
accountPublicKey: PublicKey;
|
|
10
13
|
onChange: (data: T) => void;
|
|
14
|
+
listenerId?: number;
|
|
11
15
|
|
|
12
16
|
public constructor(
|
|
13
17
|
accountName: string,
|
|
@@ -20,32 +24,78 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
async subscribe(onChange: (data: T) => void): Promise<void> {
|
|
27
|
+
if (this.listenerId) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
this.onChange = onChange;
|
|
24
32
|
await this.fetch();
|
|
25
33
|
|
|
26
|
-
this.program.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
this.listenerId = this.program.provider.connection.onAccountChange(
|
|
35
|
+
this.accountPublicKey,
|
|
36
|
+
(accountInfo, context) => {
|
|
37
|
+
this.handleRpcResponse(context, accountInfo);
|
|
38
|
+
},
|
|
39
|
+
this.program.provider.opts.commitment
|
|
40
|
+
);
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
async fetch(): Promise<void> {
|
|
35
|
-
const
|
|
36
|
-
this.
|
|
37
|
-
|
|
44
|
+
const rpcResponse =
|
|
45
|
+
await this.program.provider.connection.getAccountInfoAndContext(
|
|
46
|
+
this.accountPublicKey,
|
|
47
|
+
this.program.provider.opts.commitment
|
|
48
|
+
);
|
|
49
|
+
this.handleRpcResponse(rpcResponse.context, rpcResponse?.value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
handleRpcResponse(context: Context, accountInfo?: AccountInfo<Buffer>): void {
|
|
53
|
+
const newSlot = context.slot;
|
|
54
|
+
let newBuffer: Buffer | undefined = undefined;
|
|
55
|
+
if (accountInfo) {
|
|
56
|
+
newBuffer = accountInfo.data;
|
|
57
|
+
}
|
|
38
58
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
if (!this.accountData) {
|
|
60
|
+
this.accountData = {
|
|
61
|
+
buffer: newBuffer,
|
|
62
|
+
slot: newSlot,
|
|
63
|
+
};
|
|
64
|
+
if (newBuffer) {
|
|
65
|
+
this.data = this.program.account[
|
|
66
|
+
this.accountName
|
|
67
|
+
].coder.accounts.decode(capitalize(this.accountName), newBuffer);
|
|
68
|
+
this.onChange(this.data);
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (newSlot <= this.accountData.slot) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const oldBuffer = this.accountData.buffer;
|
|
78
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
79
|
+
this.accountData = {
|
|
80
|
+
buffer: newBuffer,
|
|
81
|
+
slot: newSlot,
|
|
82
|
+
};
|
|
83
|
+
this.data = this.program.account[this.accountName].coder.accounts.decode(
|
|
84
|
+
capitalize(this.accountName),
|
|
85
|
+
newBuffer
|
|
86
|
+
);
|
|
42
87
|
this.onChange(this.data);
|
|
43
88
|
}
|
|
44
89
|
}
|
|
45
90
|
|
|
46
91
|
unsubscribe(): Promise<void> {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
92
|
+
if (this.listenerId) {
|
|
93
|
+
const promise =
|
|
94
|
+
this.program.provider.connection.removeAccountChangeListener(
|
|
95
|
+
this.listenerId
|
|
96
|
+
);
|
|
97
|
+
this.listenerId = undefined;
|
|
98
|
+
return promise;
|
|
99
|
+
}
|
|
50
100
|
}
|
|
51
101
|
}
|
package/src/clearingHouse.ts
CHANGED
|
@@ -414,6 +414,20 @@ export class ClearingHouse {
|
|
|
414
414
|
return this.userOrdersAccountPublicKey;
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
userOrdersExist?: boolean;
|
|
418
|
+
async userOrdersAccountExists(): Promise<boolean> {
|
|
419
|
+
if (this.userOrdersExist) {
|
|
420
|
+
return this.userOrdersExist;
|
|
421
|
+
}
|
|
422
|
+
const userOrdersAccountRPCResponse =
|
|
423
|
+
await this.connection.getParsedAccountInfo(
|
|
424
|
+
await this.getUserOrdersAccountPublicKey()
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
this.userOrdersExist = userOrdersAccountRPCResponse.value !== null;
|
|
428
|
+
return this.userOrdersExist;
|
|
429
|
+
}
|
|
430
|
+
|
|
417
431
|
public async depositCollateral(
|
|
418
432
|
amount: BN,
|
|
419
433
|
collateralAccountPublicKey: PublicKey,
|
|
@@ -668,6 +682,27 @@ export class ClearingHouse {
|
|
|
668
682
|
);
|
|
669
683
|
}
|
|
670
684
|
|
|
685
|
+
public async initializeUserOrdersThenPlaceOrder(
|
|
686
|
+
orderParams: OrderParams,
|
|
687
|
+
discountToken?: PublicKey,
|
|
688
|
+
referrer?: PublicKey
|
|
689
|
+
): Promise<TransactionSignature> {
|
|
690
|
+
const instructions: anchor.web3.TransactionInstruction[] = [];
|
|
691
|
+
const userOrdersAccountExists = await this.userOrdersAccountExists();
|
|
692
|
+
if (!userOrdersAccountExists) {
|
|
693
|
+
instructions.push(await this.getInitializeUserOrdersInstruction());
|
|
694
|
+
}
|
|
695
|
+
instructions.push(
|
|
696
|
+
await this.getPlaceOrderIx(orderParams, discountToken, referrer)
|
|
697
|
+
);
|
|
698
|
+
const tx = new Transaction();
|
|
699
|
+
for (const instruction of instructions) {
|
|
700
|
+
tx.add(instruction);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
return await this.txSender.send(tx, [], this.opts);
|
|
704
|
+
}
|
|
705
|
+
|
|
671
706
|
public async placeOrder(
|
|
672
707
|
orderParams: OrderParams,
|
|
673
708
|
discountToken?: PublicKey,
|
|
@@ -872,6 +907,27 @@ export class ClearingHouse {
|
|
|
872
907
|
});
|
|
873
908
|
}
|
|
874
909
|
|
|
910
|
+
public async initializeUserOrdersThenPlaceAndFillOrder(
|
|
911
|
+
orderParams: OrderParams,
|
|
912
|
+
discountToken?: PublicKey,
|
|
913
|
+
referrer?: PublicKey
|
|
914
|
+
): Promise<TransactionSignature> {
|
|
915
|
+
const instructions: anchor.web3.TransactionInstruction[] = [];
|
|
916
|
+
const userOrdersAccountExists = await this.userOrdersAccountExists();
|
|
917
|
+
if (!userOrdersAccountExists) {
|
|
918
|
+
instructions.push(await this.getInitializeUserOrdersInstruction());
|
|
919
|
+
}
|
|
920
|
+
instructions.push(
|
|
921
|
+
await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
|
|
922
|
+
);
|
|
923
|
+
const tx = new Transaction();
|
|
924
|
+
for (const instruction of instructions) {
|
|
925
|
+
tx.add(instruction);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return await this.txSender.send(tx, [], this.opts);
|
|
929
|
+
}
|
|
930
|
+
|
|
875
931
|
public async placeAndFillOrder(
|
|
876
932
|
orderParams: OrderParams,
|
|
877
933
|
discountToken?: PublicKey,
|
package/src/clearingHouseUser.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PublicKey } from '@solana/web3.js';
|
|
2
|
-
import BN from 'bn.js';
|
|
3
2
|
import { EventEmitter } from 'events';
|
|
4
3
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
4
|
import { ClearingHouse } from './clearingHouse';
|
|
@@ -33,6 +32,7 @@ import {
|
|
|
33
32
|
getUserOrdersAccountPublicKey,
|
|
34
33
|
calculateNewStateAfterOrder,
|
|
35
34
|
calculateTradeSlippage,
|
|
35
|
+
BN,
|
|
36
36
|
} from '.';
|
|
37
37
|
import { getUserAccountPublicKey } from './addresses';
|
|
38
38
|
import {
|
|
@@ -120,7 +120,7 @@ export class ClearingHouseUser {
|
|
|
120
120
|
return this.accountSubscriber.getUserPositionsAccount();
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
public getUserOrdersAccount(): UserOrdersAccount {
|
|
123
|
+
public getUserOrdersAccount(): UserOrdersAccount | undefined {
|
|
124
124
|
return this.accountSubscriber.getUserOrdersAccount();
|
|
125
125
|
}
|
|
126
126
|
|
package/src/config.ts
CHANGED
|
@@ -11,7 +11,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
11
11
|
devnet: {
|
|
12
12
|
ENV: 'devnet',
|
|
13
13
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
14
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
14
|
+
CLEARING_HOUSE_PROGRAM_ID: '3PfbDmWxR6e2rJ2brhSv7KJyUrHbSCu63d3FHqdLhxUJ',
|
|
15
15
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
16
16
|
},
|
|
17
17
|
'mainnet-beta': {
|
package/src/constants/markets.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BN from '
|
|
1
|
+
import { BN } from '../';
|
|
2
2
|
|
|
3
3
|
type Market = {
|
|
4
4
|
symbol: string;
|
|
@@ -98,6 +98,14 @@ export const Markets: Market[] = [
|
|
|
98
98
|
mainnetPythOracle: 'HqFyq1wh1xKvL7KDqqT7NJeSPdAqsDqnmBisUC2XdXAX',
|
|
99
99
|
launchTs: 1643686767000,
|
|
100
100
|
},
|
|
101
|
+
{
|
|
102
|
+
symbol: 'FTT-PERP',
|
|
103
|
+
baseAssetSymbol: 'FTT',
|
|
104
|
+
marketIndex: new BN(11),
|
|
105
|
+
devnetPythOracle: '6vivTRs5ZPeeXbjo7dfburfaYDWoXjBtdtuYgQRuGfu',
|
|
106
|
+
mainnetPythOracle: '8JPJJkmDScpcNmBRKGZuPuG2GYAveQgP3t5gFuMymwvF',
|
|
107
|
+
launchTs: 1644382122000,
|
|
108
|
+
},
|
|
101
109
|
// {
|
|
102
110
|
// symbol: 'mSOL-PERP',
|
|
103
111
|
// baseAssetSymbol: 'mSOL',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BN from '
|
|
1
|
+
import { BN } from '../';
|
|
2
2
|
|
|
3
3
|
export const ZERO = new BN(0);
|
|
4
4
|
export const ONE = new BN(1);
|
|
@@ -15,6 +15,7 @@ export const FUNDING_PAYMENT_PRECISION = new BN(10000);
|
|
|
15
15
|
export const PEG_PRECISION = new BN(1000);
|
|
16
16
|
|
|
17
17
|
export const AMM_RESERVE_PRECISION = new BN(10 ** 13);
|
|
18
|
+
export const BASE_PRECISION = AMM_RESERVE_PRECISION;
|
|
18
19
|
export const AMM_TO_QUOTE_PRECISION_RATIO =
|
|
19
20
|
AMM_RESERVE_PRECISION.div(QUOTE_PRECISION); // 10^7
|
|
20
21
|
export const PRICE_TO_QUOTE_PRECISION =
|
|
@@ -95,7 +95,10 @@ const main = async () => {
|
|
|
95
95
|
clearingHouse.getMarket(solMarketInfo.marketIndex)
|
|
96
96
|
);
|
|
97
97
|
|
|
98
|
-
const formattedPrice = convertToNumber(
|
|
98
|
+
const formattedPrice = convertToNumber(
|
|
99
|
+
currentMarketPrice,
|
|
100
|
+
MARK_PRICE_PRECISION
|
|
101
|
+
);
|
|
99
102
|
|
|
100
103
|
console.log(`Current Market Price is $${formattedPrice}`);
|
|
101
104
|
|
|
@@ -3547,6 +3547,10 @@
|
|
|
3547
3547
|
"name": "price",
|
|
3548
3548
|
"type": "u128"
|
|
3549
3549
|
},
|
|
3550
|
+
{
|
|
3551
|
+
"name": "userBaseAssetAmount",
|
|
3552
|
+
"type": "i128"
|
|
3553
|
+
},
|
|
3550
3554
|
{
|
|
3551
3555
|
"name": "quoteAssetAmount",
|
|
3552
3556
|
"type": "u128"
|
|
@@ -3734,10 +3738,10 @@
|
|
|
3734
3738
|
"name": "Limit"
|
|
3735
3739
|
},
|
|
3736
3740
|
{
|
|
3737
|
-
"name": "
|
|
3741
|
+
"name": "TriggerMarket"
|
|
3738
3742
|
},
|
|
3739
3743
|
{
|
|
3740
|
-
"name": "
|
|
3744
|
+
"name": "TriggerLimit"
|
|
3741
3745
|
}
|
|
3742
3746
|
]
|
|
3743
3747
|
}
|
package/src/math/conversion.ts
CHANGED
package/src/math/position.ts
CHANGED
package/src/math/utils.ts
CHANGED