flash-sdk 1.0.1 → 1.0.3

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.
@@ -24,42 +24,72 @@ import {
24
24
  TOKEN_PROGRAM_ID,
25
25
  } from "@solana/spl-token";
26
26
 
27
- import fetch from "node-fetch";
28
27
  import { sha256 } from "js-sha256";
29
28
  import { encode } from "bs58";
30
- import { readFileSync } from "fs";
31
-
32
29
  import { PoolAccount } from "./PoolAccount";
33
30
  import { PositionAccount } from "./PositionAccount";
34
31
  import { BorrowRateParams, Custody, Fees, OracleParams, Permissions, Position, PositionSide, PricingParams, TokenRatios, isVariant } from "./types";
35
32
  import { OraclePrice } from "./OraclePrice";
36
33
  import { CustodyAccount } from "./CustodyAccount";
37
- import { Perpetuals } from "./target/types/perpetuals"
38
- // import { Perpetuals } from "../../target/types/perpetuals"
34
+ import { Perpetuals } from "./target/types/perpetuals";
35
+ import {IDL} from './target/types/perpetuals';
36
+
37
+
38
+ /* USEAGE
39
+
40
+ UI ---
41
+ provider = from phatom
42
+
43
+ client = new PerpetualsClient(provider, user.pubkey , programId);
44
+
45
+ BOT cli --------
39
46
 
47
+ provider = await getProvider(new DefaultWallet(DEFAULT_PERPS_USER));
40
48
 
49
+ AnchorProvider.local(clusterUrl, {
50
+ commitment: "confirmed",
51
+ preflightCommitment: "confirmed",
52
+ skipPreflight: true
53
+ });
54
+ process.env["ANCHOR_WALLET"] = adminKeyPath;
55
+
56
+ client = new PerpetualsClient(provider, DEFAULT_PERPS_USER.pubkey , programId);
57
+
58
+ */
41
59
  export class PerpetualsClient {
42
60
  provider: AnchorProvider;
43
61
  program: Program<Perpetuals>;
44
- admin: Keypair;
62
+ admin: PublicKey;
63
+ programId: PublicKey;
45
64
 
46
65
  // pdas
47
66
  multisig: { publicKey: PublicKey; bump: number };
48
67
  authority: { publicKey: PublicKey; bump: number };
49
68
  perpetuals: { publicKey: PublicKey; bump: number };
50
69
 
51
- constructor(clusterUrl: string, adminKey: string) {
52
- this.provider = AnchorProvider.local(clusterUrl, {
53
- commitment: "confirmed",
54
- preflightCommitment: "confirmed",
55
- skipPreflight: true
56
- });
57
- setProvider(this.provider);
58
- this.program = workspace.Perpetuals as Program<Perpetuals>;
59
-
60
- this.admin = Keypair.fromSecretKey(
61
- new Uint8Array(JSON.parse(readFileSync(adminKey).toString()))
62
- );
70
+ constructor(provider: AnchorProvider, programId: PublicKey) {
71
+ // this.provider = AnchorProvider.local(clusterUrl, {
72
+ // commitment: "confirmed",
73
+ // preflightCommitment: "confirmed",
74
+ // skipPreflight: true
75
+ // });
76
+ // setProvider(this.provider);
77
+ this.provider = provider;
78
+ setProvider(provider);
79
+
80
+ // const idl = JSON.parse( fs.readFileSync("./target/idl/perpetuals.json", "utf8"));
81
+ // const idl = JSON.parse(IDL);
82
+ // const program = new anchor.Program(idl, programId, provider);
83
+ this.program = new Program(IDL, programId);
84
+ //this.program = workspace.Perpetuals as Program<Perpetuals>;
85
+ console.log("client constructor programID : ",this.program.programId.toBase58());
86
+
87
+ // this.admin = Keypair.fromSecretKey(
88
+ // new Uint8Array(JSON.parse(readFileSync(adminKey).toString()))
89
+ // );
90
+
91
+ this.admin = this.provider.wallet.publicKey;
92
+ console.log("admin:",this.admin.toBase58())
63
93
 
64
94
  this.multisig = this.findProgramAddress("multisig");
65
95
  this.authority = this.findProgramAddress("transfer_authority");
@@ -343,11 +373,11 @@ export class PerpetualsClient {
343
373
  minSignatures,
344
374
  })
345
375
  .accounts({
346
- admin: this.admin.publicKey,
376
+ admin: this.admin,
347
377
  multisig: this.multisig.publicKey,
348
378
  })
349
379
  .remainingAccounts(adminMetas)
350
- .signers([this.admin])
380
+ // .signers([this.admin])
351
381
  .rpc();
352
382
  } catch (err) {
353
383
  // @ts-ignore
@@ -362,7 +392,7 @@ export class PerpetualsClient {
362
392
  await this.program.methods
363
393
  .addPool({ name })
364
394
  .accounts({
365
- admin: this.admin.publicKey,
395
+ admin: this.provider.wallet.publicKey,
366
396
  multisig: this.multisig.publicKey,
367
397
  transferAuthority: this.authority.publicKey,
368
398
  perpetuals: this.perpetuals.publicKey,
@@ -372,7 +402,7 @@ export class PerpetualsClient {
372
402
  tokenProgram: TOKEN_PROGRAM_ID,
373
403
  rent: SYSVAR_RENT_PUBKEY,
374
404
  })
375
- .signers([this.admin])
405
+ // .signers([this.admin])
376
406
  .rpc()
377
407
  .catch((err) => {
378
408
  console.error(err);
@@ -384,14 +414,14 @@ export class PerpetualsClient {
384
414
  await this.program.methods
385
415
  .removePool({})
386
416
  .accounts({
387
- admin: this.admin.publicKey,
417
+ admin: this.admin,
388
418
  multisig: this.multisig.publicKey,
389
419
  transferAuthority: this.authority.publicKey,
390
420
  perpetuals: this.perpetuals.publicKey,
391
421
  pool: this.getPoolKey(name),
392
422
  systemProgram: SystemProgram.programId,
393
423
  })
394
- .signers([this.admin])
424
+ // .signers([this.admin])
395
425
  .rpc()
396
426
  .catch((err) => {
397
427
  console.error(err);
@@ -425,7 +455,7 @@ export class PerpetualsClient {
425
455
  ratios,
426
456
  })
427
457
  .accounts({
428
- admin: this.admin.publicKey,
458
+ admin: this.admin,
429
459
  multisig: this.multisig.publicKey,
430
460
  transferAuthority: this.authority.publicKey,
431
461
  perpetuals: this.perpetuals.publicKey,
@@ -440,7 +470,7 @@ export class PerpetualsClient {
440
470
  tokenProgram: TOKEN_PROGRAM_ID,
441
471
  rent: SYSVAR_RENT_PUBKEY,
442
472
  })
443
- .signers([this.admin])
473
+ // .signers([this.admin])
444
474
  .rpc()
445
475
  .catch((err) => {
446
476
  console.error(err);
@@ -481,7 +511,7 @@ export class PerpetualsClient {
481
511
  ratios,
482
512
  })
483
513
  .accounts({
484
- admin: this.admin.publicKey,
514
+ admin: this.admin,
485
515
  multisig: this.multisig.publicKey,
486
516
  transferAuthority: this.authority.publicKey,
487
517
  perpetuals: this.perpetuals.publicKey,
@@ -496,7 +526,7 @@ export class PerpetualsClient {
496
526
  tokenProgram: TOKEN_PROGRAM_ID,
497
527
  rent: SYSVAR_RENT_PUBKEY,
498
528
  })
499
- .signers([this.admin])
529
+ // .signers([this.admin])
500
530
  .rpc()
501
531
  .catch((err) => {
502
532
  console.error(err);
@@ -509,7 +539,7 @@ export class PerpetualsClient {
509
539
  await this.program.methods
510
540
  .removeCustody({ ratios })
511
541
  .accounts({
512
- admin: this.admin.publicKey,
542
+ admin: this.admin,
513
543
  multisig: this.multisig.publicKey,
514
544
  transferAuthority: this.authority.publicKey,
515
545
  perpetuals: this.perpetuals.publicKey,
@@ -522,7 +552,7 @@ export class PerpetualsClient {
522
552
  systemProgram: SystemProgram.programId,
523
553
  tokenProgram: TOKEN_PROGRAM_ID,
524
554
  })
525
- .signers([this.admin])
555
+ // .signers([this.admin])
526
556
  .rpc()
527
557
  .catch((err) => {
528
558
  console.error(err);
@@ -534,13 +564,13 @@ export class PerpetualsClient {
534
564
  await this.program.methods
535
565
  .upgradeCustody({})
536
566
  .accounts({
537
- admin: this.admin.publicKey,
567
+ admin: this.admin,
538
568
  multisig: this.multisig.publicKey,
539
569
  pool: this.getPoolKey(poolName),
540
570
  custody: this.getCustodyKey(poolName, tokenMint),
541
571
  systemProgram: SystemProgram.programId,
542
572
  })
543
- .signers([this.admin])
573
+ // .signers([this.admin])
544
574
  .rpc()
545
575
  .catch((err) => {
546
576
  console.error(err);
@@ -2,7 +2,7 @@
2
2
  import { BN_ZERO, BPS_DECIMALS, BPS_POWER, PERCENTAGE_DECIMALS, PRICE_DECIMALS, USD_DECIMALS } from "./constants";
3
3
  import { BN } from "@coral-xyz/anchor";
4
4
  import { Mint } from "@solana/spl-token";
5
- import { Custody, FeesMode, Pool, Side, TokenRatios, isVariant } from "./types";
5
+ import { AumCalcMode, Custody, FeesMode, Pool, Side, TokenRatios, isVariant } from "./types";
6
6
  import { PublicKey } from "@solana/web3.js";
7
7
  import {CustodyAccount} from "./CustodyAccount";
8
8
  import { OraclePrice } from "./OraclePrice";
@@ -10,7 +10,8 @@ import { PositionAccount } from "./PositionAccount";
10
10
  import { checkedCeilDiv, checkedDecimalCeilMul, checkedDecimalMul, scaleToExponent } from "./utils";
11
11
 
12
12
 
13
- export class PoolAccount {
13
+
14
+ export class PoolAccount implements Pool {
14
15
 
15
16
  publicKey: PublicKey;
16
17
 
@@ -42,9 +43,6 @@ export class PoolAccount {
42
43
  return this.custodies.findIndex(i => i.toBase58()==custodyKey.toBase58())
43
44
  }
44
45
 
45
- // loadlpData(lpTokenInfo : Mint){
46
- // this.lpTokenInfo = lpTokenInfo
47
- // }
48
46
 
49
47
  getAddLiquidityFee(
50
48
  tokenId: number,
@@ -367,5 +365,78 @@ export class PoolAccount {
367
365
  }
368
366
  }
369
367
  } //getPnlUsd
368
+
369
+
370
+ getAssetsUnderManagementUsd(
371
+ token_prices: OraclePrice[],
372
+ token_ema_prices: OraclePrice[],
373
+ custodies : CustodyAccount[],
374
+ aum_calc_mode: AumCalcMode,
375
+ ) :BN {
376
+
377
+ let pool_amount_usd: BN = BN_ZERO;
378
+
379
+ for (let index=0;index<this.custodies.length;index++) {
380
+
381
+ if( token_prices.length != this.custodies.length || token_prices.length != token_ema_prices.length ){
382
+ throw Error("token prices length incorrect");
383
+ }
384
+
385
+
386
+ let aum_token_price : OraclePrice;
387
+ // switch unable to match enum
388
+ if(isVariant(aum_calc_mode,"last")){
389
+ aum_token_price = token_prices[index];
390
+ } else if( isVariant(aum_calc_mode, "ema") ){
391
+ aum_token_price = token_ema_prices[index];
392
+ } else if( isVariant(aum_calc_mode, "min") ) {
393
+ if (token_prices[index].cmp(token_ema_prices[index])) {
394
+ aum_token_price = token_prices[index];
395
+ } else {
396
+ aum_token_price = token_ema_prices[index];
397
+ }
398
+ } else if( isVariant(aum_calc_mode, "max") ) {
399
+ if (token_ema_prices[index].cmp(token_prices[index])) {
400
+ aum_token_price = token_prices[index];
401
+ } else {
402
+ aum_token_price = token_ema_prices[index];
403
+ }
404
+ }
405
+
406
+ let token_amount_usd :BN =
407
+ aum_token_price.getAssetAmountUsd(custodies[index].assets.owned, custodies[index].decimals);
408
+
409
+ pool_amount_usd = pool_amount_usd.add(token_amount_usd);
410
+
411
+ // if (custodies[index].pricing.useUnrealizedPnlInAum) {
412
+ // // compute aggregate unrealized pnl
413
+ // let (long_profit, long_loss, _) = this.getPnlUsd(
414
+ // &custodies[index].get_collective_position(Side::Long)?,
415
+ // &token_price,
416
+ // &token_ema_price,
417
+ // &custodies[index],
418
+ // curtime,
419
+ // false,
420
+ // )?;
421
+ // let (short_profit, short_loss, _) = self.get_pnl_usd(
422
+ // &custodies[index].get_collective_position(Side::Short)?,
423
+ // &token_price,
424
+ // &token_ema_price,
425
+ // &custodies[index],
426
+ // curtime,
427
+ // false,
428
+ // )?;
429
+
430
+ // // adjust pool amount by collective profit/loss
431
+ // pool_amount_usd = math::checked_add(pool_amount_usd, long_profit as u128)?;
432
+ // pool_amount_usd = math::checked_add(pool_amount_usd, short_profit as u128)?;
433
+ // pool_amount_usd = pool_amount_usd.saturating_sub(long_loss as u128);
434
+ // pool_amount_usd = pool_amount_usd.saturating_sub(short_loss as u128);
435
+ // }
436
+ throw Error("Incomplete")
437
+ }
438
+
439
+ return pool_amount_usd;
440
+ }
370
441
 
371
442
  } // Pool
@@ -4,20 +4,170 @@ import { BN } from "@coral-xyz/anchor";
4
4
  import { Mint } from "@solana/spl-token";
5
5
  import { Custody, FeesMode, Pool, Side, TokenRatios, isVariant } from "./types";
6
6
  import { PublicKey } from "@solana/web3.js";
7
- import {CustodyAccount} from "./CustodyAccount";
7
+ import { CustodyAccount } from "./CustodyAccount";
8
8
  import { OraclePrice } from "./OraclePrice";
9
9
  import { PositionAccount } from "./PositionAccount";
10
- import { checkedCeilDiv, checkedDecimalCeilMul, checkedDecimalMul, scaleToExponent } from "./utils";
10
+ import { checkedCeilDiv, checkedDecimalCeilMul, checkedDecimalMul, scaleToExponent, toUiDecimals } from "./utils";
11
11
  import { PoolConfig } from "./PoolConfig";
12
+ import { PoolAccount } from "./PoolAccount";
12
13
 
13
14
  export class PoolDisplayData {
14
15
 
15
16
  public poolConfig: PoolConfig;
16
- public poolData : Pool;
17
- public lpTokenInfo : Mint;
18
- public custodies : CustodyAccount[];
19
- public totalPoolValueUsd : BN;
17
+ public pool: PoolAccount;
18
+ public lpTokenInfo: Mint;
19
+ public custodies: CustodyAccount[];
20
+ public totalPoolValueUsd: BN;
20
21
 
22
+ constructor(poolConfig: PoolConfig, pool: PoolAccount, lpTokenInfo: Mint, custodies: CustodyAccount[]) {
23
+ this.poolConfig = poolConfig;
24
+ this.pool = pool;
25
+ this.lpTokenInfo = lpTokenInfo;
26
+ this.custodies = custodies;
27
+ this.totalPoolValueUsd = new BN(-1); // -1 meaning unset
28
+ }
21
29
 
30
+ loadCustodies(custodies: CustodyAccount[]) {
31
+ this.custodies = custodies;
32
+ }
22
33
 
23
- } // Pool
34
+ loadPoolData(pool: PoolAccount) {
35
+ this.pool = pool
36
+ }
37
+
38
+ loadlpData(lpTokenInfo: Mint) {
39
+ this.lpTokenInfo = lpTokenInfo
40
+ }
41
+
42
+ // TODO :: replace this with PoolAccount.getAssetsUnderManagementUsd()
43
+ // should take pnl's into account
44
+ getLpStats(prices: any) {
45
+
46
+ let stableCoinAmount = new BN(0);
47
+ let totalPoolValueUsd = new BN(0);
48
+
49
+ for (const custody of this.poolConfig.custodies) {
50
+ const custodyData = this.custodies.find(t => t.mint.toBase58() === custody.mintKey.toBase58())
51
+ if (custodyData) {
52
+ if (custodyData.isStable) {
53
+ stableCoinAmount = stableCoinAmount.add(custodyData.assets.owned)
54
+ }
55
+ const priceBN = new BN(prices.get(custody.symbol) * 10 ** PRICE_DECIMALS); // so always keep prices with 6 decimals
56
+ const custodyValue = priceBN.mul(custodyData.assets.owned).div(new BN(10 ** custody.decimals));
57
+ totalPoolValueUsd = totalPoolValueUsd.add(custodyValue)
58
+ }
59
+ }
60
+
61
+ // console.log("totalPoolValueUsd.toNumber():",totalPoolValueUsd.toString())
62
+ // console.log("stableCoinAmount.toNumber():",stableCoinAmount.toString())
63
+
64
+ // if(this.lpTokenInfo.supply.toString() =='0' || totalPoolValueUsd.toString()=='0'){
65
+ // console.error("supply or amt cannot be zero")
66
+ // throw "supply or amt cannot be zero";
67
+ // }
68
+ this.totalPoolValueUsd = totalPoolValueUsd;
69
+ const lpPrice = totalPoolValueUsd.div(new BN(this.lpTokenInfo.supply.toString() === '0' ? 1 : this.lpTokenInfo.supply.toString()))
70
+
71
+ return {
72
+ lpTokenSupply: new BN(this.lpTokenInfo.supply.toString()),
73
+ decimals: this.poolConfig.lpDecimals,
74
+ totalPoolValue: totalPoolValueUsd,
75
+ price: lpPrice,
76
+ stableCoinPercentage: totalPoolValueUsd.toNumber() != 0 ? stableCoinAmount.mul(new BN(PERCENTAGE_DECIMALS)).div(totalPoolValueUsd) : new BN(1),
77
+ marketCap: lpPrice.mul(new BN(this.lpTokenInfo.supply.toString())),
78
+ // totalStaked : BN,
79
+ }
80
+ }
81
+
82
+ getOiLongUI() {
83
+ let totalAmount = new BN('0');
84
+ this.custodies.forEach(i => {
85
+ totalAmount = totalAmount.add(i.tradeStats.oiLongUsd);
86
+ })
87
+ return totalAmount;
88
+ }
89
+
90
+ getOiShortUI() {
91
+ let totalAmount = new BN('0');
92
+ this.custodies.forEach(i => {
93
+ totalAmount = totalAmount.add(i.tradeStats.oiShortUsd);
94
+ })
95
+ return totalAmount;
96
+ }
97
+
98
+ // handle decimal and this should accept a list of prices probs map or object
99
+ getCustodyDetails(prices: any) {
100
+ const custodyDetails = [];
101
+
102
+ for (let i = 0; i < this.poolConfig.custodies.length; i++) {
103
+ const custody = this.poolConfig.custodies[i];
104
+ if (!custody) continue;
105
+
106
+ // console.log('this.pool :>> ', this.pool);
107
+ // const token = this.pool.tokens.find(t => t.custody.toBase58() === custody.custodyAccount.toBase58());
108
+ const tokenRatio = this.pool.ratios[i]
109
+ const custodyData = this.custodies.find(t => t.mint.toBase58() === custody.mintKey.toBase58())
110
+ const priceBN = new BN(prices.get(custody.symbol) * 10 ** 6); // so always keep prices with 6 decimals
111
+
112
+ if (this.totalPoolValueUsd.toString() == "-1") {
113
+ console.error("call getLpStats first")
114
+ throw "call getLpStats first";
115
+ }
116
+
117
+ // if(this.totalPoolValueUsd.toString()=='0'){
118
+ // console.error("call getLpStats first , totalPoolValueUsd ZERO")
119
+ // return defaultData.custodyDetails;
120
+ // }
121
+ // console.log("this.totalPoolValueUsd:",this.totalPoolValueUsd.toString())
122
+
123
+ if (custodyData && tokenRatio) {
124
+ custodyDetails.push({
125
+ symbol: custody.symbol,
126
+ price: new BN(prices.get(custody.symbol)),
127
+ targetWeight: tokenRatio.target,
128
+ currentWeight: this.totalPoolValueUsd.toNumber() ?
129
+ (custodyData.assets.owned.mul(priceBN)).mul(new BN(10 ** PERCENTAGE_DECIMALS)).div(this.totalPoolValueUsd).div(new BN(10 ** custody.decimals))
130
+ : new BN(0),
131
+ utilization: custodyData.assets.owned.toNumber() ?
132
+ toUiDecimals(custodyData.assets.locked.mul(new BN(10 ** PERCENTAGE_DECIMALS)).div(custodyData.assets.owned), PERCENTAGE_DECIMALS, 2)
133
+ : '0',
134
+ // assetsAmountUi : (custodyData.assets.owned.toNumber() / 10**(custody.decimals)).toFixed(4),
135
+ assetsAmountUi: toUiDecimals(custodyData.assets.owned, custody.decimals, 4, true),
136
+ // totalUsdAmountUi : ((custodyData.assets.owned.mul(priceBN)).div(new BN(10**(custody.decimals))).toNumber() / 10**6).toFixed(4),
137
+ totalUsdAmountUi: toUiDecimals((custodyData.assets.owned.mul(priceBN)), custody.decimals + PRICE_DECIMALS, 2, true),
138
+ })
139
+ }
140
+ }
141
+ return custodyDetails;
142
+ }
143
+
144
+ getPoolStats() {
145
+ let totalFees = new BN(0)
146
+ let totalVolume = new BN(0)
147
+ let currentLongPositionsUsd = new BN(0)
148
+ let currentShortPositionsUsd = new BN(0)
149
+
150
+ for (const custody of this.poolConfig.custodies) {
151
+ const custodyData = this.custodies.find(t => t.mint.toBase58() === custody.mintKey.toBase58())
152
+ if (custodyData) {
153
+ const custodyFeeTotal = Object.values(custodyData.collectedFees).reduce((a: BN, b: BN) => a.add(b), new BN(0))
154
+ totalFees = totalFees.add(custodyFeeTotal)
155
+
156
+ const custodyVolume = Object.values(custodyData.volumeStats).reduce((a: BN, b: BN) => a.add(b), new BN(0))
157
+ totalVolume = totalVolume.add(custodyVolume)
158
+
159
+ currentLongPositionsUsd = currentLongPositionsUsd.add(custodyData.tradeStats.oiLongUsd)
160
+ currentShortPositionsUsd = currentShortPositionsUsd.add(custodyData.tradeStats.oiShortUsd)
161
+ }
162
+ }
163
+ return {
164
+ totalFees,
165
+ totalVolume,
166
+ currentLongPositionsUsd,
167
+ currentShortPositionsUsd
168
+ }
169
+ }
170
+
171
+
172
+
173
+ } // PoolDisplayData
@@ -3,7 +3,7 @@ import { Connection, PublicKey } from "@solana/web3.js";
3
3
  import { isVariant, Position, Side } from "./types";
4
4
 
5
5
 
6
- export class PositionAccount {
6
+ export class PositionAccount implements Position {
7
7
 
8
8
  public publicKey: PublicKey;
9
9
 
@@ -25,6 +25,7 @@ export class PositionAccount {
25
25
  public lockedAmount: BN;
26
26
  public collateralAmount: BN;
27
27
  // extra
28
+ public bump: number
28
29
 
29
30
  constructor( publicKey : PublicKey, parseData : Position) {
30
31
  this.publicKey = publicKey;
package/src/readme.md CHANGED
@@ -1,4 +1,24 @@
1
- # strict JS types <=> Rust types
1
+ # Flash SDK
2
+ Client SDK for interacting with FLASH.TRADE's smart-contracts
2
3
 
3
- 1) u65 : unisigned intergar - so no decimals => BN
4
- 2) u8 : number
4
+ ## Install
5
+ ```
6
+ npm i flash-sdk / yarn add flash-sdk
7
+ ```
8
+
9
+ ## Using the SDK
10
+
11
+ ### connect sdk locally
12
+ `
13
+ import { AnchorProvider } from "@coral-xyz/anchor";
14
+
15
+ const provider : AnchorProvider = AnchorProvider.local(clusterUrl, {
16
+ commitment: "confirmed",
17
+ preflightCommitment: "confirmed",
18
+ skipPreflight: true
19
+ });
20
+ client = new PerpetualsClient(provider, programId);
21
+ `
22
+
23
+
24
+ ### To fetch all the pool data