@drift-labs/sdk 0.1.24 → 0.1.27
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 +1 -0
- package/lib/accounts/bulkAccountLoader.js +16 -2
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +3 -3
- package/lib/accounts/pollingOracleSubscriber.d.ts +26 -0
- package/lib/accounts/pollingOracleSubscriber.js +79 -0
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +4 -4
- package/lib/accounts/types.d.ts +14 -1
- package/lib/accounts/webSocketAccountSubscriber.js +2 -2
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +2 -2
- package/lib/addresses.js +5 -1
- package/lib/admin.d.ts +1 -1
- package/lib/admin.js +15 -10
- package/lib/clearingHouse.d.ts +4 -4
- package/lib/clearingHouse.js +56 -25
- package/lib/clearingHouseUser.js +18 -18
- package/lib/constants/markets.d.ts +8 -6
- package/lib/constants/markets.js +85 -26
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +2 -1
- package/lib/examples/makeTradeExample.js +6 -6
- package/lib/factory/oracleClient.d.ts +5 -0
- package/lib/factory/oracleClient.js +16 -0
- package/lib/idl/clearing_house.json +22 -2
- package/lib/idl/switchboard_v2.json +4663 -0
- package/lib/index.d.ts +5 -1
- package/lib/index.js +10 -2
- package/lib/math/amm.js +12 -12
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +5 -17
- package/lib/math/market.d.ts +2 -0
- package/lib/math/market.js +8 -3
- package/lib/math/orders.js +9 -9
- package/lib/math/position.js +1 -1
- package/lib/math/trade.js +18 -18
- package/lib/mockUSDCFaucet.js +5 -1
- package/lib/oracles/pythClient.d.ts +14 -0
- package/lib/oracles/pythClient.js +53 -0
- package/lib/oracles/switchboardClient.d.ts +13 -0
- package/lib/oracles/switchboardClient.js +76 -0
- package/lib/oracles/types.d.ts +15 -0
- package/lib/oracles/types.js +2 -0
- package/lib/orderParams.d.ts +1 -1
- package/lib/orderParams.js +3 -3
- package/lib/orders.d.ts +3 -2
- package/lib/orders.js +29 -22
- package/lib/tx/retryTxSender.js +1 -1
- package/lib/types.d.ts +1 -0
- package/package.json +2 -1
- package/src/accounts/bulkAccountLoader.js +180 -0
- package/src/accounts/bulkAccountLoader.js.map +1 -0
- package/src/accounts/bulkAccountLoader.ts +19 -0
- package/src/accounts/bulkUserSubscription.js +56 -0
- package/src/accounts/bulkUserSubscription.js.map +1 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +210 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.js.map +1 -0
- package/src/accounts/pollingOracleSubscriber.js +65 -0
- package/src/accounts/pollingOracleSubscriber.js.map +1 -0
- package/src/accounts/pollingOracleSubscriber.ts +103 -0
- package/src/accounts/pollingTokenAccountSubscriber.js +65 -0
- package/src/accounts/pollingTokenAccountSubscriber.js.map +1 -0
- package/src/accounts/pollingUserAccountSubscriber.js +139 -0
- package/src/accounts/pollingUserAccountSubscriber.js.map +1 -0
- package/src/accounts/types.js +1 -0
- package/src/accounts/types.js.map +1 -0
- package/src/accounts/types.ts +22 -1
- package/src/accounts/utils.js +1 -0
- package/src/accounts/utils.js.map +1 -0
- package/src/accounts/webSocketAccountSubscriber.js +15 -27
- package/src/accounts/webSocketAccountSubscriber.js.map +1 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +212 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js.map +1 -0
- package/src/accounts/webSocketUserAccountSubscriber.js +78 -0
- package/src/accounts/webSocketUserAccountSubscriber.js.map +1 -0
- package/src/addresses.js +20 -44
- package/src/addresses.js.map +1 -0
- package/src/admin.js +443 -0
- package/src/admin.js.map +1 -0
- package/src/admin.ts +2 -0
- package/src/assert/assert.js +10 -0
- package/src/assert/assert.js.map +1 -0
- package/src/clearingHouse.js +769 -0
- package/src/clearingHouse.js.map +1 -0
- package/src/clearingHouse.ts +47 -7
- package/src/clearingHouseUser.js +581 -0
- package/src/clearingHouseUser.js.map +1 -0
- package/src/config.js +37 -0
- package/src/config.js.map +1 -0
- package/src/constants/markets.js +167 -0
- package/src/constants/markets.js.map +1 -0
- package/src/constants/markets.ts +93 -31
- package/src/constants/numericConstants.js +22 -0
- package/src/constants/numericConstants.js.map +1 -0
- package/src/constants/numericConstants.ts +1 -0
- package/src/factory/clearingHouse.js +65 -0
- package/src/factory/clearingHouse.js.map +1 -0
- package/src/factory/clearingHouseUser.js +35 -0
- package/src/factory/clearingHouseUser.js.map +1 -0
- package/src/factory/oracleClient.js +17 -0
- package/src/factory/oracleClient.js.map +1 -0
- package/src/factory/oracleClient.ts +22 -0
- package/src/idl/clearing_house.json +22 -2
- package/src/idl/switchboard_v2.json +4663 -0
- package/src/index.js +56 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +5 -1
- package/src/math/amm.js +285 -0
- package/src/math/amm.js.map +1 -0
- package/src/math/conversion.js +16 -0
- package/src/math/conversion.js.map +1 -0
- package/src/math/funding.js +223 -0
- package/src/math/funding.js.map +1 -0
- package/src/math/funding.ts +9 -25
- package/src/math/insuranceFund.js +23 -0
- package/src/math/insuranceFund.js.map +1 -0
- package/src/math/market.js +30 -0
- package/src/math/market.js.map +1 -0
- package/src/math/market.ts +9 -0
- package/src/math/orders.js +73 -0
- package/src/math/orders.js.map +1 -0
- package/src/math/position.js +121 -0
- package/src/math/position.js.map +1 -0
- package/src/math/trade.js +182 -0
- package/src/math/trade.js.map +1 -0
- package/src/math/utils.js +27 -0
- package/src/math/utils.js.map +1 -0
- package/src/mockUSDCFaucet.js +88 -116
- package/src/mockUSDCFaucet.js.map +1 -0
- package/src/oracles/pythClient.js +39 -0
- package/src/oracles/pythClient.js.map +1 -0
- package/src/oracles/pythClient.ts +49 -0
- package/src/oracles/switchboardClient.js +60 -0
- package/src/oracles/switchboardClient.js.map +1 -0
- package/src/oracles/switchboardClient.ts +87 -0
- package/src/oracles/types.js +3 -0
- package/src/oracles/types.js.map +1 -0
- package/src/oracles/types.ts +15 -0
- package/src/orderParams.js +109 -0
- package/src/orderParams.js.map +1 -0
- package/src/orderParams.ts +5 -3
- package/src/orders.js +172 -0
- package/src/orders.js.map +1 -0
- package/src/orders.ts +17 -4
- package/src/token/index.js +39 -0
- package/src/token/index.js.map +1 -0
- package/src/tx/defaultTxSender.js +13 -0
- package/src/tx/defaultTxSender.js.map +1 -0
- package/src/tx/retryTxSender.js +137 -0
- package/src/tx/retryTxSender.js.map +1 -0
- package/src/tx/types.js +3 -0
- package/src/tx/types.js.map +1 -0
- package/src/tx/utils.js +9 -0
- package/src/tx/utils.js.map +1 -0
- package/src/types.js +1 -0
- package/src/types.js.map +1 -0
- package/src/types.ts +1 -0
- package/src/util/computeUnits.js +17 -0
- package/src/util/computeUnits.js.map +1 -0
- package/src/util/tps.js +17 -0
- package/src/util/tps.js.map +1 -0
- package/src/wallet.js +23 -0
- package/src/wallet.js.map +1 -0
- package/lib/pythClient.d.ts +0 -7
- package/lib/pythClient.js +0 -25
- package/src/pythClient.ts +0 -15
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SwitchboardClient = void 0;
|
|
16
|
+
const switchboard_v2_1 = require("@switchboard-xyz/switchboard-v2");
|
|
17
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
18
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
19
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
20
|
+
const wallet_1 = require("../wallet");
|
|
21
|
+
const switchboard_v2_json_1 = __importDefault(require("../idl/switchboard_v2.json"));
|
|
22
|
+
// cache switchboard program for every client object since itll always be the same
|
|
23
|
+
const programMap = new Map();
|
|
24
|
+
class SwitchboardClient {
|
|
25
|
+
constructor(connection, env) {
|
|
26
|
+
this.connection = connection;
|
|
27
|
+
this.env = env;
|
|
28
|
+
}
|
|
29
|
+
getOraclePriceData(pricePublicKey) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const accountInfo = yield this.connection.getAccountInfo(pricePublicKey);
|
|
32
|
+
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
getOraclePriceDataFromBuffer(buffer) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const program = yield this.getProgram();
|
|
38
|
+
const aggregatorAccountData = program.account.aggregatorAccountData.coder.accounts.decode('AggregatorAccountData', buffer);
|
|
39
|
+
const price = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound.result);
|
|
40
|
+
const confidence = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound
|
|
41
|
+
.stdDeviation);
|
|
42
|
+
const slot = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
|
|
43
|
+
return {
|
|
44
|
+
price,
|
|
45
|
+
slot,
|
|
46
|
+
confidence,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
getProgram() {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
if (programMap.has(this.env)) {
|
|
53
|
+
return programMap.get(this.env);
|
|
54
|
+
}
|
|
55
|
+
const program = yield getSwitchboardProgram(this.env, this.connection);
|
|
56
|
+
programMap.set(this.env, program);
|
|
57
|
+
return program;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.SwitchboardClient = SwitchboardClient;
|
|
62
|
+
function getSwitchboardProgram(env, connection) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const DEFAULT_KEYPAIR = web3_js_1.Keypair.fromSeed(new Uint8Array(32).fill(1));
|
|
65
|
+
const programId = (0, switchboard_v2_1.getSwitchboardPid)(env);
|
|
66
|
+
const wallet = new wallet_1.Wallet(DEFAULT_KEYPAIR);
|
|
67
|
+
const provider = new anchor_1.Provider(connection, wallet, {});
|
|
68
|
+
return new anchor_1.Program(switchboard_v2_json_1.default, programId, provider);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function convertSwitchboardDecimal(switchboardDecimal) {
|
|
72
|
+
const switchboardPrecision = numericConstants_1.TEN.pow(new anchor_1.BN(switchboardDecimal.scale));
|
|
73
|
+
return switchboardDecimal.mantissa
|
|
74
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
75
|
+
.div(switchboardPrecision);
|
|
76
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="bn.js" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { BN } from '@project-serum/anchor';
|
|
4
|
+
import { PublicKey } from '@solana/web3.js';
|
|
5
|
+
export declare type OraclePriceData = {
|
|
6
|
+
price: BN;
|
|
7
|
+
slot: BN;
|
|
8
|
+
confidence: BN;
|
|
9
|
+
twap?: BN;
|
|
10
|
+
twapConfidence?: BN;
|
|
11
|
+
};
|
|
12
|
+
export interface OracleClient {
|
|
13
|
+
getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
|
|
14
|
+
getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
|
|
15
|
+
}
|
package/lib/orderParams.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { OrderParams, OrderTriggerCondition, PositionDirection } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
-
export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
|
|
4
|
+
export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number, postOnly?: boolean, oraclePriceOffset?: BN): OrderParams;
|
|
5
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
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
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
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
|
-
function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
|
|
6
|
+
function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0, postOnly = false, oraclePriceOffset = numericConstants_1.ZERO) {
|
|
7
7
|
return {
|
|
8
8
|
orderType: types_1.OrderType.LIMIT,
|
|
9
9
|
userOrderId,
|
|
@@ -13,7 +13,7 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
|
|
|
13
13
|
baseAssetAmount,
|
|
14
14
|
price,
|
|
15
15
|
reduceOnly,
|
|
16
|
-
postOnly
|
|
16
|
+
postOnly,
|
|
17
17
|
immediateOrCancel: false,
|
|
18
18
|
positionLimit: numericConstants_1.ZERO,
|
|
19
19
|
padding0: true,
|
|
@@ -24,7 +24,7 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
|
|
|
24
24
|
},
|
|
25
25
|
triggerCondition: types_1.OrderTriggerCondition.ABOVE,
|
|
26
26
|
triggerPrice: numericConstants_1.ZERO,
|
|
27
|
-
oraclePriceOffset
|
|
27
|
+
oraclePriceOffset,
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
exports.getLimitOrderParams = getLimitOrderParams;
|
package/lib/orders.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { Market, Order, UserAccount, UserPosition } from './types';
|
|
3
3
|
import { BN, ClearingHouseUser } from '.';
|
|
4
|
+
import { OraclePriceData } from '.';
|
|
4
5
|
export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: Market, order: Order): [UserAccount, UserPosition, Market] | null;
|
|
5
|
-
export declare function calculateBaseAssetAmountMarketCanExecute(market: Market, order: Order): BN;
|
|
6
|
-
export declare function calculateAmountToTradeForLimit(market: Market, order: Order): BN;
|
|
6
|
+
export declare function calculateBaseAssetAmountMarketCanExecute(market: Market, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
7
|
+
export declare function calculateAmountToTradeForLimit(market: Market, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
7
8
|
export declare function calculateAmountToTradeForTriggerLimit(market: Market, order: Order): BN;
|
|
8
9
|
export declare function calculateBaseAssetAmountUserCanExecute(market: Market, order: Order, user: ClearingHouseUser): BN;
|
package/lib/orders.js
CHANGED
|
@@ -8,7 +8,7 @@ const numericConstants_1 = require("./constants/numericConstants");
|
|
|
8
8
|
const amm_1 = require("./math/amm");
|
|
9
9
|
const position_1 = require("./math/position");
|
|
10
10
|
function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
|
|
11
|
-
if (types_1.isVariant(order.status, 'init')) {
|
|
11
|
+
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
14
|
const baseAssetAmountToTrade = calculateBaseAssetAmountMarketCanExecute(market, order);
|
|
@@ -17,11 +17,11 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
|
|
|
17
17
|
}
|
|
18
18
|
const userAccountAfter = Object.assign({}, userAccount);
|
|
19
19
|
const userPositionAfter = Object.assign({}, userPosition);
|
|
20
|
-
const currentPositionDirection = position_1.positionCurrentDirection(userPosition);
|
|
20
|
+
const currentPositionDirection = (0, position_1.positionCurrentDirection)(userPosition);
|
|
21
21
|
const increasePosition = userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) ||
|
|
22
22
|
isSameDirection(order.direction, currentPositionDirection);
|
|
23
23
|
if (increasePosition) {
|
|
24
|
-
const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountToTrade, order.direction, market);
|
|
24
|
+
const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
|
|
25
25
|
const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(market, marketAfter);
|
|
26
26
|
userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
|
|
27
27
|
userPositionAfter.quoteAssetAmount = userPositionAfter.quoteAssetAmount.add(quoteAssetAmountSwapped);
|
|
@@ -30,10 +30,10 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
|
|
|
30
30
|
else {
|
|
31
31
|
const reversePosition = baseAssetAmountToTrade.gt(userPosition.baseAssetAmount.abs());
|
|
32
32
|
if (reversePosition) {
|
|
33
|
-
const intermediateMarket = market_1.calculateNewMarketAfterTrade(userPosition.baseAssetAmount, position_1.findDirectionToClose(userPosition), market);
|
|
33
|
+
const intermediateMarket = (0, market_1.calculateNewMarketAfterTrade)(userPosition.baseAssetAmount, (0, position_1.findDirectionToClose)(userPosition), market);
|
|
34
34
|
const { quoteAssetAmountSwapped: baseAssetValue } = calculateAmountSwapped(market, intermediateMarket);
|
|
35
35
|
let pnl;
|
|
36
|
-
if (types_1.isVariant(currentPositionDirection, 'long')) {
|
|
36
|
+
if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
|
|
37
37
|
pnl = baseAssetValue.sub(userPosition.quoteAssetAmount);
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
@@ -41,20 +41,20 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
|
|
|
41
41
|
}
|
|
42
42
|
userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
|
|
43
43
|
const baseAssetAmountLeft = baseAssetAmountToTrade.sub(userPosition.baseAssetAmount.abs());
|
|
44
|
-
const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountLeft, order.direction, intermediateMarket);
|
|
44
|
+
const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountLeft, order.direction, intermediateMarket);
|
|
45
45
|
const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(intermediateMarket, marketAfter);
|
|
46
46
|
userPositionAfter.quoteAssetAmount = quoteAssetAmountSwapped;
|
|
47
47
|
userPositionAfter.baseAssetAmount = baseAssetAmountSwapped;
|
|
48
48
|
return [userAccountAfter, userPositionAfter, marketAfter];
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountToTrade, order.direction, market);
|
|
51
|
+
const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
|
|
52
52
|
const { quoteAssetAmountSwapped: baseAssetValue, baseAssetAmountSwapped, } = calculateAmountSwapped(market, marketAfter);
|
|
53
53
|
const costBasisRealized = userPosition.quoteAssetAmount
|
|
54
54
|
.mul(baseAssetAmountSwapped.abs())
|
|
55
55
|
.div(userPosition.baseAssetAmount.abs());
|
|
56
56
|
let pnl;
|
|
57
|
-
if (types_1.isVariant(currentPositionDirection, 'long')) {
|
|
57
|
+
if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
|
|
58
58
|
pnl = baseAssetValue.sub(costBasisRealized);
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
@@ -80,14 +80,14 @@ function calculateAmountSwapped(marketBefore, marketAfter) {
|
|
|
80
80
|
baseAssetAmountSwapped: marketBefore.amm.baseAssetReserve.sub(marketAfter.amm.baseAssetReserve),
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
function calculateBaseAssetAmountMarketCanExecute(market, order) {
|
|
84
|
-
if (types_1.isVariant(order.orderType, 'limit')) {
|
|
85
|
-
return calculateAmountToTradeForLimit(market, order);
|
|
83
|
+
function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData) {
|
|
84
|
+
if ((0, types_1.isVariant)(order.orderType, 'limit')) {
|
|
85
|
+
return calculateAmountToTradeForLimit(market, order, oraclePriceData);
|
|
86
86
|
}
|
|
87
|
-
else if (types_1.isVariant(order.orderType, 'triggerLimit')) {
|
|
87
|
+
else if ((0, types_1.isVariant)(order.orderType, 'triggerLimit')) {
|
|
88
88
|
return calculateAmountToTradeForTriggerLimit(market, order);
|
|
89
89
|
}
|
|
90
|
-
else if (types_1.isVariant(order.orderType, 'market')) {
|
|
90
|
+
else if ((0, types_1.isVariant)(order.orderType, 'market')) {
|
|
91
91
|
// should never be a market order queued
|
|
92
92
|
return numericConstants_1.ZERO;
|
|
93
93
|
}
|
|
@@ -96,8 +96,15 @@ function calculateBaseAssetAmountMarketCanExecute(market, order) {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
exports.calculateBaseAssetAmountMarketCanExecute = calculateBaseAssetAmountMarketCanExecute;
|
|
99
|
-
function calculateAmountToTradeForLimit(market, order) {
|
|
100
|
-
|
|
99
|
+
function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
|
|
100
|
+
let limitPrice = order.price;
|
|
101
|
+
if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
|
|
102
|
+
if (!oraclePriceData) {
|
|
103
|
+
throw Error('Cant calculate limit price for oracle offset oracle without OraclePriceData');
|
|
104
|
+
}
|
|
105
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
106
|
+
}
|
|
107
|
+
const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice);
|
|
101
108
|
// Check that directions are the same
|
|
102
109
|
const sameDirection = isSameDirection(direction, order.direction);
|
|
103
110
|
if (!sameDirection) {
|
|
@@ -119,8 +126,8 @@ function calculateAmountToTradeForTriggerLimit(market, order) {
|
|
|
119
126
|
}
|
|
120
127
|
exports.calculateAmountToTradeForTriggerLimit = calculateAmountToTradeForTriggerLimit;
|
|
121
128
|
function isSameDirection(firstDirection, secondDirection) {
|
|
122
|
-
return ((types_1.isVariant(firstDirection, 'long') && types_1.isVariant(secondDirection, 'long')) ||
|
|
123
|
-
(types_1.isVariant(firstDirection, 'short') && types_1.isVariant(secondDirection, 'short')));
|
|
129
|
+
return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
|
|
130
|
+
((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
|
|
124
131
|
}
|
|
125
132
|
function calculateAmountToTradeForTriggerMarket(market, order) {
|
|
126
133
|
return isTriggerConditionSatisfied(market, order)
|
|
@@ -128,8 +135,8 @@ function calculateAmountToTradeForTriggerMarket(market, order) {
|
|
|
128
135
|
: numericConstants_1.ZERO;
|
|
129
136
|
}
|
|
130
137
|
function isTriggerConditionSatisfied(market, order) {
|
|
131
|
-
const markPrice = market_1.calculateMarkPrice(market);
|
|
132
|
-
if (types_1.isVariant(order.triggerCondition, 'above')) {
|
|
138
|
+
const markPrice = (0, market_1.calculateMarkPrice)(market);
|
|
139
|
+
if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
|
|
133
140
|
return markPrice.gt(order.triggerPrice);
|
|
134
141
|
}
|
|
135
142
|
else {
|
|
@@ -140,13 +147,13 @@ function calculateBaseAssetAmountUserCanExecute(market, order, user) {
|
|
|
140
147
|
const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
|
|
141
148
|
const freeCollateral = user.getFreeCollateral();
|
|
142
149
|
let quoteAssetAmount;
|
|
143
|
-
if (_1.isOrderRiskIncreasingInSameDirection(user, order)) {
|
|
150
|
+
if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
|
|
144
151
|
quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
|
|
145
152
|
}
|
|
146
153
|
else {
|
|
147
154
|
const position = user.getUserPosition(order.marketIndex) ||
|
|
148
155
|
user.getEmptyPosition(order.marketIndex);
|
|
149
|
-
const positionValue = _1.calculateBaseAssetValue(market, position);
|
|
156
|
+
const positionValue = (0, _1.calculateBaseAssetValue)(market, position);
|
|
150
157
|
quoteAssetAmount = freeCollateral
|
|
151
158
|
.mul(maxLeverage)
|
|
152
159
|
.div(_1.TEN_THOUSAND)
|
|
@@ -156,7 +163,7 @@ function calculateBaseAssetAmountUserCanExecute(market, order, user) {
|
|
|
156
163
|
return numericConstants_1.ZERO;
|
|
157
164
|
}
|
|
158
165
|
const baseAssetReservesBefore = market.amm.baseAssetReserve;
|
|
159
|
-
const [_, baseAssetReservesAfter] = _1.calculateAmmReservesAfterSwap(market.amm, 'quote', quoteAssetAmount, types_1.isVariant(order.direction, 'long')
|
|
166
|
+
const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(market.amm, 'quote', quoteAssetAmount, (0, types_1.isVariant)(order.direction, 'long')
|
|
160
167
|
? types_1.SwapDirection.ADD
|
|
161
168
|
: types_1.SwapDirection.REMOVE);
|
|
162
169
|
return baseAssetReservesBefore.sub(baseAssetReservesAfter).abs();
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -93,7 +93,7 @@ class RetryTxSender {
|
|
|
93
93
|
catch (err) {
|
|
94
94
|
throw new Error('signature must be base58 encoded: ' + signature);
|
|
95
95
|
}
|
|
96
|
-
assert_1.default(decodedSignature.length === 64, 'signature has invalid length');
|
|
96
|
+
(0, assert_1.default)(decodedSignature.length === 64, 'signature has invalid length');
|
|
97
97
|
const start = Date.now();
|
|
98
98
|
const subscriptionCommitment = commitment || this.provider.opts.commitment;
|
|
99
99
|
let subscriptionId;
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"@pythnetwork/client": "^2.5.1",
|
|
33
33
|
"@solana/spl-token": "^0.1.6",
|
|
34
34
|
"@solana/web3.js": "^1.22.0",
|
|
35
|
+
"@switchboard-xyz/switchboard-v2": "^0.0.67",
|
|
35
36
|
"strict-event-emitter-types": "^2.0.0",
|
|
36
37
|
"uuid": "^8.3.2"
|
|
37
38
|
},
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BulkAccountLoader = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const uuid_1 = require("uuid");
|
|
6
|
+
const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
|
|
7
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
8
|
+
class BulkAccountLoader {
|
|
9
|
+
constructor(connection, commitment, pollingFrequency) {
|
|
10
|
+
this.accountsToLoad = new Map();
|
|
11
|
+
this.accountData = new Map();
|
|
12
|
+
this.errorCallbacks = new Map();
|
|
13
|
+
this.loggingEnabled = false;
|
|
14
|
+
this.lastUpdate = Date.now();
|
|
15
|
+
this.connection = connection;
|
|
16
|
+
this.commitment = commitment;
|
|
17
|
+
this.pollingFrequency = pollingFrequency;
|
|
18
|
+
}
|
|
19
|
+
addAccount(publicKey, callback) {
|
|
20
|
+
const existingSize = this.accountsToLoad.size;
|
|
21
|
+
const callbackId = (0, uuid_1.v4)();
|
|
22
|
+
const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
|
|
23
|
+
if (existingAccountToLoad) {
|
|
24
|
+
existingAccountToLoad.callbacks.set(callbackId, callback);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const callbacks = new Map();
|
|
28
|
+
callbacks.set(callbackId, callback);
|
|
29
|
+
const newAccountToLoad = {
|
|
30
|
+
publicKey,
|
|
31
|
+
callbacks,
|
|
32
|
+
};
|
|
33
|
+
this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
|
|
34
|
+
}
|
|
35
|
+
if (existingSize === 0) {
|
|
36
|
+
this.startPolling();
|
|
37
|
+
}
|
|
38
|
+
// if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
|
|
39
|
+
this.loadPromise = undefined;
|
|
40
|
+
return callbackId;
|
|
41
|
+
}
|
|
42
|
+
removeAccount(publicKey, callbackId) {
|
|
43
|
+
const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
|
|
44
|
+
if (existingAccountToLoad) {
|
|
45
|
+
existingAccountToLoad.callbacks.delete(callbackId);
|
|
46
|
+
if (existingAccountToLoad.callbacks.size === 0) {
|
|
47
|
+
this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (this.accountsToLoad.size === 0) {
|
|
51
|
+
this.stopPolling();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
addErrorCallbacks(callback) {
|
|
55
|
+
const callbackId = (0, uuid_1.v4)();
|
|
56
|
+
this.errorCallbacks.set(callbackId, callback);
|
|
57
|
+
return callbackId;
|
|
58
|
+
}
|
|
59
|
+
removeErrorCallbacks(callbackId) {
|
|
60
|
+
this.errorCallbacks.delete(callbackId);
|
|
61
|
+
}
|
|
62
|
+
chunks(array, size) {
|
|
63
|
+
return new Array(Math.ceil(array.length / size))
|
|
64
|
+
.fill(null)
|
|
65
|
+
.map((_, index) => index * size)
|
|
66
|
+
.map((begin) => array.slice(begin, begin + size));
|
|
67
|
+
}
|
|
68
|
+
async load() {
|
|
69
|
+
if (this.loadPromise) {
|
|
70
|
+
return this.loadPromise;
|
|
71
|
+
}
|
|
72
|
+
this.loadPromise = new Promise((resolver) => {
|
|
73
|
+
this.loadPromiseResolver = resolver;
|
|
74
|
+
});
|
|
75
|
+
if (this.loggingEnabled) {
|
|
76
|
+
console.log('Loading accounts');
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const chunks = this.chunks(Array.from(this.accountsToLoad.values()), GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE);
|
|
80
|
+
await Promise.all(chunks.map((chunk) => {
|
|
81
|
+
return this.loadChunk(chunk);
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
console.error(`Error in bulkAccountLoader.load()`);
|
|
86
|
+
console.error(e);
|
|
87
|
+
for (const [_, callback] of this.errorCallbacks) {
|
|
88
|
+
callback(e);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this.loadPromiseResolver();
|
|
93
|
+
this.loadPromise = undefined;
|
|
94
|
+
const now = Date.now();
|
|
95
|
+
if (now - this.lastUpdate > fiveMinutes) {
|
|
96
|
+
if (this.loggingEnabled) {
|
|
97
|
+
console.log("Haven't seen updated account in five minutes. Bulk account loader creating new Connection Object");
|
|
98
|
+
}
|
|
99
|
+
this.connection = new web3_js_1.Connection(
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
this.connection._rpcEndpoint, this.connection.commitment);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async loadChunk(accountsToLoad) {
|
|
106
|
+
if (accountsToLoad.length === 0) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const args = [
|
|
110
|
+
accountsToLoad.map((accountToLoad) => {
|
|
111
|
+
return accountToLoad.publicKey.toBase58();
|
|
112
|
+
}),
|
|
113
|
+
{ commitment: this.commitment },
|
|
114
|
+
];
|
|
115
|
+
// @ts-ignore
|
|
116
|
+
const rpcResponse = await this.connection._rpcRequest('getMultipleAccounts', args);
|
|
117
|
+
const newSlot = rpcResponse.result.context.slot;
|
|
118
|
+
for (const i in accountsToLoad) {
|
|
119
|
+
const accountToLoad = accountsToLoad[i];
|
|
120
|
+
const key = accountToLoad.publicKey.toString();
|
|
121
|
+
const oldRPCResponse = this.accountData.get(key);
|
|
122
|
+
let newBuffer = undefined;
|
|
123
|
+
if (rpcResponse.result.value[i]) {
|
|
124
|
+
const raw = rpcResponse.result.value[i].data[0];
|
|
125
|
+
const dataType = rpcResponse.result.value[i].data[1];
|
|
126
|
+
newBuffer = Buffer.from(raw, dataType);
|
|
127
|
+
}
|
|
128
|
+
if (!oldRPCResponse) {
|
|
129
|
+
this.accountData.set(key, {
|
|
130
|
+
slot: newSlot,
|
|
131
|
+
buffer: newBuffer,
|
|
132
|
+
});
|
|
133
|
+
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
134
|
+
this.lastUpdate = Date.now();
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (newSlot <= oldRPCResponse.slot) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const oldBuffer = oldRPCResponse.buffer;
|
|
141
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
142
|
+
this.accountData.set(key, {
|
|
143
|
+
slot: newSlot,
|
|
144
|
+
buffer: newBuffer,
|
|
145
|
+
});
|
|
146
|
+
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
147
|
+
this.lastUpdate = Date.now();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
handleAccountCallbacks(accountToLoad, buffer) {
|
|
152
|
+
for (const [_, callback] of accountToLoad.callbacks) {
|
|
153
|
+
callback(buffer);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
getAccountData(publicKey) {
|
|
157
|
+
const accountData = this.accountData.get(publicKey.toString());
|
|
158
|
+
return accountData === null || accountData === void 0 ? void 0 : accountData.buffer;
|
|
159
|
+
}
|
|
160
|
+
startPolling() {
|
|
161
|
+
if (this.intervalId) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (this.loggingEnabled) {
|
|
165
|
+
console.log(`startPolling`);
|
|
166
|
+
}
|
|
167
|
+
this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
|
|
168
|
+
}
|
|
169
|
+
stopPolling() {
|
|
170
|
+
if (this.intervalId) {
|
|
171
|
+
clearInterval(this.intervalId);
|
|
172
|
+
this.intervalId = undefined;
|
|
173
|
+
if (this.loggingEnabled) {
|
|
174
|
+
console.log(`stopPolling`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.BulkAccountLoader = BulkAccountLoader;
|
|
180
|
+
//# sourceMappingURL=bulkAccountLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkAccountLoader.js","sourceRoot":"","sources":["bulkAccountLoader.ts"],"names":[],"mappings":";;;AAAA,6CAAoE;AACpE,+BAAoC;AAQpC,MAAM,gCAAgC,GAAG,EAAE,CAAC;AAE5C,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAElC,MAAa,iBAAiB;IAc7B,YACC,UAAsB,EACtB,UAAsB,EACtB,gBAAwB;QAbzB,mBAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;QAClD,gBAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;QAC7C,mBAAc,GAAG,IAAI,GAAG,EAAuB,CAAC;QAKhD,mBAAc,GAAG,KAAK,CAAC;QACvB,eAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAOvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;IAC1C,CAAC;IAEM,UAAU,CAChB,SAAoB,EACpB,QAAkC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;QAE9C,MAAM,UAAU,GAAG,IAAA,SAAM,GAAE,CAAC;QAC5B,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5E,IAAI,qBAAqB,EAAE;YAC1B,qBAAqB,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;SAC1D;aAAM;YACN,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoC,CAAC;YAC9D,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACpC,MAAM,gBAAgB,GAAG;gBACxB,SAAS;gBACT,SAAS;aACT,CAAC;YACF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,gBAAgB,CAAC,CAAC;SAChE;QAED,IAAI,YAAY,KAAK,CAAC,EAAE;YACvB,IAAI,CAAC,YAAY,EAAE,CAAC;SACpB;QAED,iHAAiH;QACjH,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAE7B,OAAO,UAAU,CAAC;IACnB,CAAC;IAEM,aAAa,CAAC,SAAoB,EAAE,UAAkB;QAC5D,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5E,IAAI,qBAAqB,EAAE;YAC1B,qBAAqB,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACnD,IAAI,qBAAqB,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;gBAC/C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;aACvE;SACD;QAED,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE;YACnC,IAAI,CAAC,WAAW,EAAE,CAAC;SACnB;IACF,CAAC;IAEM,iBAAiB,CAAC,QAAgC;QACxD,MAAM,UAAU,GAAG,IAAA,SAAM,GAAE,CAAC;QAC5B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,UAAU,CAAC;IACnB,CAAC;IAEM,oBAAoB,CAAC,UAAkB;QAC7C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAI,KAAmB,EAAE,IAAY;QAC1C,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;aAC9C,IAAI,CAAC,IAAI,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC;aAC/B,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;IAEM,KAAK,CAAC,IAAI;QAChB,IAAI,IAAI,CAAC,WAAW,EAAE;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;SACxB;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC3C,IAAI,CAAC,mBAAmB,GAAG,QAAQ,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,cAAc,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;SAChC;QAED,IAAI;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CACzB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,EACxC,gCAAgC,CAChC,CAAC;YAEF,MAAM,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,CACF,CAAC;SACF;QAAC,OAAO,CAAC,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE;gBAChD,QAAQ,CAAC,CAAC,CAAC,CAAC;aACZ;SACD;gBAAS;YACT,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;YAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,WAAW,EAAE;gBACxC,IAAI,IAAI,CAAC,cAAc,EAAE;oBACxB,OAAO,CAAC,GAAG,CACV,kGAAkG,CAClG,CAAC;iBACF;gBACD,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAU;gBAC/B,aAAa;gBACb,IAAI,CAAC,UAAU,CAAC,YAAY,EAC5B,IAAI,CAAC,UAAU,CAAC,UAAU,CAC1B,CAAC;aACF;SACD;IACF,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,cAA+B;QAC9C,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;YAChC,OAAO;SACP;QAED,MAAM,IAAI,GAAG;YACZ,cAAc,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE;gBACpC,OAAO,aAAa,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3C,CAAC,CAAC;YACF,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;SAC/B,CAAC;QAEF,aAAa;QACb,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CACpD,qBAAqB,EACrB,IAAI,CACJ,CAAC;QAEF,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;QAEhD,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE;YAC/B,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEjD,IAAI,SAAS,GAAuB,SAAS,CAAC;YAC9C,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAChC,MAAM,GAAG,GAAW,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACrD,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;aACvC;YAED,IAAI,CAAC,cAAc,EAAE;gBACpB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE;oBACzB,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,SAAS;iBACjB,CAAC,CAAC;gBACH,IAAI,CAAC,sBAAsB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBACtD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7B,SAAS;aACT;YAED,IAAI,OAAO,IAAI,cAAc,CAAC,IAAI,EAAE;gBACnC,SAAS;aACT;YAED,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC;YACxC,IAAI,SAAS,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE;gBAC9D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE;oBACzB,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,SAAS;iBACjB,CAAC,CAAC;gBACH,IAAI,CAAC,sBAAsB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBACtD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;aAC7B;SACD;IACF,CAAC;IAED,sBAAsB,CAAC,aAA4B,EAAE,MAAc;QAClE,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE;YACpD,QAAQ,CAAC,MAAM,CAAC,CAAC;SACjB;IACF,CAAC;IAEM,cAAc,CAAC,SAAoB;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,OAAO,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,CAAC;IAC5B,CAAC;IAEM,YAAY;QAClB,IAAI,IAAI,CAAC,UAAU,EAAE;YACpB,OAAO;SACP;QAED,IAAI,IAAI,CAAC,cAAc,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;SAC5B;QAED,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC5E,CAAC;IAEM,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACpB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAE5B,IAAI,IAAI,CAAC,cAAc,EAAE;gBACxB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;aAC3B;SACD;IACF,CAAC;CACD;AAjOD,8CAiOC"}
|
|
@@ -9,6 +9,8 @@ type AccountToLoad = {
|
|
|
9
9
|
|
|
10
10
|
const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
|
|
11
11
|
|
|
12
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
13
|
+
|
|
12
14
|
export class BulkAccountLoader {
|
|
13
15
|
connection: Connection;
|
|
14
16
|
commitment: Commitment;
|
|
@@ -21,6 +23,7 @@ export class BulkAccountLoader {
|
|
|
21
23
|
loadPromise?: Promise<void>;
|
|
22
24
|
loadPromiseResolver: () => void;
|
|
23
25
|
loggingEnabled = false;
|
|
26
|
+
lastUpdate = Date.now();
|
|
24
27
|
|
|
25
28
|
public constructor(
|
|
26
29
|
connection: Connection,
|
|
@@ -125,6 +128,20 @@ export class BulkAccountLoader {
|
|
|
125
128
|
} finally {
|
|
126
129
|
this.loadPromiseResolver();
|
|
127
130
|
this.loadPromise = undefined;
|
|
131
|
+
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
if (now - this.lastUpdate > fiveMinutes) {
|
|
134
|
+
if (this.loggingEnabled) {
|
|
135
|
+
console.log(
|
|
136
|
+
"Haven't seen updated account in five minutes. Bulk account loader creating new Connection Object"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
this.connection = new Connection(
|
|
140
|
+
// @ts-ignore
|
|
141
|
+
this.connection._rpcEndpoint,
|
|
142
|
+
this.connection.commitment
|
|
143
|
+
);
|
|
144
|
+
}
|
|
128
145
|
}
|
|
129
146
|
}
|
|
130
147
|
|
|
@@ -166,6 +183,7 @@ export class BulkAccountLoader {
|
|
|
166
183
|
buffer: newBuffer,
|
|
167
184
|
});
|
|
168
185
|
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
186
|
+
this.lastUpdate = Date.now();
|
|
169
187
|
continue;
|
|
170
188
|
}
|
|
171
189
|
|
|
@@ -180,6 +198,7 @@ export class BulkAccountLoader {
|
|
|
180
198
|
buffer: newBuffer,
|
|
181
199
|
});
|
|
182
200
|
this.handleAccountCallbacks(accountToLoad, newBuffer);
|
|
201
|
+
this.lastUpdate = Date.now();
|
|
183
202
|
}
|
|
184
203
|
}
|
|
185
204
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bulkPollingUserSubscribe = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @param users
|
|
6
|
+
* @param accountLoader
|
|
7
|
+
*/
|
|
8
|
+
async function bulkPollingUserSubscribe(users, accountLoader) {
|
|
9
|
+
if (users.length === 0) {
|
|
10
|
+
await accountLoader.load();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
// Fetch all the accounts first
|
|
14
|
+
const program = users[0].clearingHouse.program;
|
|
15
|
+
let userProgramAccounts;
|
|
16
|
+
let orderProgramAccounts;
|
|
17
|
+
await Promise.all([
|
|
18
|
+
(async () => {
|
|
19
|
+
userProgramAccounts = await program.account.user.all();
|
|
20
|
+
})(),
|
|
21
|
+
(async () => {
|
|
22
|
+
orderProgramAccounts = await program.account.userOrders.all();
|
|
23
|
+
})(),
|
|
24
|
+
]);
|
|
25
|
+
// Create a map of the authority to keys
|
|
26
|
+
const authorityToKeys = new Map();
|
|
27
|
+
const userToAuthority = new Map();
|
|
28
|
+
for (const userProgramAccount of userProgramAccounts) {
|
|
29
|
+
const userAccountPublicKey = userProgramAccount.publicKey;
|
|
30
|
+
const userAccount = userProgramAccount.account;
|
|
31
|
+
authorityToKeys.set(userAccount.authority.toString(), {
|
|
32
|
+
user: userAccountPublicKey,
|
|
33
|
+
userPositions: userAccount.positions,
|
|
34
|
+
userOrders: undefined,
|
|
35
|
+
});
|
|
36
|
+
userToAuthority.set(userAccountPublicKey.toString(), userAccount.authority.toString());
|
|
37
|
+
}
|
|
38
|
+
for (const orderProgramAccount of orderProgramAccounts) {
|
|
39
|
+
const userOrderAccountPublicKey = orderProgramAccount.publicKey;
|
|
40
|
+
const userOrderAccount = orderProgramAccount.account;
|
|
41
|
+
const authority = userToAuthority.get(userOrderAccount.user.toString());
|
|
42
|
+
const userPublicKeys = authorityToKeys.get(authority);
|
|
43
|
+
userPublicKeys.userOrders = userOrderAccountPublicKey;
|
|
44
|
+
}
|
|
45
|
+
await Promise.all(users.map((user) => {
|
|
46
|
+
// Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
|
|
47
|
+
const userPublicKeys = authorityToKeys.get(user.authority.toString());
|
|
48
|
+
return user.accountSubscriber.addToAccountLoader(userPublicKeys);
|
|
49
|
+
}));
|
|
50
|
+
await accountLoader.load();
|
|
51
|
+
await Promise.all(users.map(async (user) => {
|
|
52
|
+
return user.subscribe();
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
exports.bulkPollingUserSubscribe = bulkPollingUserSubscribe;
|
|
56
|
+
//# sourceMappingURL=bulkUserSubscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkUserSubscription.js","sourceRoot":"","sources":["bulkUserSubscription.ts"],"names":[],"mappings":";;;AAOA;;;GAGG;AACI,KAAK,UAAU,wBAAwB,CAC7C,KAA0B,EAC1B,aAAgC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO;KACP;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC;IAC/C,IAAI,mBAAqC,CAAC;IAC1C,IAAI,oBAAsC,CAAC;IAC3C,MAAM,OAAO,CAAC,GAAG,CAAC;QACjB,CAAC,KAAK,IAAI,EAAE;YACX,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACxD,CAAC,CAAC,EAAE;QACJ,CAAC,KAAK,IAAI,EAAE;YACX,oBAAoB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAC/D,CAAC,CAAC,EAAE;KACJ,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1D,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,kBAAkB,IAAI,mBAAmB,EAAE;QACrD,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,SAAS,CAAC;QAC1D,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAsB,CAAC;QAE9D,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE;YACrD,IAAI,EAAE,oBAAoB;YAC1B,aAAa,EAAE,WAAW,CAAC,SAAS;YACpC,UAAU,EAAE,SAAS;SACrB,CAAC,CAAC;QAEH,eAAe,CAAC,GAAG,CAClB,oBAAoB,CAAC,QAAQ,EAAE,EAC/B,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,CAChC,CAAC;KACF;IACD,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE;QACvD,MAAM,yBAAyB,GAAG,mBAAmB,CAAC,SAAS,CAAC;QAChE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAA4B,CAAC;QAE1E,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtD,cAAc,CAAC,UAAU,GAAG,yBAAyB,CAAC;KACtD;IAED,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClB,0FAA0F;QAC1F,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtE,OACC,IAAI,CAAC,iBACL,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC,CAAC,CACF,CAAC;IAEF,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAE3B,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACxB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC,CAAC,CACF,CAAC;AACH,CAAC;AAlED,4DAkEC"}
|