@wireio/stake 0.3.1 → 0.4.0
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/stake.browser.js +3601 -1920
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +3269 -1361
- package/lib/stake.js +4374 -2733
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +3601 -1920
- package/lib/stake.m.js.map +1 -1
- package/package.json +3 -1
- package/src/assets/solana/idl/liqsol_core.json +2327 -887
- package/src/assets/solana/idl/liqsol_token.json +1 -1
- package/src/assets/solana/idl/transfer_hook.json +192 -0
- package/src/assets/solana/idl/validator_leaderboard.json +147 -4
- package/src/assets/solana/types/liqsol_core.ts +2327 -887
- package/src/assets/solana/types/liqsol_token.ts +1 -1
- package/src/assets/solana/types/transfer_hook.ts +198 -0
- package/src/assets/solana/types/validator_leaderboard.ts +147 -4
- package/src/networks/ethereum/ethereum.ts +0 -5
- package/src/networks/ethereum/utils.ts +1 -1
- package/src/networks/solana/clients/deposit.client.ts +154 -8
- package/src/networks/solana/clients/distribution.client.ts +72 -291
- package/src/networks/solana/clients/leaderboard.client.ts +59 -14
- package/src/networks/solana/clients/outpost.client.ts +188 -359
- package/src/networks/solana/clients/token.client.ts +85 -100
- package/src/networks/solana/constants.ts +155 -64
- package/src/networks/solana/solana.ts +273 -154
- package/src/networks/solana/types.ts +532 -71
- package/src/networks/solana/utils.ts +68 -51
- package/src/types.ts +108 -17
|
@@ -6,20 +6,31 @@ import {
|
|
|
6
6
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
7
7
|
} from '@solana/spl-token';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
buildOutpostAccounts,
|
|
11
|
+
type OutpostAccounts,
|
|
12
|
+
} from '../utils';
|
|
13
|
+
|
|
10
14
|
import { SolanaProgramService } from '../program';
|
|
11
|
-
import { LiqsolCore } from '../../../assets/solana/types/liqsol_core';
|
|
15
|
+
import type { LiqsolCore } from '../../../assets/solana/types/liqsol_core';
|
|
16
|
+
|
|
12
17
|
import {
|
|
13
18
|
GlobalState,
|
|
14
19
|
PriceHistory,
|
|
15
20
|
TrancheState,
|
|
16
|
-
UserWarrantRecord,
|
|
17
21
|
WalletLike,
|
|
18
|
-
|
|
22
|
+
OutpostAccount,
|
|
23
|
+
UserPretokenRecord,
|
|
19
24
|
} from '../types';
|
|
20
|
-
|
|
21
|
-
import
|
|
22
|
-
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
derivePriceHistoryPda,
|
|
28
|
+
CHAINLINK_FEED,
|
|
29
|
+
CHAINLINK_PROGRAM,
|
|
30
|
+
PROGRAM_IDS,
|
|
31
|
+
deriveExtraAccountMetaListPda,
|
|
32
|
+
} from '../constants';
|
|
33
|
+
|
|
23
34
|
|
|
24
35
|
export class TokenClient {
|
|
25
36
|
private readonly program: Program<LiqsolCore>;
|
|
@@ -28,6 +39,10 @@ export class TokenClient {
|
|
|
28
39
|
return this.provider.wallet;
|
|
29
40
|
}
|
|
30
41
|
|
|
42
|
+
get connection(): Connection {
|
|
43
|
+
return this.provider.connection;
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
constructor(private readonly provider: AnchorProvider) {
|
|
32
47
|
const svc = new SolanaProgramService(provider);
|
|
33
48
|
this.program = svc.getProgram('liqsolCore');
|
|
@@ -51,92 +66,83 @@ export class TokenClient {
|
|
|
51
66
|
return this.program.account.trancheState.fetch(trancheState);
|
|
52
67
|
}
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Fetch the per-user Outpost account (old "wire receipt").
|
|
71
|
+
* Returns null if the user has never interacted with Outpost.
|
|
72
|
+
*/
|
|
73
|
+
async fetchOutpostAccount(user: PublicKey): Promise<OutpostAccount | null> {
|
|
74
|
+
const { outpostAccount } = await this.getAccounts(user);
|
|
75
|
+
return this.program.account.outpostAccount.fetchNullable(outpostAccount);
|
|
57
76
|
}
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Fetch the per-user pretoken purchase record.
|
|
80
|
+
* Returns null if the user has never purchased pretokens.
|
|
81
|
+
*/
|
|
82
|
+
async fetchUserPretokenRecord(
|
|
83
|
+
user: PublicKey,
|
|
84
|
+
): Promise<UserPretokenRecord | null> {
|
|
85
|
+
const { userPretokenRecord } = await this.getAccounts(user);
|
|
86
|
+
return this.program.account.userPretokenRecord.fetchNullable(
|
|
87
|
+
userPretokenRecord,
|
|
88
|
+
);
|
|
62
89
|
}
|
|
63
90
|
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
// Tranche snapshot / quoting
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
|
|
68
91
|
// ---------------------------------------------------------------------------
|
|
69
92
|
// Instruction builders (no send / confirm)
|
|
70
93
|
// ---------------------------------------------------------------------------
|
|
71
94
|
|
|
72
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Build a pretoken `purchase` instruction using liqSOL from the user’s ATA.
|
|
97
|
+
*
|
|
98
|
+
* This mirrors capital-staking `executePurchase` wiring:
|
|
99
|
+
* - amountLamports: liqSOL amount (raw token-2022 units, not SOL)
|
|
100
|
+
*/
|
|
101
|
+
async buildPurchaseIx(
|
|
73
102
|
amountLamports: bigint,
|
|
74
103
|
user = this.wallet.publicKey,
|
|
75
104
|
): Promise<TransactionInstruction> {
|
|
76
105
|
const a = await this.getAccounts(user);
|
|
77
106
|
|
|
107
|
+
const extraAccountMetaList = deriveExtraAccountMetaListPda(a.liqsolMint);
|
|
108
|
+
const liqsolCoreProgram = PROGRAM_IDS.LIQSOL_CORE;
|
|
109
|
+
const transferHookProgram = PROGRAM_IDS.TRANSFER_HOOK;
|
|
110
|
+
|
|
78
111
|
return this.program.methods
|
|
79
|
-
.
|
|
112
|
+
.purchase(new BN(amountLamports.toString()))
|
|
80
113
|
.accounts({
|
|
81
114
|
user: a.user,
|
|
82
115
|
liqsolMint: a.liqsolMint,
|
|
83
116
|
globalState: a.globalState,
|
|
117
|
+
distributionState: a.distributionState,
|
|
84
118
|
|
|
119
|
+
// buyer’s liqSOL
|
|
120
|
+
buyerAta: a.userAta,
|
|
121
|
+
|
|
122
|
+
// pool / bucket context
|
|
85
123
|
poolAuthority: a.poolAuthority,
|
|
86
|
-
liqsolPoolAta: a.liqsolPoolAta,
|
|
87
|
-
liqsolPoolUserRecord: a.poolUserRecord,
|
|
88
|
-
distributionState: a.distributionState,
|
|
89
|
-
payRateHistory: a.payRateHistory,
|
|
90
124
|
bucketAuthority: a.bucketAuthority,
|
|
91
125
|
bucketTokenAccount: a.bucketTokenAccount,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// IDL name is warrantDepositRecord (wireReceipt PDA)
|
|
95
|
-
warrantDepositRecord: a.wireReceipt,
|
|
126
|
+
bucketUserRecord: a.bucketUserRecord,
|
|
96
127
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
chainlinkFeed: a.chainLinkFeed,
|
|
101
|
-
chainlinkProgram: a.chainLinkProgram,
|
|
102
|
-
|
|
103
|
-
tokenProgram: TOKEN_2022_PROGRAM_ID,
|
|
104
|
-
systemProgram: SystemProgram.programId,
|
|
105
|
-
})
|
|
106
|
-
.instruction();
|
|
107
|
-
}
|
|
128
|
+
// distribution userRecords (token-account keyed)
|
|
129
|
+
senderUserRecord: a.userUserRecord,
|
|
130
|
+
receiverUserRecord: a.liqsolPoolUserRecord,
|
|
108
131
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const a = await this.getAccounts(user);
|
|
132
|
+
// transfer-hook wiring
|
|
133
|
+
extraAccountMetaList,
|
|
134
|
+
liqsolCoreProgram,
|
|
135
|
+
transferHookProgram,
|
|
114
136
|
|
|
115
|
-
|
|
116
|
-
.purchaseWithLiqsol(new BN(amountLamports.toString()))
|
|
117
|
-
.accounts({
|
|
118
|
-
user: a.user,
|
|
119
|
-
liqsolMint: a.liqsolMint,
|
|
120
|
-
globalState: a.globalState,
|
|
121
|
-
|
|
122
|
-
buyerAta: a.userAta,
|
|
123
|
-
poolAuthority: a.poolAuthority,
|
|
137
|
+
// pool + outpost + tranche
|
|
124
138
|
liqsolPoolAta: a.liqsolPoolAta,
|
|
125
|
-
|
|
126
|
-
warrantDepositRecord: a.wireReceipt,
|
|
127
|
-
|
|
128
|
-
liqsolPoolUserRecord: a.poolUserRecord,
|
|
129
|
-
distributionState: a.distributionState,
|
|
130
|
-
payRateHistory: a.payRateHistory,
|
|
131
|
-
bucketAuthority: a.bucketAuthority,
|
|
132
|
-
bucketTokenAccount: a.bucketTokenAccount,
|
|
133
|
-
solBucket: a.solBucket,
|
|
134
|
-
|
|
139
|
+
outpostAccount: a.outpostAccount,
|
|
135
140
|
trancheState: a.trancheState,
|
|
136
|
-
|
|
141
|
+
userPretokenRecord: a.userPretokenRecord,
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
// Chainlink pricing
|
|
144
|
+
chainlinkFeed: a.chainLinkFeed ?? CHAINLINK_FEED,
|
|
145
|
+
chainlinkProgram: a.chainLinkProgram ?? CHAINLINK_PROGRAM,
|
|
140
146
|
|
|
141
147
|
tokenProgram: TOKEN_2022_PROGRAM_ID,
|
|
142
148
|
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
@@ -145,37 +151,12 @@ export class TokenClient {
|
|
|
145
151
|
.instruction();
|
|
146
152
|
}
|
|
147
153
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
.purchaseWarrantsFromYield()
|
|
155
|
-
.accounts({
|
|
156
|
-
user: a.user,
|
|
157
|
-
globalState: a.globalState,
|
|
158
|
-
liqsolMint: a.liqsolMint,
|
|
159
|
-
poolAuthority: a.poolAuthority,
|
|
160
|
-
liqsolPoolAta: a.liqsolPoolAta,
|
|
161
|
-
solBucket: a.solBucket,
|
|
162
|
-
|
|
163
|
-
liqsolPoolUserRecord: a.poolUserRecord,
|
|
164
|
-
distributionState: a.distributionState,
|
|
165
|
-
payRateHistory: a.payRateHistory,
|
|
166
|
-
bucketAuthority: a.bucketAuthority,
|
|
167
|
-
bucketTokenAccount: a.bucketTokenAccount,
|
|
168
|
-
|
|
169
|
-
trancheState: a.trancheState,
|
|
170
|
-
userWarrantRecord: a.userWarrantRecord,
|
|
171
|
-
chainlinkFeed: a.chainLinkFeed,
|
|
172
|
-
chainlinkProgram: a.chainLinkProgram,
|
|
173
|
-
|
|
174
|
-
tokenProgram: TOKEN_2022_PROGRAM_ID,
|
|
175
|
-
systemProgram: SystemProgram.programId,
|
|
176
|
-
})
|
|
177
|
-
.instruction();
|
|
178
|
-
}
|
|
154
|
+
// NOTE:
|
|
155
|
+
// - There is no longer `purchaseWithSol` in the IDL - SOL → liqSOL happens
|
|
156
|
+
// through the deposit / liqSOL minting path, not directly in pretokens.
|
|
157
|
+
// - `purchaseFromYield` is an operator-facing / protocol flow and you
|
|
158
|
+
// indicated you’ll trigger it from Wire infra, so we don’t expose a
|
|
159
|
+
// client helper here for now.
|
|
179
160
|
|
|
180
161
|
// ---------------------------------------------------------------------------
|
|
181
162
|
// Price helpers (SOL/USD via priceHistory account)
|
|
@@ -193,7 +174,7 @@ export class TokenClient {
|
|
|
193
174
|
|
|
194
175
|
/**
|
|
195
176
|
* Fetch latest SOL/USD price (1e8 scale) from liqsol_core.priceHistory.
|
|
196
|
-
* Uses the ring-buffer semantics from
|
|
177
|
+
* Uses the ring-buffer semantics from capital-staking.
|
|
197
178
|
*/
|
|
198
179
|
async getSolPriceUsd(): Promise<bigint> {
|
|
199
180
|
const priceHistoryPda = derivePriceHistoryPda();
|
|
@@ -204,19 +185,23 @@ export class TokenClient {
|
|
|
204
185
|
const { prices, nextIndex, count, windowSize } = history;
|
|
205
186
|
|
|
206
187
|
if (!prices || prices.length === 0 || !count) {
|
|
207
|
-
throw new Error('Price history is empty
|
|
188
|
+
throw new Error('Price history is empty - no SOL price available');
|
|
208
189
|
}
|
|
209
190
|
|
|
210
191
|
const capacity = prices.length || windowSize;
|
|
211
192
|
if (!capacity) {
|
|
212
|
-
throw new Error(
|
|
193
|
+
throw new Error(
|
|
194
|
+
'Price history capacity is zero - check account layout',
|
|
195
|
+
);
|
|
213
196
|
}
|
|
214
197
|
|
|
215
198
|
const lastIndex = nextIndex === 0 ? capacity - 1 : nextIndex - 1;
|
|
216
199
|
const latest = prices[lastIndex];
|
|
217
200
|
|
|
218
201
|
if (!BN.isBN(latest)) {
|
|
219
|
-
throw new Error(
|
|
202
|
+
throw new Error(
|
|
203
|
+
'Latest price entry is not a BN - check IDL/decoder',
|
|
204
|
+
);
|
|
220
205
|
}
|
|
221
206
|
|
|
222
207
|
return BigInt(latest.toString());
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/networks/solana/constants.ts
|
|
2
2
|
import { PublicKey, StakeProgram } from '@solana/web3.js';
|
|
3
3
|
|
|
4
|
-
import liqsolCoreIDL from
|
|
5
|
-
import liqSolTokenIDL from
|
|
6
|
-
import validatorLeaderboardIDL from
|
|
4
|
+
import liqsolCoreIDL from '../../assets/solana/idl/liqsol_core.json';
|
|
5
|
+
import liqSolTokenIDL from '../../assets/solana/idl/liqsol_token.json';
|
|
6
|
+
import validatorLeaderboardIDL from '../../assets/solana/idl/validator_leaderboard.json';
|
|
7
|
+
import transferHookIDL from '../../assets/solana/idl/transfer_hook.json';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* ---------------------------------------------------------------------------
|
|
@@ -14,27 +15,24 @@ import validatorLeaderboardIDL from "../../assets/solana/idl/validator_leaderboa
|
|
|
14
15
|
* - `metadata.address` in your Anchor IDLs under src/assets/solana/idl/*.json
|
|
15
16
|
* - The program IDs printed by your deploy scripts
|
|
16
17
|
*/
|
|
17
|
-
// Extract program IDs from IDL files
|
|
18
18
|
export const PROGRAM_IDS = {
|
|
19
19
|
LIQSOL_CORE: new PublicKey(liqsolCoreIDL.address),
|
|
20
20
|
LIQSOL_TOKEN: new PublicKey(liqSolTokenIDL.address),
|
|
21
21
|
VALIDATOR_LEADERBOARD: new PublicKey(validatorLeaderboardIDL.address),
|
|
22
|
+
TRANSFER_HOOK: new PublicKey(transferHookIDL.address),
|
|
22
23
|
} as const;
|
|
23
24
|
|
|
24
|
-
// Export individual program IDs for convenience
|
|
25
25
|
export const {
|
|
26
26
|
LIQSOL_CORE,
|
|
27
27
|
LIQSOL_TOKEN,
|
|
28
28
|
VALIDATOR_LEADERBOARD,
|
|
29
|
+
TRANSFER_HOOK,
|
|
29
30
|
} = PROGRAM_IDS;
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* ---------------------------------------------------------------------------
|
|
33
34
|
* PDA SEEDS (must match on-chain programs)
|
|
34
35
|
* ---------------------------------------------------------------------------
|
|
35
|
-
*
|
|
36
|
-
* These strings are baked into the on-chain programs and are already used in
|
|
37
|
-
* your test utils. We centralize them here so all clients share them.
|
|
38
36
|
*/
|
|
39
37
|
|
|
40
38
|
export const PDA_SEEDS = {
|
|
@@ -52,156 +50,238 @@ export const PDA_SEEDS = {
|
|
|
52
50
|
|
|
53
51
|
// distribution program (embedded in liqsol_core)
|
|
54
52
|
DISTRIBUTION_STATE: 'distribution_state',
|
|
53
|
+
// NOTE: in the current IDL, userRecord is keyed by the USER (wallet), not ATA
|
|
55
54
|
USER_RECORD: 'user_record',
|
|
56
55
|
|
|
57
|
-
// pay-rate history
|
|
56
|
+
// pay-rate / price history
|
|
58
57
|
PAY_RATE_HISTORY: 'pay_rate_history',
|
|
58
|
+
PRICE_HISTORY: 'price_history',
|
|
59
59
|
|
|
60
60
|
// validator leaderboard (state + records)
|
|
61
61
|
LEADERBOARD_STATE: 'leaderboard_state',
|
|
62
62
|
VALIDATOR_RECORD: 'validator',
|
|
63
63
|
GLOBAL_STAKE_INFO: 'global_stake_info',
|
|
64
64
|
|
|
65
|
-
// Outpost
|
|
66
|
-
|
|
65
|
+
// Outpost / Wire pretokens
|
|
66
|
+
OUTPOST_GLOBAL_STATE: 'outpost_global_state',
|
|
67
67
|
LIQSOL_POOL: 'liqsol_pool',
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
OUTPOST_ACCOUNT: 'outpost_account',
|
|
69
|
+
USER_PRETOKEN_RECORD: 'user_pretoken_record',
|
|
70
70
|
TRANCHE_STATE: 'tranche_state',
|
|
71
|
-
USER_WARRANT_RECORD: 'user_warrant_record',
|
|
72
71
|
|
|
73
|
-
// BAR
|
|
72
|
+
// BAR module (bonded actor roles)
|
|
74
73
|
BAR_STATE_SEED: 'bar_state',
|
|
75
74
|
BONDED_ACTOR_SEED: 'bonded_actor',
|
|
76
75
|
BOND_LEVEL_SEED: 'bond_level',
|
|
77
76
|
|
|
78
|
-
//
|
|
79
|
-
|
|
77
|
+
// SPL transfer-hook extra account metas
|
|
78
|
+
EXTRA_ACCOUNT_METAS: 'extra-account-metas',
|
|
79
|
+
|
|
80
|
+
// Withdraw module / receipts
|
|
81
|
+
WITHDRAW_GLOBAL: 'global',
|
|
82
|
+
STAKE_ALLOCATION_STATE: 'stake_allocation_state',
|
|
83
|
+
STAKE_METRICS: 'stake_metrics',
|
|
84
|
+
MAINTENANCE_LEDGER: 'maintenance_ledger',
|
|
85
|
+
WITHDRAW_MINT_AUTHORITY: 'mint_authority',
|
|
86
|
+
MINT_METADATA: 'mint_metadata',
|
|
87
|
+
LIQ_RECEIPT_DATA: 'liq_receipt_data',
|
|
88
|
+
WITHDRAW_MINT: 'mint',
|
|
80
89
|
} as const;
|
|
81
90
|
|
|
82
91
|
/**
|
|
83
|
-
*
|
|
92
|
+
* ---------------------------------------------------------------------------
|
|
93
|
+
* CORE / DISTRIBUTION / DEPOSIT PDAS
|
|
94
|
+
* ---------------------------------------------------------------------------
|
|
84
95
|
*/
|
|
96
|
+
|
|
85
97
|
export const deriveLiqsolMintPda = () =>
|
|
86
98
|
PublicKey.findProgramAddressSync(
|
|
87
99
|
[Buffer.from(PDA_SEEDS.LIQSOL_MINT)],
|
|
88
|
-
|
|
100
|
+
LIQSOL_TOKEN,
|
|
89
101
|
)[0];
|
|
90
102
|
|
|
91
103
|
export const deriveLiqsolMintAuthorityPda = () =>
|
|
92
104
|
PublicKey.findProgramAddressSync(
|
|
93
105
|
[Buffer.from(PDA_SEEDS.LIQSOL_MINT_AUTHORITY)],
|
|
94
|
-
|
|
106
|
+
LIQSOL_TOKEN,
|
|
95
107
|
)[0];
|
|
96
108
|
|
|
97
109
|
export const deriveDepositAuthorityPda = () =>
|
|
98
110
|
PublicKey.findProgramAddressSync(
|
|
99
111
|
[Buffer.from(PDA_SEEDS.DEPOSIT_AUTHORITY)],
|
|
100
|
-
|
|
112
|
+
LIQSOL_CORE,
|
|
101
113
|
)[0];
|
|
102
114
|
|
|
103
115
|
export const deriveVaultPda = () =>
|
|
104
116
|
PublicKey.findProgramAddressSync(
|
|
105
117
|
[Buffer.from(PDA_SEEDS.VAULT)],
|
|
106
|
-
|
|
118
|
+
LIQSOL_CORE,
|
|
107
119
|
)[0];
|
|
108
120
|
|
|
109
121
|
export const deriveReservePoolPda = () =>
|
|
110
122
|
PublicKey.findProgramAddressSync(
|
|
111
123
|
[Buffer.from(PDA_SEEDS.RESERVE_POOL)],
|
|
112
|
-
|
|
124
|
+
LIQSOL_CORE,
|
|
113
125
|
)[0];
|
|
114
126
|
|
|
115
127
|
export const deriveStakeControllerStatePda = () =>
|
|
116
128
|
PublicKey.findProgramAddressSync(
|
|
117
129
|
[Buffer.from(PDA_SEEDS.STAKE_CONTROLLER_STATE)],
|
|
118
|
-
|
|
130
|
+
LIQSOL_CORE,
|
|
119
131
|
)[0];
|
|
120
132
|
|
|
121
133
|
export const derivePayoutStatePda = () =>
|
|
122
134
|
PublicKey.findProgramAddressSync(
|
|
123
135
|
[Buffer.from(PDA_SEEDS.PAYOUT_STATE)],
|
|
124
|
-
|
|
136
|
+
LIQSOL_CORE,
|
|
125
137
|
)[0];
|
|
126
138
|
|
|
127
139
|
export const deriveBucketAuthorityPda = () =>
|
|
128
140
|
PublicKey.findProgramAddressSync(
|
|
129
141
|
[Buffer.from(PDA_SEEDS.BUCKET_AUTHORITY)],
|
|
130
|
-
|
|
142
|
+
LIQSOL_CORE,
|
|
131
143
|
)[0];
|
|
132
144
|
|
|
133
145
|
export const deriveDistributionStatePda = () =>
|
|
134
146
|
PublicKey.findProgramAddressSync(
|
|
135
147
|
[Buffer.from(PDA_SEEDS.DISTRIBUTION_STATE)],
|
|
136
|
-
|
|
148
|
+
LIQSOL_CORE,
|
|
137
149
|
)[0];
|
|
138
150
|
|
|
151
|
+
/**
|
|
152
|
+
* user_record PDA
|
|
153
|
+
*
|
|
154
|
+
* In the current liqsol_core IDL, this is keyed by USER (wallet),
|
|
155
|
+
* not by token account.
|
|
156
|
+
*/
|
|
139
157
|
export const deriveUserRecordPda = (user: PublicKey) =>
|
|
140
158
|
PublicKey.findProgramAddressSync(
|
|
141
159
|
[Buffer.from(PDA_SEEDS.USER_RECORD), user.toBuffer()],
|
|
142
|
-
|
|
160
|
+
LIQSOL_CORE,
|
|
143
161
|
)[0];
|
|
144
162
|
|
|
145
163
|
export const derivePayRateHistoryPda = () =>
|
|
146
164
|
PublicKey.findProgramAddressSync(
|
|
147
165
|
[Buffer.from(PDA_SEEDS.PAY_RATE_HISTORY)],
|
|
148
|
-
|
|
166
|
+
LIQSOL_CORE,
|
|
149
167
|
)[0];
|
|
150
168
|
|
|
151
|
-
|
|
169
|
+
/**
|
|
170
|
+
* ---------------------------------------------------------------------------
|
|
171
|
+
* WITHDRAW MODULE / RECEIPTS
|
|
172
|
+
* ---------------------------------------------------------------------------
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
export const deriveWithdrawGlobalPda = () =>
|
|
152
176
|
PublicKey.findProgramAddressSync(
|
|
153
|
-
[Buffer.from(PDA_SEEDS.
|
|
154
|
-
|
|
177
|
+
[Buffer.from(PDA_SEEDS.WITHDRAW_GLOBAL)],
|
|
178
|
+
LIQSOL_CORE,
|
|
155
179
|
)[0];
|
|
156
180
|
|
|
157
|
-
export const
|
|
181
|
+
export const deriveStakeAllocationStatePda = () =>
|
|
158
182
|
PublicKey.findProgramAddressSync(
|
|
159
|
-
[Buffer.from(PDA_SEEDS.
|
|
160
|
-
|
|
183
|
+
[Buffer.from(PDA_SEEDS.STAKE_ALLOCATION_STATE)],
|
|
184
|
+
LIQSOL_CORE,
|
|
161
185
|
)[0];
|
|
162
186
|
|
|
163
|
-
export const
|
|
187
|
+
export const deriveStakeMetricsPda = () =>
|
|
164
188
|
PublicKey.findProgramAddressSync(
|
|
165
|
-
[Buffer.from(PDA_SEEDS.
|
|
166
|
-
|
|
189
|
+
[Buffer.from(PDA_SEEDS.STAKE_METRICS)],
|
|
190
|
+
LIQSOL_CORE,
|
|
191
|
+
)[0];
|
|
192
|
+
|
|
193
|
+
export const deriveMaintenanceLedgerPda = () =>
|
|
194
|
+
PublicKey.findProgramAddressSync(
|
|
195
|
+
[Buffer.from(PDA_SEEDS.MAINTENANCE_LEDGER)],
|
|
196
|
+
LIQSOL_CORE,
|
|
197
|
+
)[0];
|
|
198
|
+
|
|
199
|
+
export const deriveWithdrawMintAuthorityPda = () =>
|
|
200
|
+
PublicKey.findProgramAddressSync(
|
|
201
|
+
[Buffer.from(PDA_SEEDS.WITHDRAW_MINT_AUTHORITY)],
|
|
202
|
+
LIQSOL_CORE,
|
|
203
|
+
)[0];
|
|
204
|
+
|
|
205
|
+
export const deriveWithdrawMintMetadataPda = () =>
|
|
206
|
+
PublicKey.findProgramAddressSync(
|
|
207
|
+
[Buffer.from(PDA_SEEDS.MINT_METADATA)],
|
|
208
|
+
LIQSOL_CORE,
|
|
167
209
|
)[0];
|
|
168
210
|
|
|
169
211
|
/**
|
|
170
|
-
*
|
|
212
|
+
* NFT mint for withdrawal receipt, derived from nextReceiptId.
|
|
171
213
|
*/
|
|
172
|
-
export const
|
|
214
|
+
export const deriveWithdrawNftMintPda = (receiptId: bigint | number) => {
|
|
215
|
+
const receiptIdBytes = Buffer.alloc(8);
|
|
216
|
+
// receiptId comes in as BN or bigint upstream → normalize
|
|
217
|
+
const asBigInt =
|
|
218
|
+
typeof receiptId === 'bigint'
|
|
219
|
+
? receiptId
|
|
220
|
+
: BigInt(receiptId.toString());
|
|
221
|
+
receiptIdBytes.writeBigUInt64LE(asBigInt);
|
|
222
|
+
return PublicKey.findProgramAddressSync(
|
|
223
|
+
[Buffer.from(PDA_SEEDS.WITHDRAW_MINT), receiptIdBytes],
|
|
224
|
+
LIQSOL_CORE,
|
|
225
|
+
)[0];
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export const deriveLiqReceiptDataPda = (nftMint: PublicKey) =>
|
|
173
229
|
PublicKey.findProgramAddressSync(
|
|
174
|
-
[Buffer.from(PDA_SEEDS.
|
|
230
|
+
[Buffer.from(PDA_SEEDS.LIQ_RECEIPT_DATA), nftMint.toBuffer()],
|
|
175
231
|
LIQSOL_CORE,
|
|
176
232
|
)[0];
|
|
177
233
|
|
|
178
|
-
|
|
234
|
+
/**
|
|
235
|
+
* ---------------------------------------------------------------------------
|
|
236
|
+
* VALIDATOR LEADERBOARD
|
|
237
|
+
* ---------------------------------------------------------------------------
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
export const deriveLeaderboardStatePda = () =>
|
|
179
241
|
PublicKey.findProgramAddressSync(
|
|
180
|
-
[Buffer.from(PDA_SEEDS.
|
|
242
|
+
[Buffer.from(PDA_SEEDS.LEADERBOARD_STATE)],
|
|
243
|
+
VALIDATOR_LEADERBOARD,
|
|
244
|
+
)[0];
|
|
245
|
+
|
|
246
|
+
export const deriveValidatorRecordPda = (voteAccount: PublicKey) =>
|
|
247
|
+
PublicKey.findProgramAddressSync(
|
|
248
|
+
[Buffer.from(PDA_SEEDS.VALIDATOR_RECORD), voteAccount.toBuffer()],
|
|
249
|
+
VALIDATOR_LEADERBOARD,
|
|
250
|
+
)[0];
|
|
251
|
+
|
|
252
|
+
export const deriveStakeControllerVaultPda = () =>
|
|
253
|
+
PublicKey.findProgramAddressSync(
|
|
254
|
+
[Buffer.from(PDA_SEEDS.VAULT)],
|
|
181
255
|
LIQSOL_CORE,
|
|
182
256
|
)[0];
|
|
183
257
|
|
|
184
|
-
|
|
258
|
+
/**
|
|
259
|
+
* ---------------------------------------------------------------------------
|
|
260
|
+
* OUTPOST / PRETOKENS
|
|
261
|
+
* ---------------------------------------------------------------------------
|
|
262
|
+
*/
|
|
263
|
+
|
|
264
|
+
export const deriveOutpostGlobalStatePda = () =>
|
|
185
265
|
PublicKey.findProgramAddressSync(
|
|
186
|
-
[Buffer.from(PDA_SEEDS.
|
|
266
|
+
[Buffer.from(PDA_SEEDS.OUTPOST_GLOBAL_STATE)],
|
|
187
267
|
LIQSOL_CORE,
|
|
188
268
|
)[0];
|
|
189
269
|
|
|
190
|
-
export const
|
|
270
|
+
export const deriveOutpostPoolAuthorityPda = () =>
|
|
191
271
|
PublicKey.findProgramAddressSync(
|
|
192
|
-
[Buffer.from(PDA_SEEDS.
|
|
272
|
+
[Buffer.from(PDA_SEEDS.LIQSOL_POOL)],
|
|
193
273
|
LIQSOL_CORE,
|
|
194
274
|
)[0];
|
|
195
275
|
|
|
196
|
-
export const
|
|
276
|
+
export const deriveOutpostAccountPda = (user: PublicKey) =>
|
|
197
277
|
PublicKey.findProgramAddressSync(
|
|
198
|
-
[Buffer.from(PDA_SEEDS.
|
|
278
|
+
[Buffer.from(PDA_SEEDS.OUTPOST_ACCOUNT), user.toBuffer()],
|
|
199
279
|
LIQSOL_CORE,
|
|
200
280
|
)[0];
|
|
201
281
|
|
|
202
|
-
export const
|
|
282
|
+
export const deriveUserPretokenRecordPda = (user: PublicKey) =>
|
|
203
283
|
PublicKey.findProgramAddressSync(
|
|
204
|
-
[Buffer.from(PDA_SEEDS.
|
|
284
|
+
[Buffer.from(PDA_SEEDS.USER_PRETOKEN_RECORD), user.toBuffer()],
|
|
205
285
|
LIQSOL_CORE,
|
|
206
286
|
)[0];
|
|
207
287
|
|
|
@@ -211,12 +291,16 @@ export const deriveTrancheStatePda = () =>
|
|
|
211
291
|
LIQSOL_CORE,
|
|
212
292
|
)[0];
|
|
213
293
|
|
|
214
|
-
export const
|
|
294
|
+
export const derivePriceHistoryPda = () =>
|
|
215
295
|
PublicKey.findProgramAddressSync(
|
|
216
|
-
[Buffer.from(PDA_SEEDS.
|
|
296
|
+
[Buffer.from(PDA_SEEDS.PRICE_HISTORY)],
|
|
217
297
|
LIQSOL_CORE,
|
|
218
298
|
)[0];
|
|
219
299
|
|
|
300
|
+
/**
|
|
301
|
+
* BAR (bonded actor roles)
|
|
302
|
+
*/
|
|
303
|
+
|
|
220
304
|
export const deriveBarConfigPda = () =>
|
|
221
305
|
PublicKey.findProgramAddressSync(
|
|
222
306
|
[Buffer.from(PDA_SEEDS.BAR_STATE_SEED)],
|
|
@@ -235,10 +319,13 @@ export const deriveBondedActorPda = (actor: PublicKey) =>
|
|
|
235
319
|
LIQSOL_CORE,
|
|
236
320
|
)[0];
|
|
237
321
|
|
|
238
|
-
|
|
322
|
+
/**
|
|
323
|
+
* SPL Transfer-hook: extra-account-metas PDA for the liqSOL mint.
|
|
324
|
+
*/
|
|
325
|
+
export const deriveExtraAccountMetaListPda = (liqsolMint: PublicKey) =>
|
|
239
326
|
PublicKey.findProgramAddressSync(
|
|
240
|
-
[Buffer.from(PDA_SEEDS.
|
|
241
|
-
|
|
327
|
+
[Buffer.from(PDA_SEEDS.EXTRA_ACCOUNT_METAS), liqsolMint.toBuffer()],
|
|
328
|
+
PROGRAM_IDS.TRANSFER_HOOK,
|
|
242
329
|
)[0];
|
|
243
330
|
|
|
244
331
|
/**
|
|
@@ -247,18 +334,21 @@ export const derivePriceHistoryPda = () =>
|
|
|
247
334
|
*/
|
|
248
335
|
export const deriveEphemeralStakeAddress = async (
|
|
249
336
|
user: PublicKey,
|
|
250
|
-
seed:
|
|
337
|
+
seed: number,
|
|
251
338
|
): Promise<PublicKey> => {
|
|
252
339
|
const seedStr = `ephemeral_${seed}`;
|
|
253
|
-
return
|
|
340
|
+
return PublicKey.createWithSeed(user, seedStr, StakeProgram.programId);
|
|
254
341
|
};
|
|
255
342
|
|
|
256
343
|
/**
|
|
257
|
-
* Constant keys
|
|
344
|
+
* Constant keys (Chainlink)
|
|
258
345
|
*/
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
346
|
+
export const CHAINLINK_FEED = new PublicKey(
|
|
347
|
+
'99B2bTijsU6f1GCT73HmdR7HCFFjGMBcPZY6jZ96ynrR',
|
|
348
|
+
);
|
|
349
|
+
export const CHAINLINK_PROGRAM = new PublicKey(
|
|
350
|
+
'HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny',
|
|
351
|
+
);
|
|
262
352
|
|
|
263
353
|
/**
|
|
264
354
|
* ---------------------------------------------------------------------------
|
|
@@ -276,14 +366,15 @@ export const DEFAULT_AVERAGE_PAY_RATE = BigInt(191_780_821);
|
|
|
276
366
|
export const DEFAULT_PAY_RATE_LOOKBACK = 5;
|
|
277
367
|
|
|
278
368
|
// Rent exemption for ephemeral stake account (lamports)
|
|
279
|
-
// Mirrors EPHEMERAL_RENT_EXEMPTION = 2_282_880 used in tests
|
|
280
369
|
export const EPHEMERAL_RENT_EXEMPTION = 2_282_880;
|
|
281
370
|
|
|
282
371
|
// For convenience: lamports <-> SOL helpers (no RPC dependency)
|
|
283
372
|
export const LAMPORTS_PER_SOL = 1_000_000_000;
|
|
284
373
|
|
|
374
|
+
export const INDEX_SCALE = BigInt(1_000_000_000_000); // 1e12
|
|
375
|
+
|
|
285
376
|
export const lamportsToSol = (lamports: number | bigint): number =>
|
|
286
377
|
Number(lamports) / LAMPORTS_PER_SOL;
|
|
287
378
|
|
|
288
379
|
export const solToLamports = (sol: number): bigint =>
|
|
289
|
-
BigInt(Math.round(sol * LAMPORTS_PER_SOL));
|
|
380
|
+
BigInt(Math.round(sol * LAMPORTS_PER_SOL));
|