@drift-labs/sdk 0.1.36-master.3 → 0.1.36-master.6
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 +4 -0
- package/lib/admin.js +1 -1
- package/lib/clearingHouse.d.ts +6 -4
- package/lib/clearingHouse.js +46 -8
- package/lib/examples/makeTradeExample.js +1 -1
- package/lib/factory/clearingHouse.js +4 -4
- package/lib/idl/clearing_house.json +72 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +26 -0
- package/lib/math/trade.d.ts +10 -6
- package/lib/math/trade.js +68 -13
- package/lib/mockUSDCFaucet.d.ts +2 -2
- package/lib/mockUSDCFaucet.js +3 -3
- package/lib/oracles/pythClient.js +1 -0
- package/lib/oracles/switchboardClient.js +4 -1
- package/lib/oracles/types.d.ts +1 -0
- package/lib/tx/defaultTxSender.d.ts +3 -3
- package/lib/tx/defaultTxSender.js +1 -1
- package/lib/tx/retryTxSender.d.ts +3 -3
- package/package.json +2 -2
- package/src/accounts/bulkAccountLoader.ts +5 -0
- package/src/accounts/webSocketAccountSubscriber.ts +3 -3
- package/src/admin.ts +2 -2
- package/src/clearingHouse.ts +81 -10
- package/src/examples/makeTradeExample.ts +6 -2
- package/src/factory/clearingHouse.ts +13 -5
- package/src/idl/clearing_house.json +72 -1
- package/src/index.ts +1 -0
- package/src/math/oracles.ts +36 -0
- package/src/math/trade.ts +84 -16
- package/src/mockUSDCFaucet.ts +5 -5
- package/src/oracles/pythClient.ts +1 -0
- package/src/oracles/switchboardClient.ts +7 -2
- package/src/oracles/types.ts +1 -0
- package/src/tx/defaultTxSender.ts +4 -4
- package/src/tx/retryTxSender.ts +3 -3
|
@@ -16,6 +16,7 @@ export declare class BulkAccountLoader {
|
|
|
16
16
|
loadPromise?: Promise<void>;
|
|
17
17
|
loadPromiseResolver: () => void;
|
|
18
18
|
lastTimeLoadingPromiseCleared: number;
|
|
19
|
+
mostRecentSlot: number;
|
|
19
20
|
constructor(connection: Connection, commitment: Commitment, pollingFrequency: number);
|
|
20
21
|
addAccount(publicKey: PublicKey, callback: (buffer: Buffer) => void): string;
|
|
21
22
|
removeAccount(publicKey: PublicKey, callbackId: string): void;
|
|
@@ -20,6 +20,7 @@ class BulkAccountLoader {
|
|
|
20
20
|
this.accountData = new Map();
|
|
21
21
|
this.errorCallbacks = new Map();
|
|
22
22
|
this.lastTimeLoadingPromiseCleared = Date.now();
|
|
23
|
+
this.mostRecentSlot = 0;
|
|
23
24
|
this.connection = connection;
|
|
24
25
|
this.commitment = commitment;
|
|
25
26
|
this.pollingFrequency = pollingFrequency;
|
|
@@ -127,6 +128,9 @@ class BulkAccountLoader {
|
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
130
|
const newSlot = rpcResponse.result.context.slot;
|
|
131
|
+
if (newSlot > this.mostRecentSlot) {
|
|
132
|
+
this.mostRecentSlot = newSlot;
|
|
133
|
+
}
|
|
130
134
|
for (const i in accountsToLoad) {
|
|
131
135
|
const accountToLoad = accountsToLoad[i];
|
|
132
136
|
const key = accountToLoad.publicKey.toString();
|
package/lib/admin.js
CHANGED
|
@@ -45,7 +45,7 @@ const trade_1 = require("./math/trade");
|
|
|
45
45
|
const amm_1 = require("./math/amm");
|
|
46
46
|
const clearingHouse_2 = require("./factory/clearingHouse");
|
|
47
47
|
class Admin extends clearingHouse_1.ClearingHouse {
|
|
48
|
-
static from(connection, wallet, clearingHouseProgramId, opts = anchor_1.
|
|
48
|
+
static from(connection, wallet, clearingHouseProgramId, opts = anchor_1.AnchorProvider.defaultOptions()) {
|
|
49
49
|
const config = (0, clearingHouse_2.getWebSocketClearingHouseConfig)(connection, wallet, clearingHouseProgramId, opts);
|
|
50
50
|
return (0, clearingHouse_2.getAdmin)(config);
|
|
51
51
|
}
|
package/lib/clearingHouse.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="bn.js" />
|
|
3
|
-
import { BN, Program
|
|
3
|
+
import { AnchorProvider, BN, Program } from '@project-serum/anchor';
|
|
4
4
|
import { MarketsAccount, StateAccount, DepositHistoryAccount, FundingPaymentHistoryAccount, FundingRateHistoryAccount, IWallet, LiquidationHistoryAccount, PositionDirection, TradeHistoryAccount, UserAccount, Market, OrderHistoryAccount, OrderStateAccount, OrderParams, Order, ExtendedCurveHistoryAccount, UserPositionsAccount } from './types';
|
|
5
5
|
import { Connection, PublicKey, TransactionSignature, Keypair, ConfirmOptions, TransactionInstruction } from '@solana/web3.js';
|
|
6
6
|
import { MockUSDCFaucet } from './mockUSDCFaucet';
|
|
@@ -19,7 +19,7 @@ export declare class ClearingHouse {
|
|
|
19
19
|
connection: Connection;
|
|
20
20
|
wallet: IWallet;
|
|
21
21
|
program: Program;
|
|
22
|
-
provider:
|
|
22
|
+
provider: AnchorProvider;
|
|
23
23
|
opts?: ConfirmOptions;
|
|
24
24
|
accountSubscriber: ClearingHouseAccountSubscriber;
|
|
25
25
|
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
@@ -126,8 +126,10 @@ export declare class ClearingHouse {
|
|
|
126
126
|
getCancelOrderIx(orderId: BN, oracle?: PublicKey): Promise<TransactionInstruction>;
|
|
127
127
|
cancelOrderByUserId(userOrderId: number, oracle?: PublicKey): Promise<TransactionSignature>;
|
|
128
128
|
getCancelOrderByUserIdIx(userOrderId: number, oracle?: PublicKey): Promise<TransactionInstruction>;
|
|
129
|
-
cancelAllOrders(oracles?: PublicKey[]): Promise<TransactionSignature>;
|
|
130
|
-
getCancelAllOrdersIx(oracles: PublicKey[]): Promise<TransactionInstruction>;
|
|
129
|
+
cancelAllOrders(oracles?: PublicKey[], bestEffort?: boolean): Promise<TransactionSignature>;
|
|
130
|
+
getCancelAllOrdersIx(oracles: PublicKey[], bestEffort?: boolean): Promise<TransactionInstruction>;
|
|
131
|
+
cancelOrdersByMarketAndSide(oracles?: PublicKey[], bestEffort?: boolean, marketIndexOnly?: BN, directionOnly?: PositionDirection): Promise<TransactionSignature>;
|
|
132
|
+
getCancelOrdersByMarketAndSideIx(oracles: PublicKey[], bestEffort?: boolean, marketIndexOnly?: BN, directionOnly?: PositionDirection): Promise<TransactionInstruction>;
|
|
131
133
|
fillOrder(userAccountPublicKey: PublicKey, userOrdersAccountPublicKey: PublicKey, order: Order): Promise<TransactionSignature>;
|
|
132
134
|
getFillOrderIx(userAccountPublicKey: PublicKey, userOrdersAccountPublicKey: PublicKey, order: Order): Promise<TransactionInstruction>;
|
|
133
135
|
initializeUserOrdersThenPlaceAndFillOrder(orderParams: OrderParams, discountToken?: PublicKey, referrer?: PublicKey): Promise<TransactionSignature>;
|
package/lib/clearingHouse.js
CHANGED
|
@@ -77,7 +77,7 @@ class ClearingHouse {
|
|
|
77
77
|
* @param opts
|
|
78
78
|
* @returns
|
|
79
79
|
*/
|
|
80
|
-
static from(connection, wallet, clearingHouseProgramId, opts = anchor_1.
|
|
80
|
+
static from(connection, wallet, clearingHouseProgramId, opts = anchor_1.AnchorProvider.defaultOptions()) {
|
|
81
81
|
const config = (0, clearingHouse_1.getWebSocketClearingHouseConfig)(connection, wallet, clearingHouseProgramId, opts);
|
|
82
82
|
return (0, clearingHouse_1.getClearingHouse)(config);
|
|
83
83
|
}
|
|
@@ -185,7 +185,7 @@ class ClearingHouse {
|
|
|
185
185
|
* @param newWallet
|
|
186
186
|
*/
|
|
187
187
|
updateWallet(newWallet) {
|
|
188
|
-
const newProvider = new anchor_1.
|
|
188
|
+
const newProvider = new anchor_1.AnchorProvider(this.connection, newWallet, this.opts);
|
|
189
189
|
const newProgram = new anchor_1.Program(clearing_house_json_1.default, this.program.programId, newProvider);
|
|
190
190
|
// Update provider for txSender with new wallet details
|
|
191
191
|
this.txSender.provider = newProvider;
|
|
@@ -352,7 +352,7 @@ class ClearingHouse {
|
|
|
352
352
|
.add(initializeUserAccountIx)
|
|
353
353
|
.add(initializeUserOrdersAccountIx)
|
|
354
354
|
.add(depositCollateralIx);
|
|
355
|
-
const txSig = yield this.
|
|
355
|
+
const txSig = yield this.txSender.send(tx, [userPositionsAccount]);
|
|
356
356
|
return [txSig, userAccountPublicKey];
|
|
357
357
|
});
|
|
358
358
|
}
|
|
@@ -367,7 +367,9 @@ class ClearingHouse {
|
|
|
367
367
|
.add(initializeUserAccountIx)
|
|
368
368
|
.add(initializeUserOrdersAccountIx)
|
|
369
369
|
.add(depositCollateralIx);
|
|
370
|
-
const txSig = yield this.program.provider.
|
|
370
|
+
const txSig = yield this.program.provider.sendAndConfirm(tx, [
|
|
371
|
+
userPositionsAccount,
|
|
372
|
+
]);
|
|
371
373
|
return [txSig, userAccountPublicKey];
|
|
372
374
|
});
|
|
373
375
|
}
|
|
@@ -620,12 +622,48 @@ class ClearingHouse {
|
|
|
620
622
|
});
|
|
621
623
|
});
|
|
622
624
|
}
|
|
623
|
-
cancelAllOrders(oracles) {
|
|
625
|
+
cancelAllOrders(oracles, bestEffort) {
|
|
626
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
627
|
+
return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelAllOrdersIx(oracles, bestEffort)), [], this.opts);
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
getCancelAllOrdersIx(oracles, bestEffort) {
|
|
631
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
632
|
+
const userAccountPublicKey = yield this.getUserAccountPublicKey();
|
|
633
|
+
const userAccount = yield this.getUserAccount();
|
|
634
|
+
const state = this.getStateAccount();
|
|
635
|
+
const orderState = this.getOrderStateAccount();
|
|
636
|
+
const remainingAccounts = [];
|
|
637
|
+
for (const oracle of oracles) {
|
|
638
|
+
remainingAccounts.push({
|
|
639
|
+
pubkey: oracle,
|
|
640
|
+
isWritable: false,
|
|
641
|
+
isSigner: false,
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
return yield this.program.instruction.cancelAllOrders(bestEffort, {
|
|
645
|
+
accounts: {
|
|
646
|
+
state: yield this.getStatePublicKey(),
|
|
647
|
+
user: userAccountPublicKey,
|
|
648
|
+
authority: this.wallet.publicKey,
|
|
649
|
+
markets: state.markets,
|
|
650
|
+
userOrders: yield this.getUserOrdersAccountPublicKey(),
|
|
651
|
+
userPositions: userAccount.positions,
|
|
652
|
+
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
653
|
+
fundingRateHistory: state.fundingRateHistory,
|
|
654
|
+
orderState: yield this.getOrderStatePublicKey(),
|
|
655
|
+
orderHistory: orderState.orderHistory,
|
|
656
|
+
},
|
|
657
|
+
remainingAccounts,
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
cancelOrdersByMarketAndSide(oracles, bestEffort, marketIndexOnly, directionOnly) {
|
|
624
662
|
return __awaiter(this, void 0, void 0, function* () {
|
|
625
|
-
return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.
|
|
663
|
+
return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelOrdersByMarketAndSideIx(oracles, bestEffort, marketIndexOnly, directionOnly)), [], this.opts);
|
|
626
664
|
});
|
|
627
665
|
}
|
|
628
|
-
|
|
666
|
+
getCancelOrdersByMarketAndSideIx(oracles, bestEffort, marketIndexOnly, directionOnly) {
|
|
629
667
|
return __awaiter(this, void 0, void 0, function* () {
|
|
630
668
|
const userAccountPublicKey = yield this.getUserAccountPublicKey();
|
|
631
669
|
const userAccount = yield this.getUserAccount();
|
|
@@ -639,7 +677,7 @@ class ClearingHouse {
|
|
|
639
677
|
isSigner: false,
|
|
640
678
|
});
|
|
641
679
|
}
|
|
642
|
-
return yield this.program.instruction.
|
|
680
|
+
return yield this.program.instruction.cancelOrdersByMarketAndSide(bestEffort, marketIndexOnly, directionOnly, {
|
|
643
681
|
accounts: {
|
|
644
682
|
state: yield this.getStatePublicKey(),
|
|
645
683
|
user: userAccountPublicKey,
|
|
@@ -30,7 +30,7 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
30
30
|
const rpcAddress = process.env.RPC_ADDRESS; // can use: https://api.devnet.solana.com for devnet; https://api.mainnet-beta.solana.com for mainnet;
|
|
31
31
|
const connection = new web3_js_1.Connection(rpcAddress);
|
|
32
32
|
// Set up the Provider
|
|
33
|
-
const provider = new anchor_1.
|
|
33
|
+
const provider = new anchor_1.AnchorProvider(connection, wallet, anchor_1.AnchorProvider.defaultOptions());
|
|
34
34
|
// Check SOL Balance
|
|
35
35
|
const lamportsBalance = yield connection.getBalance(wallet.publicKey);
|
|
36
36
|
console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
|
|
@@ -12,7 +12,7 @@ const defaultTxSender_1 = require("../tx/defaultTxSender");
|
|
|
12
12
|
const pollingClearingHouseAccountSubscriber_1 = require("../accounts/pollingClearingHouseAccountSubscriber");
|
|
13
13
|
const admin_1 = require("../admin");
|
|
14
14
|
const retryTxSender_1 = require("../tx/retryTxSender");
|
|
15
|
-
function getWebSocketClearingHouseConfig(connection, wallet, programID, opts = anchor_1.
|
|
15
|
+
function getWebSocketClearingHouseConfig(connection, wallet, programID, opts = anchor_1.AnchorProvider.defaultOptions(), txSenderConfig) {
|
|
16
16
|
return {
|
|
17
17
|
type: 'websocket',
|
|
18
18
|
connection,
|
|
@@ -23,7 +23,7 @@ function getWebSocketClearingHouseConfig(connection, wallet, programID, opts = a
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
exports.getWebSocketClearingHouseConfig = getWebSocketClearingHouseConfig;
|
|
26
|
-
function getPollingClearingHouseConfig(connection, wallet, programID, accountLoader, opts = anchor_1.
|
|
26
|
+
function getPollingClearingHouseConfig(connection, wallet, programID, accountLoader, opts = anchor_1.AnchorProvider.defaultOptions(), txSenderConfig) {
|
|
27
27
|
return {
|
|
28
28
|
type: 'polling',
|
|
29
29
|
connection,
|
|
@@ -37,7 +37,7 @@ function getPollingClearingHouseConfig(connection, wallet, programID, accountLoa
|
|
|
37
37
|
exports.getPollingClearingHouseConfig = getPollingClearingHouseConfig;
|
|
38
38
|
function getClearingHouse(config) {
|
|
39
39
|
var _a;
|
|
40
|
-
const provider = new anchor_1.
|
|
40
|
+
const provider = new anchor_1.AnchorProvider(config.connection, config.wallet, config.opts);
|
|
41
41
|
const program = new anchor_1.Program(clearing_house_json_1.default, config.programID, provider);
|
|
42
42
|
let accountSubscriber;
|
|
43
43
|
if (config.type === 'websocket') {
|
|
@@ -59,7 +59,7 @@ function getClearingHouse(config) {
|
|
|
59
59
|
exports.getClearingHouse = getClearingHouse;
|
|
60
60
|
function getAdmin(config) {
|
|
61
61
|
var _a;
|
|
62
|
-
const provider = new anchor_1.
|
|
62
|
+
const provider = new anchor_1.AnchorProvider(config.connection, config.wallet, config.opts);
|
|
63
63
|
const program = new anchor_1.Program(clearing_house_json_1.default, config.programID, provider);
|
|
64
64
|
let accountSubscriber;
|
|
65
65
|
if (config.type === 'websocket') {
|
|
@@ -726,7 +726,78 @@
|
|
|
726
726
|
"isSigner": false
|
|
727
727
|
}
|
|
728
728
|
],
|
|
729
|
-
"args": [
|
|
729
|
+
"args": [
|
|
730
|
+
{
|
|
731
|
+
"name": "bestEffort",
|
|
732
|
+
"type": "bool"
|
|
733
|
+
}
|
|
734
|
+
]
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"name": "cancelOrdersByMarketAndSide",
|
|
738
|
+
"accounts": [
|
|
739
|
+
{
|
|
740
|
+
"name": "state",
|
|
741
|
+
"isMut": false,
|
|
742
|
+
"isSigner": false
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
"name": "orderState",
|
|
746
|
+
"isMut": false,
|
|
747
|
+
"isSigner": false
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
"name": "user",
|
|
751
|
+
"isMut": false,
|
|
752
|
+
"isSigner": false
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
"name": "authority",
|
|
756
|
+
"isMut": false,
|
|
757
|
+
"isSigner": true
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
"name": "markets",
|
|
761
|
+
"isMut": false,
|
|
762
|
+
"isSigner": false
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
"name": "userPositions",
|
|
766
|
+
"isMut": true,
|
|
767
|
+
"isSigner": false
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
"name": "userOrders",
|
|
771
|
+
"isMut": true,
|
|
772
|
+
"isSigner": false
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
"name": "fundingPaymentHistory",
|
|
776
|
+
"isMut": true,
|
|
777
|
+
"isSigner": false
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"name": "orderHistory",
|
|
781
|
+
"isMut": true,
|
|
782
|
+
"isSigner": false
|
|
783
|
+
}
|
|
784
|
+
],
|
|
785
|
+
"args": [
|
|
786
|
+
{
|
|
787
|
+
"name": "bestEffort",
|
|
788
|
+
"type": "bool"
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
"name": "marketIndexOnly",
|
|
792
|
+
"type": "u64"
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"name": "directionOnly",
|
|
796
|
+
"type": {
|
|
797
|
+
"defined": "PositionDirection"
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
]
|
|
730
801
|
},
|
|
731
802
|
{
|
|
732
803
|
"name": "expireOrders",
|
package/lib/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export * from './math/funding';
|
|
|
25
25
|
export * from './math/insuranceFund';
|
|
26
26
|
export * from './math/market';
|
|
27
27
|
export * from './math/position';
|
|
28
|
+
export * from './math/oracles';
|
|
28
29
|
export * from './math/amm';
|
|
29
30
|
export * from './math/trade';
|
|
30
31
|
export * from './math/orders';
|
package/lib/index.js
CHANGED
|
@@ -44,6 +44,7 @@ __exportStar(require("./math/funding"), exports);
|
|
|
44
44
|
__exportStar(require("./math/insuranceFund"), exports);
|
|
45
45
|
__exportStar(require("./math/market"), exports);
|
|
46
46
|
__exportStar(require("./math/position"), exports);
|
|
47
|
+
__exportStar(require("./math/oracles"), exports);
|
|
47
48
|
__exportStar(require("./math/amm"), exports);
|
|
48
49
|
__exportStar(require("./math/trade"), exports);
|
|
49
50
|
__exportStar(require("./math/orders"), exports);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isOracleValid = void 0;
|
|
4
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
|
|
7
|
+
const isOraclePriceNonPositive = oraclePriceData.price.lt(numericConstants_1.ZERO);
|
|
8
|
+
const isOraclePriceTooVolatile = oraclePriceData.price
|
|
9
|
+
.div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
|
|
10
|
+
.gt(oracleGuardRails.validity.tooVolatileRatio) ||
|
|
11
|
+
amm.lastOraclePriceTwap
|
|
12
|
+
.div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
|
|
13
|
+
.gt(oracleGuardRails.validity.tooVolatileRatio);
|
|
14
|
+
const isConfidenceTooLarge = oraclePriceData.price
|
|
15
|
+
.div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
|
|
16
|
+
.lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
|
|
17
|
+
const oracleIsStale = oraclePriceData.slot
|
|
18
|
+
.sub(new index_1.BN(slot))
|
|
19
|
+
.gt(oracleGuardRails.validity.slotsBeforeStale);
|
|
20
|
+
return !(!oraclePriceData.hasSufficientNumberOfDataPoints ||
|
|
21
|
+
oracleIsStale ||
|
|
22
|
+
isOraclePriceNonPositive ||
|
|
23
|
+
isOraclePriceTooVolatile ||
|
|
24
|
+
isConfidenceTooLarge);
|
|
25
|
+
}
|
|
26
|
+
exports.isOracleValid = isOracleValid;
|
package/lib/math/trade.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
|
|
|
8
8
|
* @param direction
|
|
9
9
|
* @param amount
|
|
10
10
|
* @param market
|
|
11
|
+
* @param inputAssetType which asset is being traded
|
|
12
|
+
* @param useSpread whether to consider spread with calculating slippage
|
|
11
13
|
* @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
|
|
12
14
|
*
|
|
13
15
|
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
|
|
@@ -18,7 +20,7 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
|
|
|
18
20
|
*
|
|
19
21
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
20
22
|
*/
|
|
21
|
-
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType): [BN, BN, BN, BN];
|
|
23
|
+
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType, useSpread?: boolean): [BN, BN, BN, BN];
|
|
22
24
|
/**
|
|
23
25
|
* Calculates acquired amounts for trade executed
|
|
24
26
|
* @param direction
|
|
@@ -27,7 +29,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
|
|
|
27
29
|
* @param inputAssetType
|
|
28
30
|
* @param useSpread
|
|
29
31
|
* @return
|
|
30
|
-
* | 'acquiredBase' => positive/negative change in user's base : BN
|
|
32
|
+
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
31
33
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
32
34
|
*/
|
|
33
35
|
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType, useSpread?: boolean): [BN, BN];
|
|
@@ -37,13 +39,15 @@ export declare function calculateTradeAcquiredAmounts(direction: PositionDirecti
|
|
|
37
39
|
* @param market
|
|
38
40
|
* @param targetPrice
|
|
39
41
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
42
|
+
* @param outputAssetType which asset to trade.
|
|
43
|
+
* @param useSpread whether or not to consider the spread when calculating the trade size
|
|
40
44
|
* @returns trade direction/size in order to push price to a targetPrice,
|
|
41
45
|
*
|
|
42
46
|
* [
|
|
43
|
-
* direction => direction of trade required,
|
|
47
|
+
* direction => direction of trade required, PositionDirection
|
|
44
48
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
45
|
-
* entryPrice => the entry price for the trade,
|
|
46
|
-
* targetPrice => the target price
|
|
49
|
+
* entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
|
|
50
|
+
* targetPrice => the target price MARK_PRICE_PRECISION
|
|
47
51
|
* ]
|
|
48
52
|
*/
|
|
49
|
-
export declare function calculateTargetPriceTrade(market: Market, targetPrice: BN, pct?: BN, outputAssetType?: AssetType): [PositionDirection, BN, BN, BN];
|
|
53
|
+
export declare function calculateTargetPriceTrade(market: Market, targetPrice: BN, pct?: BN, outputAssetType?: AssetType, useSpread?: boolean): [PositionDirection, BN, BN, BN];
|
package/lib/math/trade.js
CHANGED
|
@@ -8,12 +8,15 @@ const numericConstants_1 = require("../constants/numericConstants");
|
|
|
8
8
|
const market_1 = require("./market");
|
|
9
9
|
const amm_1 = require("./amm");
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
|
+
const types_2 = require("../types");
|
|
11
12
|
const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
12
13
|
/**
|
|
13
14
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
14
15
|
* @param direction
|
|
15
16
|
* @param amount
|
|
16
17
|
* @param market
|
|
18
|
+
* @param inputAssetType which asset is being traded
|
|
19
|
+
* @param useSpread whether to consider spread with calculating slippage
|
|
17
20
|
* @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
|
|
18
21
|
*
|
|
19
22
|
* 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
|
|
@@ -24,14 +27,38 @@ const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
|
24
27
|
*
|
|
25
28
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
26
29
|
*/
|
|
27
|
-
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote') {
|
|
28
|
-
|
|
30
|
+
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
|
|
31
|
+
let oldPrice;
|
|
32
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
33
|
+
if ((0, types_2.isVariant)(direction, 'long')) {
|
|
34
|
+
oldPrice = (0, market_1.calculateAskPrice)(market);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
oldPrice = (0, market_1.calculateBidPrice)(market);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
oldPrice = (0, market_1.calculateMarkPrice)(market);
|
|
42
|
+
}
|
|
29
43
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
30
44
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
31
45
|
}
|
|
32
|
-
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType);
|
|
46
|
+
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, useSpread);
|
|
33
47
|
const entryPrice = (0, amm_1.calculatePrice)(acquiredBase, acquiredQuote, market.amm.pegMultiplier).mul(new anchor_1.BN(-1));
|
|
34
|
-
|
|
48
|
+
let amm;
|
|
49
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
50
|
+
const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
|
|
51
|
+
amm = {
|
|
52
|
+
baseAssetReserve,
|
|
53
|
+
quoteAssetReserve,
|
|
54
|
+
sqrtK: market.amm.sqrtK,
|
|
55
|
+
pegMultiplier: market.amm.pegMultiplier,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
amm = market.amm;
|
|
60
|
+
}
|
|
61
|
+
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBase), amm.quoteAssetReserve.sub(acquiredQuote), amm.pegMultiplier);
|
|
35
62
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
36
63
|
(0, assert_1.assert)(newPrice.lt(oldPrice));
|
|
37
64
|
}
|
|
@@ -59,7 +86,7 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
|
|
|
59
86
|
* @param inputAssetType
|
|
60
87
|
* @param useSpread
|
|
61
88
|
* @return
|
|
62
|
-
* | 'acquiredBase' => positive/negative change in user's base : BN
|
|
89
|
+
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
63
90
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
64
91
|
*/
|
|
65
92
|
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', useSpread = true) {
|
|
@@ -92,35 +119,50 @@ exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
|
92
119
|
* @param market
|
|
93
120
|
* @param targetPrice
|
|
94
121
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
122
|
+
* @param outputAssetType which asset to trade.
|
|
123
|
+
* @param useSpread whether or not to consider the spread when calculating the trade size
|
|
95
124
|
* @returns trade direction/size in order to push price to a targetPrice,
|
|
96
125
|
*
|
|
97
126
|
* [
|
|
98
|
-
* direction => direction of trade required,
|
|
127
|
+
* direction => direction of trade required, PositionDirection
|
|
99
128
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
100
|
-
* entryPrice => the entry price for the trade,
|
|
101
|
-
* targetPrice => the target price
|
|
129
|
+
* entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
|
|
130
|
+
* targetPrice => the target price MARK_PRICE_PRECISION
|
|
102
131
|
* ]
|
|
103
132
|
*/
|
|
104
|
-
function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote') {
|
|
133
|
+
function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote', useSpread = true) {
|
|
105
134
|
(0, assert_1.assert)(market.amm.baseAssetReserve.gt(numericConstants_1.ZERO));
|
|
106
135
|
(0, assert_1.assert)(targetPrice.gt(numericConstants_1.ZERO));
|
|
107
136
|
(0, assert_1.assert)(pct.lte(MAXPCT) && pct.gt(numericConstants_1.ZERO));
|
|
108
137
|
const markPriceBefore = (0, market_1.calculateMarkPrice)(market);
|
|
138
|
+
const bidPriceBefore = (0, market_1.calculateBidPrice)(market);
|
|
139
|
+
const askPriceBefore = (0, market_1.calculateAskPrice)(market);
|
|
140
|
+
let direction;
|
|
109
141
|
if (targetPrice.gt(markPriceBefore)) {
|
|
110
142
|
const priceGap = targetPrice.sub(markPriceBefore);
|
|
111
143
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
112
144
|
targetPrice = markPriceBefore.add(priceGapScaled);
|
|
145
|
+
direction = types_1.PositionDirection.LONG;
|
|
113
146
|
}
|
|
114
147
|
else {
|
|
115
148
|
const priceGap = markPriceBefore.sub(targetPrice);
|
|
116
149
|
const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
|
|
117
150
|
targetPrice = markPriceBefore.sub(priceGapScaled);
|
|
151
|
+
direction = types_1.PositionDirection.SHORT;
|
|
118
152
|
}
|
|
119
|
-
let direction;
|
|
120
153
|
let tradeSize;
|
|
121
154
|
let baseSize;
|
|
122
|
-
|
|
123
|
-
|
|
155
|
+
let baseAssetReserveBefore;
|
|
156
|
+
let quoteAssetReserveBefore;
|
|
157
|
+
if (useSpread && market.amm.baseSpread > 0) {
|
|
158
|
+
const { baseAssetReserve, quoteAssetReserve } = (0, amm_1.calculateSpreadReserves)(market.amm, direction);
|
|
159
|
+
baseAssetReserveBefore = baseAssetReserve;
|
|
160
|
+
quoteAssetReserveBefore = quoteAssetReserve;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
baseAssetReserveBefore = market.amm.baseAssetReserve;
|
|
164
|
+
quoteAssetReserveBefore = market.amm.quoteAssetReserve;
|
|
165
|
+
}
|
|
124
166
|
const peg = market.amm.pegMultiplier;
|
|
125
167
|
const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
126
168
|
const k = invariant.mul(numericConstants_1.MARK_PRICE_PRECISION);
|
|
@@ -128,7 +170,20 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
|
|
|
128
170
|
let quoteAssetReserveAfter;
|
|
129
171
|
const biasModifier = new anchor_1.BN(1);
|
|
130
172
|
let markPriceAfter;
|
|
131
|
-
if (
|
|
173
|
+
if (useSpread &&
|
|
174
|
+
targetPrice.lt(askPriceBefore) &&
|
|
175
|
+
targetPrice.gt(bidPriceBefore)) {
|
|
176
|
+
// no trade, market is at target
|
|
177
|
+
if (markPriceBefore.gt(targetPrice)) {
|
|
178
|
+
direction = types_1.PositionDirection.SHORT;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
direction = types_1.PositionDirection.LONG;
|
|
182
|
+
}
|
|
183
|
+
tradeSize = numericConstants_1.ZERO;
|
|
184
|
+
return [direction, tradeSize, targetPrice, targetPrice];
|
|
185
|
+
}
|
|
186
|
+
else if (markPriceBefore.gt(targetPrice)) {
|
|
132
187
|
// overestimate y2
|
|
133
188
|
baseAssetReserveAfter = (0, utils_1.squareRootBN)(k.div(targetPrice).mul(peg).div(numericConstants_1.PEG_PRECISION).sub(biasModifier)).sub(new anchor_1.BN(1));
|
|
134
189
|
quoteAssetReserveAfter = k
|
package/lib/mockUSDCFaucet.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import * as anchor from '@project-serum/anchor';
|
|
3
|
-
import {
|
|
3
|
+
import { AnchorProvider, Program } from '@project-serum/anchor';
|
|
4
4
|
import { AccountInfo } from '@solana/spl-token';
|
|
5
5
|
import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
|
|
6
6
|
import { BN } from '.';
|
|
@@ -9,7 +9,7 @@ export declare class MockUSDCFaucet {
|
|
|
9
9
|
connection: Connection;
|
|
10
10
|
wallet: IWallet;
|
|
11
11
|
program: Program;
|
|
12
|
-
provider:
|
|
12
|
+
provider: AnchorProvider;
|
|
13
13
|
opts?: ConfirmOptions;
|
|
14
14
|
constructor(connection: Connection, wallet: IWallet, programId: PublicKey, opts?: ConfirmOptions);
|
|
15
15
|
getMockUSDCFaucetStatePublicKeyAndNonce(): Promise<[
|
package/lib/mockUSDCFaucet.js
CHANGED
|
@@ -45,8 +45,8 @@ class MockUSDCFaucet {
|
|
|
45
45
|
constructor(connection, wallet, programId, opts) {
|
|
46
46
|
this.connection = connection;
|
|
47
47
|
this.wallet = wallet;
|
|
48
|
-
this.opts = opts || anchor_1.
|
|
49
|
-
const provider = new anchor_1.
|
|
48
|
+
this.opts = opts || anchor_1.AnchorProvider.defaultOptions();
|
|
49
|
+
const provider = new anchor_1.AnchorProvider(connection, wallet, this.opts);
|
|
50
50
|
this.provider = provider;
|
|
51
51
|
this.program = new anchor_1.Program(mock_usdc_faucet_json_1.default, programId, provider);
|
|
52
52
|
}
|
|
@@ -117,7 +117,7 @@ class MockUSDCFaucet {
|
|
|
117
117
|
return __awaiter(this, void 0, void 0, function* () {
|
|
118
118
|
const [associatedTokenPublicKey, createAssociatedAccountIx, mintToTx] = yield this.createAssociatedTokenAccountAndMintToInstructions(userPublicKey, amount);
|
|
119
119
|
const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToTx);
|
|
120
|
-
const txSig = yield this.program.provider.
|
|
120
|
+
const txSig = yield this.program.provider.sendAndConfirm(tx, [], this.opts);
|
|
121
121
|
return [associatedTokenPublicKey, txSig];
|
|
122
122
|
});
|
|
123
123
|
}
|
|
@@ -38,6 +38,7 @@ class PythClient {
|
|
|
38
38
|
confidence: convertPythPrice(priceData.confidence, priceData.exponent),
|
|
39
39
|
twap: convertPythPrice(priceData.twap.value, priceData.exponent),
|
|
40
40
|
twapConfidence: convertPythPrice(priceData.twac.value, priceData.exponent),
|
|
41
|
+
hasSufficientNumberOfDataPoints: true,
|
|
41
42
|
};
|
|
42
43
|
});
|
|
43
44
|
}
|
|
@@ -39,11 +39,14 @@ class SwitchboardClient {
|
|
|
39
39
|
const price = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound.result);
|
|
40
40
|
const confidence = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound
|
|
41
41
|
.stdDeviation);
|
|
42
|
+
const hasSufficientNumberOfDataPoints = aggregatorAccountData.latestConfirmedRound.numSuccess >=
|
|
43
|
+
aggregatorAccountData.minOracleResults;
|
|
42
44
|
const slot = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
|
|
43
45
|
return {
|
|
44
46
|
price,
|
|
45
47
|
slot,
|
|
46
48
|
confidence,
|
|
49
|
+
hasSufficientNumberOfDataPoints,
|
|
47
50
|
};
|
|
48
51
|
});
|
|
49
52
|
}
|
|
@@ -64,7 +67,7 @@ function getSwitchboardProgram(env, connection) {
|
|
|
64
67
|
const DEFAULT_KEYPAIR = web3_js_1.Keypair.fromSeed(new Uint8Array(32).fill(1));
|
|
65
68
|
const programId = (0, switchboard_v2_1.getSwitchboardPid)(env);
|
|
66
69
|
const wallet = new wallet_1.Wallet(DEFAULT_KEYPAIR);
|
|
67
|
-
const provider = new anchor_1.
|
|
70
|
+
const provider = new anchor_1.AnchorProvider(connection, wallet, {});
|
|
68
71
|
return new anchor_1.Program(switchboard_v2_json_1.default, programId, provider);
|
|
69
72
|
});
|
|
70
73
|
}
|
package/lib/oracles/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TxSender } from './types';
|
|
2
2
|
import { ConfirmOptions, Signer, Transaction, TransactionSignature } from '@solana/web3.js';
|
|
3
|
-
import {
|
|
3
|
+
import { AnchorProvider } from '@project-serum/anchor';
|
|
4
4
|
export declare class DefaultTxSender implements TxSender {
|
|
5
|
-
provider:
|
|
6
|
-
constructor(provider:
|
|
5
|
+
provider: AnchorProvider;
|
|
6
|
+
constructor(provider: AnchorProvider);
|
|
7
7
|
send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<TransactionSignature>;
|
|
8
8
|
}
|
|
@@ -6,7 +6,7 @@ class DefaultTxSender {
|
|
|
6
6
|
this.provider = provider;
|
|
7
7
|
}
|
|
8
8
|
send(tx, additionalSigners, opts) {
|
|
9
|
-
return this.provider.
|
|
9
|
+
return this.provider.sendAndConfirm(tx, additionalSigners, opts);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
exports.DefaultTxSender = DefaultTxSender;
|