@wireio/stake 0.3.0 → 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.
@@ -5,7 +5,7 @@
5
5
  * IDL can be found at `target/idl/liqsol_token.json`.
6
6
  */
7
7
  export type LiqsolToken = {
8
- "address": "6cDoerqdV6UQDsGvUEq5Qj5HRxxyDxSuUaB2J6iK8cio",
8
+ "address": "6hiJ8PrSyYLr7H9MA9VYh9fvGoHxZ2TXdDAMzjeUVSXZ",
9
9
  "metadata": {
10
10
  "name": "liqsolToken",
11
11
  "version": "0.1.0",
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Program IDL in camelCase format in order to be used in JS/TS.
3
+ *
4
+ * Note that this is only a type helper and is not the actual IDL. The original
5
+ * IDL can be found at `target/idl/transfer_hook.json`.
6
+ */
7
+ export type TransferHook = {
8
+ "address": "EtqCLddkPNGjkgiH9rVUmK3M5X2FKFprQvgscBJ8g6hX",
9
+ "metadata": {
10
+ "name": "transferHook",
11
+ "version": "0.1.0",
12
+ "spec": "0.1.0",
13
+ "description": "Created with Anchor"
14
+ },
15
+ "instructions": [
16
+ {
17
+ "name": "initializeExtraAccountMetaList",
18
+ "discriminator": [
19
+ 43,
20
+ 34,
21
+ 13,
22
+ 49,
23
+ 167,
24
+ 88,
25
+ 235,
26
+ 235
27
+ ],
28
+ "accounts": [
29
+ {
30
+ "name": "payer",
31
+ "writable": true,
32
+ "signer": true
33
+ },
34
+ {
35
+ "name": "extraAccountMetaList",
36
+ "writable": true
37
+ },
38
+ {
39
+ "name": "mint"
40
+ },
41
+ {
42
+ "name": "systemProgram"
43
+ },
44
+ {
45
+ "name": "liqsolCore"
46
+ }
47
+ ],
48
+ "args": []
49
+ },
50
+ {
51
+ "name": "transferHook",
52
+ "discriminator": [
53
+ 105,
54
+ 37,
55
+ 101,
56
+ 197,
57
+ 75,
58
+ 251,
59
+ 102,
60
+ 26
61
+ ],
62
+ "accounts": [
63
+ {
64
+ "name": "sourceToken"
65
+ },
66
+ {
67
+ "name": "mint"
68
+ },
69
+ {
70
+ "name": "destinationToken"
71
+ },
72
+ {
73
+ "name": "authority"
74
+ },
75
+ {
76
+ "name": "extraAccountMetaList"
77
+ },
78
+ {
79
+ "name": "liqsolCore"
80
+ },
81
+ {
82
+ "name": "senderUserRecord",
83
+ "writable": true
84
+ },
85
+ {
86
+ "name": "receiverUserRecord",
87
+ "writable": true
88
+ },
89
+ {
90
+ "name": "distributionState",
91
+ "writable": true
92
+ },
93
+ {
94
+ "name": "bucketTokenAccount"
95
+ }
96
+ ],
97
+ "args": [
98
+ {
99
+ "name": "amount",
100
+ "type": "u64"
101
+ }
102
+ ]
103
+ }
104
+ ],
105
+ "accounts": [
106
+ {
107
+ "name": "distributionState",
108
+ "discriminator": [
109
+ 7,
110
+ 25,
111
+ 94,
112
+ 15,
113
+ 208,
114
+ 170,
115
+ 4,
116
+ 103
117
+ ]
118
+ }
119
+ ],
120
+ "errors": [
121
+ {
122
+ "code": 6000,
123
+ "name": "amountTooBig"
124
+ },
125
+ {
126
+ "code": 6001,
127
+ "name": "isNotCurrentlyTransferring"
128
+ },
129
+ {
130
+ "code": 6002,
131
+ "name": "tlvAccountResolutionError"
132
+ }
133
+ ],
134
+ "types": [
135
+ {
136
+ "name": "distributionState",
137
+ "type": {
138
+ "kind": "struct",
139
+ "fields": [
140
+ {
141
+ "name": "liqsolMint",
142
+ "type": "pubkey"
143
+ },
144
+ {
145
+ "name": "currentIndex",
146
+ "type": "u64"
147
+ },
148
+ {
149
+ "name": "totalShares",
150
+ "docs": [
151
+ "Sum of all user shares across the system"
152
+ ],
153
+ "type": "u64"
154
+ },
155
+ {
156
+ "name": "lastBucketBalance",
157
+ "docs": [
158
+ "Last observed bucket balance used for incremental index updates"
159
+ ],
160
+ "type": "u64"
161
+ },
162
+ {
163
+ "name": "bump",
164
+ "type": "u8"
165
+ },
166
+ {
167
+ "name": "bucketBump",
168
+ "docs": [
169
+ "Cached bucket authority bump to avoid repeated find_program_address calls"
170
+ ],
171
+ "type": "u8"
172
+ },
173
+ {
174
+ "name": "poolBump",
175
+ "docs": [
176
+ "Cached pool authority bump to avoid repeated find_program_address calls"
177
+ ],
178
+ "type": "u8"
179
+ },
180
+ {
181
+ "name": "bucketAuthority",
182
+ "docs": [
183
+ "Cached bucket authority pubkey for transfer-hook optimization"
184
+ ],
185
+ "type": "pubkey"
186
+ },
187
+ {
188
+ "name": "poolAuthority",
189
+ "docs": [
190
+ "Cached pool authority pubkey for transfer-hook optimization"
191
+ ],
192
+ "type": "pubkey"
193
+ }
194
+ ]
195
+ }
196
+ }
197
+ ]
198
+ };
@@ -5,7 +5,7 @@
5
5
  * IDL can be found at `target/idl/validator_leaderboard.json`.
6
6
  */
7
7
  export type ValidatorLeaderboard = {
8
- "address": "C4ddPrB1ALYpW4G1Qz4ffvETBA8YGUL7TVZaLiE6bb1q",
8
+ "address": "H6CWj2PgxCE9Z5dPi9nMrR2VxT1C4DQcqR1QjmLeon47",
9
9
  "metadata": {
10
10
  "name": "validatorLeaderboard",
11
11
  "version": "0.1.0",
@@ -69,6 +69,149 @@ export type ValidatorLeaderboard = {
69
69
  ],
70
70
  "args": []
71
71
  },
72
+ {
73
+ "name": "testClearLeaderboard",
74
+ "discriminator": [
75
+ 118,
76
+ 207,
77
+ 26,
78
+ 205,
79
+ 180,
80
+ 7,
81
+ 75,
82
+ 244
83
+ ],
84
+ "accounts": [
85
+ {
86
+ "name": "leaderboardState",
87
+ "writable": true
88
+ },
89
+ {
90
+ "name": "authority",
91
+ "signer": true
92
+ }
93
+ ],
94
+ "args": []
95
+ },
96
+ {
97
+ "name": "testForceRegisterValidator",
98
+ "discriminator": [
99
+ 136,
100
+ 156,
101
+ 132,
102
+ 32,
103
+ 96,
104
+ 240,
105
+ 7,
106
+ 115
107
+ ],
108
+ "accounts": [
109
+ {
110
+ "name": "registrant",
111
+ "writable": true,
112
+ "signer": true
113
+ },
114
+ {
115
+ "name": "voteAccount"
116
+ },
117
+ {
118
+ "name": "validatorRecord",
119
+ "writable": true
120
+ },
121
+ {
122
+ "name": "leaderboardState",
123
+ "writable": true
124
+ },
125
+ {
126
+ "name": "systemProgram"
127
+ }
128
+ ],
129
+ "args": [
130
+ {
131
+ "name": "vpp",
132
+ "type": "u8"
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ "name": "testForceUpdateVpp",
138
+ "discriminator": [
139
+ 67,
140
+ 51,
141
+ 28,
142
+ 174,
143
+ 200,
144
+ 214,
145
+ 203,
146
+ 162
147
+ ],
148
+ "accounts": [
149
+ {
150
+ "name": "registrant",
151
+ "writable": true,
152
+ "signer": true
153
+ },
154
+ {
155
+ "name": "voteAccount"
156
+ },
157
+ {
158
+ "name": "validatorRecord",
159
+ "writable": true
160
+ },
161
+ {
162
+ "name": "leaderboardState",
163
+ "writable": true
164
+ }
165
+ ],
166
+ "args": [
167
+ {
168
+ "name": "vpp",
169
+ "type": "u8"
170
+ }
171
+ ]
172
+ },
173
+ {
174
+ "name": "testSeedRandomValidators",
175
+ "discriminator": [
176
+ 48,
177
+ 155,
178
+ 181,
179
+ 112,
180
+ 163,
181
+ 242,
182
+ 43,
183
+ 146
184
+ ],
185
+ "accounts": [
186
+ {
187
+ "name": "registrant",
188
+ "writable": true,
189
+ "signer": true
190
+ },
191
+ {
192
+ "name": "leaderboardState",
193
+ "writable": true
194
+ }
195
+ ],
196
+ "args": [
197
+ {
198
+ "name": "count",
199
+ "type": "u16"
200
+ },
201
+ {
202
+ "name": "seed",
203
+ "type": "u64"
204
+ },
205
+ {
206
+ "name": "minVpp",
207
+ "type": "u8"
208
+ },
209
+ {
210
+ "name": "maxVpp",
211
+ "type": "u8"
212
+ }
213
+ ]
214
+ },
72
215
  {
73
216
  "name": "updateCommission",
74
217
  "discriminator": [
@@ -163,7 +306,7 @@ export type ValidatorLeaderboard = {
163
306
  "args": [
164
307
  {
165
308
  "name": "vpp",
166
- "type": "u64"
309
+ "type": "u8"
167
310
  },
168
311
  {
169
312
  "name": "proposedRank",
@@ -360,12 +503,12 @@ export type ValidatorLeaderboard = {
360
503
  {
361
504
  "name": "scores",
362
505
  "docs": [
363
- "VPP scores indexed by registry_index",
506
+ "VPP scores indexed by registry_index (0-100 range)",
364
507
  "registry_index is assigned on first validator registration and never changes"
365
508
  ],
366
509
  "type": {
367
510
  "array": [
368
- "u64",
511
+ "u8",
369
512
  1024
370
513
  ]
371
514
  }
@@ -242,11 +242,6 @@ export class EthereumStakingClient implements IStakingClient {
242
242
  decimals: nativeDecimals,
243
243
  symbol: liqSymbol,
244
244
  },
245
- tracked: {
246
- amount: liqBalance.toBigInt(),
247
- decimals: nativeDecimals,
248
- symbol: liqSymbol,
249
- },
250
245
  staked: {
251
246
  amount: stakedLiqBalance.toBigInt(),
252
247
  decimals: nativeDecimals,
@@ -1,6 +1,5 @@
1
1
  import { AnchorProvider, BN, Program } from '@coral-xyz/anchor';
2
2
  import {
3
- PublicKey,
4
3
  SystemProgram,
5
4
  Transaction,
6
5
  TransactionInstruction,
@@ -27,26 +26,54 @@ import {
27
26
  deriveReservePoolPda,
28
27
  deriveVaultPda,
29
28
  deriveStakeControllerStatePda,
29
+ derivePayoutStatePda,
30
30
  deriveBucketAuthorityPda,
31
31
  derivePayRateHistoryPda,
32
32
  deriveDistributionStatePda,
33
33
  deriveUserRecordPda,
34
- derivePayoutStatePda,
35
34
  deriveEphemeralStakeAddress,
35
+ deriveWithdrawGlobalPda,
36
+ deriveStakeAllocationStatePda,
37
+ deriveStakeMetricsPda,
38
+ deriveMaintenanceLedgerPda,
39
+ deriveWithdrawMintAuthorityPda,
40
+ deriveWithdrawMintMetadataPda,
41
+ deriveWithdrawNftMintPda,
42
+ deriveLiqReceiptDataPda,
36
43
  } from '../constants';
37
44
  import { WalletLike } from '../types';
38
45
 
39
46
  export class DepositClient {
40
47
  private program: Program<LiqsolCore>;
41
48
 
42
- get wallet(): WalletLike { return this.provider.wallet; }
49
+ get wallet(): WalletLike {
50
+ return this.provider.wallet;
51
+ }
43
52
 
44
53
  constructor(private provider: AnchorProvider) {
45
54
  const svc = new SolanaProgramService(provider);
46
55
  this.program = svc.getProgram('liqsolCore');
47
56
  }
48
57
 
49
- async buildDepositTx(amount: bigint, user = this.wallet.publicKey): Promise<Transaction> {
58
+ /**
59
+ * Build a deposit transaction:
60
+ * SOL -> liqSOL via liqsol_core::deposit.
61
+ */
62
+ async buildDepositTx(
63
+ amount: bigint,
64
+ user = this.wallet.publicKey,
65
+ ): Promise<Transaction> {
66
+ if (!user) {
67
+ throw new Error(
68
+ 'DepositClient.buildDepositTx: wallet not connected',
69
+ );
70
+ }
71
+ if (!amount || amount <= BigInt(0)) {
72
+ throw new Error(
73
+ 'DepositClient.buildDepositTx: amount must be greater than zero.',
74
+ );
75
+ }
76
+
50
77
  // -------------------------------------------------------------
51
78
  // PDAs
52
79
  // -------------------------------------------------------------
@@ -59,8 +86,6 @@ export class DepositClient {
59
86
  const payoutState = derivePayoutStatePda();
60
87
  const bucketAuthority = deriveBucketAuthorityPda();
61
88
  const payRateHistory = derivePayRateHistoryPda();
62
- const distributionState = deriveDistributionStatePda();
63
- const userRecord = deriveUserRecordPda(user);
64
89
 
65
90
  // -------------------------------------------------------------
66
91
  // Token-2022 ATAs
@@ -69,14 +94,20 @@ export class DepositClient {
69
94
  liqsolMint,
70
95
  user,
71
96
  false,
72
- TOKEN_2022_PROGRAM_ID
97
+ TOKEN_2022_PROGRAM_ID,
73
98
  );
74
99
 
100
+ // -------------------------------------------------------------
101
+ // Distribution state + user_record (KEYED BY TOKEN ACCOUNT)
102
+ // -------------------------------------------------------------
103
+ const distributionState = deriveDistributionStatePda();
104
+ const userRecord = deriveUserRecordPda(userAta);
105
+
75
106
  const bucketTokenAccount = getAssociatedTokenAddressSync(
76
107
  liqsolMint,
77
108
  bucketAuthority,
78
109
  true,
79
- TOKEN_2022_PROGRAM_ID
110
+ TOKEN_2022_PROGRAM_ID,
80
111
  );
81
112
 
82
113
  // -------------------------------------------------------------
@@ -124,4 +155,119 @@ export class DepositClient {
124
155
 
125
156
  return new Transaction().add(ix);
126
157
  }
158
+
159
+ /**
160
+ * Build a withdraw-request transaction:
161
+ * liqSOL -> SOL via liqsol_core::requestWithdraw.
162
+ *
163
+ * This:
164
+ * - burns liqSOL from the user
165
+ * - increments totalEncumberedFunds in global state
166
+ * - mints an NFT receipt (liqReceiptData + NFT ATA for owner)
167
+ */
168
+ async buildWithdrawTx(
169
+ amount: bigint,
170
+ user = this.wallet.publicKey,
171
+ ): Promise<Transaction> {
172
+ if (!user) {
173
+ throw new Error(
174
+ 'DepositClient.buildWithdrawTx: wallet not connected',
175
+ );
176
+ }
177
+ if (!amount || amount <= BigInt(0)) {
178
+ throw new Error(
179
+ 'DepositClient.buildWithdrawTx: amount must be greater than zero.',
180
+ );
181
+ }
182
+
183
+ // -------------------------------------------------------------
184
+ // Core program + liqSOL mint / user ATA
185
+ // -------------------------------------------------------------
186
+ const liqsolMint = deriveLiqsolMintPda();
187
+
188
+ const userAta = getAssociatedTokenAddressSync(
189
+ liqsolMint,
190
+ user,
191
+ false,
192
+ TOKEN_2022_PROGRAM_ID,
193
+ );
194
+
195
+ // Distribution / balance-tracking
196
+ // user_record is keyed by the user’s liqSOL ATA (same convention as deposit/purchase)
197
+ const userRecord = deriveUserRecordPda(userAta);
198
+ const distributionState = deriveDistributionStatePda();
199
+
200
+ // Reserve + stake controller PDAs
201
+ const global = deriveWithdrawGlobalPda();
202
+ const reservePool = deriveReservePoolPda();
203
+ const stakeAllocationState = deriveStakeAllocationStatePda();
204
+ const stakeMetrics = deriveStakeMetricsPda();
205
+ const maintenanceLedger = deriveMaintenanceLedgerPda();
206
+
207
+ // -------------------------------------------------------------
208
+ // Need nextReceiptId from withdraw global state
209
+ // -------------------------------------------------------------
210
+ const globalState = await this.program.account.global.fetch(global);
211
+ const receiptId = (globalState.nextReceiptId as BN).toBigInt();
212
+
213
+ // -------------------------------------------------------------
214
+ // NFT receipt PDAs (mint, metadata, data, ATA)
215
+ // -------------------------------------------------------------
216
+ const mintAuthority = deriveWithdrawMintAuthorityPda();
217
+ const metadata = deriveWithdrawMintMetadataPda();
218
+
219
+ const nftMint = deriveWithdrawNftMintPda(receiptId);
220
+ const receiptData = deriveLiqReceiptDataPda(nftMint);
221
+
222
+ const owner = user;
223
+ const nftAta = getAssociatedTokenAddressSync(
224
+ nftMint,
225
+ owner,
226
+ false,
227
+ TOKEN_2022_PROGRAM_ID,
228
+ );
229
+
230
+ // Bucket token account (same bucket used by deposit/distribution)
231
+ const bucketAuthority = deriveBucketAuthorityPda();
232
+ const bucketTokenAccount = getAssociatedTokenAddressSync(
233
+ liqsolMint,
234
+ bucketAuthority,
235
+ true,
236
+ TOKEN_2022_PROGRAM_ID,
237
+ );
238
+
239
+ // -------------------------------------------------------------
240
+ // BUILD IX (MUST MATCH requestWithdraw IDL)
241
+ // -------------------------------------------------------------
242
+ const ix: TransactionInstruction = await this.program.methods
243
+ .requestWithdraw(new BN(amount.toString()))
244
+ .accounts({
245
+ user,
246
+ owner,
247
+ global,
248
+ liqsolMint,
249
+ userAta,
250
+ userRecord,
251
+ reservePool,
252
+ stakeAllocationState,
253
+ stakeMetrics,
254
+ maintenanceLedger,
255
+ clock: SYSVAR_CLOCK_PUBKEY,
256
+ mintAuthority,
257
+ receiptData,
258
+ metadata,
259
+ nftMint,
260
+ nftAta,
261
+ distributionState,
262
+ bucketTokenAccount,
263
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
264
+ tokenInterface: TOKEN_2022_PROGRAM_ID,
265
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
266
+ systemProgram: SystemProgram.programId,
267
+ rent: SYSVAR_RENT_PUBKEY,
268
+ })
269
+ .instruction();
270
+
271
+ return new Transaction().add(ix);
272
+ }
127
273
  }