@wireio/stake 0.9.0 → 0.9.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.
@@ -1,7 +1,8 @@
1
1
  import { PublicKey as PublicKey$1, KeyType, SolChainID, EvmChainID } from '@wireio/core';
2
- import { PublicKey, StakeProgram, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, SYSVAR_RENT_PUBKEY, Transaction, Keypair, Connection, ComputeBudgetProgram } from '@solana/web3.js';
2
+ import { PublicKey, StakeProgram, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_CLOCK_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, SYSVAR_RENT_PUBKEY, TransactionMessage, Transaction, Keypair, Connection, ComputeBudgetProgram } from '@solana/web3.js';
3
3
  import { Program, BN, AnchorProvider } from '@coral-xyz/anchor';
4
- import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress } from '@solana/spl-token';
4
+ import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction } from '@solana/spl-token';
5
+ import * as multisig from '@sqds/multisig';
5
6
  import { ethers, Contract, BigNumber } from 'ethers';
6
7
 
7
8
  var address$3 = "5nBtmutQLrRKBUxNfHJPDjiW5u8id6QM9Hhjg1D1g1XH";
@@ -7440,6 +7441,9 @@ class DepositClient {
7440
7441
  const svc = new SolanaProgramService(provider);
7441
7442
  this.program = svc.getProgram("liqsolCore");
7442
7443
  }
7444
+ get connection() {
7445
+ return this.provider.connection;
7446
+ }
7443
7447
  get wallet() {
7444
7448
  return this.provider.wallet;
7445
7449
  }
@@ -7467,7 +7471,7 @@ class DepositClient {
7467
7471
  const userAta = getAssociatedTokenAddressSync(
7468
7472
  liqsolMint,
7469
7473
  user,
7470
- false,
7474
+ true,
7471
7475
  TOKEN_2022_PROGRAM_ID
7472
7476
  );
7473
7477
  const distributionState = deriveDistributionStatePda();
@@ -7480,7 +7484,7 @@ class DepositClient {
7480
7484
  );
7481
7485
  const seed = Math.floor(Math.random() * 2 ** 32);
7482
7486
  const ephemeralStake = await deriveEphemeralStakeAddress(user, seed);
7483
- const ix = await this.program.methods.deposit(new BN(amount.toString()), seed).accounts({
7487
+ return await this.program.methods.deposit(new BN(amount.toString()), seed).accounts({
7484
7488
  user,
7485
7489
  depositAuthority,
7486
7490
  systemProgram: SystemProgram.programId,
@@ -7507,7 +7511,58 @@ class DepositClient {
7507
7511
  rent: SYSVAR_RENT_PUBKEY,
7508
7512
  globalConfig
7509
7513
  }).instruction();
7510
- return new Transaction().add(ix);
7514
+ }
7515
+ async buildSquadsDepositProposalTx(params) {
7516
+ const { connection, multisigPda, amountLamports, wallet } = params;
7517
+ const vaultIndex = params.vaultIndex ?? 0;
7518
+ if (!wallet?.publicKey) throw new Error("wallet.publicKey missing");
7519
+ if (!amountLamports || amountLamports <= BigInt(0)) throw new Error("amountLamports must be > 0");
7520
+ const [vaultPda] = multisig.getVaultPda({ multisigPda, index: vaultIndex });
7521
+ const depositBuilt = await this.buildDepositIxForUser(amountLamports, vaultPda);
7522
+ const ms = await multisig.accounts.Multisig.fromAccountAddress(connection, multisigPda);
7523
+ const current = BigInt(ms.transactionIndex?.toString?.() ?? 0);
7524
+ const transactionIndex = current + BigInt(1);
7525
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
7526
+ const message = new TransactionMessage({
7527
+ payerKey: vaultPda,
7528
+ recentBlockhash: blockhash,
7529
+ instructions: [depositBuilt.ix]
7530
+ });
7531
+ const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
7532
+ multisigPda,
7533
+ transactionIndex,
7534
+ creator: wallet.publicKey,
7535
+ vaultIndex,
7536
+ ephemeralSigners: 0,
7537
+ transactionMessage: message
7538
+ });
7539
+ console.log("createVaultTxIx", createVaultTxIx);
7540
+ const tx = new Transaction().add(createVaultTxIx);
7541
+ return { tx, transactionIndex, vaultPda };
7542
+ }
7543
+ async buildSquadsDepositProposalTx2(params) {
7544
+ const { connection, multisigPda, amountLamports, wallet } = params;
7545
+ const vaultIndex = params.vaultIndex ?? 0;
7546
+ if (!wallet?.publicKey) throw new Error("wallet.publicKey missing");
7547
+ if (!amountLamports || amountLamports <= BigInt(0)) throw new Error("amountLamports must be > 0");
7548
+ const [vaultPda] = multisig.getVaultPda({ multisigPda, index: vaultIndex });
7549
+ const depositBuilt = await this.buildDepositIxForUser(amountLamports, vaultPda);
7550
+ const ms = await multisig.accounts.Multisig.fromAccountAddress(connection, multisigPda);
7551
+ const current = BigInt(ms.transactionIndex?.toString?.() ?? 0);
7552
+ const transactionIndex = current + BigInt(1);
7553
+ const { blockhash } = await connection.getLatestBlockhash("confirmed");
7554
+ new TransactionMessage({
7555
+ payerKey: vaultPda,
7556
+ recentBlockhash: blockhash,
7557
+ instructions: [depositBuilt.ix]
7558
+ });
7559
+ const createProposalIx = await multisig.instructions.proposalCreate({
7560
+ multisigPda,
7561
+ transactionIndex,
7562
+ creator: wallet.publicKey
7563
+ });
7564
+ const tx = new Transaction().add(createProposalIx);
7565
+ return { tx, transactionIndex, vaultPda };
7511
7566
  }
7512
7567
  async buildWithdrawTx(amount, user = this.wallet.publicKey) {
7513
7568
  if (!user) {
@@ -7524,7 +7579,7 @@ class DepositClient {
7524
7579
  const userAta = getAssociatedTokenAddressSync(
7525
7580
  liqsolMint,
7526
7581
  user,
7527
- false,
7582
+ true,
7528
7583
  TOKEN_2022_PROGRAM_ID
7529
7584
  );
7530
7585
  const userRecord = deriveUserRecordPda(userAta);
@@ -7557,7 +7612,7 @@ class DepositClient {
7557
7612
  const nftAta = getAssociatedTokenAddressSync(
7558
7613
  nftMint,
7559
7614
  owner,
7560
- false,
7615
+ true,
7561
7616
  TOKEN_2022_PROGRAM_ID
7562
7617
  );
7563
7618
  const bucketAuthority = deriveBucketAuthorityPda();
@@ -7595,6 +7650,68 @@ class DepositClient {
7595
7650
  }).instruction();
7596
7651
  return new Transaction().add(ix);
7597
7652
  }
7653
+ async buildDepositIxForUser(amount, user) {
7654
+ if (!user) {
7655
+ throw new Error("buildDepositIxForUser: user is required");
7656
+ }
7657
+ if (!amount || amount <= BigInt(0)) {
7658
+ throw new Error("buildDepositIxForUser: amount must be > 0");
7659
+ }
7660
+ const depositAuthority = deriveDepositAuthorityPda();
7661
+ const liqsolMint = deriveLiqsolMintPda();
7662
+ const liqsolMintAuthority = deriveLiqsolMintAuthorityPda();
7663
+ const reservePool = deriveReservePoolPda();
7664
+ const vault = deriveVaultPda();
7665
+ const controllerState = deriveStakeControllerStatePda();
7666
+ const payoutState = derivePayoutStatePda();
7667
+ const bucketAuthority = deriveBucketAuthorityPda();
7668
+ const payRateHistory = derivePayRateHistoryPda();
7669
+ const globalConfig = deriveGlobalConfigPda();
7670
+ const userAta = getAssociatedTokenAddressSync(
7671
+ liqsolMint,
7672
+ user,
7673
+ true,
7674
+ TOKEN_2022_PROGRAM_ID
7675
+ );
7676
+ const distributionState = deriveDistributionStatePda();
7677
+ const userRecord = deriveUserRecordPda(userAta);
7678
+ const bucketTokenAccount = getAssociatedTokenAddressSync(
7679
+ liqsolMint,
7680
+ bucketAuthority,
7681
+ true,
7682
+ TOKEN_2022_PROGRAM_ID
7683
+ );
7684
+ const seed = Math.floor(Math.random() * 2 ** 32);
7685
+ const ephemeralStake = await deriveEphemeralStakeAddress(user, seed);
7686
+ const ix = await this.program.methods.deposit(new BN(amount.toString()), seed).accounts({
7687
+ user,
7688
+ depositAuthority,
7689
+ systemProgram: SystemProgram.programId,
7690
+ tokenProgram: TOKEN_2022_PROGRAM_ID,
7691
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
7692
+ liqsolProgram: PROGRAM_IDS.LIQSOL_TOKEN,
7693
+ stakeProgram: StakeProgram.programId,
7694
+ liqsolMint,
7695
+ userAta,
7696
+ liqsolMintAuthority,
7697
+ reservePool,
7698
+ vault,
7699
+ ephemeralStake,
7700
+ controllerState,
7701
+ payoutState,
7702
+ bucketAuthority,
7703
+ bucketTokenAccount,
7704
+ userRecord,
7705
+ distributionState,
7706
+ payRateHistory,
7707
+ instructionsSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
7708
+ clock: SYSVAR_CLOCK_PUBKEY,
7709
+ stakeHistory: SYSVAR_STAKE_HISTORY_PUBKEY,
7710
+ rent: SYSVAR_RENT_PUBKEY,
7711
+ globalConfig
7712
+ }).instruction();
7713
+ return { ix, seed, userAta, ephemeralStake };
7714
+ }
7598
7715
  }
7599
7716
 
7600
7717
  const INDEX_SCALE = BigInt(1e12);
@@ -8083,7 +8200,7 @@ class DistributionClient {
8083
8200
  const ata = getAssociatedTokenAddressSync(
8084
8201
  liqsolMint,
8085
8202
  ownerOrAta,
8086
- false,
8203
+ true,
8087
8204
  TOKEN_2022_PROGRAM_ID
8088
8205
  );
8089
8206
  const pdaFromWallet = deriveUserRecordPda(ata);
@@ -8362,7 +8479,7 @@ class OutpostClient {
8362
8479
  };
8363
8480
  }
8364
8481
  static tokensToShares(amount, currentIndex) {
8365
- const numerator = amount.mul(INDEX_SCALE$1);
8482
+ const numerator = amount.mul(new BN(INDEX_SCALE$1));
8366
8483
  const shares = numerator.div(currentIndex);
8367
8484
  const remainder = numerator.mod(currentIndex);
8368
8485
  return remainder.eqn(0) ? shares : shares.addn(1);
@@ -8561,6 +8678,69 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8561
8678
  get network() {
8562
8679
  return this.config.network;
8563
8680
  }
8681
+ get feePayer() {
8682
+ if (this.signer) return this.signer;
8683
+ if (this.anchor.wallet.publicKey) return this.anchor.wallet.publicKey;
8684
+ throw new Error("No signing authority available");
8685
+ }
8686
+ get squadsX() {
8687
+ const config = this.config.extras?.squadsX;
8688
+ return config ?? null;
8689
+ }
8690
+ async createVaultLiqsolAtaOneShot(params) {
8691
+ const { connection, payer, vaultPda } = params;
8692
+ const liqsolMint = deriveLiqsolMintPda();
8693
+ const vaultAta = getAssociatedTokenAddressSync(
8694
+ liqsolMint,
8695
+ vaultPda,
8696
+ true,
8697
+ TOKEN_2022_PROGRAM_ID,
8698
+ ASSOCIATED_TOKEN_PROGRAM_ID
8699
+ );
8700
+ const info = await connection.getAccountInfo(vaultAta, "confirmed");
8701
+ console.log("info?", info);
8702
+ if (info) return null;
8703
+ const ix = createAssociatedTokenAccountInstruction(
8704
+ payer,
8705
+ vaultAta,
8706
+ vaultPda,
8707
+ liqsolMint,
8708
+ TOKEN_2022_PROGRAM_ID,
8709
+ ASSOCIATED_TOKEN_PROGRAM_ID
8710
+ );
8711
+ const tx = new Transaction().add(ix);
8712
+ return { tx, vaultAta };
8713
+ }
8714
+ async prepSquadsIxs(ix) {
8715
+ if (!this.squadsX) throw new Error("Attempting to wrap Squads instruction without SquadsX config");
8716
+ const multisigPda = this.squadsMultisigPDA;
8717
+ const vaultPda = this.squadsVaultPDA;
8718
+ const vaultIndex = this.squadsX?.vaultIndex ?? 0;
8719
+ const creator = this.solPubKey;
8720
+ const ms = await multisig.accounts.Multisig.fromAccountAddress(this.connection, multisigPda);
8721
+ const current = BigInt(ms.transactionIndex?.toString() ?? 0);
8722
+ const transactionIndex = current + BigInt(1);
8723
+ const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
8724
+ const transactionMessage = new TransactionMessage({
8725
+ payerKey: vaultPda,
8726
+ recentBlockhash: blockhash,
8727
+ instructions: [ix]
8728
+ });
8729
+ const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
8730
+ multisigPda,
8731
+ transactionIndex,
8732
+ creator,
8733
+ vaultIndex,
8734
+ transactionMessage,
8735
+ ephemeralSigners: 0
8736
+ });
8737
+ const createProposalIx = await multisig.instructions.proposalCreate({
8738
+ multisigPda,
8739
+ transactionIndex,
8740
+ creator
8741
+ });
8742
+ return [createVaultTxIx, createProposalIx];
8743
+ }
8564
8744
  async deposit(amountLamports) {
8565
8745
  this.ensureUser();
8566
8746
  if (amountLamports <= BigInt(0)) {
@@ -8568,11 +8748,40 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8568
8748
  }
8569
8749
  try {
8570
8750
  const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 });
8571
- const ix = await this.depositClient.buildDepositTx(amountLamports);
8572
- const tx = new Transaction().add(cuIx, ix);
8573
- const prepared = await this.prepareTx(tx);
8574
- const signed = await this.signTransaction(prepared.tx);
8575
- return this.sendAndConfirmHttp(signed, prepared);
8751
+ if (!!this.squadsX) {
8752
+ const createVaultTx = await this.createVaultLiqsolAtaOneShot({
8753
+ connection: this.connection,
8754
+ payer: this.solPubKey,
8755
+ vaultPda: this.squadsVaultPDA
8756
+ });
8757
+ if (createVaultTx !== null) {
8758
+ console.log("need to create vault ata first...");
8759
+ const tx0 = new Transaction().add(createVaultTx.tx);
8760
+ const prepared0 = await this.prepareTx(tx0);
8761
+ const signed0 = await this.signTransaction(prepared0.tx);
8762
+ const sent0 = await this.sendAndConfirmHttp(signed0, prepared0);
8763
+ console.log("create Vault ATA", sent0);
8764
+ }
8765
+ const ix = await this.depositClient.buildDepositTx(amountLamports, this.squadsVaultPDA);
8766
+ const squadIxs = await this.prepSquadsIxs(ix);
8767
+ const tx1 = new Transaction().add(cuIx, squadIxs[0]);
8768
+ const prepared1 = await this.prepareTx(tx1);
8769
+ const signed1 = await this.signTransaction(prepared1.tx);
8770
+ const sent1 = await this.sendAndConfirmHttp(signed1, prepared1);
8771
+ console.log("SENT 1", sent1);
8772
+ const tx2 = new Transaction().add(cuIx, squadIxs[1]);
8773
+ const prepared2 = await this.prepareTx(tx2);
8774
+ const signed2 = await this.signTransaction(prepared2.tx);
8775
+ const sent2 = await this.sendAndConfirmHttp(signed2, prepared2);
8776
+ console.log("SENT 2", sent2);
8777
+ return sent2;
8778
+ } else {
8779
+ const ix = await this.depositClient.buildDepositTx(amountLamports);
8780
+ const tx = new Transaction().add(ix);
8781
+ const prepared = await this.prepareTx(tx);
8782
+ const signed = await this.signTransaction(prepared.tx);
8783
+ return this.sendAndConfirmHttp(signed, prepared);
8784
+ }
8576
8785
  } catch (err) {
8577
8786
  throw new Error(`Failed to deposit Solana: ${err}`);
8578
8787
  }
@@ -8647,14 +8856,15 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8647
8856
  async getPortfolio() {
8648
8857
  if (!this.pubKey) throw new Error("User pubKey is undefined");
8649
8858
  try {
8650
- const user = this.solPubKey;
8859
+ const user = !!this.squadsX ? this.squadsVaultPDA : this.solPubKey;
8860
+ console.log("get portfolio for user", user.toBase58());
8651
8861
  const reservePoolPDA = deriveReservePoolPda();
8652
8862
  const vaultPDA = deriveVaultPda();
8653
8863
  const liqsolMint = deriveLiqsolMintPda();
8654
8864
  const userLiqsolAta = getAssociatedTokenAddressSync(
8655
8865
  liqsolMint,
8656
8866
  user,
8657
- false,
8867
+ true,
8658
8868
  TOKEN_2022_PROGRAM_ID,
8659
8869
  ASSOCIATED_TOKEN_PROGRAM_ID
8660
8870
  );
@@ -8735,6 +8945,17 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8735
8945
  if (!this.pubKey) throw new Error("User pubKey is undefined");
8736
8946
  return this.distributionClient.getUserRecord(this.solPubKey);
8737
8947
  }
8948
+ get squadsMultisigPDA() {
8949
+ if (!this.squadsX) return null;
8950
+ return new PublicKey(this.squadsX.multisigPDA);
8951
+ }
8952
+ get squadsVaultPDA() {
8953
+ if (!this.squadsX || !this.squadsMultisigPDA) return null;
8954
+ const multisigPda = this.squadsMultisigPDA;
8955
+ const index = this.squadsX.vaultIndex ?? 0;
8956
+ const pda = multisig.getVaultPda({ multisigPda, index });
8957
+ return pda[0];
8958
+ }
8738
8959
  async getTrancheSnapshot(options) {
8739
8960
  try {
8740
8961
  const {
@@ -8841,8 +9062,7 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8841
9062
  }
8842
9063
  async getDepositBuffer(options) {
8843
9064
  this.ensureUser();
8844
- const payer = this.solPubKey;
8845
- const balanceLamports = options?.balanceOverrideLamports ?? BigInt(await this.connection.getBalance(payer, commitment));
9065
+ const balanceLamports = options?.balanceOverrideLamports ?? BigInt(await this.connection.getBalance(this.feePayer, commitment));
8846
9066
  if (balanceLamports <= BigInt(0)) {
8847
9067
  return BigInt(0);
8848
9068
  }
@@ -8898,7 +9118,7 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8898
9118
  if (this.cachedTxFee && now - this.cachedTxFee.fetchedAt < _SolanaStakingClient.FEE_CACHE_TTL_MS) {
8899
9119
  return this.cachedTxFee.value;
8900
9120
  }
8901
- const payer = this.solPubKey;
9121
+ const payer = this.feePayer;
8902
9122
  const dummyIx = SystemProgram.transfer({
8903
9123
  fromPubkey: payer,
8904
9124
  toPubkey: payer,
@@ -8953,17 +9173,16 @@ const _SolanaStakingClient = class _SolanaStakingClient {
8953
9173
  async prepareTx(tx) {
8954
9174
  const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash("confirmed");
8955
9175
  tx.recentBlockhash = blockhash;
8956
- tx.feePayer = this.solPubKey;
9176
+ tx.feePayer = this.feePayer;
8957
9177
  return { tx, blockhash, lastValidBlockHeight };
8958
9178
  }
8959
9179
  ensureUser() {
8960
- if (!this.pubKey || !this.anchor.wallet.publicKey) {
8961
- throw new Error("User Authorization required: pubKey is undefined");
8962
- }
8963
- if (this.solPubKey.toBase58() !== this.anchor.wallet.publicKey.toBase58()) {
8964
- throw new Error(
8965
- "Write access requires connected wallet to match pubKey"
8966
- );
9180
+ if (!this.pubKey) throw new Error("User pubKey is undefined");
9181
+ const wallet = this.anchor?.wallet;
9182
+ const pk = wallet?.publicKey;
9183
+ if (!pk) throw new Error("Wallet not connected");
9184
+ if (typeof wallet.signTransaction !== "function") {
9185
+ throw new Error("Wallet does not support signTransaction");
8967
9186
  }
8968
9187
  }
8969
9188
  };
@@ -34902,6 +35121,30 @@ class ConvertClient {
34902
35121
  event
34903
35122
  };
34904
35123
  }
35124
+ async claimWithdraw(tokenId) {
35125
+ let tx, receipt;
35126
+ try {
35127
+ tx = await this.contract.DepositManager.claim(tokenId);
35128
+ receipt = await tx.wait(1);
35129
+ } catch (err) {
35130
+ let errorObj = formatContractErrors(err);
35131
+ throw new Error(errorObj.name ?? errorObj.raw);
35132
+ }
35133
+ let event;
35134
+ const ev = receipt.events?.find((e) => e.event === "Claimed");
35135
+ if (ev && ev.args) {
35136
+ const { sender, ethAmount } = ev.args;
35137
+ event = {
35138
+ sender,
35139
+ ethAmount: BigNumber.from(ethAmount)
35140
+ };
35141
+ }
35142
+ return {
35143
+ txHash: tx.hash,
35144
+ receipt,
35145
+ event
35146
+ };
35147
+ }
34905
35148
  }
34906
35149
 
34907
35150
  class StakeClient {
@@ -34922,12 +35165,13 @@ class StakeClient {
34922
35165
  async performStake(amountWei, signerAddress) {
34923
35166
  const depositor = this.contract.Depositor.address;
34924
35167
  const liqRead = this.contract.LiqEthToken;
34925
- await liqRead.balanceOf(signerAddress);
35168
+ const bal = await liqRead.balanceOf(signerAddress);
34926
35169
  const allowance = await liqRead.allowance(signerAddress, depositor);
34927
35170
  const paused = await this.contract.Depositor.paused();
34928
35171
  if (paused) {
34929
35172
  throw new Error("Error - Depositor is in a paused state");
34930
35173
  }
35174
+ if (bal.lt(amountWei)) throw new Error("Insufficient LiqETH balance");
34931
35175
  if (allowance.lt(amountWei)) {
34932
35176
  const liqWrite = this.contractService.getWrite("LiqEthToken");
34933
35177
  console.warn(`allowance insufficient (${allowance.toString()} < ${amountWei.toString()}); sending approve(${depositor}, ${amountWei.toString()})`);
@@ -35372,7 +35616,7 @@ class ReceiptClient {
35372
35616
  }
35373
35617
  async fetchPreLaunchReceipts(address, type) {
35374
35618
  const receiptContract = this.contract.ReceiptNFT;
35375
- const tokenIds = await this.getOwnedTokenIdsFor(address);
35619
+ const tokenIds = await this.getOwnedReceiptNFTsFor(address);
35376
35620
  const results = [];
35377
35621
  for (const idBN of tokenIds) {
35378
35622
  try {
@@ -35405,7 +35649,7 @@ class ReceiptClient {
35405
35649
  }
35406
35650
  return results;
35407
35651
  }
35408
- async getOwnedTokenIdsFor(owner, fromBlock = 0, toBlock = "latest") {
35652
+ async getOwnedReceiptNFTsFor(owner, fromBlock = 0, toBlock = "latest") {
35409
35653
  const receiptContract = this.contract.ReceiptNFT;
35410
35654
  const toLogs = await receiptContract.queryFilter(
35411
35655
  receiptContract.filters.Transfer(null, owner),
@@ -35430,6 +35674,56 @@ class ReceiptClient {
35430
35674
  }
35431
35675
  return Array.from(owned).map((id) => BigNumber.from(id));
35432
35676
  }
35677
+ async fetchWithdrawReceipts(address) {
35678
+ const tokenIds = await this.getOwnedWithdrawReceiptsFor(address);
35679
+ const results = [];
35680
+ for (const idBN of tokenIds) {
35681
+ try {
35682
+ const receiptData = await this.contract.WithdrawalQueue.info(idBN);
35683
+ results.push({
35684
+ tokenId: idBN.toBigInt(),
35685
+ receipt: {
35686
+ ethAmount: receiptData.ethAmount,
35687
+ ethBalance: {
35688
+ amount: receiptData.ethAmount.toBigInt(),
35689
+ decimals: 18,
35690
+ symbol: "ETH"
35691
+ },
35692
+ readyAt: new Date(Number(receiptData.readyAt.toString()) * 1e3).valueOf()
35693
+ }
35694
+ });
35695
+ } catch (err) {
35696
+ console.warn(`Failed to load receipt for tokenId=${idBN.toString()}`, err);
35697
+ continue;
35698
+ }
35699
+ }
35700
+ return results;
35701
+ }
35702
+ async getOwnedWithdrawReceiptsFor(owner, fromBlock = 0, toBlock = "latest") {
35703
+ const contract = this.contract.WithdrawalQueue;
35704
+ const toLogs = await contract.queryFilter(
35705
+ contract.filters.Transfer(null, owner),
35706
+ fromBlock,
35707
+ toBlock
35708
+ );
35709
+ const fromLogs = await contract.queryFilter(
35710
+ contract.filters.Transfer(owner, null),
35711
+ fromBlock,
35712
+ toBlock
35713
+ );
35714
+ const owned = new Set();
35715
+ for (const e of toLogs) {
35716
+ const tokenId = e.args?.tokenId;
35717
+ if (!tokenId) continue;
35718
+ owned.add(tokenId.toString());
35719
+ }
35720
+ for (const e of fromLogs) {
35721
+ const tokenId = e.args?.tokenId;
35722
+ if (!tokenId) continue;
35723
+ owned.delete(tokenId.toString());
35724
+ }
35725
+ return Array.from(owned).map((id) => BigNumber.from(id));
35726
+ }
35433
35727
  }
35434
35728
 
35435
35729
  const INITIAL_TRANCHE_SUPPLY = 35e3;
@@ -35476,6 +35770,17 @@ class EthereumStakingClient {
35476
35770
  const result = await this.convertClient.performWithdraw(address, amountWei);
35477
35771
  return result.txHash;
35478
35772
  }
35773
+ async loadPendingWithdraws() {
35774
+ this.ensureUser();
35775
+ const address = await this.signer.getAddress();
35776
+ return await this.receiptClient.fetchWithdrawReceipts(address);
35777
+ }
35778
+ async claimWithdraw(tokenId) {
35779
+ this.ensureUser();
35780
+ const tokenIdBigNum = BigNumber.from(tokenId);
35781
+ const result = await this.convertClient.claimWithdraw(tokenIdBigNum);
35782
+ return result.txHash;
35783
+ }
35479
35784
  async stake(amount) {
35480
35785
  this.ensureUser();
35481
35786
  const walletAddress = await this.signer.getAddress();
@@ -35535,6 +35840,12 @@ class EthereumStakingClient {
35535
35840
  }
35536
35841
  let estimatedClaim = BigInt(0);
35537
35842
  let estimatedYield = BigInt(0);
35843
+ if (userShares > BigInt(0) && currentIndex > BigInt(0)) {
35844
+ estimatedClaim = userShares * currentIndex / indexScale;
35845
+ if (estimatedClaim > stakeBalanceBN.toBigInt()) {
35846
+ estimatedYield = estimatedClaim - stakeBalanceBN.toBigInt();
35847
+ }
35848
+ }
35538
35849
  const portfolio = {
35539
35850
  native: {
35540
35851
  amount: nativeBalance.toBigInt(),
@@ -35692,11 +36003,9 @@ class Staker {
35692
36003
  if (!Array.isArray(config)) config = [config];
35693
36004
  config.forEach((cfg) => {
35694
36005
  switch (cfg.network.chainId) {
35695
- case SolChainID.Mainnet:
35696
36006
  case SolChainID.Devnet:
35697
36007
  this.clients.set(cfg.network.chainId, new SolanaStakingClient(cfg));
35698
36008
  break;
35699
- case EvmChainID.Ethereum:
35700
36009
  case EvmChainID.Hoodi:
35701
36010
  this.clients.set(cfg.network.chainId, new EthereumStakingClient(cfg));
35702
36011
  break;