@drift-labs/sdk 0.2.0-master.11 → 0.2.0-master.12
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/clearingHouse.d.ts +7 -2
- package/lib/clearingHouse.js +157 -37
- package/lib/clearingHouseUser.d.ts +10 -15
- package/lib/clearingHouseUser.js +92 -74
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +4 -3
- package/lib/constants/numericConstants.d.ts +2 -0
- package/lib/constants/numericConstants.js +3 -1
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +2 -1
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +37 -11
- package/lib/idl/clearing_house.json +97 -19
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/bankBalance.d.ts +3 -1
- package/lib/math/bankBalance.js +54 -1
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +42 -12
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +2 -77
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/tokenFaucet.js +23 -12
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/types.d.ts +24 -3
- package/lib/types.js +6 -0
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +1 -1
- package/src/clearingHouse.ts +301 -47
- package/src/clearingHouseConfig.js +2 -0
- package/src/clearingHouseUser.ts +213 -104
- package/src/clearingHouseUserConfig.js +2 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +6 -3
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +3 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/types.ts +2 -0
- package/src/factory/bigNum.js +37 -11
- package/src/factory/bigNum.ts +43 -13
- package/src/idl/clearing_house.json +97 -19
- package/src/index.js +67 -98
- package/src/index.ts +1 -0
- package/src/math/bankBalance.ts +98 -1
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/position.ts +59 -9
- package/src/orders.ts +4 -157
- package/src/tokenFaucet.js +189 -0
- package/src/tokenFaucet.ts +38 -15
- package/src/tx/retryTxSender.ts +11 -3
- package/src/types.js +12 -1
- package/src/types.ts +25 -3
- package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +2 -0
- package/src/addresses/pda.js +0 -104
- package/src/math/bankBalance.js +0 -75
- package/src/math/market.js +0 -57
- package/src/math/orders.js +0 -110
- package/src/math/position.js +0 -140
- package/src/orders.js +0 -134
- package/src/tx/retryTxSender.js +0 -188
package/src/orders.ts
CHANGED
|
@@ -1,163 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isVariant,
|
|
3
|
-
MarketAccount,
|
|
4
|
-
Order,
|
|
5
|
-
PositionDirection,
|
|
6
|
-
UserAccount,
|
|
7
|
-
UserPosition,
|
|
8
|
-
} from './types';
|
|
1
|
+
import { isVariant, MarketAccount, Order, PositionDirection } from './types';
|
|
9
2
|
import { BN, standardizeBaseAssetAmount } from '.';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
13
|
-
PEG_PRECISION,
|
|
14
|
-
ZERO,
|
|
15
|
-
} from './constants/numericConstants';
|
|
3
|
+
import { ZERO } from './constants/numericConstants';
|
|
16
4
|
import { calculateMaxBaseAssetAmountToTrade } from './math/amm';
|
|
17
|
-
import {
|
|
18
|
-
findDirectionToClose,
|
|
19
|
-
positionCurrentDirection,
|
|
20
|
-
} from './math/position';
|
|
21
5
|
import { OraclePriceData } from '.';
|
|
22
6
|
|
|
23
|
-
export function calculateNewStateAfterOrder(
|
|
24
|
-
userAccount: UserAccount,
|
|
25
|
-
userPosition: UserPosition,
|
|
26
|
-
market: MarketAccount,
|
|
27
|
-
order: Order
|
|
28
|
-
): [UserAccount, UserPosition, MarketAccount] | null {
|
|
29
|
-
if (isVariant(order.status, 'init')) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const baseAssetAmountToTrade = calculateBaseAssetAmountMarketCanExecute(
|
|
34
|
-
market,
|
|
35
|
-
order
|
|
36
|
-
);
|
|
37
|
-
if (baseAssetAmountToTrade.lt(market.amm.baseAssetAmountStepSize)) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const userAccountAfter = Object.assign({}, userAccount);
|
|
42
|
-
const userPositionAfter = Object.assign({}, userPosition);
|
|
43
|
-
|
|
44
|
-
const currentPositionDirection = positionCurrentDirection(userPosition);
|
|
45
|
-
const increasePosition =
|
|
46
|
-
userPosition.baseAssetAmount.eq(ZERO) ||
|
|
47
|
-
isSameDirection(order.direction, currentPositionDirection);
|
|
48
|
-
|
|
49
|
-
if (increasePosition) {
|
|
50
|
-
const marketAfter = calculateNewMarketAfterTrade(
|
|
51
|
-
baseAssetAmountToTrade,
|
|
52
|
-
order.direction,
|
|
53
|
-
market
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const { quoteAssetAmountSwapped, baseAssetAmountSwapped } =
|
|
57
|
-
calculateAmountSwapped(market, marketAfter);
|
|
58
|
-
|
|
59
|
-
userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(
|
|
60
|
-
baseAssetAmountSwapped
|
|
61
|
-
);
|
|
62
|
-
userPositionAfter.quoteAssetAmount = userPositionAfter.quoteAssetAmount.add(
|
|
63
|
-
quoteAssetAmountSwapped
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
return [userAccountAfter, userPositionAfter, marketAfter];
|
|
67
|
-
} else {
|
|
68
|
-
const reversePosition = baseAssetAmountToTrade.gt(
|
|
69
|
-
userPosition.baseAssetAmount.abs()
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (reversePosition) {
|
|
73
|
-
const intermediateMarket = calculateNewMarketAfterTrade(
|
|
74
|
-
userPosition.baseAssetAmount,
|
|
75
|
-
findDirectionToClose(userPosition),
|
|
76
|
-
market
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const { quoteAssetAmountSwapped: baseAssetValue } =
|
|
80
|
-
calculateAmountSwapped(market, intermediateMarket);
|
|
81
|
-
|
|
82
|
-
let pnl;
|
|
83
|
-
if (isVariant(currentPositionDirection, 'long')) {
|
|
84
|
-
pnl = baseAssetValue.sub(userPosition.quoteAssetAmount);
|
|
85
|
-
} else {
|
|
86
|
-
pnl = userPosition.quoteAssetAmount.sub(baseAssetValue);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
|
|
90
|
-
|
|
91
|
-
const baseAssetAmountLeft = baseAssetAmountToTrade.sub(
|
|
92
|
-
userPosition.baseAssetAmount.abs()
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
const marketAfter = calculateNewMarketAfterTrade(
|
|
96
|
-
baseAssetAmountLeft,
|
|
97
|
-
order.direction,
|
|
98
|
-
intermediateMarket
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const { quoteAssetAmountSwapped, baseAssetAmountSwapped } =
|
|
102
|
-
calculateAmountSwapped(intermediateMarket, marketAfter);
|
|
103
|
-
|
|
104
|
-
userPositionAfter.quoteAssetAmount = quoteAssetAmountSwapped;
|
|
105
|
-
userPositionAfter.baseAssetAmount = baseAssetAmountSwapped;
|
|
106
|
-
|
|
107
|
-
return [userAccountAfter, userPositionAfter, marketAfter];
|
|
108
|
-
} else {
|
|
109
|
-
const marketAfter = calculateNewMarketAfterTrade(
|
|
110
|
-
baseAssetAmountToTrade,
|
|
111
|
-
order.direction,
|
|
112
|
-
market
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const {
|
|
116
|
-
quoteAssetAmountSwapped: baseAssetValue,
|
|
117
|
-
baseAssetAmountSwapped,
|
|
118
|
-
} = calculateAmountSwapped(market, marketAfter);
|
|
119
|
-
|
|
120
|
-
const costBasisRealized = userPosition.quoteAssetAmount
|
|
121
|
-
.mul(baseAssetAmountSwapped.abs())
|
|
122
|
-
.div(userPosition.baseAssetAmount.abs());
|
|
123
|
-
|
|
124
|
-
let pnl;
|
|
125
|
-
if (isVariant(currentPositionDirection, 'long')) {
|
|
126
|
-
pnl = baseAssetValue.sub(costBasisRealized);
|
|
127
|
-
} else {
|
|
128
|
-
pnl = costBasisRealized.sub(baseAssetValue);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
|
|
132
|
-
|
|
133
|
-
userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(
|
|
134
|
-
baseAssetAmountSwapped
|
|
135
|
-
);
|
|
136
|
-
userPositionAfter.quoteAssetAmount =
|
|
137
|
-
userPositionAfter.quoteAssetAmount.sub(costBasisRealized);
|
|
138
|
-
|
|
139
|
-
return [userAccountAfter, userPositionAfter, marketAfter];
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function calculateAmountSwapped(
|
|
145
|
-
marketBefore: MarketAccount,
|
|
146
|
-
marketAfter: MarketAccount
|
|
147
|
-
): { quoteAssetAmountSwapped: BN; baseAssetAmountSwapped: BN } {
|
|
148
|
-
return {
|
|
149
|
-
quoteAssetAmountSwapped: marketBefore.amm.quoteAssetReserve
|
|
150
|
-
.sub(marketAfter.amm.quoteAssetReserve)
|
|
151
|
-
.abs()
|
|
152
|
-
.mul(marketBefore.amm.pegMultiplier)
|
|
153
|
-
.div(PEG_PRECISION)
|
|
154
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO),
|
|
155
|
-
baseAssetAmountSwapped: marketBefore.amm.baseAssetReserve.sub(
|
|
156
|
-
marketAfter.amm.baseAssetReserve
|
|
157
|
-
),
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
7
|
export function calculateBaseAssetAmountMarketCanExecute(
|
|
162
8
|
market: MarketAccount,
|
|
163
9
|
order: Order,
|
|
@@ -192,7 +38,8 @@ export function calculateAmountToTradeForLimit(
|
|
|
192
38
|
const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
|
|
193
39
|
market.amm,
|
|
194
40
|
limitPrice,
|
|
195
|
-
order.direction
|
|
41
|
+
order.direction,
|
|
42
|
+
oraclePriceData
|
|
196
43
|
);
|
|
197
44
|
|
|
198
45
|
const baseAssetAmount = standardizeBaseAssetAmount(
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.TokenFaucet = void 0;
|
|
35
|
+
const anchor = __importStar(require("@project-serum/anchor"));
|
|
36
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
37
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
38
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
39
|
+
const token_faucet_json_1 = __importDefault(require("./idl/token_faucet.json"));
|
|
40
|
+
class TokenFaucet {
|
|
41
|
+
constructor(connection, wallet, programId, mint, opts) {
|
|
42
|
+
this.connection = connection;
|
|
43
|
+
this.wallet = wallet;
|
|
44
|
+
this.opts = opts || anchor_1.AnchorProvider.defaultOptions();
|
|
45
|
+
const provider = new anchor_1.AnchorProvider(connection, wallet, this.opts);
|
|
46
|
+
this.provider = provider;
|
|
47
|
+
this.program = new anchor_1.Program(token_faucet_json_1.default, programId, provider);
|
|
48
|
+
this.mint = mint;
|
|
49
|
+
}
|
|
50
|
+
getFaucetConfigPublicKeyAndNonce() {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
return anchor.web3.PublicKey.findProgramAddress([
|
|
53
|
+
Buffer.from(anchor.utils.bytes.utf8.encode('faucet_config')),
|
|
54
|
+
this.mint.toBuffer(),
|
|
55
|
+
], this.program.programId);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
getMintAuthority() {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
return (yield anchor.web3.PublicKey.findProgramAddress([
|
|
61
|
+
Buffer.from(anchor.utils.bytes.utf8.encode('mint_authority')),
|
|
62
|
+
this.mint.toBuffer(),
|
|
63
|
+
], this.program.programId))[0];
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
getFaucetConfigPublicKey() {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
return (yield this.getFaucetConfigPublicKeyAndNonce())[0];
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
initialize() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const [faucetConfigPublicKey] = yield this.getFaucetConfigPublicKeyAndNonce();
|
|
74
|
+
return yield this.program.rpc.initialize({
|
|
75
|
+
accounts: {
|
|
76
|
+
faucetConfig: faucetConfigPublicKey,
|
|
77
|
+
admin: this.wallet.publicKey,
|
|
78
|
+
mintAccount: this.mint,
|
|
79
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
80
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
81
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
fetchState() {
|
|
87
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
+
return yield this.program.account.faucetConfig.fetch(yield this.getFaucetConfigPublicKey());
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
mintToUserIx(userTokenAccount, amount) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
return this.program.instruction.mintToUser(amount, {
|
|
94
|
+
accounts: {
|
|
95
|
+
faucetConfig: yield this.getFaucetConfigPublicKey(),
|
|
96
|
+
mintAccount: this.mint,
|
|
97
|
+
userTokenAccount,
|
|
98
|
+
mintAuthority: yield this.getMintAuthority(),
|
|
99
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
mintToUser(userTokenAccount, amount) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
const mintIx = yield this.mintToUserIx(userTokenAccount, amount);
|
|
107
|
+
const tx = new web3_js_1.Transaction().add(mintIx);
|
|
108
|
+
const txSig = yield this.program.provider.sendAndConfirm(tx, [], this.opts);
|
|
109
|
+
return txSig;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
transferMintAuthority() {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
return yield this.program.rpc.transferMintAuthority({
|
|
115
|
+
accounts: {
|
|
116
|
+
faucetConfig: yield this.getFaucetConfigPublicKey(),
|
|
117
|
+
mintAccount: this.mint,
|
|
118
|
+
mintAuthority: yield this.getMintAuthority(),
|
|
119
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
120
|
+
admin: this.wallet.publicKey,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
createAssociatedTokenAccountAndMintTo(userPublicKey, amount) {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const tx = new web3_js_1.Transaction();
|
|
128
|
+
const [associatedTokenPublicKey, createAssociatedAccountIx, mintToTx] = yield this.createAssociatedTokenAccountAndMintToInstructions(userPublicKey, amount);
|
|
129
|
+
let associatedTokenAccountExists = false;
|
|
130
|
+
try {
|
|
131
|
+
const assosciatedTokenAccount = yield this.connection.getAccountInfo(associatedTokenPublicKey);
|
|
132
|
+
associatedTokenAccountExists = !!assosciatedTokenAccount;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
// token account doesn't exist
|
|
136
|
+
associatedTokenAccountExists = false;
|
|
137
|
+
}
|
|
138
|
+
const skipAccountCreation = associatedTokenAccountExists;
|
|
139
|
+
if (!skipAccountCreation)
|
|
140
|
+
tx.add(createAssociatedAccountIx);
|
|
141
|
+
tx.add(mintToTx);
|
|
142
|
+
const txSig = yield this.program.provider.sendAndConfirm(tx, [], this.opts);
|
|
143
|
+
return [associatedTokenPublicKey, txSig];
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
createAssociatedTokenAccountAndMintToInstructions(userPublicKey, amount) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
const state = yield this.fetchState();
|
|
149
|
+
const associateTokenPublicKey = yield this.getAssosciatedMockUSDMintAddress({ userPubKey: userPublicKey });
|
|
150
|
+
const createAssociatedAccountIx = spl_token_1.Token.createAssociatedTokenAccountInstruction(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, state.mint, associateTokenPublicKey, userPublicKey, this.wallet.publicKey);
|
|
151
|
+
const mintToIx = yield this.mintToUserIx(associateTokenPublicKey, amount);
|
|
152
|
+
return [associateTokenPublicKey, createAssociatedAccountIx, mintToIx];
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
getAssosciatedMockUSDMintAddress(props) {
|
|
156
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
157
|
+
const state = yield this.fetchState();
|
|
158
|
+
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, state.mint, props.userPubKey);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
getTokenAccountInfo(props) {
|
|
162
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
const assosciatedKey = yield this.getAssosciatedMockUSDMintAddress(props);
|
|
164
|
+
const state = yield this.fetchState();
|
|
165
|
+
const token = new spl_token_1.Token(this.connection, state.mint, spl_token_1.TOKEN_PROGRAM_ID,
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
167
|
+
// @ts-ignore
|
|
168
|
+
this.provider.payer);
|
|
169
|
+
return yield token.getAccountInfo(assosciatedKey);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
subscribeToTokenAccount(props) {
|
|
173
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
+
try {
|
|
175
|
+
const tokenAccountKey = yield this.getAssosciatedMockUSDMintAddress(props);
|
|
176
|
+
props.callback(yield this.getTokenAccountInfo(props));
|
|
177
|
+
// Couldn't find a way to do it using anchor framework subscription, someone on serum discord recommended this way
|
|
178
|
+
this.connection.onAccountChange(tokenAccountKey, (_accountInfo /* accountInfo is a buffer which we don't know how to deserialize */) => __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
props.callback(yield this.getTokenAccountInfo(props));
|
|
180
|
+
}));
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
exports.TokenFaucet = TokenFaucet;
|
package/src/tokenFaucet.ts
CHANGED
|
@@ -92,11 +92,8 @@ export class TokenFaucet {
|
|
|
92
92
|
);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
amount: BN
|
|
98
|
-
): Promise<TransactionSignature> {
|
|
99
|
-
return await this.program.rpc.mintToUser(amount, {
|
|
95
|
+
private async mintToUserIx(userTokenAccount: PublicKey, amount: BN) {
|
|
96
|
+
return this.program.instruction.mintToUser(amount, {
|
|
100
97
|
accounts: {
|
|
101
98
|
faucetConfig: await this.getFaucetConfigPublicKey(),
|
|
102
99
|
mintAccount: this.mint,
|
|
@@ -107,6 +104,19 @@ export class TokenFaucet {
|
|
|
107
104
|
});
|
|
108
105
|
}
|
|
109
106
|
|
|
107
|
+
public async mintToUser(
|
|
108
|
+
userTokenAccount: PublicKey,
|
|
109
|
+
amount: BN
|
|
110
|
+
): Promise<TransactionSignature> {
|
|
111
|
+
const mintIx = await this.mintToUserIx(userTokenAccount, amount);
|
|
112
|
+
|
|
113
|
+
const tx = new Transaction().add(mintIx);
|
|
114
|
+
|
|
115
|
+
const txSig = await this.program.provider.sendAndConfirm(tx, [], this.opts);
|
|
116
|
+
|
|
117
|
+
return txSig;
|
|
118
|
+
}
|
|
119
|
+
|
|
110
120
|
public async transferMintAuthority(): Promise<TransactionSignature> {
|
|
111
121
|
return await this.program.rpc.transferMintAuthority({
|
|
112
122
|
accounts: {
|
|
@@ -123,12 +133,33 @@ export class TokenFaucet {
|
|
|
123
133
|
userPublicKey: PublicKey,
|
|
124
134
|
amount: BN
|
|
125
135
|
): Promise<[PublicKey, TransactionSignature]> {
|
|
136
|
+
const tx = new Transaction();
|
|
137
|
+
|
|
126
138
|
const [associatedTokenPublicKey, createAssociatedAccountIx, mintToTx] =
|
|
127
139
|
await this.createAssociatedTokenAccountAndMintToInstructions(
|
|
128
140
|
userPublicKey,
|
|
129
141
|
amount
|
|
130
142
|
);
|
|
131
|
-
|
|
143
|
+
|
|
144
|
+
let associatedTokenAccountExists = false;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const assosciatedTokenAccount = await this.connection.getAccountInfo(
|
|
148
|
+
associatedTokenPublicKey
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
associatedTokenAccountExists = !!assosciatedTokenAccount;
|
|
152
|
+
} catch (e) {
|
|
153
|
+
// token account doesn't exist
|
|
154
|
+
associatedTokenAccountExists = false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const skipAccountCreation = associatedTokenAccountExists;
|
|
158
|
+
|
|
159
|
+
if (!skipAccountCreation) tx.add(createAssociatedAccountIx);
|
|
160
|
+
|
|
161
|
+
tx.add(mintToTx);
|
|
162
|
+
|
|
132
163
|
const txSig = await this.program.provider.sendAndConfirm(tx, [], this.opts);
|
|
133
164
|
return [associatedTokenPublicKey, txSig];
|
|
134
165
|
}
|
|
@@ -153,15 +184,7 @@ export class TokenFaucet {
|
|
|
153
184
|
this.wallet.publicKey
|
|
154
185
|
);
|
|
155
186
|
|
|
156
|
-
const mintToIx = await this.
|
|
157
|
-
accounts: {
|
|
158
|
-
faucetConfig: await this.getFaucetConfigPublicKey(),
|
|
159
|
-
mintAccount: state.mint,
|
|
160
|
-
userTokenAccount: associateTokenPublicKey,
|
|
161
|
-
mintAuthority: state.mintAuthority,
|
|
162
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
187
|
+
const mintToIx = await this.mintToUserIx(associateTokenPublicKey, amount);
|
|
165
188
|
|
|
166
189
|
return [associateTokenPublicKey, createAssociatedAccountIx, mintToIx];
|
|
167
190
|
}
|
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -56,9 +56,17 @@ export class RetryTxSender implements TxSender {
|
|
|
56
56
|
const rawTransaction = tx.serialize();
|
|
57
57
|
const startTime = this.getTimestamp();
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
let txid: TransactionSignature;
|
|
60
|
+
try {
|
|
61
|
+
txid = await this.provider.connection.sendRawTransaction(
|
|
62
|
+
rawTransaction,
|
|
63
|
+
opts
|
|
64
|
+
);
|
|
65
|
+
this.sendToAdditionalConnections(rawTransaction, opts);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
console.error(e);
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
62
70
|
|
|
63
71
|
let done = false;
|
|
64
72
|
const resolveReference: ResolveReference = {
|
package/src/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultOrderParams = exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.BankBalanceType = exports.SwapDirection = void 0;
|
|
3
|
+
exports.DefaultOrderParams = exports.LiquidationType = exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.BankBalanceType = exports.SwapDirection = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
// # Utility Types / Enums / Constants
|
|
6
6
|
class SwapDirection {
|
|
@@ -91,6 +91,17 @@ var TradeSide;
|
|
|
91
91
|
TradeSide[TradeSide["Buy"] = 1] = "Buy";
|
|
92
92
|
TradeSide[TradeSide["Sell"] = 2] = "Sell";
|
|
93
93
|
})(TradeSide = exports.TradeSide || (exports.TradeSide = {}));
|
|
94
|
+
class LiquidationType {
|
|
95
|
+
}
|
|
96
|
+
exports.LiquidationType = LiquidationType;
|
|
97
|
+
LiquidationType.LIQUIDATE_PERP = { liquidatePerp: {} };
|
|
98
|
+
LiquidationType.LIQUIDATE_BORROW = { liquidateBorrow: {} };
|
|
99
|
+
LiquidationType.LIQUIDATE_BORROW_FOR_PERP_PNL = {
|
|
100
|
+
liquidateBorrowForPerpPnl: {},
|
|
101
|
+
};
|
|
102
|
+
LiquidationType.LIQUIDATE_PERP_PNL_FOR_DEPOSIT = {
|
|
103
|
+
liquidatePerpPnlForDeposit: {},
|
|
104
|
+
};
|
|
94
105
|
exports.DefaultOrderParams = {
|
|
95
106
|
orderType: OrderType.MARKET,
|
|
96
107
|
userOrderId: 0,
|
package/src/types.ts
CHANGED
|
@@ -67,6 +67,12 @@ export class OrderActionExplanation {
|
|
|
67
67
|
static readonly MARKET_ORDER_FILLED_TO_LIMIT_PRICE = {
|
|
68
68
|
marketOrderFilledToLimitPrice: {},
|
|
69
69
|
};
|
|
70
|
+
static readonly CANCELED_FOR_LIQUIDATION = {
|
|
71
|
+
canceledForLiquidation: {},
|
|
72
|
+
};
|
|
73
|
+
static readonly MARKET_ORDER_AUCTION_EXPIRED = {
|
|
74
|
+
marketOrderAuctionExpired: {},
|
|
75
|
+
};
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
export class OrderTriggerCondition {
|
|
@@ -166,6 +172,7 @@ export type LiquidationRecord = {
|
|
|
166
172
|
liquidationType: LiquidationType;
|
|
167
173
|
marginRequirement: BN;
|
|
168
174
|
totalCollateral: BN;
|
|
175
|
+
liquidationId: number;
|
|
169
176
|
liquidatePerp: LiquidatePerpRecord;
|
|
170
177
|
liquidateBorrow: LiquidateBorrowRecord;
|
|
171
178
|
liquidateBorrowForPerpPnl: LiquidateBorrowForPerpPnlRecord;
|
|
@@ -224,14 +231,24 @@ export type LiquidatePerpPnlForDepositRecord = {
|
|
|
224
231
|
assetTransfer: BN;
|
|
225
232
|
};
|
|
226
233
|
|
|
234
|
+
export type SettlePnlRecord = {
|
|
235
|
+
ts: BN;
|
|
236
|
+
marketIndex: BN;
|
|
237
|
+
pnl: BN;
|
|
238
|
+
baseAssetAmount: BN;
|
|
239
|
+
quoteAssetAmountAfter: BN;
|
|
240
|
+
quoteEntryamount: BN;
|
|
241
|
+
oraclePrice: BN;
|
|
242
|
+
};
|
|
243
|
+
|
|
227
244
|
export type OrderRecord = {
|
|
228
245
|
ts: BN;
|
|
229
246
|
taker: PublicKey;
|
|
230
247
|
maker: PublicKey;
|
|
231
248
|
takerOrder: Order;
|
|
232
249
|
makerOrder: Order;
|
|
233
|
-
|
|
234
|
-
|
|
250
|
+
takerPnl: BN;
|
|
251
|
+
makerPnl: BN;
|
|
235
252
|
action: OrderAction;
|
|
236
253
|
actionExplanation: OrderActionExplanation;
|
|
237
254
|
filler: PublicKey;
|
|
@@ -291,6 +308,10 @@ export type MarketAccount = {
|
|
|
291
308
|
nextFillRecordId: BN;
|
|
292
309
|
pnlPool: PoolBalance;
|
|
293
310
|
liquidationFee: BN;
|
|
311
|
+
imfFactor: BN;
|
|
312
|
+
unsettledImfFactor: BN;
|
|
313
|
+
unsettledInitialAssetWeight: number;
|
|
314
|
+
unsettledMaintenanceAssetWeight: number;
|
|
294
315
|
};
|
|
295
316
|
|
|
296
317
|
export type BankAccount = {
|
|
@@ -315,6 +336,7 @@ export type BankAccount = {
|
|
|
315
336
|
initialLiabilityWeight: BN;
|
|
316
337
|
maintenanceLiabilityWeight: BN;
|
|
317
338
|
liquidationFee: BN;
|
|
339
|
+
imfFactor: BN;
|
|
318
340
|
};
|
|
319
341
|
|
|
320
342
|
export type PoolBalance = {
|
|
@@ -376,7 +398,6 @@ export type UserPosition = {
|
|
|
376
398
|
quoteAssetAmount: BN;
|
|
377
399
|
quoteEntryAmount: BN;
|
|
378
400
|
openOrders: BN;
|
|
379
|
-
unsettledPnl: BN;
|
|
380
401
|
openBids: BN;
|
|
381
402
|
openAsks: BN;
|
|
382
403
|
};
|
|
@@ -398,6 +419,7 @@ export type UserAccount = {
|
|
|
398
419
|
positions: UserPosition[];
|
|
399
420
|
orders: Order[];
|
|
400
421
|
beingLiquidated: boolean;
|
|
422
|
+
nextLiquidationId: number;
|
|
401
423
|
};
|
|
402
424
|
|
|
403
425
|
export type UserBankBalance = {
|
|
@@ -9,21 +9,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
|
|
14
|
-
function fetchUserAccounts(connection, program, authority, limit = 8) {
|
|
12
|
+
exports.findComputeUnitConsumption = void 0;
|
|
13
|
+
function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
|
|
15
14
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return undefined;
|
|
15
|
+
const tx = yield connection.getTransaction(txSignature, { commitment });
|
|
16
|
+
const computeUnits = [];
|
|
17
|
+
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
|
|
18
|
+
tx.meta.logMessages.forEach((logMessage) => {
|
|
19
|
+
const match = logMessage.match(regex);
|
|
20
|
+
if (match && match[1]) {
|
|
21
|
+
computeUnits.push(match[1]);
|
|
24
22
|
}
|
|
25
|
-
return program.account.user.coder.accounts.decode('User', accountInfo.data);
|
|
26
23
|
});
|
|
24
|
+
return computeUnits;
|
|
27
25
|
});
|
|
28
26
|
}
|
|
29
|
-
exports.
|
|
27
|
+
exports.findComputeUnitConsumption = findComputeUnitConsumption;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTokenAddress = void 0;
|
|
4
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
7
|
+
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
8
|
+
};
|
|
9
|
+
exports.getTokenAddress = getTokenAddress;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Token,
|
|
3
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
4
|
+
TOKEN_PROGRAM_ID,
|
|
5
|
+
} from '@solana/spl-token';
|
|
6
|
+
import { PublicKey } from '@solana/web3.js';
|
|
7
|
+
|
|
8
|
+
export const getTokenAddress = (
|
|
9
|
+
mintAddress: string,
|
|
10
|
+
userPubKey: string
|
|
11
|
+
): Promise<PublicKey> => {
|
|
12
|
+
return Token.getAssociatedTokenAddress(
|
|
13
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
14
|
+
TOKEN_PROGRAM_ID,
|
|
15
|
+
new PublicKey(mintAddress),
|
|
16
|
+
new PublicKey(userPubKey)
|
|
17
|
+
);
|
|
18
|
+
};
|
package/tests/bn/test.ts
CHANGED
|
@@ -125,6 +125,8 @@ describe('BigNum Tests', () => {
|
|
|
125
125
|
expect(BigNum.fromPrint('1234567').toMillified(5)).to.equal('1.2345M');
|
|
126
126
|
expect(BigNum.fromPrint('12345678').toMillified(5)).to.equal('12.345M');
|
|
127
127
|
expect(BigNum.fromPrint('123456789').toMillified(5)).to.equal('123.45M');
|
|
128
|
+
|
|
129
|
+
expect(BigNum.from(-95, 2).print()).to.equal('-0.95');
|
|
128
130
|
});
|
|
129
131
|
|
|
130
132
|
it('can initialise from string values correctly', () => {
|