flash-sdk 1.0.22 → 1.0.23
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 → dist}/PerpetualsClient.d.ts +2 -0
- package/{lib → dist}/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -4
- package/src/CustodyAccount.ts +0 -125
- package/src/OraclePrice.ts +0 -111
- package/src/PerpetualsClient.ts +0 -2112
- package/src/PoolAccount.ts +0 -491
- package/src/PoolConfig.json +0 -322
- package/src/PoolConfig.ts +0 -182
- package/src/PoolDataClient.ts +0 -173
- package/src/PositionAccount.ts +0 -58
- package/src/Token.ts +0 -1
- package/src/constants/index.ts +0 -21
- package/src/idl/perpetuals.ts +0 -7561
- package/src/index.ts +0 -19
- package/src/type-rules.md +0 -4
- package/src/types/index.ts +0 -290
- package/src/utils/index.ts +0 -234
- package/src/utils/rpc.ts +0 -162
- package/tsconfig.json +0 -23
- /package/{lib → dist}/CustodyAccount.d.ts +0 -0
- /package/{lib → dist}/CustodyAccount.js +0 -0
- /package/{lib → dist}/OraclePrice.d.ts +0 -0
- /package/{lib → dist}/OraclePrice.js +0 -0
- /package/{lib → dist}/PerpetualsClient.js +0 -0
- /package/{lib → dist}/PoolAccount.d.ts +0 -0
- /package/{lib → dist}/PoolAccount.js +0 -0
- /package/{lib → dist}/PoolConfig.d.ts +0 -0
- /package/{lib → dist}/PoolConfig.js +0 -0
- /package/{lib → dist}/PoolConfig.json +0 -0
- /package/{lib → dist}/PoolDataClient.d.ts +0 -0
- /package/{lib → dist}/PoolDataClient.js +0 -0
- /package/{lib → dist}/PositionAccount.d.ts +0 -0
- /package/{lib → dist}/PositionAccount.js +0 -0
- /package/{lib → dist}/Token.d.ts +0 -0
- /package/{lib → dist}/Token.js +0 -0
- /package/{lib → dist}/constants/index.d.ts +0 -0
- /package/{lib → dist}/constants/index.js +0 -0
- /package/{lib → dist}/idl/perpetuals.d.ts +0 -0
- /package/{lib → dist}/idl/perpetuals.js +0 -0
- /package/{lib → dist}/index.d.ts +0 -0
- /package/{lib → dist}/index.js +0 -0
- /package/{lib → dist}/types/index.d.ts +0 -0
- /package/{lib → dist}/types/index.js +0 -0
- /package/{lib → dist}/utils/index.d.ts +0 -0
- /package/{lib → dist}/utils/index.js +0 -0
- /package/{lib → dist}/utils/rpc.d.ts +0 -0
- /package/{lib → dist}/utils/rpc.js +0 -0
package/src/PerpetualsClient.ts
DELETED
@@ -1,2112 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
setProvider,
|
3
|
-
Program,
|
4
|
-
AnchorProvider,
|
5
|
-
workspace,
|
6
|
-
utils,
|
7
|
-
BN,
|
8
|
-
} from "@coral-xyz/anchor";
|
9
|
-
import {
|
10
|
-
PublicKey,
|
11
|
-
TransactionInstruction,
|
12
|
-
Transaction,
|
13
|
-
SystemProgram,
|
14
|
-
AccountMeta,
|
15
|
-
Keypair,
|
16
|
-
SYSVAR_RENT_PUBKEY,
|
17
|
-
Commitment,
|
18
|
-
LAMPORTS_PER_SOL,
|
19
|
-
Signer,
|
20
|
-
} from "@solana/web3.js";
|
21
|
-
import {
|
22
|
-
getAccount,
|
23
|
-
getAssociatedTokenAddress,
|
24
|
-
createAssociatedTokenAccountInstruction,
|
25
|
-
createCloseAccountInstruction,
|
26
|
-
createSyncNativeInstruction,
|
27
|
-
TOKEN_PROGRAM_ID,
|
28
|
-
NATIVE_MINT,
|
29
|
-
createInitializeAccount3Instruction,
|
30
|
-
getMinimumBalanceForRentExemptAccount,
|
31
|
-
getAssociatedTokenAddressSync,
|
32
|
-
} from "@solana/spl-token";
|
33
|
-
|
34
|
-
import { sha256 } from "js-sha256";
|
35
|
-
import { encode } from "bs58";
|
36
|
-
import { PoolAccount } from "./PoolAccount";
|
37
|
-
import { PositionAccount } from "./PositionAccount";
|
38
|
-
import { AumCalcMode, BorrowRateParams, Custody, Fees, OracleParams, Permissions, Position, PositionSide, PricingParams, Side, TokenRatios, isVariant } from "./types";
|
39
|
-
import { OraclePrice } from "./OraclePrice";
|
40
|
-
import { CustodyAccount } from "./CustodyAccount";
|
41
|
-
import { Perpetuals } from "./idl/perpetuals";
|
42
|
-
import { IDL } from './idl/perpetuals';
|
43
|
-
import { sendTransaction } from "./utils/rpc";
|
44
|
-
import { PoolConfig } from "./PoolConfig";
|
45
|
-
import { checkIfAccountExists } from "./utils";
|
46
|
-
|
47
|
-
|
48
|
-
/* USEAGE
|
49
|
-
|
50
|
-
UI -----
|
51
|
-
provider = from phatom
|
52
|
-
|
53
|
-
client = new PerpetualsClient(provider, user.pubkey , programId);
|
54
|
-
|
55
|
-
BOT cli --------
|
56
|
-
|
57
|
-
provider = await getProvider(new DefaultWallet(DEFAULT_PERPS_USER));
|
58
|
-
|
59
|
-
AnchorProvider.local(clusterUrl, {
|
60
|
-
commitment: "confirmed",
|
61
|
-
preflightCommitment: "confirmed",
|
62
|
-
skipPreflight: true
|
63
|
-
});
|
64
|
-
process.env["ANCHOR_WALLET"] = adminKeyPath;
|
65
|
-
|
66
|
-
client = new PerpetualsClient(provider, DEFAULT_PERPS_USER.pubkey , programId);
|
67
|
-
|
68
|
-
*/
|
69
|
-
|
70
|
-
export type PerpClientOptions = {
|
71
|
-
postSendTxCallback?: ({ txid }: { txid: string }) => void;
|
72
|
-
prioritizationFee?: number;
|
73
|
-
txConfirmationCommitment?: Commitment;
|
74
|
-
};
|
75
|
-
|
76
|
-
export class PerpetualsClient {
|
77
|
-
provider: AnchorProvider;
|
78
|
-
program: Program<Perpetuals>;
|
79
|
-
admin: PublicKey;
|
80
|
-
programId: PublicKey;
|
81
|
-
|
82
|
-
// pdas
|
83
|
-
multisig: { publicKey: PublicKey; bump: number };
|
84
|
-
authority: { publicKey: PublicKey; bump: number };
|
85
|
-
perpetuals: { publicKey: PublicKey; bump: number };
|
86
|
-
|
87
|
-
private postSendTxCallback?: ({ txid }) => void;
|
88
|
-
private prioritizationFee: number;
|
89
|
-
private txConfirmationCommitment: Commitment;
|
90
|
-
|
91
|
-
constructor(provider: AnchorProvider, programId: PublicKey, opts: PerpClientOptions) {
|
92
|
-
// this.provider = AnchorProvider.local(clusterUrl, {
|
93
|
-
// commitment: "confirmed",
|
94
|
-
// preflightCommitment: "confirmed",
|
95
|
-
// skipPreflight: true
|
96
|
-
// });
|
97
|
-
// setProvider(this.provider);
|
98
|
-
this.provider = provider;
|
99
|
-
setProvider(provider);
|
100
|
-
|
101
|
-
// const idl = JSON.parse( fs.readFileSync("./target/idl/perpetuals.json", "utf8"));
|
102
|
-
// const idl = JSON.parse(IDL);
|
103
|
-
// const program = new anchor.Program(idl, programId, provider);
|
104
|
-
this.program = new Program(IDL, programId);
|
105
|
-
this.programId = programId;
|
106
|
-
//this.program = workspace.Perpetuals as Program<Perpetuals>;
|
107
|
-
// console.log("client constructor programID : ", this.program.programId.toBase58());
|
108
|
-
|
109
|
-
// this.admin = Keypair.fromSecretKey(
|
110
|
-
// new Uint8Array(JSON.parse(readFileSync(adminKey).toString()))
|
111
|
-
// );
|
112
|
-
|
113
|
-
this.admin = this.provider.wallet.publicKey;
|
114
|
-
// console.log("admin:", this.admin.toBase58())
|
115
|
-
|
116
|
-
this.multisig = this.findProgramAddress("multisig");
|
117
|
-
this.authority = this.findProgramAddress("transfer_authority");
|
118
|
-
this.perpetuals = this.findProgramAddress("perpetuals");
|
119
|
-
|
120
|
-
this.prioritizationFee = opts?.prioritizationFee || 0;
|
121
|
-
this.postSendTxCallback = opts?.postSendTxCallback;
|
122
|
-
this.txConfirmationCommitment = opts?.txConfirmationCommitment ?? 'processed'
|
123
|
-
|
124
|
-
BN.prototype.toJSON = function () {
|
125
|
-
return this.toString(10);
|
126
|
-
};
|
127
|
-
}
|
128
|
-
|
129
|
-
findProgramAddress = (label: string, extraSeeds: any = null) => {
|
130
|
-
let seeds = [Buffer.from(utils.bytes.utf8.encode(label))];
|
131
|
-
if (extraSeeds) {
|
132
|
-
for (let extraSeed of extraSeeds) {
|
133
|
-
if (typeof extraSeed === "string") {
|
134
|
-
seeds.push(Buffer.from(utils.bytes.utf8.encode(extraSeed)));
|
135
|
-
} else if (Array.isArray(extraSeed)) {
|
136
|
-
seeds.push(Buffer.from(extraSeed));
|
137
|
-
} else {
|
138
|
-
seeds.push(extraSeed.toBuffer());
|
139
|
-
}
|
140
|
-
}
|
141
|
-
}
|
142
|
-
let res = PublicKey.findProgramAddressSync(seeds, this.program.programId);
|
143
|
-
return { publicKey: res[0], bump: res[1] };
|
144
|
-
};
|
145
|
-
|
146
|
-
adjustTokenRatios = (ratios: TokenRatios[]) => {
|
147
|
-
if (ratios.length == 0) {
|
148
|
-
return ratios;
|
149
|
-
}
|
150
|
-
let target = Math.floor(10000 / ratios.length);
|
151
|
-
|
152
|
-
for (let ratio of ratios) {
|
153
|
-
ratio.target = new BN(target);
|
154
|
-
}
|
155
|
-
|
156
|
-
if (10000 % ratios.length !== 0) {
|
157
|
-
ratios[ratios.length - 1].target = new BN(
|
158
|
-
target + (10000 % ratios.length)
|
159
|
-
);
|
160
|
-
}
|
161
|
-
|
162
|
-
return ratios;
|
163
|
-
};
|
164
|
-
|
165
|
-
getPerpetuals = async () => {
|
166
|
-
return this.program.account.perpetuals.fetch(this.perpetuals.publicKey);
|
167
|
-
};
|
168
|
-
|
169
|
-
getPoolKey = (name: string) => {
|
170
|
-
return this.findProgramAddress("pool", name).publicKey;
|
171
|
-
};
|
172
|
-
|
173
|
-
getPool = async (name: string) => {
|
174
|
-
// console.log("pool:", this.getPoolKey(name).toBase58())
|
175
|
-
return this.program.account.pool.fetch(this.getPoolKey(name));
|
176
|
-
};
|
177
|
-
|
178
|
-
getPools = async () => {
|
179
|
-
//return this.program.account.pool.all();
|
180
|
-
let perpetuals = await this.getPerpetuals();
|
181
|
-
return this.program.account.pool.fetchMultiple(perpetuals.pools);
|
182
|
-
};
|
183
|
-
|
184
|
-
getPoolLpTokenKey = (name: string) => {
|
185
|
-
return this.findProgramAddress("lp_token_mint", [this.getPoolKey(name)])
|
186
|
-
.publicKey;
|
187
|
-
};
|
188
|
-
|
189
|
-
getCustodyKey = (poolName: string, tokenMint: PublicKey) => {
|
190
|
-
return this.findProgramAddress("custody", [
|
191
|
-
this.getPoolKey(poolName),
|
192
|
-
tokenMint,
|
193
|
-
]).publicKey;
|
194
|
-
};
|
195
|
-
|
196
|
-
getCustodyTokenAccountKey = (poolName: string, tokenMint: PublicKey) => {
|
197
|
-
return this.findProgramAddress("custody_token_account", [
|
198
|
-
this.getPoolKey(poolName),
|
199
|
-
tokenMint,
|
200
|
-
]).publicKey;
|
201
|
-
};
|
202
|
-
|
203
|
-
getCustodyOracleAccountKey = async (
|
204
|
-
poolName: string,
|
205
|
-
tokenMint: PublicKey
|
206
|
-
) => {
|
207
|
-
return (await this.getCustody(poolName, tokenMint)).oracle.oracleAccount;
|
208
|
-
};
|
209
|
-
|
210
|
-
getCustodyTestOracleAccountKey = (poolName: string, tokenMint: PublicKey) => {
|
211
|
-
return this.findProgramAddress("oracle_account", [
|
212
|
-
this.getPoolKey(poolName),
|
213
|
-
tokenMint,
|
214
|
-
]).publicKey;
|
215
|
-
};
|
216
|
-
|
217
|
-
getCustody = async (poolName: string, tokenMint: PublicKey) => {
|
218
|
-
// console.log("custody key :", this.getCustodyKey(poolName, tokenMint).toBase58());
|
219
|
-
return this.program.account.custody.fetch(
|
220
|
-
this.getCustodyKey(poolName, tokenMint)
|
221
|
-
);
|
222
|
-
};
|
223
|
-
|
224
|
-
getCustodies = async (poolName: string) => {
|
225
|
-
//return this.program.account.custody.all();
|
226
|
-
let pool = await this.getPool(poolName);
|
227
|
-
return this.program.account.custody.fetchMultiple(
|
228
|
-
pool.custodies
|
229
|
-
);
|
230
|
-
};
|
231
|
-
|
232
|
-
getCustodyMetas = async (poolName: string) => {
|
233
|
-
let pool = await this.getPool(poolName);
|
234
|
-
let custodies: any = await this.program.account.custody.fetchMultiple(
|
235
|
-
pool.custodies
|
236
|
-
);
|
237
|
-
let custodyMetas = [];
|
238
|
-
for (const custody of pool.custodies) {
|
239
|
-
custodyMetas.push({
|
240
|
-
isSigner: false,
|
241
|
-
isWritable: false,
|
242
|
-
pubkey: custody,
|
243
|
-
});
|
244
|
-
}
|
245
|
-
for (const custody of custodies) {
|
246
|
-
custodyMetas.push({
|
247
|
-
isSigner: false,
|
248
|
-
isWritable: false,
|
249
|
-
pubkey: custody?.oracle.oracleAccount,
|
250
|
-
});
|
251
|
-
}
|
252
|
-
return custodyMetas;
|
253
|
-
};
|
254
|
-
|
255
|
-
getMultisig = async () => {
|
256
|
-
return this.program.account.multisig.fetch(this.multisig.publicKey);
|
257
|
-
};
|
258
|
-
|
259
|
-
getPositionKey = (
|
260
|
-
wallet: PublicKey,
|
261
|
-
poolName: string,
|
262
|
-
tokenMint: PublicKey,
|
263
|
-
side: PositionSide
|
264
|
-
) => {
|
265
|
-
let pool = this.getPoolKey(poolName);
|
266
|
-
let custody = this.getCustodyKey(poolName, tokenMint);
|
267
|
-
return this.findProgramAddress("position", [
|
268
|
-
wallet,
|
269
|
-
pool,
|
270
|
-
custody,
|
271
|
-
side === "long" ? [1] : [2],
|
272
|
-
]).publicKey;
|
273
|
-
};
|
274
|
-
|
275
|
-
getPosition = async (postionKey: PublicKey) => {
|
276
|
-
return this.program.account.position.fetch(postionKey);
|
277
|
-
};
|
278
|
-
|
279
|
-
getUserPosition = async (
|
280
|
-
wallet: PublicKey,
|
281
|
-
poolName: string,
|
282
|
-
tokenMint: PublicKey,
|
283
|
-
side: PositionSide
|
284
|
-
) => {
|
285
|
-
return this.program.account.position.fetch(
|
286
|
-
this.getPositionKey(wallet, poolName, tokenMint, side)
|
287
|
-
);
|
288
|
-
};
|
289
|
-
|
290
|
-
getUserPositions = async (
|
291
|
-
wallet: PublicKey,
|
292
|
-
poolConfig: PoolConfig
|
293
|
-
) => {
|
294
|
-
|
295
|
-
const positionKeys = [
|
296
|
-
...poolConfig.getNonStableTokens().map(mint => this.getPositionKey(wallet, poolConfig.poolName, mint, 'long')),
|
297
|
-
...poolConfig.getNonStableTokens().map(mint => this.getPositionKey(wallet, poolConfig.poolName, mint, 'short')),
|
298
|
-
]
|
299
|
-
|
300
|
-
let positionsDatas = (await this.provider.connection.getMultipleAccountsInfo(positionKeys)) ?? [];
|
301
|
-
|
302
|
-
type Position = Awaited<ReturnType<typeof this.program.account.position.fetch>>
|
303
|
-
|
304
|
-
return positionsDatas
|
305
|
-
.map((p, i) => ({ pubkey: positionKeys[i], data: p }))
|
306
|
-
.filter(f => f.data !== null)
|
307
|
-
.map(k => ({ pubkey: k.pubkey, ...this.program.account.position.coder.accounts.decode<Position>('position', k.data!.data) }))
|
308
|
-
};
|
309
|
-
|
310
|
-
getPoolTokenPositions = async (poolName: string, tokenMint: PublicKey) => {
|
311
|
-
let poolKey = this.getPoolKey(poolName);
|
312
|
-
let custodyKey = this.getCustodyKey(poolName, tokenMint);
|
313
|
-
let data = encode(
|
314
|
-
Buffer.concat([poolKey.toBuffer(), custodyKey.toBuffer()])
|
315
|
-
);
|
316
|
-
let positions = await this.provider.connection.getProgramAccounts(
|
317
|
-
this.program.programId,
|
318
|
-
{
|
319
|
-
filters: [{ dataSize: 200 }, { memcmp: { bytes: data, offset: 40 } }],
|
320
|
-
}
|
321
|
-
);
|
322
|
-
return Promise.all(
|
323
|
-
positions.map((position) => {
|
324
|
-
return this.program.account.position.fetch(position.pubkey);
|
325
|
-
})
|
326
|
-
);
|
327
|
-
};
|
328
|
-
|
329
|
-
getAllPositions = async () => {
|
330
|
-
return this.program.account.position.all();
|
331
|
-
};
|
332
|
-
|
333
|
-
getAccountDiscriminator = (name: string) => {
|
334
|
-
return Buffer.from(sha256.digest(`account:${name}`)).slice(0, 8);
|
335
|
-
};
|
336
|
-
|
337
|
-
|
338
|
-
log = (...message: string[]) => {
|
339
|
-
let date = new Date();
|
340
|
-
let date_str = date.toDateString();
|
341
|
-
let time = date.toLocaleTimeString();
|
342
|
-
console.log(`[${date_str} ${time}] ${message}`);
|
343
|
-
};
|
344
|
-
|
345
|
-
prettyPrint = (object: object) => {
|
346
|
-
console.log(JSON.stringify(object, null, 2));
|
347
|
-
};
|
348
|
-
|
349
|
-
///////
|
350
|
-
// instructions
|
351
|
-
|
352
|
-
init = async (admins: PublicKey[], config: any) => {
|
353
|
-
let perpetualsProgramData = PublicKey.findProgramAddressSync(
|
354
|
-
[this.program.programId.toBuffer()],
|
355
|
-
new PublicKey("BPFLoaderUpgradeab1e11111111111111111111111")
|
356
|
-
)[0];
|
357
|
-
|
358
|
-
let adminMetas = [];
|
359
|
-
for (const admin of admins) {
|
360
|
-
adminMetas.push({
|
361
|
-
isSigner: false,
|
362
|
-
isWritable: false,
|
363
|
-
pubkey: admin,
|
364
|
-
});
|
365
|
-
}
|
366
|
-
|
367
|
-
await this.program.methods
|
368
|
-
.init(config)
|
369
|
-
.accounts({
|
370
|
-
upgradeAuthority: this.provider.wallet.publicKey,
|
371
|
-
multisig: this.multisig.publicKey,
|
372
|
-
transferAuthority: this.authority.publicKey,
|
373
|
-
perpetuals: this.perpetuals.publicKey,
|
374
|
-
perpetualsProgram: this.program.programId,
|
375
|
-
perpetualsProgramData,
|
376
|
-
systemProgram: SystemProgram.programId,
|
377
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
378
|
-
})
|
379
|
-
.remainingAccounts(adminMetas)
|
380
|
-
.rpc()
|
381
|
-
.catch((err) => {
|
382
|
-
console.error(err);
|
383
|
-
throw err;
|
384
|
-
});
|
385
|
-
};
|
386
|
-
|
387
|
-
setAdminSigners = async (admins: PublicKey[], minSignatures: number) => {
|
388
|
-
let adminMetas = [];
|
389
|
-
for (const admin of admins) {
|
390
|
-
adminMetas.push({
|
391
|
-
isSigner: false,
|
392
|
-
isWritable: false,
|
393
|
-
pubkey: admin,
|
394
|
-
});
|
395
|
-
}
|
396
|
-
try {
|
397
|
-
await this.program.methods
|
398
|
-
.setAdminSigners({
|
399
|
-
minSignatures,
|
400
|
-
})
|
401
|
-
.accounts({
|
402
|
-
admin: this.admin,
|
403
|
-
multisig: this.multisig.publicKey,
|
404
|
-
})
|
405
|
-
.remainingAccounts(adminMetas)
|
406
|
-
// .signers([this.admin])
|
407
|
-
.rpc();
|
408
|
-
} catch (err) {
|
409
|
-
// @ts-ignore
|
410
|
-
if (this.printErrors) {
|
411
|
-
console.error("setAdminSigners err:",err);
|
412
|
-
}
|
413
|
-
throw err;
|
414
|
-
}
|
415
|
-
};
|
416
|
-
|
417
|
-
addPool = async (name: string) => {
|
418
|
-
await this.program.methods
|
419
|
-
.addPool({ name })
|
420
|
-
.accounts({
|
421
|
-
admin: this.provider.wallet.publicKey,
|
422
|
-
multisig: this.multisig.publicKey,
|
423
|
-
transferAuthority: this.authority.publicKey,
|
424
|
-
perpetuals: this.perpetuals.publicKey,
|
425
|
-
pool: this.getPoolKey(name),
|
426
|
-
lpTokenMint: this.getPoolLpTokenKey(name),
|
427
|
-
systemProgram: SystemProgram.programId,
|
428
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
429
|
-
rent: SYSVAR_RENT_PUBKEY,
|
430
|
-
})
|
431
|
-
// .signers([this.admin])
|
432
|
-
.rpc()
|
433
|
-
.catch((err) => {
|
434
|
-
console.error(err);
|
435
|
-
throw err;
|
436
|
-
});
|
437
|
-
};
|
438
|
-
|
439
|
-
removePool = async (name: string) => {
|
440
|
-
await this.program.methods
|
441
|
-
.removePool({})
|
442
|
-
.accounts({
|
443
|
-
admin: this.admin,
|
444
|
-
multisig: this.multisig.publicKey,
|
445
|
-
transferAuthority: this.authority.publicKey,
|
446
|
-
perpetuals: this.perpetuals.publicKey,
|
447
|
-
pool: this.getPoolKey(name),
|
448
|
-
systemProgram: SystemProgram.programId,
|
449
|
-
})
|
450
|
-
// .signers([this.admin])
|
451
|
-
.rpc()
|
452
|
-
.catch((err) => {
|
453
|
-
console.error(err);
|
454
|
-
throw err;
|
455
|
-
});
|
456
|
-
};
|
457
|
-
|
458
|
-
addCustody = async (
|
459
|
-
poolName: string,
|
460
|
-
tokenMint: PublicKey,
|
461
|
-
isStable: boolean,
|
462
|
-
oracle: OracleParams,
|
463
|
-
pricing: PricingParams,
|
464
|
-
permissions: Permissions,
|
465
|
-
fees: Fees,
|
466
|
-
borrowRate: BorrowRateParams,
|
467
|
-
ratios: TokenRatios[]
|
468
|
-
) => {
|
469
|
-
// console.log("CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
|
470
|
-
// console.log("getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
|
471
|
-
try {
|
472
|
-
const trx_id = await this.program.methods
|
473
|
-
// @ts-ignore
|
474
|
-
.addCustody({
|
475
|
-
isStable,
|
476
|
-
oracle,
|
477
|
-
pricing,
|
478
|
-
permissions,
|
479
|
-
fees,
|
480
|
-
borrowRate,
|
481
|
-
ratios,
|
482
|
-
})
|
483
|
-
.accounts({
|
484
|
-
admin: this.admin,
|
485
|
-
multisig: this.multisig.publicKey,
|
486
|
-
transferAuthority: this.authority.publicKey,
|
487
|
-
perpetuals: this.perpetuals.publicKey,
|
488
|
-
pool: this.getPoolKey(poolName),
|
489
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
490
|
-
custodyTokenAccount: this.getCustodyTokenAccountKey(
|
491
|
-
poolName,
|
492
|
-
tokenMint
|
493
|
-
),
|
494
|
-
custodyTokenMint: tokenMint,
|
495
|
-
systemProgram: SystemProgram.programId,
|
496
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
497
|
-
rent: SYSVAR_RENT_PUBKEY,
|
498
|
-
})
|
499
|
-
// .signers([this.admin])
|
500
|
-
.rpc()
|
501
|
-
.catch((err) => {
|
502
|
-
console.error(err);
|
503
|
-
throw err;
|
504
|
-
});
|
505
|
-
|
506
|
-
console.log("trx_id:", `https://explorer.solana.com/tx/${trx_id}?cluster=devnet`)
|
507
|
-
} catch (error) {
|
508
|
-
console.error("cli error :", error);
|
509
|
-
}
|
510
|
-
|
511
|
-
|
512
|
-
};
|
513
|
-
|
514
|
-
editCustody = async (
|
515
|
-
poolName: string,
|
516
|
-
tokenMint: PublicKey,
|
517
|
-
isStable: boolean,
|
518
|
-
oracle: OracleParams,
|
519
|
-
pricing: PricingParams,
|
520
|
-
permissions: Permissions,
|
521
|
-
fees: Fees,
|
522
|
-
borrowRate: BorrowRateParams,
|
523
|
-
ratios: TokenRatios[]
|
524
|
-
) => {
|
525
|
-
// console.log("editCustody CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
|
526
|
-
// console.log("editCustody getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
|
527
|
-
|
528
|
-
const trx_id = await this.program.methods
|
529
|
-
//@ts-ignore
|
530
|
-
.testingEditCustody({
|
531
|
-
isStable,
|
532
|
-
oracle,
|
533
|
-
pricing,
|
534
|
-
permissions,
|
535
|
-
fees,
|
536
|
-
borrowRate,
|
537
|
-
ratios,
|
538
|
-
})
|
539
|
-
.accounts({
|
540
|
-
admin: this.admin,
|
541
|
-
multisig: this.multisig.publicKey,
|
542
|
-
transferAuthority: this.authority.publicKey,
|
543
|
-
perpetuals: this.perpetuals.publicKey,
|
544
|
-
pool: this.getPoolKey(poolName),
|
545
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
546
|
-
custodyTokenAccount: this.getCustodyTokenAccountKey(
|
547
|
-
poolName,
|
548
|
-
tokenMint
|
549
|
-
),
|
550
|
-
custodyTokenMint: tokenMint,
|
551
|
-
systemProgram: SystemProgram.programId,
|
552
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
553
|
-
rent: SYSVAR_RENT_PUBKEY,
|
554
|
-
})
|
555
|
-
// .signers([this.admin])
|
556
|
-
.rpc()
|
557
|
-
.catch((err) => {
|
558
|
-
console.error(err);
|
559
|
-
throw err;
|
560
|
-
});
|
561
|
-
console.log("trx_id:", `https://explorer.solana.com/tx/${trx_id}?cluster=devnet`)
|
562
|
-
};
|
563
|
-
|
564
|
-
removeCustody = async (poolName: string, tokenMint: PublicKey, ratios: TokenRatios[]) => {
|
565
|
-
await this.program.methods
|
566
|
-
.removeCustody({ ratios })
|
567
|
-
.accounts({
|
568
|
-
admin: this.admin,
|
569
|
-
multisig: this.multisig.publicKey,
|
570
|
-
transferAuthority: this.authority.publicKey,
|
571
|
-
perpetuals: this.perpetuals.publicKey,
|
572
|
-
pool: this.getPoolKey(poolName),
|
573
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
574
|
-
custodyTokenAccount: this.getCustodyTokenAccountKey(
|
575
|
-
poolName,
|
576
|
-
tokenMint
|
577
|
-
),
|
578
|
-
systemProgram: SystemProgram.programId,
|
579
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
580
|
-
})
|
581
|
-
// .signers([this.admin])
|
582
|
-
.rpc()
|
583
|
-
.catch((err) => {
|
584
|
-
console.error(err);
|
585
|
-
throw err;
|
586
|
-
});
|
587
|
-
};
|
588
|
-
|
589
|
-
upgradeCustody = async (poolName: string, tokenMint: PublicKey) => {
|
590
|
-
await this.program.methods
|
591
|
-
.upgradeCustody({})
|
592
|
-
.accounts({
|
593
|
-
admin: this.admin,
|
594
|
-
multisig: this.multisig.publicKey,
|
595
|
-
pool: this.getPoolKey(poolName),
|
596
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
597
|
-
systemProgram: SystemProgram.programId,
|
598
|
-
})
|
599
|
-
// .signers([this.admin])
|
600
|
-
.rpc()
|
601
|
-
.catch((err) => {
|
602
|
-
console.error(err);
|
603
|
-
throw err;
|
604
|
-
});
|
605
|
-
};
|
606
|
-
|
607
|
-
liquidate = async (
|
608
|
-
wallet: PublicKey,
|
609
|
-
poolName: string,
|
610
|
-
tokenMint: PublicKey,
|
611
|
-
side: PositionSide,
|
612
|
-
receivingAccount: PublicKey,
|
613
|
-
rewardsReceivingAccount: PublicKey
|
614
|
-
) => {
|
615
|
-
return await this.program.methods
|
616
|
-
.liquidate({})
|
617
|
-
.accounts({
|
618
|
-
signer: this.provider.wallet.publicKey,
|
619
|
-
receivingAccount,
|
620
|
-
rewardsReceivingAccount,
|
621
|
-
transferAuthority: this.authority.publicKey,
|
622
|
-
perpetuals: this.perpetuals.publicKey,
|
623
|
-
pool: this.getPoolKey(poolName),
|
624
|
-
position: this.getPositionKey(wallet, poolName, tokenMint, side),
|
625
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
626
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
627
|
-
poolName,
|
628
|
-
tokenMint
|
629
|
-
),
|
630
|
-
custodyTokenAccount: this.getCustodyTokenAccountKey(
|
631
|
-
poolName,
|
632
|
-
tokenMint
|
633
|
-
),
|
634
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
635
|
-
})
|
636
|
-
.rpc()
|
637
|
-
.catch((err) => {
|
638
|
-
console.error(err);
|
639
|
-
throw err;
|
640
|
-
});
|
641
|
-
};
|
642
|
-
|
643
|
-
getOraclePrice = async (
|
644
|
-
poolName: string,
|
645
|
-
tokenMint: PublicKey,
|
646
|
-
ema: boolean
|
647
|
-
) => {
|
648
|
-
return await this.program.methods
|
649
|
-
.getOraclePrice({
|
650
|
-
ema,
|
651
|
-
})
|
652
|
-
.accounts({
|
653
|
-
// signer: this.provider.wallet.publicKey,
|
654
|
-
perpetuals: this.perpetuals.publicKey,
|
655
|
-
pool: this.getPoolKey(poolName),
|
656
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
657
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
658
|
-
poolName,
|
659
|
-
tokenMint
|
660
|
-
),
|
661
|
-
})
|
662
|
-
.view()
|
663
|
-
.catch((err) => {
|
664
|
-
console.error(err);
|
665
|
-
throw err;
|
666
|
-
});
|
667
|
-
};
|
668
|
-
|
669
|
-
getAddLiquidityAmountAndFee = async (
|
670
|
-
poolName: string,
|
671
|
-
tokenMint: PublicKey,
|
672
|
-
amount: BN
|
673
|
-
) => {
|
674
|
-
return await this.program.methods
|
675
|
-
.getAddLiquidityAmountAndFee({
|
676
|
-
amountIn: amount,
|
677
|
-
})
|
678
|
-
.accounts({
|
679
|
-
perpetuals: this.perpetuals.publicKey,
|
680
|
-
pool: this.getPoolKey(poolName),
|
681
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
682
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
683
|
-
poolName,
|
684
|
-
tokenMint
|
685
|
-
),
|
686
|
-
lpTokenMint: this.getPoolLpTokenKey(poolName),
|
687
|
-
})
|
688
|
-
.remainingAccounts(await this.getCustodyMetas(poolName))
|
689
|
-
.view()
|
690
|
-
.catch((err) => {
|
691
|
-
console.error(err);
|
692
|
-
throw err;
|
693
|
-
});
|
694
|
-
};
|
695
|
-
|
696
|
-
getRemoveLiquidityAmountAndFee = async (
|
697
|
-
poolName: string,
|
698
|
-
tokenMint: PublicKey,
|
699
|
-
lpAmount: BN
|
700
|
-
) => {
|
701
|
-
return await this.program.methods
|
702
|
-
.getRemoveLiquidityAmountAndFee({
|
703
|
-
lpAmountIn: lpAmount,
|
704
|
-
})
|
705
|
-
.accounts({
|
706
|
-
perpetuals: this.perpetuals.publicKey,
|
707
|
-
pool: this.getPoolKey(poolName),
|
708
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
709
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
710
|
-
poolName,
|
711
|
-
tokenMint
|
712
|
-
),
|
713
|
-
lpTokenMint: this.getPoolLpTokenKey(poolName),
|
714
|
-
})
|
715
|
-
.remainingAccounts(await this.getCustodyMetas(poolName))
|
716
|
-
.view()
|
717
|
-
.catch((err) => {
|
718
|
-
console.error(err);
|
719
|
-
throw err;
|
720
|
-
});
|
721
|
-
};
|
722
|
-
|
723
|
-
getEntryPriceAndFee = async (
|
724
|
-
poolName: string,
|
725
|
-
tokenMint: PublicKey,
|
726
|
-
collateral: BN,
|
727
|
-
size: BN,
|
728
|
-
side: PositionSide
|
729
|
-
) => {
|
730
|
-
// console.log("perps: ", this.perpetuals.publicKey.toBase58())
|
731
|
-
// console.log("poolKey: ", this.getPoolKey(poolName).toBase58())
|
732
|
-
// console.log("custody key : ", this.getCustodyKey(poolName, tokenMint).toBase58());
|
733
|
-
// console.log("oracle: ", (await this.getCustodyOracleAccountKey(poolName, tokenMint)).toBase58())
|
734
|
-
|
735
|
-
//@ts-ignore
|
736
|
-
return await this.program.methods
|
737
|
-
//@ts-ignore
|
738
|
-
.getEntryPriceAndFee({
|
739
|
-
collateral,
|
740
|
-
size,
|
741
|
-
side: side == "long" ? { long: {} } : { short: {} },
|
742
|
-
})
|
743
|
-
.accounts({
|
744
|
-
// signer: this.provider.wallet.publicKey,
|
745
|
-
perpetuals: this.perpetuals.publicKey,
|
746
|
-
pool: this.getPoolKey(poolName),
|
747
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
748
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
749
|
-
poolName,
|
750
|
-
tokenMint
|
751
|
-
),
|
752
|
-
// lockCustody: this.getCustodyKey(poolName, tokenMint),
|
753
|
-
// lockCustodyOracleAccount: await this.getCustodyOracleAccountKey(
|
754
|
-
// poolName,
|
755
|
-
// tokenMint
|
756
|
-
// ),
|
757
|
-
})
|
758
|
-
.view()
|
759
|
-
.catch((err) => {
|
760
|
-
console.error(err);
|
761
|
-
throw err;
|
762
|
-
});
|
763
|
-
};
|
764
|
-
|
765
|
-
getExitPriceAndFee = async (
|
766
|
-
wallet: PublicKey,
|
767
|
-
poolName: string,
|
768
|
-
tokenMint: PublicKey,
|
769
|
-
side: PositionSide
|
770
|
-
) => {
|
771
|
-
return await this.program.methods
|
772
|
-
.getExitPriceAndFee({})
|
773
|
-
.accounts({
|
774
|
-
perpetuals: this.perpetuals.publicKey,
|
775
|
-
pool: this.getPoolKey(poolName),
|
776
|
-
position: this.getPositionKey(wallet, poolName, tokenMint, side),
|
777
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
778
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
779
|
-
poolName,
|
780
|
-
tokenMint
|
781
|
-
),
|
782
|
-
})
|
783
|
-
.view()
|
784
|
-
.catch((err) => {
|
785
|
-
console.error(err);
|
786
|
-
throw err;
|
787
|
-
});
|
788
|
-
};
|
789
|
-
|
790
|
-
getLiquidationPriceView = async (
|
791
|
-
wallet: PublicKey,
|
792
|
-
poolName: string,
|
793
|
-
tokenMint: PublicKey,
|
794
|
-
side: PositionSide,
|
795
|
-
addCollateral = new BN(0),
|
796
|
-
removeCollateral = new BN(0)
|
797
|
-
) => {
|
798
|
-
return await this.program.methods
|
799
|
-
.getLiquidationPrice({
|
800
|
-
addCollateral,
|
801
|
-
removeCollateral,
|
802
|
-
})
|
803
|
-
.accounts({
|
804
|
-
perpetuals: this.perpetuals.publicKey,
|
805
|
-
pool: this.getPoolKey(poolName),
|
806
|
-
position: this.getPositionKey(wallet, poolName, tokenMint, side),
|
807
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
808
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
809
|
-
poolName,
|
810
|
-
tokenMint
|
811
|
-
),
|
812
|
-
})
|
813
|
-
.view()
|
814
|
-
.catch((err) => {
|
815
|
-
console.error(err);
|
816
|
-
throw err;
|
817
|
-
});
|
818
|
-
};
|
819
|
-
|
820
|
-
getLiquidationPriceTrx = async (
|
821
|
-
wallet: PublicKey,
|
822
|
-
poolName: string,
|
823
|
-
tokenMint: PublicKey,
|
824
|
-
side: PositionSide,
|
825
|
-
addCollateral = new BN(0),
|
826
|
-
removeCollateral = new BN(0)
|
827
|
-
) => {
|
828
|
-
return await this.program.methods
|
829
|
-
.getLiquidationPrice({
|
830
|
-
addCollateral,
|
831
|
-
removeCollateral,
|
832
|
-
})
|
833
|
-
.accounts({
|
834
|
-
perpetuals: this.perpetuals.publicKey,
|
835
|
-
pool: this.getPoolKey(poolName),
|
836
|
-
position: this.getPositionKey(wallet, poolName, tokenMint, side),
|
837
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
838
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
839
|
-
poolName,
|
840
|
-
tokenMint
|
841
|
-
),
|
842
|
-
})
|
843
|
-
.rpc()
|
844
|
-
.catch((err) => {
|
845
|
-
console.error(err);
|
846
|
-
throw err;
|
847
|
-
});
|
848
|
-
};
|
849
|
-
|
850
|
-
// TODO: currently just static, need to write
|
851
|
-
getLiquidationPrice = (
|
852
|
-
postionKey: PublicKey,
|
853
|
-
postionData: Position,
|
854
|
-
tokenPrice: OraclePrice,
|
855
|
-
tokenEmaPrice: OraclePrice,
|
856
|
-
custodyAccount: CustodyAccount,
|
857
|
-
poolAccount: PoolAccount,
|
858
|
-
currentTime: BN,
|
859
|
-
addCollateral = new BN(0),
|
860
|
-
removeCollateral = new BN(0)
|
861
|
-
) => {
|
862
|
-
// const positionAccount = PositionAccount.from(postionKey, postionData);
|
863
|
-
let x : BN;
|
864
|
-
if (isVariant(postionData.side, 'long')) {
|
865
|
-
x = tokenPrice.price.mul(new BN(90)).div(new BN(90))
|
866
|
-
} else {
|
867
|
-
x = tokenPrice.price.mul(new BN(100)).div(new BN(90))
|
868
|
-
}
|
869
|
-
return new OraclePrice({price: x ,exponent : tokenPrice.exponent})
|
870
|
-
};
|
871
|
-
|
872
|
-
getLiquidationState = async (
|
873
|
-
wallet: PublicKey,
|
874
|
-
poolName: string,
|
875
|
-
tokenMint: PublicKey,
|
876
|
-
side: PositionSide
|
877
|
-
) => {
|
878
|
-
return await this.program.methods
|
879
|
-
.getLiquidationState({})
|
880
|
-
.accounts({
|
881
|
-
perpetuals: this.perpetuals.publicKey,
|
882
|
-
pool: this.getPoolKey(poolName),
|
883
|
-
position: this.getPositionKey(wallet, poolName, tokenMint, side),
|
884
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
885
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
886
|
-
poolName,
|
887
|
-
tokenMint
|
888
|
-
),
|
889
|
-
})
|
890
|
-
.view()
|
891
|
-
.catch((err) => {
|
892
|
-
console.error(err);
|
893
|
-
throw err;
|
894
|
-
});
|
895
|
-
};
|
896
|
-
|
897
|
-
getPnlView = async (
|
898
|
-
wallet: PublicKey,
|
899
|
-
poolName: string,
|
900
|
-
tokenMint: PublicKey,
|
901
|
-
side: PositionSide
|
902
|
-
) => {
|
903
|
-
const pos = this.getPositionKey(wallet, poolName, tokenMint, side);
|
904
|
-
// console.log("pos:", pos.toBase58())
|
905
|
-
return await this.program.methods
|
906
|
-
.getPnl({})
|
907
|
-
.accounts({
|
908
|
-
perpetuals: this.perpetuals.publicKey,
|
909
|
-
pool: this.getPoolKey(poolName),
|
910
|
-
position: pos,
|
911
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
912
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
913
|
-
poolName,
|
914
|
-
tokenMint
|
915
|
-
),
|
916
|
-
})
|
917
|
-
.view()
|
918
|
-
.catch((err) => {
|
919
|
-
console.error(err);
|
920
|
-
throw err;
|
921
|
-
});
|
922
|
-
};
|
923
|
-
|
924
|
-
|
925
|
-
getPnlTrx = async (
|
926
|
-
wallet: PublicKey,
|
927
|
-
poolName: string,
|
928
|
-
tokenMint: PublicKey,
|
929
|
-
side: PositionSide
|
930
|
-
) => {
|
931
|
-
const pos = this.getPositionKey(wallet, poolName, tokenMint, side);
|
932
|
-
// console.log("pos:", pos.toBase58())
|
933
|
-
return await this.program.methods
|
934
|
-
.getPnl({})
|
935
|
-
.accounts({
|
936
|
-
perpetuals: this.perpetuals.publicKey,
|
937
|
-
pool: this.getPoolKey(poolName),
|
938
|
-
position: pos,
|
939
|
-
custody: this.getCustodyKey(poolName, tokenMint),
|
940
|
-
custodyOracleAccount: await this.getCustodyOracleAccountKey(
|
941
|
-
poolName,
|
942
|
-
tokenMint
|
943
|
-
),
|
944
|
-
})
|
945
|
-
.rpc()
|
946
|
-
.catch((err) => {
|
947
|
-
console.error(err);
|
948
|
-
throw err;
|
949
|
-
});
|
950
|
-
};
|
951
|
-
|
952
|
-
|
953
|
-
getPnl = (
|
954
|
-
postionKey: PublicKey,
|
955
|
-
postionData: Position,
|
956
|
-
tokenPrice: OraclePrice,
|
957
|
-
tokenEmaPrice: OraclePrice,
|
958
|
-
custodyAccount: CustodyAccount,
|
959
|
-
poolAccount: PoolAccount,
|
960
|
-
currentTime: BN
|
961
|
-
) => {
|
962
|
-
|
963
|
-
const positionAccount = PositionAccount.from(postionKey, postionData);
|
964
|
-
// console.log("positionAccount:",positionAccount);
|
965
|
-
// console.log("side :", postionData.side, (isVariant(postionData.side, 'long')))
|
966
|
-
|
967
|
-
let { profit, loss, exitFee } = poolAccount.getPnlUsd(
|
968
|
-
positionAccount,
|
969
|
-
tokenPrice,
|
970
|
-
tokenEmaPrice,
|
971
|
-
custodyAccount,
|
972
|
-
currentTime,
|
973
|
-
false,
|
974
|
-
);
|
975
|
-
|
976
|
-
return {
|
977
|
-
profit,
|
978
|
-
loss
|
979
|
-
}
|
980
|
-
|
981
|
-
}
|
982
|
-
|
983
|
-
getSwapAmountAndFees = async (
|
984
|
-
poolName: string,
|
985
|
-
tokenMintIn: PublicKey,
|
986
|
-
tokenMintOut: PublicKey,
|
987
|
-
amountIn: BN
|
988
|
-
) => {
|
989
|
-
return await this.program.methods
|
990
|
-
.getSwapAmountAndFees({
|
991
|
-
amountIn,
|
992
|
-
})
|
993
|
-
.accounts({
|
994
|
-
perpetuals: this.perpetuals.publicKey,
|
995
|
-
pool: this.getPoolKey(poolName),
|
996
|
-
receivingCustody: this.getCustodyKey(poolName, tokenMintIn),
|
997
|
-
receivingCustodyOracleAccount: await this.getCustodyOracleAccountKey(
|
998
|
-
poolName,
|
999
|
-
tokenMintIn
|
1000
|
-
),
|
1001
|
-
dispensingCustody: this.getCustodyKey(poolName, tokenMintOut),
|
1002
|
-
dispensingCustodyOracleAccount: await this.getCustodyOracleAccountKey(
|
1003
|
-
poolName,
|
1004
|
-
tokenMintOut
|
1005
|
-
),
|
1006
|
-
})
|
1007
|
-
.view()
|
1008
|
-
.catch((err) => {
|
1009
|
-
console.error(err);
|
1010
|
-
throw err;
|
1011
|
-
});
|
1012
|
-
};
|
1013
|
-
|
1014
|
-
getAumView = async (poolName: string) => {
|
1015
|
-
return await this.program.methods
|
1016
|
-
.getAssetsUnderManagement({})
|
1017
|
-
.accounts({
|
1018
|
-
perpetuals: this.perpetuals.publicKey,
|
1019
|
-
pool: this.getPoolKey(poolName),
|
1020
|
-
})
|
1021
|
-
.remainingAccounts(await this.getCustodyMetas(poolName))
|
1022
|
-
.view()
|
1023
|
-
.catch((err) => {
|
1024
|
-
console.error(err);
|
1025
|
-
throw err;
|
1026
|
-
});
|
1027
|
-
};
|
1028
|
-
|
1029
|
-
getAumTrx = async (poolName: string) => {
|
1030
|
-
return await this.program.methods
|
1031
|
-
.getAssetsUnderManagement({})
|
1032
|
-
.accounts({
|
1033
|
-
perpetuals: this.perpetuals.publicKey,
|
1034
|
-
pool: this.getPoolKey(poolName),
|
1035
|
-
})
|
1036
|
-
.remainingAccounts(await this.getCustodyMetas(poolName))
|
1037
|
-
.rpc()
|
1038
|
-
.catch((err) => {
|
1039
|
-
console.error(err);
|
1040
|
-
throw err;
|
1041
|
-
});
|
1042
|
-
};
|
1043
|
-
|
1044
|
-
getAumSdk = (
|
1045
|
-
poolAccount: PoolAccount,
|
1046
|
-
token_prices: OraclePrice[],
|
1047
|
-
token_ema_prices: OraclePrice[],
|
1048
|
-
custodies: CustodyAccount[],
|
1049
|
-
aum_calc_mode: AumCalcMode,
|
1050
|
-
currentTime: BN
|
1051
|
-
) => {
|
1052
|
-
// console.log("poolAccount:",poolAccount);
|
1053
|
-
|
1054
|
-
return poolAccount.getAssetsUnderManagementUsd(
|
1055
|
-
token_prices,
|
1056
|
-
token_ema_prices,
|
1057
|
-
custodies,
|
1058
|
-
aum_calc_mode,
|
1059
|
-
currentTime
|
1060
|
-
);
|
1061
|
-
};
|
1062
|
-
|
1063
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - DONE
|
1064
|
-
// TODO: Balance checks - DONE
|
1065
|
-
// TODO: ATA check - else create - DONE
|
1066
|
-
// Create WSOL Token account and not ATA and close it in end
|
1067
|
-
// TODO: close other Accounts - NOT NEEDED
|
1068
|
-
openPosition = async (
|
1069
|
-
payTokenSymbol: string,
|
1070
|
-
priceAfterSlippage: BN,
|
1071
|
-
collateralWithfee: BN,
|
1072
|
-
fee : BN,
|
1073
|
-
size: BN,
|
1074
|
-
side: Side,
|
1075
|
-
poolConfig: PoolConfig,
|
1076
|
-
createUserWSOLATA = true,
|
1077
|
-
skipBalanceChecks = false
|
1078
|
-
): Promise< { instructions : TransactionInstruction[] , additionalSigners: Signer[]} > => {
|
1079
|
-
|
1080
|
-
console.log("open position :::", payTokenSymbol, poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey.toBase58());
|
1081
|
-
|
1082
|
-
// const slippageMultiplier = isVariant(side, 'long') ? -1 : 1;
|
1083
|
-
// const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
|
1084
|
-
|
1085
|
-
let publicKey = this.provider.wallet.publicKey;
|
1086
|
-
const payTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey))!;
|
1087
|
-
|
1088
|
-
let userCustodyTokenAccount = await getAssociatedTokenAddress(
|
1089
|
-
poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey,
|
1090
|
-
publicKey
|
1091
|
-
);
|
1092
|
-
|
1093
|
-
let wrappedSolAccount: Keypair | undefined;
|
1094
|
-
let preInstructions: TransactionInstruction[] = [];
|
1095
|
-
let instructions: TransactionInstruction[] = [];
|
1096
|
-
let postInstructions: TransactionInstruction[] = [];
|
1097
|
-
const additionalSigners: Signer[] = [];
|
1098
|
-
|
1099
|
-
try {
|
1100
|
-
|
1101
|
-
// https://github.com/blockworks-foundation/mango-v4/blob/1ba6513b5ea2b0e557808e712fcf0a811968b45b/ts/client/src/client.ts#L1252
|
1102
|
-
// Create WSOL Token account and not ATA and close it in end
|
1103
|
-
if (payTokenSymbol == 'SOL' && createUserWSOLATA) {
|
1104
|
-
console.log("payTokenSymbol === sol", payTokenSymbol);
|
1105
|
-
wrappedSolAccount = new Keypair();
|
1106
|
-
const accCreationLamports = (await getMinimumBalanceForRentExemptAccount(this.provider.connection)); // for account creation
|
1107
|
-
console.log("accCreationLamports:",accCreationLamports)
|
1108
|
-
const lamports = collateralWithfee.add(new BN(accCreationLamports)); // for account creation
|
1109
|
-
|
1110
|
-
preInstructions = [
|
1111
|
-
SystemProgram.createAccount({
|
1112
|
-
fromPubkey: publicKey,
|
1113
|
-
newAccountPubkey: wrappedSolAccount.publicKey,
|
1114
|
-
lamports: lamports.toNumber(), //will this break for large amounts ??
|
1115
|
-
space: 165,
|
1116
|
-
programId: TOKEN_PROGRAM_ID,
|
1117
|
-
}),
|
1118
|
-
createInitializeAccount3Instruction(
|
1119
|
-
wrappedSolAccount.publicKey,
|
1120
|
-
NATIVE_MINT,
|
1121
|
-
publicKey,
|
1122
|
-
),
|
1123
|
-
];
|
1124
|
-
postInstructions = [
|
1125
|
-
createCloseAccountInstruction(
|
1126
|
-
wrappedSolAccount.publicKey,
|
1127
|
-
publicKey,
|
1128
|
-
publicKey,
|
1129
|
-
),
|
1130
|
-
];
|
1131
|
-
additionalSigners.push(wrappedSolAccount);
|
1132
|
-
|
1133
|
-
} else if(createUserWSOLATA == false){
|
1134
|
-
console.log("skip WSOL checks and creation ,since createUserWSOLATA == false")
|
1135
|
-
} else {
|
1136
|
-
// for other tokens check if ATA and balance
|
1137
|
-
if (!(await checkIfAccountExists(userCustodyTokenAccount, this.provider.connection))) {
|
1138
|
-
throw "Insufficient Funds , token Account doesn't exist"
|
1139
|
-
}
|
1140
|
-
|
1141
|
-
if(!skipBalanceChecks){
|
1142
|
-
const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userCustodyTokenAccount)).value.amount);
|
1143
|
-
if (tokenAccountBalance.lt(collateralWithfee)) {
|
1144
|
-
throw `Insufficient Funds need more ${collateralWithfee.sub(tokenAccountBalance)} tokens`
|
1145
|
-
}
|
1146
|
-
}
|
1147
|
-
|
1148
|
-
}
|
1149
|
-
|
1150
|
-
// replace with getPositionKey()
|
1151
|
-
let positionAccount = PublicKey.findProgramAddressSync(
|
1152
|
-
[
|
1153
|
-
Buffer.from("position"),
|
1154
|
-
publicKey.toBuffer(),
|
1155
|
-
poolConfig.poolAddress.toBuffer(),
|
1156
|
-
payTokenCustody.custodyAccount.toBuffer(),
|
1157
|
-
isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
|
1158
|
-
],
|
1159
|
-
this.programId
|
1160
|
-
)[0];
|
1161
|
-
|
1162
|
-
const params: any = {
|
1163
|
-
price: priceAfterSlippage,
|
1164
|
-
collateral : collateralWithfee,
|
1165
|
-
size,
|
1166
|
-
side,
|
1167
|
-
};
|
1168
|
-
|
1169
|
-
let instruction = await this.program.methods
|
1170
|
-
.openPosition(params)
|
1171
|
-
.accounts({
|
1172
|
-
owner: publicKey,
|
1173
|
-
fundingAccount: payTokenSymbol == 'SOL' ? wrappedSolAccount.publicKey : userCustodyTokenAccount,
|
1174
|
-
transferAuthority: poolConfig.transferAuthority,
|
1175
|
-
perpetuals: poolConfig.perpetuals,
|
1176
|
-
pool: poolConfig.poolAddress,
|
1177
|
-
position: positionAccount,
|
1178
|
-
custody: payTokenCustody.custodyAccount,
|
1179
|
-
custodyOracleAccount:
|
1180
|
-
payTokenCustody.oracleAddress,
|
1181
|
-
custodyTokenAccount:
|
1182
|
-
payTokenCustody.tokenAccount,
|
1183
|
-
systemProgram: SystemProgram.programId,
|
1184
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1185
|
-
}).instruction()
|
1186
|
-
|
1187
|
-
|
1188
|
-
instructions.push(instruction);
|
1189
|
-
|
1190
|
-
} catch (error) {
|
1191
|
-
console.log("perpClient openPosition error:", error)
|
1192
|
-
}
|
1193
|
-
return {
|
1194
|
-
instructions : [...preInstructions, ...instructions ,...postInstructions],
|
1195
|
-
additionalSigners
|
1196
|
-
};
|
1197
|
-
}
|
1198
|
-
|
1199
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - NOT NEEDED
|
1200
|
-
// TODO : Balance checks - NOT NEEDED
|
1201
|
-
// TODO: ATA check - else create - DONE
|
1202
|
-
// TODO: for close Accounts - DONE BY ANCHOR
|
1203
|
-
// TODO : if out token WSOL -> unwrap to SOL - DONE
|
1204
|
-
closePosition = async (
|
1205
|
-
receivingTokenSymbol: string,
|
1206
|
-
priceAfterSlippage: BN,
|
1207
|
-
side: Side,
|
1208
|
-
poolConfig: PoolConfig,
|
1209
|
-
createUserATA = true,
|
1210
|
-
closeUsersWSOLATA = false // to get back WSOL=>SOL
|
1211
|
-
): Promise< { instructions : TransactionInstruction[] , additionalSigners: Signer[]}> => {
|
1212
|
-
|
1213
|
-
console.log("close position :::", receivingTokenSymbol, poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey.toBase58());
|
1214
|
-
|
1215
|
-
// opp during close
|
1216
|
-
// const slippageMultiplier = isVariant(side, 'short') ? -1 : 1;
|
1217
|
-
// const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
|
1218
|
-
|
1219
|
-
let publicKey = this.provider.wallet.publicKey;
|
1220
|
-
|
1221
|
-
let userReceivingTokenAccount : PublicKey;
|
1222
|
-
let wrappedSolAccount: Keypair | undefined;
|
1223
|
-
let preInstructions: TransactionInstruction[] = [];
|
1224
|
-
let instructions: TransactionInstruction[] = [];
|
1225
|
-
let postInstructions: TransactionInstruction[] = [];
|
1226
|
-
const additionalSigners: Signer[] = [];
|
1227
|
-
try {
|
1228
|
-
|
1229
|
-
if (receivingTokenSymbol == 'SOL') {
|
1230
|
-
wrappedSolAccount = new Keypair();
|
1231
|
-
userReceivingTokenAccount = wrappedSolAccount.publicKey;
|
1232
|
-
const lamports = (await getMinimumBalanceForRentExemptAccount(this.provider.connection)); // for account creation
|
1233
|
-
|
1234
|
-
preInstructions = [
|
1235
|
-
SystemProgram.createAccount({
|
1236
|
-
fromPubkey: publicKey,
|
1237
|
-
newAccountPubkey: wrappedSolAccount.publicKey,
|
1238
|
-
lamports: lamports, //will this break for large amounts ??
|
1239
|
-
space: 165,
|
1240
|
-
programId: TOKEN_PROGRAM_ID,
|
1241
|
-
}),
|
1242
|
-
createInitializeAccount3Instruction(
|
1243
|
-
wrappedSolAccount.publicKey,
|
1244
|
-
NATIVE_MINT,
|
1245
|
-
publicKey,
|
1246
|
-
),
|
1247
|
-
];
|
1248
|
-
postInstructions = [
|
1249
|
-
createCloseAccountInstruction(
|
1250
|
-
wrappedSolAccount.publicKey,
|
1251
|
-
publicKey,
|
1252
|
-
publicKey,
|
1253
|
-
),
|
1254
|
-
];
|
1255
|
-
additionalSigners.push(wrappedSolAccount);
|
1256
|
-
} else {
|
1257
|
-
|
1258
|
-
userReceivingTokenAccount = await getAssociatedTokenAddress(
|
1259
|
-
poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey,
|
1260
|
-
publicKey
|
1261
|
-
);
|
1262
|
-
|
1263
|
-
if (createUserATA && !(await checkIfAccountExists(userReceivingTokenAccount, this.provider.connection))) {
|
1264
|
-
preInstructions.push(
|
1265
|
-
createAssociatedTokenAccountInstruction(
|
1266
|
-
publicKey,
|
1267
|
-
userReceivingTokenAccount,
|
1268
|
-
publicKey,
|
1269
|
-
poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey
|
1270
|
-
)
|
1271
|
-
);
|
1272
|
-
}
|
1273
|
-
|
1274
|
-
}
|
1275
|
-
|
1276
|
-
|
1277
|
-
const receivingTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey))!;
|
1278
|
-
|
1279
|
-
// replace with getPositionKey
|
1280
|
-
let positionAccount = PublicKey.findProgramAddressSync(
|
1281
|
-
[
|
1282
|
-
Buffer.from("position"),
|
1283
|
-
publicKey.toBuffer(),
|
1284
|
-
poolConfig.poolAddress.toBuffer(),
|
1285
|
-
receivingTokenCustody.custodyAccount.toBuffer(),
|
1286
|
-
isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
|
1287
|
-
],
|
1288
|
-
this.programId
|
1289
|
-
)[0];
|
1290
|
-
|
1291
|
-
// console.log("positionAccount:", positionAccount.toBase58())
|
1292
|
-
const params: any = {
|
1293
|
-
price: priceAfterSlippage,
|
1294
|
-
};
|
1295
|
-
|
1296
|
-
let instruction = await this.program.methods
|
1297
|
-
.closePosition(params)
|
1298
|
-
.accounts({
|
1299
|
-
owner: publicKey,
|
1300
|
-
receivingAccount: userReceivingTokenAccount,
|
1301
|
-
transferAuthority: poolConfig.transferAuthority,
|
1302
|
-
perpetuals: poolConfig.perpetuals,
|
1303
|
-
pool: poolConfig.poolAddress,
|
1304
|
-
position: positionAccount,
|
1305
|
-
custody: receivingTokenCustody.custodyAccount,
|
1306
|
-
custodyOracleAccount:
|
1307
|
-
receivingTokenCustody.oracleAddress,
|
1308
|
-
custodyTokenAccount:
|
1309
|
-
receivingTokenCustody.tokenAccount,
|
1310
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1311
|
-
}).instruction();
|
1312
|
-
instructions.push(instruction)
|
1313
|
-
|
1314
|
-
if (receivingTokenSymbol == 'WSOL' && closeUsersWSOLATA) {
|
1315
|
-
const closeWsolATAIns = createCloseAccountInstruction(userReceivingTokenAccount, publicKey, publicKey);
|
1316
|
-
postInstructions.push(closeWsolATAIns);
|
1317
|
-
}
|
1318
|
-
} catch (error) {
|
1319
|
-
console.error("perpclient closePosition error:", error);
|
1320
|
-
}
|
1321
|
-
|
1322
|
-
return {
|
1323
|
-
instructions : [...preInstructions, ...instructions ,...postInstructions],
|
1324
|
-
additionalSigners
|
1325
|
-
};
|
1326
|
-
}
|
1327
|
-
|
1328
|
-
|
1329
|
-
// ==== OLD
|
1330
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - DONE
|
1331
|
-
// TODO: Balance checks - DONE
|
1332
|
-
// TODO: ATA check - else create - DONE
|
1333
|
-
// TODO: for close Accounts - NOT NEEDED
|
1334
|
-
openPositionOld = async (
|
1335
|
-
payTokenSymbol: string,
|
1336
|
-
priceAfterSlippage: BN,
|
1337
|
-
collateral: BN,
|
1338
|
-
fee : BN,
|
1339
|
-
size: BN,
|
1340
|
-
side: Side,
|
1341
|
-
poolConfig: PoolConfig,
|
1342
|
-
createUserWSOLATA = true // if false will also skip balance checks
|
1343
|
-
): Promise<TransactionInstruction[]> => {
|
1344
|
-
|
1345
|
-
console.log("open position :::", payTokenSymbol, poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey.toBase58());
|
1346
|
-
|
1347
|
-
// const slippageMultiplier = isVariant(side, 'long') ? -1 : 1;
|
1348
|
-
// const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
|
1349
|
-
|
1350
|
-
let publicKey = this.provider.wallet.publicKey;
|
1351
|
-
const payTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey))!;
|
1352
|
-
|
1353
|
-
let userCustodyTokenAccount = await getAssociatedTokenAddress(
|
1354
|
-
poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey,
|
1355
|
-
publicKey
|
1356
|
-
);
|
1357
|
-
|
1358
|
-
const instructions = [];
|
1359
|
-
try {
|
1360
|
-
|
1361
|
-
if (payTokenSymbol == 'SOL' && createUserWSOLATA) {
|
1362
|
-
console.log("payTokenSymbol === sol", payTokenSymbol);
|
1363
|
-
const wsolAssociatedTokenAccount = userCustodyTokenAccount;
|
1364
|
-
// await getAssociatedTokenAddress(
|
1365
|
-
// NATIVE_MINT,
|
1366
|
-
// publicKey
|
1367
|
-
// );
|
1368
|
-
const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
|
1369
|
-
if (!wsolATAExist) {
|
1370
|
-
console.log("wsol ata does not exist");
|
1371
|
-
instructions.push(
|
1372
|
-
createAssociatedTokenAccountInstruction(
|
1373
|
-
publicKey,
|
1374
|
-
wsolAssociatedTokenAccount,
|
1375
|
-
publicKey,
|
1376
|
-
NATIVE_MINT
|
1377
|
-
)
|
1378
|
-
);
|
1379
|
-
}
|
1380
|
-
|
1381
|
-
const collateralWithfee = collateral.add(fee);
|
1382
|
-
|
1383
|
-
// get balance of WSOL associated token account
|
1384
|
-
const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
|
1385
|
-
if (wsolBalance.lt(collateralWithfee)) {
|
1386
|
-
console.log("WSOL balance insufficient \n so Convert SOL to WSOL");
|
1387
|
-
let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
|
1388
|
-
const totalSolBal = unWrappedSolBalance.add(wsolBalance);
|
1389
|
-
// const rentExemptSolNeedforATA = new BN(0.02 * LAMPORTS_PER_SOL);
|
1390
|
-
// console.log("rentExemptSolNeedforATA:",rentExemptSolNeedforATA.toString())
|
1391
|
-
//TODOD :: add(rentExemptSolNeedforATA)
|
1392
|
-
if (totalSolBal.lt(collateralWithfee)) {
|
1393
|
-
throw "Insufficient SOL Funds"
|
1394
|
-
} else {
|
1395
|
-
console.log("SOL balance sufficient so transfer from SOL to WSOL ATA")
|
1396
|
-
}
|
1397
|
-
|
1398
|
-
let conversionAmt = collateralWithfee.sub(wsolBalance);
|
1399
|
-
console.log("conversionAmt:",conversionAmt.toString())
|
1400
|
-
instructions.push(
|
1401
|
-
SystemProgram.transfer({
|
1402
|
-
fromPubkey: publicKey,
|
1403
|
-
toPubkey: wsolAssociatedTokenAccount,
|
1404
|
-
lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER
|
1405
|
-
}),
|
1406
|
-
createSyncNativeInstruction(wsolAssociatedTokenAccount)
|
1407
|
-
);
|
1408
|
-
}
|
1409
|
-
} else if(createUserWSOLATA == false){
|
1410
|
-
console.log("skip WSOL checks and creation ,since createUserWSOLATA == false")
|
1411
|
-
} else {
|
1412
|
-
// for other tokens check if ATA and balance
|
1413
|
-
if (!(await checkIfAccountExists(userCustodyTokenAccount, this.provider.connection))) {
|
1414
|
-
throw "Insufficient Funds , token Account doesn't exist"
|
1415
|
-
}
|
1416
|
-
const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userCustodyTokenAccount)).value.amount);
|
1417
|
-
if (tokenAccountBalance.lt(collateral.add(fee))) {
|
1418
|
-
throw "Insufficient Funds"
|
1419
|
-
}
|
1420
|
-
}
|
1421
|
-
|
1422
|
-
// replace with getPositionKey()
|
1423
|
-
let positionAccount = PublicKey.findProgramAddressSync(
|
1424
|
-
[
|
1425
|
-
Buffer.from("position"),
|
1426
|
-
publicKey.toBuffer(),
|
1427
|
-
poolConfig.poolAddress.toBuffer(),
|
1428
|
-
payTokenCustody.custodyAccount.toBuffer(),
|
1429
|
-
isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
|
1430
|
-
],
|
1431
|
-
this.programId
|
1432
|
-
)[0];
|
1433
|
-
|
1434
|
-
const params: any = {
|
1435
|
-
price: priceAfterSlippage,
|
1436
|
-
collateral,
|
1437
|
-
size,
|
1438
|
-
side,
|
1439
|
-
};
|
1440
|
-
|
1441
|
-
let instruction = await this.program.methods
|
1442
|
-
.openPosition(params)
|
1443
|
-
.accounts({
|
1444
|
-
owner: publicKey,
|
1445
|
-
fundingAccount: userCustodyTokenAccount,
|
1446
|
-
transferAuthority: poolConfig.transferAuthority,
|
1447
|
-
perpetuals: poolConfig.perpetuals,
|
1448
|
-
pool: poolConfig.poolAddress,
|
1449
|
-
position: positionAccount,
|
1450
|
-
custody: payTokenCustody.custodyAccount,
|
1451
|
-
custodyOracleAccount:
|
1452
|
-
payTokenCustody.oracleAddress,
|
1453
|
-
custodyTokenAccount:
|
1454
|
-
payTokenCustody.tokenAccount,
|
1455
|
-
systemProgram: SystemProgram.programId,
|
1456
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1457
|
-
}).instruction()
|
1458
|
-
instructions.push(instruction);
|
1459
|
-
|
1460
|
-
} catch (error) {
|
1461
|
-
console.log("perpClient openPosition error:", error)
|
1462
|
-
}
|
1463
|
-
return instructions;
|
1464
|
-
}
|
1465
|
-
|
1466
|
-
// ==== OLD
|
1467
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - NOT NEEDED
|
1468
|
-
// TODO : Balance checks - NOT NEEDED
|
1469
|
-
// TODO: ATA check - else create - DONE
|
1470
|
-
// TODO: for close Accounts - DONE BY ANCHOR
|
1471
|
-
// TODO : if out token WSOL -> unwrap to SOL - DONE
|
1472
|
-
closePositionOld = async (
|
1473
|
-
receivingTokenSymbol: string,
|
1474
|
-
priceAfterSlippage: BN,
|
1475
|
-
side: Side,
|
1476
|
-
poolConfig: PoolConfig
|
1477
|
-
): Promise<TransactionInstruction[]> => {
|
1478
|
-
|
1479
|
-
console.log("close position :::", receivingTokenSymbol, poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey.toBase58());
|
1480
|
-
|
1481
|
-
// opp during close
|
1482
|
-
// const slippageMultiplier = isVariant(side, 'short') ? -1 : 1;
|
1483
|
-
// const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
|
1484
|
-
|
1485
|
-
let publicKey = this.provider.wallet.publicKey;
|
1486
|
-
|
1487
|
-
let userReceivingTokenAccount = await getAssociatedTokenAddress(
|
1488
|
-
poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey,
|
1489
|
-
publicKey
|
1490
|
-
);
|
1491
|
-
const instructions = [];
|
1492
|
-
try {
|
1493
|
-
|
1494
|
-
if (!(await checkIfAccountExists(userReceivingTokenAccount, this.provider.connection))) {
|
1495
|
-
instructions.push(
|
1496
|
-
createAssociatedTokenAccountInstruction(
|
1497
|
-
publicKey,
|
1498
|
-
userReceivingTokenAccount,
|
1499
|
-
publicKey,
|
1500
|
-
poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey
|
1501
|
-
)
|
1502
|
-
);
|
1503
|
-
}
|
1504
|
-
|
1505
|
-
const receivingTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey))!;
|
1506
|
-
|
1507
|
-
// replace with getPositionKey
|
1508
|
-
let positionAccount = PublicKey.findProgramAddressSync(
|
1509
|
-
[
|
1510
|
-
Buffer.from("position"),
|
1511
|
-
publicKey.toBuffer(),
|
1512
|
-
poolConfig.poolAddress.toBuffer(),
|
1513
|
-
receivingTokenCustody.custodyAccount.toBuffer(),
|
1514
|
-
isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
|
1515
|
-
],
|
1516
|
-
this.programId
|
1517
|
-
)[0];
|
1518
|
-
|
1519
|
-
console.log("positionAccount:", positionAccount.toBase58())
|
1520
|
-
const params: any = {
|
1521
|
-
price: priceAfterSlippage,
|
1522
|
-
};
|
1523
|
-
|
1524
|
-
let instruction = await this.program.methods
|
1525
|
-
.closePosition(params)
|
1526
|
-
.accounts({
|
1527
|
-
owner: publicKey,
|
1528
|
-
receivingAccount: userReceivingTokenAccount,
|
1529
|
-
transferAuthority: poolConfig.transferAuthority,
|
1530
|
-
perpetuals: poolConfig.perpetuals,
|
1531
|
-
pool: poolConfig.poolAddress,
|
1532
|
-
position: positionAccount,
|
1533
|
-
custody: receivingTokenCustody.custodyAccount,
|
1534
|
-
custodyOracleAccount:
|
1535
|
-
receivingTokenCustody.oracleAddress,
|
1536
|
-
custodyTokenAccount:
|
1537
|
-
receivingTokenCustody.tokenAccount,
|
1538
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1539
|
-
}).instruction();
|
1540
|
-
instructions.push(instruction)
|
1541
|
-
|
1542
|
-
// SOL is only retrievable by closing the token account and choosing the desired address to send the token account's lamports.
|
1543
|
-
if (receivingTokenSymbol == 'SOL') {
|
1544
|
-
// await closeAccount()
|
1545
|
-
const closeWsolATAIns = createCloseAccountInstruction(userReceivingTokenAccount, publicKey, publicKey);
|
1546
|
-
instructions.push(closeWsolATAIns);
|
1547
|
-
}
|
1548
|
-
} catch (error) {
|
1549
|
-
console.error("perpclient closePosition error:", error);
|
1550
|
-
}
|
1551
|
-
|
1552
|
-
return instructions;
|
1553
|
-
}
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
// TODO: ATA check - else create - DONE
|
1558
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - DONE
|
1559
|
-
// TODO : Balance checks - NOT NEEDED
|
1560
|
-
// TODO: for close Accounts - DONE BY ANCHOR
|
1561
|
-
// TODO : if out token WSOL -> unwrap to SOL - DONE
|
1562
|
-
swap = async (
|
1563
|
-
poolReceivingTokenSymbol: string,
|
1564
|
-
poolDispensingTokenSymbol: string,
|
1565
|
-
amountIn: BN,
|
1566
|
-
minAmountOut: BN,
|
1567
|
-
poolConfig: PoolConfig,
|
1568
|
-
unWrapSol = false
|
1569
|
-
): Promise<TransactionInstruction[]> => {
|
1570
|
-
|
1571
|
-
const userReceivingTokenSymbol = poolDispensingTokenSymbol;
|
1572
|
-
const userDispensingTokenSymbol= poolReceivingTokenSymbol;
|
1573
|
-
|
1574
|
-
const poolReceivingCustodyConfig = poolConfig.custodies.find(
|
1575
|
-
(i) => i.mintKey.toBase58() === poolConfig.getTokenFromSymbol(poolReceivingTokenSymbol).mintKey.toBase58()
|
1576
|
-
);
|
1577
|
-
if (!poolReceivingCustodyConfig) {
|
1578
|
-
throw "receivingTokenCustody not found";
|
1579
|
-
}
|
1580
|
-
const poolDispensingCustodyConfig = poolConfig.custodies.find(
|
1581
|
-
(i) => i.mintKey.toBase58() === poolConfig.getTokenFromSymbol(poolDispensingTokenSymbol).mintKey.toBase58()
|
1582
|
-
);
|
1583
|
-
if (!poolDispensingCustodyConfig) {
|
1584
|
-
throw "dispensingTokenCustody not found";
|
1585
|
-
}
|
1586
|
-
let publicKey = this.provider.wallet.publicKey;
|
1587
|
-
|
1588
|
-
|
1589
|
-
const instructions = [];
|
1590
|
-
try {
|
1591
|
-
let userReceivingTokenAccount = await getAssociatedTokenAddress(
|
1592
|
-
poolDispensingCustodyConfig.mintKey,
|
1593
|
-
publicKey
|
1594
|
-
);
|
1595
|
-
if (!(await checkIfAccountExists(userReceivingTokenAccount, this.provider.connection))) {
|
1596
|
-
instructions.push(
|
1597
|
-
createAssociatedTokenAccountInstruction(
|
1598
|
-
publicKey,
|
1599
|
-
userReceivingTokenAccount,
|
1600
|
-
publicKey,
|
1601
|
-
poolDispensingCustodyConfig.mintKey
|
1602
|
-
)
|
1603
|
-
);
|
1604
|
-
}
|
1605
|
-
|
1606
|
-
let userDispensingCustodyTokenAccount = await getAssociatedTokenAddress(
|
1607
|
-
poolReceivingCustodyConfig.mintKey,
|
1608
|
-
publicKey
|
1609
|
-
);
|
1610
|
-
// handle Wrapping of SOL if user input token is SOL
|
1611
|
-
if (userDispensingTokenSymbol == 'SOL') {
|
1612
|
-
console.log("userDispensingTokenSymbol === sol", userDispensingTokenSymbol);
|
1613
|
-
const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
|
1614
|
-
NATIVE_MINT,
|
1615
|
-
publicKey
|
1616
|
-
);
|
1617
|
-
const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
|
1618
|
-
if (!wsolATAExist) {
|
1619
|
-
console.log("wsol ata does not exist");
|
1620
|
-
instructions.push(
|
1621
|
-
createAssociatedTokenAccountInstruction(
|
1622
|
-
publicKey,
|
1623
|
-
wsolAssociatedTokenAccount,
|
1624
|
-
publicKey,
|
1625
|
-
NATIVE_MINT
|
1626
|
-
)
|
1627
|
-
);
|
1628
|
-
}
|
1629
|
-
|
1630
|
-
// get balance of WSOL associated token account
|
1631
|
-
const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
|
1632
|
-
if (wsolBalance.lt(amountIn)) {
|
1633
|
-
// console.log("WSOL balance insufficient");
|
1634
|
-
// so Convert SOL to WSOL
|
1635
|
-
let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
|
1636
|
-
const totalSolBal = unWrappedSolBalance.add(wsolBalance);
|
1637
|
-
if (totalSolBal.lt(amountIn)) {
|
1638
|
-
throw "Insufficient SOL Funds"
|
1639
|
-
}
|
1640
|
-
|
1641
|
-
let conversionAmt = amountIn.sub(wsolBalance);
|
1642
|
-
instructions.push(
|
1643
|
-
SystemProgram.transfer({
|
1644
|
-
fromPubkey: publicKey,
|
1645
|
-
toPubkey: wsolAssociatedTokenAccount,
|
1646
|
-
lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER ?
|
1647
|
-
}),
|
1648
|
-
createSyncNativeInstruction(wsolAssociatedTokenAccount)
|
1649
|
-
);
|
1650
|
-
}
|
1651
|
-
} else {
|
1652
|
-
if (!(await checkIfAccountExists(userDispensingCustodyTokenAccount, this.provider.connection))) {
|
1653
|
-
throw "Insufficient Funds , Token Account doesn't exist"
|
1654
|
-
}
|
1655
|
-
const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userDispensingCustodyTokenAccount)).value.amount);
|
1656
|
-
if (tokenAccountBalance.lt(amountIn)) {
|
1657
|
-
throw "Insufficient Funds"
|
1658
|
-
}
|
1659
|
-
}
|
1660
|
-
|
1661
|
-
const params = {
|
1662
|
-
amountIn,
|
1663
|
-
minAmountOut,
|
1664
|
-
};
|
1665
|
-
let inx = await this.program.methods
|
1666
|
-
.swap(params)
|
1667
|
-
.accounts({
|
1668
|
-
owner: publicKey,
|
1669
|
-
fundingAccount: userDispensingCustodyTokenAccount,
|
1670
|
-
receivingAccount: userReceivingTokenAccount,
|
1671
|
-
transferAuthority: poolConfig.transferAuthority,
|
1672
|
-
perpetuals: poolConfig.perpetuals,
|
1673
|
-
pool: poolConfig.poolAddress,
|
1674
|
-
|
1675
|
-
receivingCustody: poolReceivingCustodyConfig.custodyAccount,
|
1676
|
-
receivingCustodyOracleAccount: poolReceivingCustodyConfig.oracleAddress,
|
1677
|
-
receivingCustodyTokenAccount: poolReceivingCustodyConfig.tokenAccount,
|
1678
|
-
|
1679
|
-
dispensingCustody: poolDispensingCustodyConfig.custodyAccount,
|
1680
|
-
dispensingCustodyOracleAccount: poolDispensingCustodyConfig.oracleAddress,
|
1681
|
-
dispensingCustodyTokenAccount: poolDispensingCustodyConfig.tokenAccount,
|
1682
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1683
|
-
})
|
1684
|
-
.instruction();
|
1685
|
-
|
1686
|
-
instructions.push(inx)
|
1687
|
-
|
1688
|
-
// SOL is only retrievable by closing the token account and choosing the desired address to send the token account's lamports.
|
1689
|
-
if (userReceivingTokenSymbol == 'SOL' && unWrapSol) {
|
1690
|
-
// await closeAccount()
|
1691
|
-
const closeWsolATAIns = createCloseAccountInstruction(userReceivingTokenAccount, publicKey, publicKey);
|
1692
|
-
instructions.push(closeWsolATAIns);
|
1693
|
-
}
|
1694
|
-
|
1695
|
-
} catch (err) {
|
1696
|
-
console.error("perpClient Swap error:: ", err);
|
1697
|
-
throw err;
|
1698
|
-
}
|
1699
|
-
|
1700
|
-
return instructions;
|
1701
|
-
}
|
1702
|
-
|
1703
|
-
addCollateral = async (
|
1704
|
-
collateralWithoutFee: BN,
|
1705
|
-
fee: BN,
|
1706
|
-
collateralSymbol: string,
|
1707
|
-
positionPubKey: PublicKey,
|
1708
|
-
poolConfig: PoolConfig
|
1709
|
-
): Promise<TransactionInstruction[]> => {
|
1710
|
-
let publicKey = this.provider.wallet.publicKey;
|
1711
|
-
|
1712
|
-
const custody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(collateralSymbol).mintKey))!;
|
1713
|
-
|
1714
|
-
if (!custody) {
|
1715
|
-
throw "payTokenCustody not found";
|
1716
|
-
}
|
1717
|
-
|
1718
|
-
const instructions = [];
|
1719
|
-
|
1720
|
-
let userPayingTokenAccount = getAssociatedTokenAddressSync(
|
1721
|
-
custody.mintKey,
|
1722
|
-
publicKey
|
1723
|
-
);
|
1724
|
-
|
1725
|
-
const collateralWithfee = collateralWithoutFee.add(fee);
|
1726
|
-
|
1727
|
-
if (collateralSymbol == 'SOL') {
|
1728
|
-
console.log("collateralSymbol === sol", collateralSymbol);
|
1729
|
-
const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
|
1730
|
-
NATIVE_MINT,
|
1731
|
-
publicKey
|
1732
|
-
);
|
1733
|
-
|
1734
|
-
const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
|
1735
|
-
if (!wsolATAExist) {
|
1736
|
-
console.log("wsol ata does not exist");
|
1737
|
-
instructions.push(
|
1738
|
-
createAssociatedTokenAccountInstruction(
|
1739
|
-
publicKey,
|
1740
|
-
wsolAssociatedTokenAccount,
|
1741
|
-
publicKey,
|
1742
|
-
NATIVE_MINT
|
1743
|
-
)
|
1744
|
-
);
|
1745
|
-
}
|
1746
|
-
|
1747
|
-
// get balance of WSOL associated token account
|
1748
|
-
const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
|
1749
|
-
if (wsolBalance.lt(collateralWithfee)) {
|
1750
|
-
// console.log("WSOL balance insufficient");
|
1751
|
-
// so Convert SOL to WSOL
|
1752
|
-
let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
|
1753
|
-
const totalSolBal = unWrappedSolBalance.add(wsolBalance);
|
1754
|
-
if (totalSolBal.lt(collateralWithfee)) {
|
1755
|
-
throw "Insufficient SOL Funds"
|
1756
|
-
}
|
1757
|
-
|
1758
|
-
let conversionAmt = collateralWithfee.sub(wsolBalance);
|
1759
|
-
instructions.push(
|
1760
|
-
SystemProgram.transfer({
|
1761
|
-
fromPubkey: publicKey,
|
1762
|
-
toPubkey: wsolAssociatedTokenAccount,
|
1763
|
-
lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER
|
1764
|
-
}),
|
1765
|
-
createSyncNativeInstruction(wsolAssociatedTokenAccount)
|
1766
|
-
);
|
1767
|
-
}
|
1768
|
-
}
|
1769
|
-
|
1770
|
-
let inx = await this.program.methods.addCollateral({
|
1771
|
-
collateral: collateralWithoutFee
|
1772
|
-
}).accounts({
|
1773
|
-
owner: publicKey,
|
1774
|
-
position: positionPubKey,
|
1775
|
-
fundingAccount: userPayingTokenAccount, // user token account for custody token account
|
1776
|
-
transferAuthority: poolConfig.transferAuthority,
|
1777
|
-
perpetuals: poolConfig.perpetuals,
|
1778
|
-
pool: poolConfig.poolAddress,
|
1779
|
-
custody: custody.custodyAccount,
|
1780
|
-
custodyOracleAccount: custody.oracleAddress,
|
1781
|
-
custodyTokenAccount: custody.tokenAccount,
|
1782
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1783
|
-
})
|
1784
|
-
.instruction();
|
1785
|
-
|
1786
|
-
instructions.push(inx)
|
1787
|
-
|
1788
|
-
return instructions
|
1789
|
-
}
|
1790
|
-
|
1791
|
-
removeCollateral = async (
|
1792
|
-
collateralWithoutFee: BN,
|
1793
|
-
collateralSymbol: string,
|
1794
|
-
positionPubKey: PublicKey,
|
1795
|
-
poolConfig: PoolConfig
|
1796
|
-
): Promise<TransactionInstruction[]> => {
|
1797
|
-
let publicKey = this.provider.wallet.publicKey;
|
1798
|
-
|
1799
|
-
const custody = poolConfig.custodies.find((i) =>
|
1800
|
-
i.mintKey.equals(poolConfig.getTokenFromSymbol(collateralSymbol).mintKey)
|
1801
|
-
)!
|
1802
|
-
|
1803
|
-
if (!custody) {
|
1804
|
-
throw "payTokenCustody not found";
|
1805
|
-
}
|
1806
|
-
|
1807
|
-
const instructions = [];
|
1808
|
-
|
1809
|
-
let userReceivingTokenAccount = getAssociatedTokenAddressSync(
|
1810
|
-
poolConfig.getTokenFromSymbol(collateralSymbol).mintKey,
|
1811
|
-
publicKey!
|
1812
|
-
)
|
1813
|
-
|
1814
|
-
if (!(await checkIfAccountExists(userReceivingTokenAccount, this.provider.connection))) {
|
1815
|
-
instructions.push(
|
1816
|
-
createAssociatedTokenAccountInstruction(
|
1817
|
-
publicKey!,
|
1818
|
-
userReceivingTokenAccount,
|
1819
|
-
publicKey!,
|
1820
|
-
poolConfig.getTokenFromSymbol(collateralSymbol).mintKey
|
1821
|
-
)
|
1822
|
-
)
|
1823
|
-
}
|
1824
|
-
|
1825
|
-
const ix = await this.program.methods
|
1826
|
-
.removeCollateral({
|
1827
|
-
collateralUsd: collateralWithoutFee,
|
1828
|
-
})
|
1829
|
-
.accounts({
|
1830
|
-
owner: publicKey!,
|
1831
|
-
receivingAccount: userReceivingTokenAccount, // user token account for custody token account
|
1832
|
-
transferAuthority: poolConfig.transferAuthority,
|
1833
|
-
perpetuals: poolConfig.perpetuals,
|
1834
|
-
pool: poolConfig.poolAddress,
|
1835
|
-
position: positionPubKey,
|
1836
|
-
custody: custody.custodyAccount,
|
1837
|
-
custodyOracleAccount: custody.oracleAddress,
|
1838
|
-
custodyTokenAccount: custody.tokenAccount,
|
1839
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1840
|
-
})
|
1841
|
-
.instruction()
|
1842
|
-
|
1843
|
-
instructions.push(ix)
|
1844
|
-
|
1845
|
-
if (collateralSymbol === 'SOL') {
|
1846
|
-
const closeWsolATAIns = createCloseAccountInstruction(userReceivingTokenAccount, publicKey!, publicKey!)
|
1847
|
-
instructions.push(closeWsolATAIns)
|
1848
|
-
}
|
1849
|
-
|
1850
|
-
return instructions
|
1851
|
-
}
|
1852
|
-
|
1853
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - DONE
|
1854
|
-
// TODO :Balance checks - DONE
|
1855
|
-
// TODO: ATA check - else create - DONE
|
1856
|
-
// TODO: for close Accounts - NOT NEEDED
|
1857
|
-
addLiquidity = async (
|
1858
|
-
payTokenSymbol: string,
|
1859
|
-
tokenAmountIn: BN,
|
1860
|
-
minLpAmountOut: BN, // give this value based on slippage
|
1861
|
-
poolConfig: PoolConfig
|
1862
|
-
): Promise<TransactionInstruction[]> => {
|
1863
|
-
|
1864
|
-
const payTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey))!;
|
1865
|
-
if (!payTokenCustody) {
|
1866
|
-
throw "payTokenCustody not found";
|
1867
|
-
}
|
1868
|
-
let publicKey = this.provider.wallet.publicKey;
|
1869
|
-
|
1870
|
-
const instructions = [];
|
1871
|
-
try {
|
1872
|
-
|
1873
|
-
let userPayingTokenAccount = await getAssociatedTokenAddress(
|
1874
|
-
payTokenCustody.mintKey,
|
1875
|
-
publicKey
|
1876
|
-
);
|
1877
|
-
|
1878
|
-
let lpTokenAccount = await getAssociatedTokenAddress(
|
1879
|
-
poolConfig.lpTokenMint,
|
1880
|
-
publicKey
|
1881
|
-
);
|
1882
|
-
|
1883
|
-
let custodyAccountMetas = [];
|
1884
|
-
let custodyOracleAccountMetas = [];
|
1885
|
-
for (const custody of poolConfig.custodies) {
|
1886
|
-
custodyAccountMetas.push({
|
1887
|
-
pubkey: custody.custodyAccount,
|
1888
|
-
isSigner: false,
|
1889
|
-
isWritable: false,
|
1890
|
-
});
|
1891
|
-
|
1892
|
-
custodyOracleAccountMetas.push({
|
1893
|
-
pubkey: custody.oracleAddress,
|
1894
|
-
isSigner: false,
|
1895
|
-
isWritable: false,
|
1896
|
-
});
|
1897
|
-
}
|
1898
|
-
|
1899
|
-
if (!(await checkIfAccountExists(lpTokenAccount, this.provider.connection))) {
|
1900
|
-
instructions.push(
|
1901
|
-
createAssociatedTokenAccountInstruction(
|
1902
|
-
publicKey,
|
1903
|
-
lpTokenAccount,
|
1904
|
-
publicKey,
|
1905
|
-
poolConfig.lpTokenMint
|
1906
|
-
)
|
1907
|
-
);
|
1908
|
-
}
|
1909
|
-
|
1910
|
-
if (payTokenSymbol == 'SOL') {
|
1911
|
-
console.log("payTokenSymbol === sol", payTokenSymbol);
|
1912
|
-
const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
|
1913
|
-
NATIVE_MINT,
|
1914
|
-
publicKey
|
1915
|
-
);
|
1916
|
-
|
1917
|
-
const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
|
1918
|
-
if (!wsolATAExist) {
|
1919
|
-
console.log("wsol ata does not exist");
|
1920
|
-
instructions.push(
|
1921
|
-
createAssociatedTokenAccountInstruction(
|
1922
|
-
publicKey,
|
1923
|
-
wsolAssociatedTokenAccount,
|
1924
|
-
publicKey,
|
1925
|
-
NATIVE_MINT
|
1926
|
-
)
|
1927
|
-
);
|
1928
|
-
}
|
1929
|
-
|
1930
|
-
// get balance of WSOL associated token account
|
1931
|
-
const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
|
1932
|
-
if (wsolBalance.lt(tokenAmountIn)) {
|
1933
|
-
// console.log("WSOL balance insufficient");
|
1934
|
-
// so Convert SOL to WSOL
|
1935
|
-
let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
|
1936
|
-
const totalSolBal = unWrappedSolBalance.add(wsolBalance);
|
1937
|
-
if (totalSolBal.lt(tokenAmountIn)) {
|
1938
|
-
throw "Insufficient SOL Funds"
|
1939
|
-
}
|
1940
|
-
|
1941
|
-
let conversionAmt = tokenAmountIn.sub(wsolBalance);
|
1942
|
-
instructions.push(
|
1943
|
-
SystemProgram.transfer({
|
1944
|
-
fromPubkey: publicKey,
|
1945
|
-
toPubkey: wsolAssociatedTokenAccount,
|
1946
|
-
lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER
|
1947
|
-
}),
|
1948
|
-
createSyncNativeInstruction(wsolAssociatedTokenAccount)
|
1949
|
-
);
|
1950
|
-
}
|
1951
|
-
} else {
|
1952
|
-
if (!(await checkIfAccountExists(userPayingTokenAccount, this.provider.connection))) {
|
1953
|
-
throw "Insufficient Funds , token Account doesn't exist"
|
1954
|
-
}
|
1955
|
-
const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userPayingTokenAccount)).value.amount);
|
1956
|
-
if (tokenAccountBalance.lt(tokenAmountIn)) {
|
1957
|
-
throw "Insufficient Funds"
|
1958
|
-
}
|
1959
|
-
}
|
1960
|
-
|
1961
|
-
// console.log("in add liq", tokenAmountIn);
|
1962
|
-
|
1963
|
-
let inx = await this.program.methods
|
1964
|
-
.addLiquidity({
|
1965
|
-
amountIn: tokenAmountIn,
|
1966
|
-
minLpAmountOut
|
1967
|
-
})
|
1968
|
-
.accounts({
|
1969
|
-
owner: publicKey,
|
1970
|
-
fundingAccount: userPayingTokenAccount, // user token account for custody token account
|
1971
|
-
lpTokenAccount,
|
1972
|
-
transferAuthority: poolConfig.transferAuthority,
|
1973
|
-
perpetuals: poolConfig.perpetuals,
|
1974
|
-
pool: poolConfig.poolAddress,
|
1975
|
-
custody: payTokenCustody.custodyAccount,
|
1976
|
-
custodyOracleAccount: payTokenCustody.oracleAddress,
|
1977
|
-
custodyTokenAccount: payTokenCustody.tokenAccount,
|
1978
|
-
lpTokenMint: poolConfig.lpTokenMint,
|
1979
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
1980
|
-
})
|
1981
|
-
.remainingAccounts([...custodyAccountMetas, ...custodyOracleAccountMetas])
|
1982
|
-
.instruction();
|
1983
|
-
|
1984
|
-
instructions.push(inx)
|
1985
|
-
} catch (err) {
|
1986
|
-
console.error("perpClient addLiquidity error:: ", err);
|
1987
|
-
throw err;
|
1988
|
-
}
|
1989
|
-
|
1990
|
-
return instructions;
|
1991
|
-
}
|
1992
|
-
// TODO: handle SOL wrapping to WSOL and create a ATA - NOT NEEDED
|
1993
|
-
// TODO :Balance checks - DONE
|
1994
|
-
// TODO: ATA check - else create - DONE
|
1995
|
-
// TODO: for LP close Accounts - DONE
|
1996
|
-
// TODO : if out token WSOL -> unwrap to SOL - DONE
|
1997
|
-
removeLiquidity = async (
|
1998
|
-
recieveTokenSymbol: string,
|
1999
|
-
liquidityAmountIn: BN,
|
2000
|
-
minTokenAmountOut: BN, // give this value based on slippage
|
2001
|
-
poolConfig: PoolConfig,
|
2002
|
-
closeLpATA = false
|
2003
|
-
): Promise<TransactionInstruction[]> => {
|
2004
|
-
|
2005
|
-
const recieveTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(recieveTokenSymbol).mintKey))!;
|
2006
|
-
if (!recieveTokenCustody) {
|
2007
|
-
throw "recieveTokenCustody not found";
|
2008
|
-
}
|
2009
|
-
let publicKey = this.provider.wallet.publicKey;
|
2010
|
-
|
2011
|
-
const instructions = [];
|
2012
|
-
try {
|
2013
|
-
let userRecievingTokenAccount = await getAssociatedTokenAddress(
|
2014
|
-
recieveTokenCustody.mintKey,
|
2015
|
-
publicKey
|
2016
|
-
);
|
2017
|
-
|
2018
|
-
if (!(await checkIfAccountExists(userRecievingTokenAccount, this.provider.connection))) {
|
2019
|
-
instructions.push(
|
2020
|
-
createAssociatedTokenAccountInstruction(
|
2021
|
-
publicKey,
|
2022
|
-
userRecievingTokenAccount,
|
2023
|
-
publicKey,
|
2024
|
-
recieveTokenCustody.mintKey
|
2025
|
-
)
|
2026
|
-
);
|
2027
|
-
}
|
2028
|
-
let lpTokenAccount = await getAssociatedTokenAddress(
|
2029
|
-
poolConfig.lpTokenMint,
|
2030
|
-
publicKey
|
2031
|
-
);
|
2032
|
-
|
2033
|
-
let custodyAccountMetas = [];
|
2034
|
-
let custodyOracleAccountMetas = [];
|
2035
|
-
for (const custody of poolConfig.custodies) {
|
2036
|
-
custodyAccountMetas.push({
|
2037
|
-
pubkey: custody.custodyAccount,
|
2038
|
-
isSigner: false,
|
2039
|
-
isWritable: false,
|
2040
|
-
});
|
2041
|
-
|
2042
|
-
custodyOracleAccountMetas.push({
|
2043
|
-
pubkey: custody.oracleAddress,
|
2044
|
-
isSigner: false,
|
2045
|
-
isWritable: false,
|
2046
|
-
});
|
2047
|
-
}
|
2048
|
-
|
2049
|
-
console.log("liquidityAmountIn", liquidityAmountIn.toString());
|
2050
|
-
|
2051
|
-
let removeLiquidityTx = await this.program.methods
|
2052
|
-
.removeLiquidity({
|
2053
|
-
lpAmountIn: liquidityAmountIn,
|
2054
|
-
minAmountOut: minTokenAmountOut
|
2055
|
-
})
|
2056
|
-
.accounts({
|
2057
|
-
owner: publicKey,
|
2058
|
-
receivingAccount: userRecievingTokenAccount, // user token account for custody token account
|
2059
|
-
lpTokenAccount,
|
2060
|
-
transferAuthority: poolConfig.transferAuthority,
|
2061
|
-
perpetuals: poolConfig.perpetuals,
|
2062
|
-
pool: poolConfig.poolAddress,
|
2063
|
-
custody: recieveTokenCustody.custodyAccount,
|
2064
|
-
custodyOracleAccount: recieveTokenCustody.oracleAddress,
|
2065
|
-
custodyTokenAccount: recieveTokenCustody.tokenAccount,
|
2066
|
-
lpTokenMint: poolConfig.lpTokenMint,
|
2067
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
2068
|
-
})
|
2069
|
-
.remainingAccounts([...custodyAccountMetas, ...custodyOracleAccountMetas])
|
2070
|
-
.instruction();
|
2071
|
-
instructions.push(removeLiquidityTx)
|
2072
|
-
|
2073
|
-
if (closeLpATA) {
|
2074
|
-
const closeInx = createCloseAccountInstruction(lpTokenAccount, publicKey, publicKey);
|
2075
|
-
instructions.push(closeInx);
|
2076
|
-
}
|
2077
|
-
|
2078
|
-
// SOL is only retrievable by closing the token account and choosing the desired address to send the token account's lamports.
|
2079
|
-
if (recieveTokenSymbol == 'SOL') {
|
2080
|
-
// await closeAccount()
|
2081
|
-
const closeWsolATAIns = createCloseAccountInstruction(userRecievingTokenAccount, publicKey, publicKey);
|
2082
|
-
instructions.push(closeWsolATAIns);
|
2083
|
-
}
|
2084
|
-
|
2085
|
-
} catch (err) {
|
2086
|
-
console.log("perpClient removeLiquidity error:: ", err);
|
2087
|
-
throw err;
|
2088
|
-
}
|
2089
|
-
|
2090
|
-
return instructions;
|
2091
|
-
}
|
2092
|
-
|
2093
|
-
public async sendTransaction(
|
2094
|
-
ixs: TransactionInstruction[],
|
2095
|
-
opts: any = {},
|
2096
|
-
): Promise<string> {
|
2097
|
-
return await sendTransaction(
|
2098
|
-
this.program.provider as AnchorProvider,
|
2099
|
-
ixs,
|
2100
|
-
opts.alts ?? [],
|
2101
|
-
{
|
2102
|
-
postSendTxCallback: this.postSendTxCallback,
|
2103
|
-
prioritizationFee: this.prioritizationFee,
|
2104
|
-
txConfirmationCommitment: this.txConfirmationCommitment,
|
2105
|
-
...opts,
|
2106
|
-
},
|
2107
|
-
);
|
2108
|
-
}
|
2109
|
-
|
2110
|
-
}
|
2111
|
-
|
2112
|
-
|