@wireio/stake 1.0.0 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wireio/stake",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
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",
@@ -84,34 +84,33 @@ export class OPPClient {
84
84
  };
85
85
  }
86
86
 
87
-
88
-
89
-
90
87
  /**
91
88
  * Fetches all OPPMessage events and flattens all assertions into a single OPPAssertion[] array.
92
89
  */
93
90
  async getMessages(address: string): Promise<OPPAssertion[]> {
94
- const oppMessageFilter = this.contract.OPP.filters.OPPMessage();
95
- const events = await this.contract.OPP.queryFilter(oppMessageFilter, 0, "latest");
96
- const allAssertions: OPPAssertion[] = [];
97
- for (const event of events) {
98
- const assertions = await this.extractAssertionsFromEvent(event);
99
- allAssertions.push(...assertions);
100
- }
91
+ try {
92
+ const oppMessageFilter = this.contract.OPP.filters.OPPMessage();
93
+ const events = await this.contract.OPP.queryFilter(oppMessageFilter, 0, "latest");
94
+ const allAssertions: OPPAssertion[] = [];
95
+ for (const event of events) {
96
+ const assertions = await this.extractAssertionsFromEvent(event);
97
+ allAssertions.push(...assertions);
98
+ }
101
99
 
102
- // ! Current implementation is not ideal - no current way to filter OPP Messages by a single user
103
- const normalized = address ? address.toLowerCase() : null;
104
- const filtered = allAssertions.filter(a =>
105
- (a.from && a.from.toLowerCase() === normalized) ||
106
- (a.to && a.to.toLowerCase() === normalized)
107
- );
108
- return filtered.reverse();
100
+ // ! Current implementation is not ideal - no current way to filter OPP Messages by a single user
101
+ const normalized = address ? address.toLowerCase() : null;
102
+ const filtered = allAssertions.filter(a =>
103
+ (a.from && a.from.toLowerCase() === normalized) ||
104
+ (a.to && a.to.toLowerCase() === normalized)
105
+ );
106
+ return filtered.reverse();
107
+ }
108
+ catch (error) {
109
+ // console.log('Error fetching OPP messages:', error);
110
+ return [];
111
+ }
109
112
  }
110
113
 
111
-
112
-
113
-
114
-
115
114
  /**
116
115
  * Extracts all OPPAssertions from a single OPPMessage event, attaching event metadata to each.
117
116
  */
@@ -20,7 +20,14 @@ export class ReceiptClient {
20
20
  }
21
21
 
22
22
  async stakeReceipts(address: string): Promise<preLaunchReceipt[]> {
23
- return this.fetchPreLaunchReceipts(address, ReceiptNFTKind.STAKE);
23
+ try {
24
+ const receipts = await this.fetchPreLaunchReceipts(address, ReceiptNFTKind.STAKE);
25
+ return receipts;
26
+ }
27
+ catch (err) {
28
+ // console.log('Error fetching stake receipts:', err);
29
+ return [];
30
+ }
24
31
  }
25
32
 
26
33
  async pretokenReceipts(address: string): Promise<preLaunchReceipt[]> {
@@ -160,100 +160,109 @@ export class EthereumStakingClient implements IStakingClient {
160
160
  * tracked = liqETH tracked balance (protocol/accounting view)
161
161
  */
162
162
  async getPortfolio(): Promise<Portfolio | null> {
163
- if (!this.signer) return Promise.resolve(null);
164
163
 
165
- const walletAddress = await this.signer!.getAddress();
164
+ try {
165
+ if (!this.signer) return Promise.resolve(null);
166
166
 
167
- // 1) Native ETH balance
168
- const nativeBalance = await this.provider.getBalance(walletAddress);
169
- const nativeDecimals = this.network?.nativeCurrency?.decimals ?? 18;
170
- const nativeSymbol = this.network?.nativeCurrency?.symbol ?? 'ETH';
167
+ const walletAddress = await this.signer!.getAddress();
171
168
 
172
- // 2) liqETH ERC-20 balance (actual)
173
- const liqBalance: ethers.BigNumber = await this.contract.LiqEthToken.balanceOf(walletAddress);
174
- const liqSymbol = 'Liq' + (this.network?.nativeCurrency?.symbol ?? 'ETH');
169
+ // 1) Native ETH balance
170
+ const nativeBalance = await this.provider.getBalance(walletAddress);
171
+ const nativeDecimals = this.network?.nativeCurrency?.decimals ?? 18;
172
+ const nativeSymbol = this.network?.nativeCurrency?.symbol ?? 'ETH';
175
173
 
176
- // 3) staked liqEth ERC-20 balance (calculate from receipts)
177
- let stakeReceipts = await this.receiptClient.stakeReceipts(walletAddress);
178
- let stakeBalanceBN = BigNumber.from(0);
179
- for (let r of stakeReceipts) {
180
- stakeBalanceBN = stakeBalanceBN.add(BigNumber.from(r.receipt.principal.amount));
181
- }
182
- let stakeSharesBN = BigNumber.from(0);
183
- for (let r of stakeReceipts) {
184
- stakeSharesBN = stakeSharesBN.add(BigNumber.from(r.receipt.shares.amount));
185
- }
174
+ // 2) liqETH ERC-20 balance (actual)
175
+ const liqBalance: ethers.BigNumber = await this.contract.LiqEthToken.balanceOf(walletAddress);
176
+ const liqSymbol = 'Liq' + (this.network?.nativeCurrency?.symbol ?? 'ETH');
186
177
 
187
- // 4) WIRE pretoken balance
188
- const wireBalance: ethers.BigNumber = await this.contract.Pretoken.balanceOf(walletAddress);
178
+ // 3) staked liqEth ERC-20 balance (calculate from receipts)
179
+ let stakeReceipts = await this.receiptClient.stakeReceipts(walletAddress);
189
180
 
181
+ let stakeBalanceBN = BigNumber.from(0);
182
+ for (let r of stakeReceipts) {
183
+ stakeBalanceBN = stakeBalanceBN.add(BigNumber.from(r.receipt.principal.amount));
184
+ }
185
+ let stakeSharesBN = BigNumber.from(0);
186
+ for (let r of stakeReceipts) {
187
+ stakeSharesBN = stakeSharesBN.add(BigNumber.from(r.receipt.shares.amount));
188
+ }
190
189
 
191
- // 5) Calculate staking yield
192
- let currentIndex = BigInt(0);
193
- let totalShares = BigInt(0);
194
- let userShares = BigInt(0);
195
- const indexScale = BigInt(1e27);
196
- try {
197
- // These may throw if not implemented on contract
198
- const [indexBn, totalSharesBn] = await Promise.all([
199
- this.contract.Depositor.index().catch(() => BigNumber.from(0)),
200
- this.contract.Depositor.totalShares().catch(() => BigNumber.from(0)),
201
- ]);
190
+ // 4) WIRE pretoken balance
191
+ const wireBalance: ethers.BigNumber = await this.contract.Pretoken.balanceOf(walletAddress);
192
+
193
+ // 5) Calculate staking yield
194
+ let currentIndex = BigInt(0);
195
+ let totalShares = BigInt(0);
196
+ let userShares = BigInt(0);
197
+ const indexScale = BigInt(1e27);
198
+ try {
199
+ // These may throw if not implemented on contract
200
+ const [indexBn, totalSharesBn] = await Promise.all([
201
+ this.contract.Depositor.index().catch(() => BigNumber.from(0)),
202
+ this.contract.Depositor.totalShares().catch(() => BigNumber.from(0)),
203
+ ]);
204
+
205
+ const userSharesBn = stakeSharesBN;
206
+ currentIndex = BigInt(indexBn.toString());
207
+ totalShares = BigInt(totalSharesBn.toString());
208
+ userShares = BigInt(userSharesBn.toString());
209
+ } catch (error) {
210
+ console.log('Error fetching staking index/shares:', error);
211
+ }
202
212
 
203
- const userSharesBn = stakeSharesBN;
204
- currentIndex = BigInt(indexBn.toString());
205
- totalShares = BigInt(totalSharesBn.toString());
206
- userShares = BigInt(userSharesBn.toString());
207
- } catch { }
208
-
209
- // sharesToTokens(userShares, currentIndex) = userShares * currentIndex / indexScale
210
- let estimatedClaim = BigInt(0);
211
- let estimatedYield = BigInt(0);
212
-
213
- // started work on estimating the user's personal APY - not necessary at the moment
214
- // let estimatedAPY: number | null = null;
215
- // if (userShares > BigInt(0) && currentIndex > BigInt(0)) {
216
- // estimatedClaim = (userShares * currentIndex) / indexScale;
217
- // if (estimatedClaim > stakeBalanceBN.toBigInt()) {
218
- // estimatedYield = estimatedClaim - stakeBalanceBN.toBigInt();
219
- // }
220
-
221
- // estimatedAPY = null;
222
- // }
223
-
224
- const portfolio: Portfolio = {
225
- native: {
226
- amount: nativeBalance.toBigInt(),
227
- decimals: nativeDecimals,
228
- symbol: nativeSymbol,
229
- },
230
- liq: {
231
- amount: liqBalance.toBigInt(),
232
- decimals: nativeDecimals,
233
- symbol: liqSymbol,
234
- },
235
- staked: {
236
- amount: stakeBalanceBN.toBigInt(),
237
- decimals: nativeDecimals,
238
- symbol: liqSymbol,
239
- },
240
- wire: {
241
- amount: wireBalance.toBigInt(),
242
- decimals: 18,
243
- symbol: '$WIRE',
244
- },
245
-
246
- yield: {
247
- currentIndex,
248
- indexScale,
249
- totalShares,
250
- userShares,
251
- estimatedClaim,
252
- estimatedYield,
253
- },
254
- chainID: this.network.chainId
213
+ // sharesToTokens(userShares, currentIndex) = userShares * currentIndex / indexScale
214
+ let estimatedClaim = BigInt(0);
215
+ let estimatedYield = BigInt(0);
216
+
217
+ // started work on estimating the user's personal APY - not necessary at the moment
218
+ // let estimatedAPY: number | null = null;
219
+ // if (userShares > BigInt(0) && currentIndex > BigInt(0)) {
220
+ // estimatedClaim = (userShares * currentIndex) / indexScale;
221
+ // if (estimatedClaim > stakeBalanceBN.toBigInt()) {
222
+ // estimatedYield = estimatedClaim - stakeBalanceBN.toBigInt();
223
+ // }
224
+
225
+ // estimatedAPY = null;
226
+ // }
227
+
228
+ const portfolio: Portfolio = {
229
+ native: {
230
+ amount: nativeBalance.toBigInt(),
231
+ decimals: nativeDecimals,
232
+ symbol: nativeSymbol,
233
+ },
234
+ liq: {
235
+ amount: liqBalance.toBigInt(),
236
+ decimals: nativeDecimals,
237
+ symbol: liqSymbol,
238
+ },
239
+ staked: {
240
+ amount: stakeBalanceBN.toBigInt(),
241
+ decimals: nativeDecimals,
242
+ symbol: liqSymbol,
243
+ },
244
+ wire: {
245
+ amount: wireBalance.toBigInt(),
246
+ decimals: 18,
247
+ symbol: '$WIRE',
248
+ },
249
+
250
+ yield: {
251
+ currentIndex,
252
+ indexScale,
253
+ totalShares,
254
+ userShares,
255
+ estimatedClaim,
256
+ estimatedYield,
257
+ },
258
+ chainID: this.network.chainId
259
+ }
260
+ return portfolio;
261
+ }
262
+ catch (error) {
263
+ // console.log('Error fetching Ethereum portfolio:', error);
264
+ throw error;
255
265
  }
256
- return portfolio;
257
266
  }
258
267
 
259
268
  /**
@@ -422,7 +431,7 @@ export class EthereumStakingClient implements IStakingClient {
422
431
  txCount?: number;
423
432
  safetyMultiplier?: number;
424
433
  minBufferWei?: bigint;
425
- balanceOverrideLamports?: bigint;
434
+ balanceOverrideLamports?: bigint;
426
435
  }): Promise<bigint> {
427
436
  this.ensureUser();
428
437
 
@@ -208,14 +208,18 @@ export class SolanaStakingClient implements IStakingClient {
208
208
  }
209
209
 
210
210
  try {
211
- const tx = await this.depositClient.buildDepositTx(amountLamports);
212
- const { tx: prepared, blockhash, lastValidBlockHeight } =
213
- await this.prepareTx(tx);
214
- const signed = await this.signTransaction(prepared);
215
- return await this.sendAndConfirmHttp(signed, {
216
- blockhash,
217
- lastValidBlockHeight,
218
- });
211
+ // Build compute budget increase instruction
212
+ const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 });
213
+
214
+ // Build the Outpost synd instruction
215
+ const ix = await this.depositClient.buildDepositTx(amountLamports);
216
+
217
+ // Wrap in a transaction and send
218
+ const tx = new Transaction().add(cuIx, ix);
219
+ const prepared = await this.prepareTx(tx);
220
+ const signed = await this.signTransaction(prepared.tx);
221
+
222
+ return this.sendAndConfirmHttp(signed, prepared);
219
223
  } catch (err) {
220
224
  throw new Error(`Failed to deposit Solana: ${err}`);
221
225
  }
@@ -238,14 +242,18 @@ export class SolanaStakingClient implements IStakingClient {
238
242
  }
239
243
 
240
244
  try {
241
- const tx = await this.depositClient.buildWithdrawTx(amountLamports);
242
- const { tx: prepared, blockhash, lastValidBlockHeight } =
243
- await this.prepareTx(tx);
244
- const signed = await this.signTransaction(prepared);
245
- return await this.sendAndConfirmHttp(signed, {
246
- blockhash,
247
- lastValidBlockHeight,
248
- });
245
+ // Build compute budget increase instruction
246
+ const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 });
247
+
248
+ // Build the Outpost synd instruction
249
+ const ix = await this.depositClient.buildWithdrawTx(amountLamports);
250
+
251
+ // Wrap in a transaction and send
252
+ const tx = new Transaction().add(cuIx, ix);
253
+ const prepared = await this.prepareTx(tx);
254
+ const signed = await this.signTransaction(prepared.tx);
255
+
256
+ return this.sendAndConfirmHttp(signed, prepared);
249
257
  } catch (err) {
250
258
  throw new Error(`Failed to withdraw Solana: ${err}`);
251
259
  }
@@ -328,14 +336,12 @@ export class SolanaStakingClient implements IStakingClient {
328
336
  const user = this.solPubKey;
329
337
  const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 });
330
338
  const ix = await this.tokenClient.buildPurchaseIx(amountLamports, user);
339
+
331
340
  const tx = new Transaction().add(cuIx, ix);
332
- const { tx: prepared, blockhash, lastValidBlockHeight } =
333
- await this.prepareTx(tx);
334
- const signed = await this.signTransaction(prepared);
335
- return await this.sendAndConfirmHttp(signed, {
336
- blockhash,
337
- lastValidBlockHeight,
338
- });
341
+ const prepared = await this.prepareTx(tx);
342
+ const signed = await this.signTransaction(prepared.tx);
343
+
344
+ return this.sendAndConfirmHttp(signed, prepared);
339
345
  }
340
346
  catch (err) {
341
347
  throw new Error(`Failed to buy liqSOL pretokens: ${err}`);
package/src/staker.ts CHANGED
@@ -41,6 +41,7 @@ export class Staker {
41
41
  break;
42
42
 
43
43
  case EvmChainID.Ethereum:
44
+ case EvmChainID.Hoodi:
44
45
  this.clients.set(cfg.network.chainId, new EthereumStakingClient(cfg));
45
46
  break;
46
47