@wireio/stake 2.1.1 → 2.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wireio/stake",
3
- "version": "2.1.1",
3
+ "version": "2.2.2",
4
4
  "description": "LIQ Staking Module for Wire Network",
5
5
  "homepage": "https://gitea.gitgo.app/Wire/sdk-stake",
6
6
  "license": "FSL-1.1-Apache-2.0",
@@ -0,0 +1,61 @@
1
+ import { BigNumber, ethers } from "ethers";
2
+ import { ClaimedEvent, DepositEvent, DepositResult, SharesBurnedEvent, ValidatorDepositedEvent } from "../types";
3
+ import { EthereumContractService } from "../contract";
4
+ import { formatContractErrors } from "../utils";
5
+
6
+ export class ValidatorClient {
7
+
8
+ private readonly contractService: EthereumContractService;
9
+
10
+ get contract() { return this.contractService.contract; }
11
+
12
+ constructor(contract: EthereumContractService) {
13
+ this.contractService = contract;
14
+ }
15
+
16
+
17
+ /**
18
+ *
19
+ * @param amountWei an amount of liqETH (in WEI) to stake to the Outpost
20
+ * @returns txHash (hash of the transaction), receipt, Staked event
21
+ */
22
+ async validatorDepositAndLockBond(): Promise<any> {
23
+ const amountWei: BigNumber = ethers.utils.parseEther("32");
24
+
25
+ // simulate call first
26
+ try {
27
+ await this.contract.DepositManager.callStatic.validatorDepositAndLockBond({ value: amountWei });
28
+ } catch (err: any) {
29
+ let errorObj = formatContractErrors(err);
30
+ throw new Error(errorObj.name ?? errorObj.raw)
31
+ }
32
+
33
+
34
+ // send the tx to stake liqeth
35
+ const tx = await this.contract.DepositManager.validatorDepositAndLockBond({ value: amountWei });
36
+
37
+ // Wait for 1 confirmation
38
+ const receipt = await tx.wait(1);
39
+
40
+ // Parse ValidatorDeposited event if present
41
+ let staked: ValidatorDepositedEvent | undefined;
42
+ const ev = receipt.events?.find((e) => e.event === 'Staked');
43
+
44
+ if (ev && ev.args) {
45
+ const { sender, amount, shares } = ev.args;
46
+ staked = {
47
+ sender,
48
+ amount: BigNumber.from(amount),
49
+ shares: BigNumber.from(shares),
50
+ };
51
+ }
52
+
53
+ return {
54
+ txHash: tx.hash,
55
+ receipt,
56
+ staked,
57
+ };
58
+ }
59
+
60
+
61
+ }
@@ -15,6 +15,7 @@ import { StakeClient } from './clients/stake.client';
15
15
  import { PretokenClient } from './clients/pretoken.client';
16
16
  import { OPPClient } from './clients/opp.client';
17
17
  import { ReceiptClient } from './clients/receipt.client';
18
+ import { ValidatorClient } from './clients/validator.client';
18
19
 
19
20
  export const INITIAL_TRANCHE_SUPPLY = 35000;
20
21
 
@@ -29,6 +30,7 @@ export class EthereumStakingClient implements IStakingClient {
29
30
  private stakeClient: StakeClient;
30
31
  private oppClient: OPPClient;
31
32
  private receiptClient: ReceiptClient;
33
+ private validatorClient: ValidatorClient;
32
34
 
33
35
 
34
36
  get contract() { return this.contractService.contract; }
@@ -56,6 +58,7 @@ export class EthereumStakingClient implements IStakingClient {
56
58
  this.stakeClient = new StakeClient(this.contractService);
57
59
  this.oppClient = new OPPClient(this.contractService);
58
60
  this.receiptClient = new ReceiptClient(this.contractService);
61
+ this.validatorClient = new ValidatorClient(this.contractService)
59
62
  }
60
63
  catch (error) {
61
64
  // console.error('Error initializing EthereumStakingClient:', error);
@@ -178,6 +181,21 @@ export class EthereumStakingClient implements IStakingClient {
178
181
  }
179
182
 
180
183
 
184
+ /**
185
+ * Validator functions
186
+ */
187
+ async validatorDeposit(): Promise<string> {
188
+ this.ensureUser();
189
+
190
+ let result = await this.validatorClient.validatorDepositAndLockBond();
191
+ return result && result.txHash ? result.txHash : "Error - no resulting txHash";
192
+ }
193
+
194
+
195
+
196
+
197
+
198
+
181
199
  /**
182
200
  * Resolve the user's ETH + liqETH balances.
183
201
  *
@@ -310,6 +328,8 @@ export class EthereumStakingClient implements IStakingClient {
310
328
  return await this.oppClient.getMessages(address);
311
329
  }
312
330
 
331
+
332
+
313
333
  // Ensure that signer wallet is available for write operations
314
334
  private ensureUser() {
315
335
  if (!this.signer) {
@@ -117,7 +117,6 @@ export interface ClaimedEvent {
117
117
  amount: BigNumber;
118
118
  }
119
119
 
120
-
121
120
  export interface WithdrawReceipt {
122
121
  tokenId: bigint;
123
122
  receipt: {
@@ -125,4 +124,12 @@ export interface WithdrawReceipt {
125
124
  ethBalance: BalanceView;
126
125
  readyAt: number;
127
126
  }
128
- }
127
+ }
128
+
129
+
130
+
131
+ export interface ValidatorDepositedEvent {
132
+ sender: string;
133
+ amount: BigNumber;
134
+ shares: BigNumber
135
+ }
@@ -141,126 +141,6 @@ export class DepositClient {
141
141
  .instruction();
142
142
  }
143
143
 
144
- // async buildSquadsDepositProposalTx(params: {
145
- // connection: Connection;
146
- // multisigPda: PublicKey;
147
- // amountLamports: bigint;
148
- // wallet: WalletLikeSigner; // your WalletLikeSigner type
149
- // vaultIndex?: number;
150
- // }): Promise<{
151
- // tx: Transaction;
152
- // transactionIndex: bigint;
153
- // vaultPda: PublicKey;
154
- // }> {
155
- // const { connection, multisigPda, amountLamports, wallet } = params;
156
- // const vaultIndex = params.vaultIndex ?? 0;
157
-
158
- // if (!wallet?.publicKey) throw new Error("wallet.publicKey missing");
159
- // if (!amountLamports || amountLamports <= BigInt(0)) throw new Error("amountLamports must be > 0");
160
-
161
- // // 1) vault PDA
162
- // const [vaultPda] = multisig.getVaultPda({ multisigPda, index: vaultIndex });
163
-
164
- // // 2) build deposit ix where `user` = vaultPda (off-curve OK)
165
- // const depositBuilt = await this.buildDepositIxForUser(amountLamports, vaultPda);
166
-
167
- // // 3) compute next transactionIndex (best-effort; see note below)
168
- // const ms = await multisig.accounts.Multisig.fromAccountAddress(connection, multisigPda);
169
- // const current = BigInt((ms as any).transactionIndex?.toString?.() ?? 0);
170
- // const transactionIndex = current + BigInt(1);
171
-
172
- // // 4) inner message uses vault as payer
173
- // const { blockhash } = await connection.getLatestBlockhash("confirmed");
174
- // const message = new TransactionMessage({
175
- // payerKey: vaultPda,
176
- // recentBlockhash: blockhash,
177
- // instructions: [depositBuilt.ix],
178
- // });
179
-
180
- // // 5) squads instructions (no rpc.*)
181
- // const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
182
- // multisigPda,
183
- // transactionIndex,
184
- // creator: wallet.publicKey,
185
- // vaultIndex,
186
- // ephemeralSigners: 0,
187
- // transactionMessage: message,
188
- // });
189
-
190
- // // const createProposalIx = await multisig.instructions.proposalCreate({
191
- // // multisigPda,
192
- // // transactionIndex,
193
- // // creator: wallet.publicKey,
194
- // // });
195
- // // console.log('createVaultTxIx', createVaultTxIx);
196
-
197
-
198
- // // 6) return a normal Transaction for your pipeline
199
- // const tx = new Transaction().add(createVaultTxIx);
200
-
201
- // return { tx, transactionIndex, vaultPda };
202
- // }
203
-
204
- // async buildSquadsDepositProposalTx2(params: {
205
- // connection: Connection;
206
- // multisigPda: PublicKey;
207
- // amountLamports: bigint;
208
- // wallet: WalletLikeSigner; // your WalletLikeSigner type
209
- // vaultIndex?: number;
210
- // }): Promise<{
211
- // tx: Transaction;
212
- // transactionIndex: bigint;
213
- // vaultPda: PublicKey;
214
- // }> {
215
- // const { connection, multisigPda, amountLamports, wallet } = params;
216
- // const vaultIndex = params.vaultIndex ?? 0;
217
-
218
- // if (!wallet?.publicKey) throw new Error("wallet.publicKey missing");
219
- // if (!amountLamports || amountLamports <= BigInt(0)) throw new Error("amountLamports must be > 0");
220
-
221
- // // 1) vault PDA
222
- // const [vaultPda] = multisig.getVaultPda({ multisigPda, index: vaultIndex });
223
-
224
- // // 2) build deposit ix where `user` = vaultPda (off-curve OK)
225
- // const depositBuilt = await this.buildDepositIxForUser(amountLamports, vaultPda);
226
-
227
- // // 3) compute next transactionIndex (best-effort; see note below)
228
- // const ms = await multisig.accounts.Multisig.fromAccountAddress(connection, multisigPda);
229
- // const current = BigInt(ms.transactionIndex?.toString?.() ?? 0);
230
- // const transactionIndex = current + BigInt(1);
231
-
232
- // // 4) inner message uses vault as payer
233
- // const { blockhash } = await connection.getLatestBlockhash("confirmed");
234
- // const message = new TransactionMessage({
235
- // payerKey: vaultPda,
236
- // recentBlockhash: blockhash,
237
- // instructions: [depositBuilt.ix],
238
- // });
239
-
240
- // // 5) squads instructions (no rpc.*)
241
- // // const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
242
- // // multisigPda,
243
- // // transactionIndex,
244
- // // creator: wallet.publicKey,
245
- // // vaultIndex,
246
- // // ephemeralSigners: 0,
247
- // // transactionMessage: message,
248
- // // });
249
-
250
- // const createProposalIx = await multisig.instructions.proposalCreate({
251
- // multisigPda,
252
- // transactionIndex,
253
- // creator: wallet.publicKey,
254
- // });
255
-
256
- // // 6) return a normal Transaction for your pipeline
257
- // const tx = new Transaction().add(createProposalIx);
258
-
259
- // return { tx, transactionIndex, vaultPda };
260
- // }
261
-
262
-
263
-
264
144
  /**
265
145
  * Build a withdraw-request transaction:
266
146
  * liqSOL -> SOL via liqsol_core::requestWithdraw.
@@ -273,7 +153,7 @@ export class DepositClient {
273
153
  async buildWithdrawTx(
274
154
  amount: bigint,
275
155
  user = this.wallet.publicKey,
276
- ): Promise<Transaction> {
156
+ ): Promise<TransactionInstruction> {
277
157
  if (!user) {
278
158
  throw new Error(
279
159
  'DepositClient.buildWithdrawTx: wallet not connected',
@@ -363,7 +243,7 @@ export class DepositClient {
363
243
  // -------------------------------------------------------------
364
244
  // BUILD IX (MUST MATCH requestWithdraw IDL)
365
245
  // -------------------------------------------------------------
366
- const ix: TransactionInstruction = await this.program.methods
246
+ return await this.program.methods
367
247
  .requestWithdraw(new BN(amount.toString()))
368
248
  .accounts({
369
249
  user,
@@ -393,114 +273,7 @@ export class DepositClient {
393
273
  })
394
274
  .instruction();
395
275
 
396
- return new Transaction().add(ix);
397
- }
398
-
399
-
400
-
401
-
402
-
403
- /**
404
- * Internal helper: build the liqsol_core::deposit instruction for a specific `user`.
405
- * This is the exact same account wiring as buildDepositTx(), but returns the IX
406
- * plus useful this.pgs.derived addresses/seed for Squads flows.
407
- */
408
- private async buildDepositIxForUser(
409
- amount: bigint,
410
- user: PublicKey,
411
- ): Promise<{
412
- ix: TransactionInstruction;
413
- seed: number;
414
- userAta: PublicKey;
415
- ephemeralStake: PublicKey;
416
- }> {
417
- if (!user) {
418
- throw new Error("buildDepositIxForUser: user is required");
419
- }
420
- if (!amount || amount <= BigInt(0)) {
421
- throw new Error("buildDepositIxForUser: amount must be > 0");
422
- }
423
-
424
- // -------------------------------------------------------------
425
- // PDAs
426
- // -------------------------------------------------------------
427
- const depositAuthority = this.pgs.deriveDepositAuthorityPda();
428
- const liqsolMint = this.pgs.deriveLiqsolMintPda();
429
- const liqsolMintAuthority = this.pgs.deriveLiqsolMintAuthorityPda();
430
- const reservePool = this.pgs.deriveReservePoolPda();
431
- const vault = this.pgs.deriveVaultPda();
432
- const controllerState = this.pgs.deriveStakeControllerStatePda();
433
- const payoutState = this.pgs.derivePayoutStatePda();
434
- const bucketAuthority = this.pgs.deriveBucketAuthorityPda();
435
- const payRateHistory = this.pgs.derivePayRateHistoryPda();
436
- const globalConfig = this.pgs.deriveGlobalConfigPda();
437
-
438
- // -------------------------------------------------------------
439
- // Token-2022 ATAs
440
- // -------------------------------------------------------------
441
- const userAta = getAssociatedTokenAddressSync(
442
- liqsolMint,
443
- user,
444
- true,
445
- TOKEN_2022_PROGRAM_ID,
446
- );
447
-
448
- // -------------------------------------------------------------
449
- // Distribution state + user_record (KEYED BY TOKEN ACCOUNT)
450
- // -------------------------------------------------------------
451
- const distributionState = this.pgs.deriveDistributionStatePda();
452
- const userRecord = this.pgs.deriveUserRecordPda(userAta);
453
-
454
- const bucketTokenAccount = getAssociatedTokenAddressSync(
455
- liqsolMint,
456
- bucketAuthority,
457
- true,
458
- TOKEN_2022_PROGRAM_ID,
459
- );
460
-
461
- // -------------------------------------------------------------
462
- // Ephemeral stake
463
- // -------------------------------------------------------------
464
- const seed = Math.floor(Math.random() * 2 ** 32);
465
- const ephemeralStake = await this.pgs.deriveEphemeralStakeAddress(user, seed);
466
-
467
- // -------------------------------------------------------------
468
- // BUILD IX (MUST MATCH IDL)
469
- // -------------------------------------------------------------
470
- const ix: TransactionInstruction = await this.program.methods
471
- .deposit(new BN(amount.toString()), seed)
472
- .accounts({
473
- user,
474
- depositAuthority,
475
- systemProgram: SystemProgram.programId,
476
- tokenProgram: TOKEN_2022_PROGRAM_ID,
477
- associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
478
- liqsolProgram: this.pgs.PROGRAM_IDS.LIQSOL_TOKEN,
479
- stakeProgram: StakeProgram.programId,
480
- liqsolMint,
481
- userAta,
482
- liqsolMintAuthority,
483
- reservePool,
484
- vault,
485
- ephemeralStake,
486
- controllerState,
487
- payoutState,
488
- bucketAuthority,
489
- bucketTokenAccount,
490
- userRecord,
491
- distributionState,
492
- payRateHistory,
493
- instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
494
- clock: SYSVAR_CLOCK_PUBKEY,
495
- stakeHistory: SYSVAR_STAKE_HISTORY_PUBKEY,
496
- rent: SYSVAR_RENT_PUBKEY,
497
- globalConfig,
498
- })
499
- .instruction();
500
-
501
- return { ix, seed, userAta, ephemeralStake };
502
276
  }
503
-
504
277
  }
505
278
 
506
279
  // A “wallet-adapter-like” shape (AnchorProvider.wallet matches this)
@@ -139,19 +139,18 @@ export class OutpostClient {
139
139
  */
140
140
  async buildStakeIx(
141
141
  amountLamports: bigint,
142
- user?: PublicKey,
142
+ user: PublicKey = this.wallet.publicKey,
143
143
  ): Promise<TransactionInstruction> {
144
- const userPk = user ?? this.wallet.publicKey;
145
- if (!userPk) {
144
+ if (!user) {
146
145
  throw new Error('OutpostClient.buildStakeIx: wallet not connected');
147
146
  }
148
147
 
149
- const a = await this.buildAccounts(userPk);
148
+ const a = await this.buildAccounts(user);
150
149
 
151
150
  return this.program.methods
152
151
  .synd(new BN(amountLamports.toString()))
153
152
  .accounts({
154
- user: userPk,
153
+ user,
155
154
  liqsolMint: a.liqsolMint,
156
155
  globalState: a.globalState,
157
156
  distributionState: a.distributionState,
@@ -100,6 +100,8 @@ export class TokenClient {
100
100
  amountLamports: bigint,
101
101
  user = this.wallet.publicKey,
102
102
  ): Promise<TransactionInstruction> {
103
+ console.log('build purchase for', user.toBase58());
104
+
103
105
  const a = await this.getAccounts(user);
104
106
 
105
107
  const extraAccountMetaList = this.pgs.deriveExtraAccountMetaListPda(a.liqsolMint);
@@ -21,6 +21,7 @@ export type SolanaProgramIds = {
21
21
  LIQSOL_TOKEN: PublicKey;
22
22
  VALIDATOR_LEADERBOARD: PublicKey;
23
23
  TRANSFER_HOOK: PublicKey;
24
+ ALT_LOOKUP_TABLE: PublicKey;
24
25
  };
25
26
 
26
27
  const MAINNET_PROGRAM_IDS: SolanaProgramIds = {
@@ -28,6 +29,7 @@ const MAINNET_PROGRAM_IDS: SolanaProgramIds = {
28
29
  LIQSOL_TOKEN: new PublicKey(mainnetLiqSolTokenIDL.address),
29
30
  VALIDATOR_LEADERBOARD: new PublicKey(mainnetValidatorLeaderboardIDL.address),
30
31
  TRANSFER_HOOK: new PublicKey(mainnetTransferHookIDL.address),
32
+ ALT_LOOKUP_TABLE: new PublicKey("AQXTHwkdNBEiXeQuVA5uCoxvzgYUmudRxthQY4vWKCPS")
31
33
  };
32
34
 
33
35
  const DEVNET_PROGRAM_IDS: SolanaProgramIds = {
@@ -35,6 +37,7 @@ const DEVNET_PROGRAM_IDS: SolanaProgramIds = {
35
37
  LIQSOL_TOKEN: new PublicKey(devnetLiqSolTokenIDL.address),
36
38
  VALIDATOR_LEADERBOARD: new PublicKey(devnetValidatorLeaderboardIDL.address),
37
39
  TRANSFER_HOOK: new PublicKey(devnetTransferHookIDL.address),
40
+ ALT_LOOKUP_TABLE: new PublicKey("3MbupRDxUqPtJzoLLmjEYV3dXJdh1jojQrpDEQUqv7xb")
38
41
  };
39
42
 
40
43
  export const PROGRAM_IDS_BY_CHAIN: Record<SupportedSolChainID, SolanaProgramIds> = {