@symmetry-hq/sdk 1.0.1

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.
Files changed (121) hide show
  1. package/dist/src/constants.d.ts +23 -0
  2. package/dist/src/constants.js +38 -0
  3. package/dist/src/index.d.ts +804 -0
  4. package/dist/src/index.js +2097 -0
  5. package/dist/src/instructions/automation/auction.d.ts +6 -0
  6. package/dist/src/instructions/automation/auction.js +40 -0
  7. package/dist/src/instructions/automation/claimBounty.d.ts +12 -0
  8. package/dist/src/instructions/automation/claimBounty.js +44 -0
  9. package/dist/src/instructions/automation/flashSwap.d.ts +21 -0
  10. package/dist/src/instructions/automation/flashSwap.js +74 -0
  11. package/dist/src/instructions/automation/priceUpdate.d.ts +19 -0
  12. package/dist/src/instructions/automation/priceUpdate.js +89 -0
  13. package/dist/src/instructions/automation/rebalanceIntent.d.ts +32 -0
  14. package/dist/src/instructions/automation/rebalanceIntent.js +117 -0
  15. package/dist/src/instructions/automation/rebalanceSwap.d.ts +11 -0
  16. package/dist/src/instructions/automation/rebalanceSwap.js +42 -0
  17. package/dist/src/instructions/management/addBounty.d.ts +7 -0
  18. package/dist/src/instructions/management/addBounty.js +41 -0
  19. package/dist/src/instructions/management/admin.d.ts +9 -0
  20. package/dist/src/instructions/management/admin.js +53 -0
  21. package/dist/src/instructions/management/claimFees.d.ts +15 -0
  22. package/dist/src/instructions/management/claimFees.js +95 -0
  23. package/dist/src/instructions/management/createBasket.d.ts +21 -0
  24. package/dist/src/instructions/management/createBasket.js +98 -0
  25. package/dist/src/instructions/management/edit.d.ts +51 -0
  26. package/dist/src/instructions/management/edit.js +477 -0
  27. package/dist/src/instructions/management/luts.d.ts +30 -0
  28. package/dist/src/instructions/management/luts.js +99 -0
  29. package/dist/src/instructions/pda.d.ts +25 -0
  30. package/dist/src/instructions/pda.js +128 -0
  31. package/dist/src/instructions/user/deposit.d.ts +20 -0
  32. package/dist/src/instructions/user/deposit.js +100 -0
  33. package/dist/src/instructions/user/withdraw.d.ts +8 -0
  34. package/dist/src/instructions/user/withdraw.js +36 -0
  35. package/dist/src/jup.d.ts +49 -0
  36. package/dist/src/jup.js +80 -0
  37. package/dist/src/keeperMonitor.d.ts +52 -0
  38. package/dist/src/keeperMonitor.js +624 -0
  39. package/dist/src/layouts/basket.d.ts +191 -0
  40. package/dist/src/layouts/basket.js +51 -0
  41. package/dist/src/layouts/config.d.ts +281 -0
  42. package/dist/src/layouts/config.js +237 -0
  43. package/dist/src/layouts/fraction.d.ts +20 -0
  44. package/dist/src/layouts/fraction.js +164 -0
  45. package/dist/src/layouts/intents/bounty.d.ts +18 -0
  46. package/dist/src/layouts/intents/bounty.js +19 -0
  47. package/dist/src/layouts/intents/intent.d.ts +209 -0
  48. package/dist/src/layouts/intents/intent.js +97 -0
  49. package/dist/src/layouts/intents/rebalanceIntent.d.ts +212 -0
  50. package/dist/src/layouts/intents/rebalanceIntent.js +94 -0
  51. package/dist/src/layouts/lookupTable.d.ts +7 -0
  52. package/dist/src/layouts/lookupTable.js +10 -0
  53. package/dist/src/layouts/oracle.d.ts +63 -0
  54. package/dist/src/layouts/oracle.js +96 -0
  55. package/dist/src/states/basket.d.ts +14 -0
  56. package/dist/src/states/basket.js +479 -0
  57. package/dist/src/states/config.d.ts +3 -0
  58. package/dist/src/states/config.js +71 -0
  59. package/dist/src/states/intents/intent.d.ts +10 -0
  60. package/dist/src/states/intents/intent.js +316 -0
  61. package/dist/src/states/intents/rebalanceIntent.d.ts +42 -0
  62. package/dist/src/states/intents/rebalanceIntent.js +680 -0
  63. package/dist/src/states/oracles/constants.d.ts +9 -0
  64. package/dist/src/states/oracles/constants.js +15 -0
  65. package/dist/src/states/oracles/oracle.d.ts +24 -0
  66. package/dist/src/states/oracles/oracle.js +168 -0
  67. package/dist/src/states/oracles/pythOracle.d.ts +132 -0
  68. package/dist/src/states/oracles/pythOracle.js +609 -0
  69. package/dist/src/states/oracles/raydiumClmmOracle.d.ts +184 -0
  70. package/dist/src/states/oracles/raydiumClmmOracle.js +843 -0
  71. package/dist/src/states/oracles/raydiumCpmmOracle.d.ts +120 -0
  72. package/dist/src/states/oracles/raydiumCpmmOracle.js +540 -0
  73. package/dist/src/states/oracles/switchboardOracle.d.ts +0 -0
  74. package/dist/src/states/oracles/switchboardOracle.js +1 -0
  75. package/dist/src/states/withdrawBasketFees.d.ts +10 -0
  76. package/dist/src/states/withdrawBasketFees.js +154 -0
  77. package/dist/src/txUtils.d.ts +65 -0
  78. package/dist/src/txUtils.js +306 -0
  79. package/dist/test.d.ts +1 -0
  80. package/dist/test.js +561 -0
  81. package/package.json +31 -0
  82. package/src/constants.ts +40 -0
  83. package/src/index.ts +2431 -0
  84. package/src/instructions/automation/auction.ts +55 -0
  85. package/src/instructions/automation/claimBounty.ts +69 -0
  86. package/src/instructions/automation/flashSwap.ts +104 -0
  87. package/src/instructions/automation/priceUpdate.ts +117 -0
  88. package/src/instructions/automation/rebalanceIntent.ts +181 -0
  89. package/src/instructions/management/addBounty.ts +55 -0
  90. package/src/instructions/management/admin.ts +72 -0
  91. package/src/instructions/management/claimFees.ts +129 -0
  92. package/src/instructions/management/createBasket.ts +138 -0
  93. package/src/instructions/management/edit.ts +602 -0
  94. package/src/instructions/management/luts.ts +157 -0
  95. package/src/instructions/pda.ts +151 -0
  96. package/src/instructions/user/deposit.ts +143 -0
  97. package/src/instructions/user/withdraw.ts +53 -0
  98. package/src/jup.ts +113 -0
  99. package/src/keeperMonitor.ts +585 -0
  100. package/src/layouts/basket.ts +233 -0
  101. package/src/layouts/config.ts +576 -0
  102. package/src/layouts/fraction.ts +164 -0
  103. package/src/layouts/intents/bounty.ts +35 -0
  104. package/src/layouts/intents/intent.ts +324 -0
  105. package/src/layouts/intents/rebalanceIntent.ts +306 -0
  106. package/src/layouts/lookupTable.ts +14 -0
  107. package/src/layouts/oracle.ts +157 -0
  108. package/src/states/basket.ts +527 -0
  109. package/src/states/config.ts +62 -0
  110. package/src/states/intents/intent.ts +311 -0
  111. package/src/states/intents/rebalanceIntent.ts +751 -0
  112. package/src/states/oracles/constants.ts +13 -0
  113. package/src/states/oracles/oracle.ts +212 -0
  114. package/src/states/oracles/pythOracle.ts +874 -0
  115. package/src/states/oracles/raydiumClmmOracle.ts +1193 -0
  116. package/src/states/oracles/raydiumCpmmOracle.ts +784 -0
  117. package/src/states/oracles/switchboardOracle.ts +0 -0
  118. package/src/states/withdrawBasketFees.ts +160 -0
  119. package/src/txUtils.ts +424 -0
  120. package/test.ts +609 -0
  121. package/tsconfig.json +101 -0
@@ -0,0 +1,157 @@
1
+ import BN from 'bn.js';
2
+ import { AccountMeta, PublicKey, SystemProgram, TransactionInstruction } from '@solana/web3.js';
3
+
4
+ import {
5
+ ADDRESS_LOOKUP_TABLE_PROGRAM_ID, BASKETS_V3_PROGRAM_ID, PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT,
6
+ PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT
7
+ } from '../../constants';
8
+ import { getGlobalConfigPda, getLookupTableInfoAccount } from '../pda';
9
+
10
+ const CREATE_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([227,98,152,128,87,46,244,99]);
11
+ const EXTEND_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([98, 129, 153, 127, 181, 160, 117, 74]);
12
+ const OVERWRITE_BASKET_LOOKUP_TABLES_DISCRIMINATOR = Buffer.from([197, 116, 189, 147, 222, 188, 6, 165]);
13
+ const CLOSE_DEACTIVATED_LOOKUP_TABLE_DISCRIMINATOR = Buffer.from([19, 4, 214, 20, 26, 43, 71, 233]);
14
+
15
+
16
+ export function createBasketLookupTablesInstruction(params: {
17
+ signer: PublicKey;
18
+ basket: PublicKey;
19
+ oldTempLookupTable0: PublicKey;
20
+ oldTempLookupTable1: PublicKey;
21
+ newTempLookupTable0: PublicKey;
22
+ newTempLookupTable1: PublicKey;
23
+ slot: number;
24
+ }): TransactionInstruction {
25
+ const {
26
+ signer,
27
+ basket,
28
+ oldTempLookupTable0,
29
+ oldTempLookupTable1,
30
+ newTempLookupTable0,
31
+ newTempLookupTable1,
32
+ slot,
33
+ } = params;
34
+
35
+ const globalConfig = getGlobalConfigPda();
36
+ const hasOldTemp = !oldTempLookupTable0.equals(PublicKey.default)
37
+ && !oldTempLookupTable1.equals(PublicKey.default);
38
+
39
+ const data = Buffer.concat([
40
+ CREATE_BASKET_LOOKUP_TABLES_DISCRIMINATOR,
41
+ Buffer.from(new BN(slot).toArray("le", 8)),
42
+ ]);
43
+
44
+ const keys: AccountMeta[] = [
45
+ { pubkey: signer, isSigner: true, isWritable: true },
46
+ { pubkey: basket, isSigner: false, isWritable: true },
47
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
48
+ { pubkey: hasOldTemp ? oldTempLookupTable0 : PYTHNET_CUSTODY_PRICE_USDC_ACCOUNT, isSigner: false, isWritable: true },
49
+ { pubkey: hasOldTemp ? oldTempLookupTable1 : PYTHNET_CUSTODY_PRICE_WSOL_ACCOUNT, isSigner: false, isWritable: true },
50
+ { pubkey: newTempLookupTable0, isSigner: false, isWritable: true },
51
+ { pubkey: newTempLookupTable1, isSigner: false, isWritable: true },
52
+ ];
53
+
54
+ if (hasOldTemp) {
55
+ keys.push(
56
+ { pubkey: getLookupTableInfoAccount(oldTempLookupTable0), isSigner: false, isWritable: true },
57
+ { pubkey: getLookupTableInfoAccount(oldTempLookupTable1), isSigner: false, isWritable: true },
58
+ );
59
+ }
60
+ else {
61
+ keys.push(
62
+ { pubkey: BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false },
63
+ { pubkey: BASKETS_V3_PROGRAM_ID, isSigner: false, isWritable: false },
64
+ );
65
+ }
66
+
67
+ keys.push(
68
+ { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isSigner: false, isWritable: false },
69
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
70
+ );
71
+
72
+ return new TransactionInstruction({
73
+ keys,
74
+ programId: BASKETS_V3_PROGRAM_ID,
75
+ data,
76
+ });
77
+ }
78
+
79
+ export function extendBasketLookupTablesIx(
80
+ params: {
81
+ signer: PublicKey;
82
+ basket: PublicKey;
83
+ tempLookupTable0: PublicKey;
84
+ tempLookupTable1: PublicKey;
85
+ additionalAccounts: PublicKey[];
86
+ }): TransactionInstruction {
87
+
88
+ const keys = [
89
+ { pubkey: params.signer, isWritable: true, isSigner: true },
90
+ { pubkey: params.basket, isWritable: true, isSigner: false },
91
+ { pubkey: params.tempLookupTable0, isWritable: true, isSigner: false },
92
+ { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
93
+ { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
94
+ { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
95
+ ...params.additionalAccounts.map(pubkey => ({pubkey, isWritable: false, isSigner: false})),
96
+ ];
97
+
98
+ return new TransactionInstruction({
99
+ keys,
100
+ programId: BASKETS_V3_PROGRAM_ID,
101
+ data: EXTEND_BASKET_LOOKUP_TABLES_DISCRIMINATOR,
102
+ });
103
+ }
104
+
105
+ export function overwriteBasketLookupTablesIx(
106
+ params: {
107
+ signer: PublicKey;
108
+ basket: PublicKey;
109
+ tempLookupTable0: PublicKey;
110
+ tempLookupTable1: PublicKey;
111
+ activeLookupTable0: PublicKey;
112
+ activeLookupTable1: PublicKey;
113
+
114
+ }): TransactionInstruction {
115
+
116
+ const keys = [
117
+ { pubkey: params.signer, isWritable: true, isSigner: true },
118
+ { pubkey: params.basket, isWritable: true, isSigner: false },
119
+ { pubkey: params.tempLookupTable0, isWritable: true, isSigner: false },
120
+ { pubkey: params.tempLookupTable1, isWritable: true, isSigner: false },
121
+ { pubkey: params.activeLookupTable0, isWritable: true, isSigner: false },
122
+ { pubkey: params.activeLookupTable1, isWritable: true, isSigner: false },
123
+ { pubkey: getLookupTableInfoAccount(params.activeLookupTable0), isWritable: true, isSigner: false },
124
+ { pubkey: getLookupTableInfoAccount(params.activeLookupTable1), isWritable: true, isSigner: false },
125
+ { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
126
+ { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
127
+ ];
128
+
129
+ return new TransactionInstruction({
130
+ keys,
131
+ programId: BASKETS_V3_PROGRAM_ID,
132
+ data: OVERWRITE_BASKET_LOOKUP_TABLES_DISCRIMINATOR,
133
+ });
134
+ }
135
+
136
+ export function closeDeactivatedLookupTableIx(params: {
137
+ rentPayer: PublicKey,
138
+ basket: PublicKey,
139
+ lookupTable: PublicKey
140
+ }): TransactionInstruction {
141
+ let lookupTableInfo = getLookupTableInfoAccount(params.lookupTable);
142
+
143
+ const keys = [
144
+ { pubkey: params.rentPayer, isWritable: true, isSigner: false },
145
+ { pubkey: params.basket, isWritable: true, isSigner: false },
146
+ { pubkey: params.lookupTable, isWritable: true, isSigner: false },
147
+ { pubkey: lookupTableInfo, isWritable: true, isSigner: false },
148
+ { pubkey: ADDRESS_LOOKUP_TABLE_PROGRAM_ID, isWritable: false, isSigner: false },
149
+ { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
150
+ ];
151
+
152
+ return new TransactionInstruction({
153
+ keys,
154
+ programId: BASKETS_V3_PROGRAM_ID,
155
+ data: CLOSE_DEACTIVATED_LOOKUP_TABLE_DISCRIMINATOR,
156
+ });
157
+ }
@@ -0,0 +1,151 @@
1
+ import { randomBytes } from 'crypto';
2
+
3
+ import BN from 'bn.js';
4
+ import { getAssociatedTokenAddressSync } from '@solana/spl-token';
5
+ import { AddressLookupTableProgram, PublicKey } from '@solana/web3.js';
6
+
7
+ import { BASKETS_V3_PROGRAM_ID } from '../constants';
8
+
9
+ export const GLOBAL_CONFIG_SEED = Buffer.from("global_config");
10
+ export const BASKET_FEES_SEED = Buffer.from("basket_fees");
11
+ export const WITHDRAW_BASKET_FEES_SEED = Buffer.from("withdraw_basket_fees");
12
+ export const BASKET_SEED = Buffer.from("basket");
13
+ export const MINT_SEED = Buffer.from("mint");
14
+ export const RENT_PAYER_SEED = Buffer.from("rent_payer");
15
+ export const BOUNTY_VAULT_SEED = Buffer.from("bounty_vault");
16
+ export const REBALANCE_INTENT_SEED = Buffer.from("rebalance_intent");
17
+ export const TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
18
+
19
+ export function serializeString(input: string): Uint8Array {
20
+ const utf8 = new TextEncoder().encode(input);
21
+ const length = utf8.length;
22
+
23
+ const out = new Uint8Array(4 + length);
24
+
25
+ // encode length as little-endian u32
26
+ out[0] = length & 0xff;
27
+ out[1] = (length >> 8) & 0xff;
28
+ out[2] = (length >> 16) & 0xff;
29
+ out[3] = (length >> 24) & 0xff;
30
+
31
+ // copy utf8 bytes after the 4-byte length
32
+ out.set(utf8, 4);
33
+
34
+ return out;
35
+ }
36
+
37
+ export function getRandomSeed(): number[] {
38
+ return Array.from(randomBytes(16));
39
+ }
40
+
41
+ export function getBasketTokenMintPda(basketId: number) {
42
+ return PublicKey.findProgramAddressSync([
43
+ MINT_SEED,
44
+ new BN(basketId).toArrayLike(Buffer, "le", 8)
45
+ ], BASKETS_V3_PROGRAM_ID)[0];
46
+ }
47
+
48
+ export function getBasketState(mint: PublicKey) {
49
+ return PublicKey.findProgramAddressSync([
50
+ BASKET_SEED,
51
+ mint.toBuffer()
52
+ ], BASKETS_V3_PROGRAM_ID)[0];
53
+ }
54
+
55
+
56
+ export function getBountyVaultPda() {
57
+ return PublicKey.findProgramAddressSync([
58
+ BOUNTY_VAULT_SEED,
59
+ ], BASKETS_V3_PROGRAM_ID)[0];
60
+ }
61
+
62
+ export function getBasketFeesPda(basket: PublicKey) {
63
+ return PublicKey.findProgramAddressSync([
64
+ BASKET_FEES_SEED,
65
+ basket.toBuffer()
66
+ ], BASKETS_V3_PROGRAM_ID)[0];
67
+ }
68
+
69
+ export function getWithdrawBasketFeesPda(basket: PublicKey, feeType: number) {
70
+ return PublicKey.findProgramAddressSync([
71
+ WITHDRAW_BASKET_FEES_SEED,
72
+ basket.toBuffer(),
73
+ Buffer.from([feeType]) // u8, not u64
74
+ ], BASKETS_V3_PROGRAM_ID)[0];
75
+ }
76
+
77
+ export function getGlobalConfigPda() {
78
+ return PublicKey.findProgramAddressSync([
79
+ GLOBAL_CONFIG_SEED
80
+ ], BASKETS_V3_PROGRAM_ID)[0];
81
+ }
82
+
83
+ export function getRentPayerPda() {
84
+ return PublicKey.findProgramAddressSync([
85
+ RENT_PAYER_SEED
86
+ ], BASKETS_V3_PROGRAM_ID)[0];
87
+ }
88
+
89
+ export function getIntentPda(
90
+ basket: PublicKey,
91
+ intentSeedArray: Uint8Array,
92
+ editType: number,
93
+ ) {
94
+ return PublicKey.findProgramAddressSync([
95
+ basket.toBuffer(),
96
+ intentSeedArray,
97
+ Uint8Array.from([editType]),
98
+ ], BASKETS_V3_PROGRAM_ID)[0];
99
+ }
100
+
101
+ export function getRebalanceIntentPda(
102
+ basket: PublicKey,
103
+ owner: PublicKey,
104
+ ) {
105
+ return PublicKey.findProgramAddressSync([
106
+ REBALANCE_INTENT_SEED,
107
+ basket.toBuffer(),
108
+ owner.toBuffer(),
109
+ ], BASKETS_V3_PROGRAM_ID)[0];
110
+ }
111
+
112
+ export function getMetadataAccount(
113
+ tokenMint: PublicKey
114
+ ): PublicKey {
115
+ return PublicKey.findProgramAddressSync(
116
+ [
117
+ Buffer.from("metadata"),
118
+ TOKEN_METADATA_PROGRAM_ID.toBuffer(),
119
+ tokenMint.toBuffer(),
120
+ ],
121
+ TOKEN_METADATA_PROGRAM_ID
122
+ )[0];
123
+ }
124
+
125
+ export function getLookupTableAccount(
126
+ creator: PublicKey,
127
+ slot: number,
128
+ ): PublicKey {
129
+ const ixAndPubkey = AddressLookupTableProgram.createLookupTable({
130
+ authority: creator,
131
+ recentSlot: slot,
132
+ payer: creator,
133
+ });
134
+ return ixAndPubkey[1];
135
+ }
136
+
137
+ export function getLookupTableInfoAccount(
138
+ lookupTable: PublicKey,
139
+ ): PublicKey {
140
+ return PublicKey.findProgramAddressSync([
141
+ lookupTable.toBuffer()
142
+ ], BASKETS_V3_PROGRAM_ID)[0];
143
+ }
144
+
145
+ export function getAta(
146
+ wallet: PublicKey,
147
+ tokenMint: PublicKey,
148
+ tokenProgram?: PublicKey
149
+ ): PublicKey {
150
+ return getAssociatedTokenAddressSync(tokenMint, wallet, true, tokenProgram);
151
+ }
@@ -0,0 +1,143 @@
1
+ import BN from 'bn.js';
2
+ import {
3
+ ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID
4
+ } from '@solana/spl-token';
5
+ import {
6
+ PublicKey, SystemProgram, TransactionInstruction
7
+ } from '@solana/web3.js';
8
+
9
+ import { BASKETS_V3_PROGRAM_ID } from '../../constants';
10
+ import {
11
+ getAta, getBasketFeesPda, getGlobalConfigPda,
12
+ getRebalanceIntentPda
13
+ } from '../pda';
14
+
15
+ const DEPOSIT_TOKENS_DISCRIMINATOR = Buffer.from([88, 92, 158, 219, 83, 71, 239, 164]);
16
+ const LOCK_DEPOSITS_DISCRIMINATOR = Buffer.from([64, 238, 171, 198, 135, 253, 37, 9]);
17
+ const MINT_BASKET_DISCRIMINATOR = Buffer.from([161, 207, 48, 45, 7, 156, 233, 143]);
18
+
19
+
20
+ export function depositTokensIx(params: {
21
+ owner: PublicKey;
22
+ basket: PublicKey;
23
+ contributions: {mint: PublicKey, amount: number}[]; // length 10
24
+ }): TransactionInstruction[] {
25
+
26
+ const { owner, basket, contributions } = params;
27
+
28
+ let rebalanceIntent = getRebalanceIntentPda(basket, owner);
29
+
30
+ const discriminator = DEPOSIT_TOKENS_DISCRIMINATOR;
31
+
32
+ let ixs: TransactionInstruction[] = [];
33
+
34
+ let batch_size = 5;
35
+ for (let i = 0; i < contributions.length; i += batch_size) {
36
+ let batch_contributions = contributions.slice(i, i + batch_size);
37
+ let amounts = batch_contributions.map((contribution) => contribution.amount);
38
+ while (amounts.length < 10) amounts.push(0);
39
+ const amountsBuffer = Buffer.concat(
40
+ amounts.map((amount) => Buffer.from(new BN(amount).toArray("le", 8)))
41
+ );
42
+
43
+ const data = Buffer.concat([discriminator, amountsBuffer]);
44
+
45
+ const keys = [
46
+ { pubkey: owner, isSigner: true, isWritable: true },
47
+ { pubkey: basket, isSigner: false, isWritable: true },
48
+ { pubkey: rebalanceIntent, isSigner: false, isWritable: true },
49
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
50
+ { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false },
51
+ { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
52
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
53
+ ];
54
+
55
+ // remaining accounts
56
+ batch_contributions.forEach((contribution) => {
57
+ let mint = contribution.mint;
58
+ let ownerAta = getAta(owner, mint);
59
+ let basketAta = getAta(basket, mint);
60
+ keys.push({ pubkey: mint, isSigner: false, isWritable: false });
61
+ keys.push({ pubkey: ownerAta, isSigner: false, isWritable: true });
62
+ keys.push({ pubkey: basketAta, isSigner: false, isWritable: true });
63
+ });
64
+
65
+ ixs.push(
66
+ new TransactionInstruction({
67
+ keys,
68
+ programId: BASKETS_V3_PROGRAM_ID,
69
+ data,
70
+ })
71
+ );
72
+ }
73
+
74
+ return ixs;
75
+ }
76
+
77
+
78
+ export function lockDepositsIx(params: {
79
+ owner: PublicKey;
80
+ basket: PublicKey;
81
+ }): TransactionInstruction {
82
+ const { owner, basket } = params;
83
+ let rebalanceIntent = getRebalanceIntentPda(basket, owner);
84
+ let globalConfig = getGlobalConfigPda();
85
+
86
+ const keys = [
87
+ { pubkey: params.owner, isSigner: true , isWritable: true},
88
+ { pubkey: rebalanceIntent, isSigner: false, isWritable: true },
89
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
90
+ ];
91
+
92
+ return new TransactionInstruction({
93
+ keys,
94
+ programId: BASKETS_V3_PROGRAM_ID,
95
+ data: LOCK_DEPOSITS_DISCRIMINATOR,
96
+ });
97
+ }
98
+
99
+
100
+ export function mintBasketIx(params: {
101
+ keeper: PublicKey;
102
+ basket: PublicKey;
103
+ basketTokenMint: PublicKey;
104
+ buyer: PublicKey;
105
+ basketRebalanceIntent?: PublicKey;
106
+ }): TransactionInstruction {
107
+
108
+ const { keeper, basket, basketTokenMint, buyer } = params;
109
+ let rebalanceIntent = getRebalanceIntentPda(basket, buyer);
110
+
111
+ let basketFees = getBasketFeesPda(basket);
112
+
113
+ let globalConfig = getGlobalConfigPda();
114
+
115
+ let buyerBasketATA = getAta(buyer, basketTokenMint);
116
+ let basketFeesAta = getAta(basketFees, basketTokenMint);
117
+
118
+ const keys = [
119
+ { pubkey: keeper, isWritable: true, isSigner: true },
120
+ { pubkey: basket, isWritable: true, isSigner: false },
121
+ { pubkey: rebalanceIntent, isWritable: true, isSigner: false },
122
+ { pubkey: basketTokenMint, isWritable: true, isSigner: false },
123
+ { pubkey: buyer, isWritable: true, isSigner: false },
124
+ { pubkey: buyerBasketATA, isWritable: true, isSigner: false },
125
+ { pubkey: globalConfig, isWritable: false, isSigner: false },
126
+ { pubkey: basketFees, isWritable: true, isSigner: false },
127
+ { pubkey: basketFeesAta, isWritable: true, isSigner: false },
128
+ { pubkey: params.basketRebalanceIntent ?? BASKETS_V3_PROGRAM_ID, isWritable: params.basketRebalanceIntent ? true : false, isSigner: false },
129
+ { pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
130
+ { pubkey: TOKEN_2022_PROGRAM_ID, isWritable: false, isSigner: false },
131
+ { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
132
+ { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
133
+ ];
134
+
135
+ return new TransactionInstruction({
136
+ keys,
137
+ programId: BASKETS_V3_PROGRAM_ID,
138
+ data: MINT_BASKET_DISCRIMINATOR,
139
+ });
140
+ }
141
+
142
+
143
+
@@ -0,0 +1,53 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import { BASKETS_V3_PROGRAM_ID } from "../../constants";
3
+ import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
4
+ import { getAta, getRebalanceIntentPda } from "../pda";
5
+ import { TransactionInstruction } from "@solana/web3.js";
6
+ import { SystemProgram } from "@solana/web3.js";
7
+
8
+ const REDEEM_TOKENS_DISCRIMINATOR = Buffer.from([83, 49, 112, 2, 105, 193, 106, 126]);
9
+
10
+ export function redeemTokensIx(
11
+ params: {
12
+ keeper: PublicKey;
13
+ basket: PublicKey;
14
+ owner: PublicKey;
15
+ tokenMints: PublicKey[];
16
+ },
17
+ ): TransactionInstruction {
18
+ const {
19
+ keeper,
20
+ basket,
21
+ owner,
22
+ } = params;
23
+
24
+ let rebalanceIntent = getRebalanceIntentPda(basket, owner);
25
+
26
+ const keys = [
27
+ { pubkey: keeper, isSigner: true, isWritable: true },
28
+ { pubkey: basket, isSigner: false, isWritable: true },
29
+ { pubkey: rebalanceIntent, isSigner: false, isWritable: true },
30
+ { pubkey: owner, isSigner: false, isWritable: true },
31
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
32
+ { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false },
33
+ { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
34
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
35
+ ];
36
+
37
+ // remaining accounts
38
+ params.tokenMints.forEach((mint) => {
39
+ keys.push({ pubkey: mint, isWritable: false, isSigner: false });
40
+ keys.push({ pubkey: getAta(owner, mint), isWritable: true, isSigner: false });
41
+ keys.push({ pubkey: getAta(basket, mint), isWritable: true, isSigner: false });
42
+ });
43
+
44
+ const discriminator = REDEEM_TOKENS_DISCRIMINATOR;
45
+
46
+ const data = discriminator;
47
+
48
+ return new TransactionInstruction({
49
+ keys,
50
+ programId: BASKETS_V3_PROGRAM_ID,
51
+ data,
52
+ });
53
+ }
package/src/jup.ts ADDED
@@ -0,0 +1,113 @@
1
+ import { PublicKey, TransactionInstruction } from "@solana/web3.js";
2
+
3
+ export function processJupInstruction(instruction: {
4
+ programId: string;
5
+ accounts: {
6
+ pubkey: string;
7
+ isSigner: boolean;
8
+ isWritable: boolean;
9
+ }[];
10
+ data: string;
11
+ }): TransactionInstruction {
12
+ return {
13
+ programId: new PublicKey(instruction.programId),
14
+ keys: instruction.accounts.map((a: {
15
+ pubkey: string;
16
+ isSigner: boolean;
17
+ isWritable: boolean;
18
+ }) => ({
19
+ ...a,
20
+ pubkey: new PublicKey(a.pubkey)
21
+ })),
22
+ data: Buffer.from(instruction.data, "base64")
23
+ };
24
+ }
25
+
26
+ export async function getJupQuote(params: {
27
+ keeper: PublicKey,
28
+ basketMintIn: PublicKey,
29
+ basketMintOut: PublicKey,
30
+ basketAmountIn: number,
31
+ basketAmountOut: number,
32
+ swapMode: "exact_in" | "exact_out" | "ioc",
33
+ apiKey: string,
34
+ maxJupAccounts: number,
35
+ }): Promise<{
36
+ mode: string,
37
+ inputMint: string,
38
+ outputMint: string,
39
+ inAmount: number,
40
+ outAmount: number,
41
+ swapUsdValue: number,
42
+ routePlan: any,
43
+ transaction: string,
44
+ }> {
45
+ let options = {method: 'GET', headers: {'x-api-key': params.apiKey}};
46
+ let reqUrl = 'https://api.jup.ag/swap/v1/quote' +
47
+ '?inputMint=' + params.basketMintOut.toBase58() +
48
+ '&outputMint=' + params.basketMintIn.toBase58() +
49
+ '&amount=' + (params.swapMode == "exact_in" ? params.basketAmountIn : params.basketAmountOut) +
50
+ '&swapMode=' + (params.swapMode == "exact_in" ? "ExactOut" : "ExactIn") +
51
+ '&maxAccounts=' + params.maxJupAccounts;
52
+ let res = await fetch(reqUrl, options).then(res => res.json())
53
+ return res;
54
+ }
55
+
56
+ export async function getJupSwapInstructions(params: {
57
+ keeper: PublicKey,
58
+ quoteResponse: any,
59
+ apiKey: string,
60
+ }): Promise<any> {
61
+ let reqUrl = 'https://api.jup.ag/swap/v1/swap-instructions'
62
+ let body = {
63
+ userPublicKey: params.keeper.toBase58(),
64
+ quoteResponse: params.quoteResponse,
65
+ wrapAndUnwrapSol: false,
66
+ useTokenLedger: true,
67
+ }
68
+ let options = {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ 'x-api-key': params.apiKey
73
+ },
74
+ body: JSON.stringify(body),
75
+ };
76
+ let res = await fetch(reqUrl, options).then(res => res.json())
77
+ return res;
78
+ }
79
+
80
+ export async function getJupTokenLedgerAndSwapInstructions(params: {
81
+ keeper: PublicKey,
82
+ basketMintIn: PublicKey,
83
+ basketMintOut: PublicKey,
84
+ basketAmountIn: number,
85
+ basketAmountOut: number,
86
+ swapMode: "exact_in" | "exact_out" | "ioc",
87
+ apiKey: string,
88
+ maxJupAccounts: number,
89
+ }): Promise<{
90
+ tokenLedgerInstruction: TransactionInstruction,
91
+ swapInstruction: TransactionInstruction,
92
+ addressLookupTableAddresses: PublicKey[],
93
+ quoteResponse: any,
94
+ }> {
95
+ try {
96
+ let quoteResponse = await getJupQuote(params);
97
+ let swapInstructions = await getJupSwapInstructions({ ...params, quoteResponse });
98
+ return {
99
+ tokenLedgerInstruction: processJupInstruction(swapInstructions.tokenLedgerInstruction),
100
+ swapInstruction: processJupInstruction(swapInstructions.swapInstruction),
101
+ addressLookupTableAddresses: swapInstructions.addressLookupTableAddresses.map((a: string) => new PublicKey(a)),
102
+ quoteResponse: quoteResponse,
103
+ };
104
+ } catch (e) {
105
+ console.log("Error getting Jup Instructions:", params.basketMintOut.toBase58(), params.basketMintIn.toBase58(), params.basketAmountOut);
106
+ return {
107
+ tokenLedgerInstruction: undefined as any,
108
+ swapInstruction: undefined as any,
109
+ addressLookupTableAddresses: [],
110
+ quoteResponse: undefined,
111
+ };
112
+ }
113
+ }