@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.
- package/dist/src/constants.d.ts +23 -0
- package/dist/src/constants.js +38 -0
- package/dist/src/index.d.ts +804 -0
- package/dist/src/index.js +2097 -0
- package/dist/src/instructions/automation/auction.d.ts +6 -0
- package/dist/src/instructions/automation/auction.js +40 -0
- package/dist/src/instructions/automation/claimBounty.d.ts +12 -0
- package/dist/src/instructions/automation/claimBounty.js +44 -0
- package/dist/src/instructions/automation/flashSwap.d.ts +21 -0
- package/dist/src/instructions/automation/flashSwap.js +74 -0
- package/dist/src/instructions/automation/priceUpdate.d.ts +19 -0
- package/dist/src/instructions/automation/priceUpdate.js +89 -0
- package/dist/src/instructions/automation/rebalanceIntent.d.ts +32 -0
- package/dist/src/instructions/automation/rebalanceIntent.js +117 -0
- package/dist/src/instructions/automation/rebalanceSwap.d.ts +11 -0
- package/dist/src/instructions/automation/rebalanceSwap.js +42 -0
- package/dist/src/instructions/management/addBounty.d.ts +7 -0
- package/dist/src/instructions/management/addBounty.js +41 -0
- package/dist/src/instructions/management/admin.d.ts +9 -0
- package/dist/src/instructions/management/admin.js +53 -0
- package/dist/src/instructions/management/claimFees.d.ts +15 -0
- package/dist/src/instructions/management/claimFees.js +95 -0
- package/dist/src/instructions/management/createBasket.d.ts +21 -0
- package/dist/src/instructions/management/createBasket.js +98 -0
- package/dist/src/instructions/management/edit.d.ts +51 -0
- package/dist/src/instructions/management/edit.js +477 -0
- package/dist/src/instructions/management/luts.d.ts +30 -0
- package/dist/src/instructions/management/luts.js +99 -0
- package/dist/src/instructions/pda.d.ts +25 -0
- package/dist/src/instructions/pda.js +128 -0
- package/dist/src/instructions/user/deposit.d.ts +20 -0
- package/dist/src/instructions/user/deposit.js +100 -0
- package/dist/src/instructions/user/withdraw.d.ts +8 -0
- package/dist/src/instructions/user/withdraw.js +36 -0
- package/dist/src/jup.d.ts +49 -0
- package/dist/src/jup.js +80 -0
- package/dist/src/keeperMonitor.d.ts +52 -0
- package/dist/src/keeperMonitor.js +624 -0
- package/dist/src/layouts/basket.d.ts +191 -0
- package/dist/src/layouts/basket.js +51 -0
- package/dist/src/layouts/config.d.ts +281 -0
- package/dist/src/layouts/config.js +237 -0
- package/dist/src/layouts/fraction.d.ts +20 -0
- package/dist/src/layouts/fraction.js +164 -0
- package/dist/src/layouts/intents/bounty.d.ts +18 -0
- package/dist/src/layouts/intents/bounty.js +19 -0
- package/dist/src/layouts/intents/intent.d.ts +209 -0
- package/dist/src/layouts/intents/intent.js +97 -0
- package/dist/src/layouts/intents/rebalanceIntent.d.ts +212 -0
- package/dist/src/layouts/intents/rebalanceIntent.js +94 -0
- package/dist/src/layouts/lookupTable.d.ts +7 -0
- package/dist/src/layouts/lookupTable.js +10 -0
- package/dist/src/layouts/oracle.d.ts +63 -0
- package/dist/src/layouts/oracle.js +96 -0
- package/dist/src/states/basket.d.ts +14 -0
- package/dist/src/states/basket.js +479 -0
- package/dist/src/states/config.d.ts +3 -0
- package/dist/src/states/config.js +71 -0
- package/dist/src/states/intents/intent.d.ts +10 -0
- package/dist/src/states/intents/intent.js +316 -0
- package/dist/src/states/intents/rebalanceIntent.d.ts +42 -0
- package/dist/src/states/intents/rebalanceIntent.js +680 -0
- package/dist/src/states/oracles/constants.d.ts +9 -0
- package/dist/src/states/oracles/constants.js +15 -0
- package/dist/src/states/oracles/oracle.d.ts +24 -0
- package/dist/src/states/oracles/oracle.js +168 -0
- package/dist/src/states/oracles/pythOracle.d.ts +132 -0
- package/dist/src/states/oracles/pythOracle.js +609 -0
- package/dist/src/states/oracles/raydiumClmmOracle.d.ts +184 -0
- package/dist/src/states/oracles/raydiumClmmOracle.js +843 -0
- package/dist/src/states/oracles/raydiumCpmmOracle.d.ts +120 -0
- package/dist/src/states/oracles/raydiumCpmmOracle.js +540 -0
- package/dist/src/states/oracles/switchboardOracle.d.ts +0 -0
- package/dist/src/states/oracles/switchboardOracle.js +1 -0
- package/dist/src/states/withdrawBasketFees.d.ts +10 -0
- package/dist/src/states/withdrawBasketFees.js +154 -0
- package/dist/src/txUtils.d.ts +65 -0
- package/dist/src/txUtils.js +306 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +561 -0
- package/package.json +31 -0
- package/src/constants.ts +40 -0
- package/src/index.ts +2431 -0
- package/src/instructions/automation/auction.ts +55 -0
- package/src/instructions/automation/claimBounty.ts +69 -0
- package/src/instructions/automation/flashSwap.ts +104 -0
- package/src/instructions/automation/priceUpdate.ts +117 -0
- package/src/instructions/automation/rebalanceIntent.ts +181 -0
- package/src/instructions/management/addBounty.ts +55 -0
- package/src/instructions/management/admin.ts +72 -0
- package/src/instructions/management/claimFees.ts +129 -0
- package/src/instructions/management/createBasket.ts +138 -0
- package/src/instructions/management/edit.ts +602 -0
- package/src/instructions/management/luts.ts +157 -0
- package/src/instructions/pda.ts +151 -0
- package/src/instructions/user/deposit.ts +143 -0
- package/src/instructions/user/withdraw.ts +53 -0
- package/src/jup.ts +113 -0
- package/src/keeperMonitor.ts +585 -0
- package/src/layouts/basket.ts +233 -0
- package/src/layouts/config.ts +576 -0
- package/src/layouts/fraction.ts +164 -0
- package/src/layouts/intents/bounty.ts +35 -0
- package/src/layouts/intents/intent.ts +324 -0
- package/src/layouts/intents/rebalanceIntent.ts +306 -0
- package/src/layouts/lookupTable.ts +14 -0
- package/src/layouts/oracle.ts +157 -0
- package/src/states/basket.ts +527 -0
- package/src/states/config.ts +62 -0
- package/src/states/intents/intent.ts +311 -0
- package/src/states/intents/rebalanceIntent.ts +751 -0
- package/src/states/oracles/constants.ts +13 -0
- package/src/states/oracles/oracle.ts +212 -0
- package/src/states/oracles/pythOracle.ts +874 -0
- package/src/states/oracles/raydiumClmmOracle.ts +1193 -0
- package/src/states/oracles/raydiumCpmmOracle.ts +784 -0
- package/src/states/oracles/switchboardOracle.ts +0 -0
- package/src/states/withdrawBasketFees.ts +160 -0
- package/src/txUtils.ts +424 -0
- package/test.ts +609 -0
- 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
|
+
}
|