@wireio/stake 2.0.0 → 2.1.1

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.
@@ -29,6 +29,25 @@ import type { LiqsolCore as LiqSolCoreDevnet } from '../../assets/solana/devnet/
29
29
  import type { LiqsolToken as LiqsolTokenDevnet } from '../../assets/solana/devnet/types/liqsol_token';
30
30
  import type { ValidatorLeaderboard as ValidatorLeaderboardDevnet } from '../../assets/solana/devnet/types/validator_leaderboard';
31
31
 
32
+ // “Client” IDLs = mainnet OR devnet, plus `address` field we add at runtime
33
+
34
+ export type LiqsolCoreClientIdl =
35
+ (LiqSolCoreMainnet | LiqSolCoreDevnet) & { address: string };
36
+
37
+ export type LiqsolTokenClientIdl =
38
+ (LiqsolTokenMainnet | LiqsolTokenDevnet) & { address: string };
39
+
40
+ export type ValidatorLeaderboardClientIdl =
41
+ (ValidatorLeaderboardMainnet | ValidatorLeaderboardDevnet) & { address: string };
42
+
43
+ export type SolanaProgramIdlMap = {
44
+ liqsolCore: LiqsolCoreClientIdl;
45
+ liqsolToken: LiqsolTokenClientIdl;
46
+ validatorLeaderboard: ValidatorLeaderboardClientIdl;
47
+ };
48
+
49
+ export type SolanaProgramName = keyof SolanaProgramIdlMap;
50
+
32
51
  type Entry<IDL> = {
33
52
  idl: IDL & { address: string };
34
53
  address: string;
@@ -65,9 +84,6 @@ const PROGRAMS_BY_CHAIN = {
65
84
  },
66
85
  } as const;
67
86
 
68
- export type SolanaProgramName =
69
- keyof (typeof PROGRAMS_BY_CHAIN)[SolChainID.Mainnet];
70
-
71
87
  export class SolanaProgramService {
72
88
  private readonly ids: SolanaProgramIds;
73
89
  private readonly programs: (typeof PROGRAMS_BY_CHAIN)[SolChainID.Mainnet];
@@ -90,15 +106,14 @@ export class SolanaProgramService {
90
106
  return this.ids;
91
107
  }
92
108
 
93
- /** Anchor Program getter */
109
+ // Generic getProgram, typed by name → union IDL
94
110
  getProgram<K extends SolanaProgramName>(
95
111
  name: K,
96
- ): Program<(typeof this.programs)[K]['idl']> {
112
+ ): Program<SolanaProgramIdlMap[K]> {
97
113
  const { idl, address } = this.programs[name];
98
- const idlWithAddr = { ...idl, address };
99
- return new Program(idlWithAddr, this.provider) as Program<
100
- (typeof this.programs)[K]['idl']
101
- >;
114
+ const idlWithAddr = { ...(idl as any), address } as SolanaProgramIdlMap[K];
115
+
116
+ return new Program(idlWithAddr, this.provider) as Program<SolanaProgramIdlMap[K]>;
102
117
  }
103
118
 
104
119
  listProgramNames(): SolanaProgramName[] {
@@ -4,12 +4,14 @@ import {
4
4
  Connection,
5
5
  ConnectionConfig,
6
6
  PerfSample,
7
+ SendTransactionError,
7
8
  PublicKey as SolPubKey,
8
9
  SystemProgram,
9
10
  Transaction,
10
11
  TransactionInstruction,
11
12
  TransactionMessage,
12
13
  TransactionSignature,
14
+ VersionedTransaction,
13
15
  } from '@solana/web3.js';
14
16
  import { AnchorProvider, BN } from '@coral-xyz/anchor';
15
17
  import { BaseSignerWalletAdapter } from '@solana/wallet-adapter-base';
@@ -343,15 +345,16 @@ export class SolanaStakingClient implements IStakingClient {
343
345
  // return sent2;
344
346
  // }
345
347
  // else {
346
- const ix = await this.depositClient.buildDepositTx(amountLamports)
347
- const tx = new Transaction().add(ix);
348
- const prepared = await this.prepareTx(tx);
349
- const signed = await this.signTransaction(prepared.tx);
348
+ const ix = await this.depositClient.buildDepositTx(amountLamports)
349
+ const tx = new Transaction().add(ix);
350
+ const prepared = await this.prepareTx(tx);
351
+ const signed = await this.signTransaction(prepared.tx);
350
352
 
351
- return this.sendAndConfirmHttp(signed, prepared);
353
+ return this.sendAndConfirmHttp(signed, prepared);
352
354
  // }
353
355
  } catch (err) {
354
- throw new Error(`Failed to deposit Solana: ${err}`);
356
+ console.log(`Failed to deposit Solana: ${err}`);
357
+ throw err;
355
358
  }
356
359
  }
357
360
 
@@ -385,7 +388,8 @@ export class SolanaStakingClient implements IStakingClient {
385
388
 
386
389
  return this.sendAndConfirmHttp(signed, prepared);
387
390
  } catch (err) {
388
- throw new Error(`Failed to withdraw Solana: ${err}`);
391
+ console.log(`Failed to withdraw Solana: ${err}`);
392
+ throw err;
389
393
  }
390
394
  }
391
395
 
@@ -415,7 +419,8 @@ export class SolanaStakingClient implements IStakingClient {
415
419
 
416
420
  return this.sendAndConfirmHttp(signed, prepared);
417
421
  } catch (err) {
418
- throw new Error(`Failed to stake Solana: ${err}`);
422
+ console.log(`Failed to stake Solana: ${err}`);
423
+ throw err;
419
424
  }
420
425
  }
421
426
 
@@ -446,7 +451,8 @@ export class SolanaStakingClient implements IStakingClient {
446
451
  return this.sendAndConfirmHttp(signed, prepared);
447
452
  }
448
453
  catch (err) {
449
- throw new Error(`Failed to unstake Solana: ${err}`);
454
+ console.log(`Failed to unstake Solana: ${err}`);
455
+ throw err;
450
456
  }
451
457
  }
452
458
 
@@ -474,7 +480,8 @@ export class SolanaStakingClient implements IStakingClient {
474
480
  return this.sendAndConfirmHttp(signed, prepared);
475
481
  }
476
482
  catch (err) {
477
- throw new Error(`Failed to buy liqSOL pretokens: ${err}`);
483
+ console.log(`Failed to buy liqSOL pretokens: ${err}`);
484
+ throw err;
478
485
  }
479
486
  }
480
487
 
@@ -627,7 +634,8 @@ export class SolanaStakingClient implements IStakingClient {
627
634
  };
628
635
  }
629
636
  catch (err) {
630
- throw new Error(`Failed to get Solana portfolio: ${err}`);
637
+ console.log(`Failed to get Solana portfolio: ${err}`);
638
+ throw err;
631
639
  }
632
640
  }
633
641
 
@@ -689,7 +697,8 @@ export class SolanaStakingClient implements IStakingClient {
689
697
  });
690
698
  }
691
699
  catch (err) {
692
- throw new Error(`Failed to build Solana tranche snapshot: ${err}`);
700
+ console.log(`Failed to build Solana tranche snapshot: ${err}`);
701
+ throw err;
693
702
  }
694
703
  }
695
704
 
@@ -711,7 +720,8 @@ export class SolanaStakingClient implements IStakingClient {
711
720
 
712
721
  return apyPercent;
713
722
  } catch (err) {
714
- throw new Error(`Failed to compute Solana system APY: ${err}`);
723
+ console.log(`Failed to compute Solana system APY: ${err}`);
724
+ throw err;
715
725
  }
716
726
  }
717
727
 
@@ -1024,40 +1034,58 @@ export class SolanaStakingClient implements IStakingClient {
1024
1034
  // ---------------------------------------------------------------------
1025
1035
 
1026
1036
  /**
1027
- * Send a signed transaction over HTTP RPC and wait for confirmation.
1028
- * Throws if the transaction fails.
1037
+ * Send a signed transaction over HTTP RPC.
1038
+ *
1039
+ * - Returns immediately on successful sendRawTransaction.
1040
+ * - If sendRawTransaction throws a SendTransactionError with
1041
+ * "already been processed", we treat it as success and
1042
+ * just return a derived signature.
1043
+ * - No confirmTransaction / polling / blockheight handling.
1029
1044
  */
1030
1045
  private async sendAndConfirmHttp(
1031
1046
  signed: SolanaTransaction,
1032
- ctx: { blockhash: string; lastValidBlockHeight: number },
1047
+ _ctx: { blockhash: string; lastValidBlockHeight: number },
1033
1048
  ): Promise<string> {
1034
1049
  this.ensureUser();
1035
1050
 
1036
- const signature = await this.connection.sendRawTransaction(
1037
- signed.serialize(),
1038
- {
1051
+ const rawTx = signed.serialize();
1052
+
1053
+ try {
1054
+ // Normal happy path: RPC accepts the tx and returns a signature
1055
+ const signature = await this.connection.sendRawTransaction(rawTx, {
1039
1056
  skipPreflight: false,
1040
1057
  preflightCommitment: commitment,
1041
1058
  maxRetries: 3,
1042
- },
1043
- );
1059
+ });
1060
+ return signature;
1061
+ } catch (e: any) {
1062
+ const msg = e?.message ?? '';
1063
+ const isSendTxError =
1064
+ e instanceof SendTransactionError || e?.name === 'SendTransactionError';
1065
+
1066
+ // Benign duplicate case: tx is already in the ledger / cache
1067
+ if (isSendTxError && msg.includes('already been processed')) {
1068
+ console.warn(
1069
+ 'sendRawTransaction reports "already been processed"; ' +
1070
+ 'treating as success without further confirmation.',
1071
+ );
1044
1072
 
1045
- const conf = await this.connection.confirmTransaction(
1046
- {
1047
- signature,
1048
- blockhash: ctx.blockhash,
1049
- lastValidBlockHeight: ctx.lastValidBlockHeight,
1050
- },
1051
- commitment,
1052
- );
1073
+ // Try to derive a signature from the signed Transaction.
1074
+ // If SolanaTransaction is a legacy Transaction, this works.
1075
+ const legacy = signed as unknown as Transaction;
1076
+ const first = legacy.signatures?.[0]?.signature;
1053
1077
 
1054
- if (conf.value.err) {
1055
- throw new Error(
1056
- `Transaction failed: ${JSON.stringify(conf.value.err)}`,
1057
- );
1058
- }
1078
+ if (first) {
1079
+ return bs58.encode(first);
1080
+ }
1081
+
1082
+ // Fallback: return a dummy string
1083
+ return 'already-processed';
1084
+ }
1059
1085
 
1060
- return signature;
1086
+ // Any other send error is a real failure
1087
+ throw e;
1088
+ }
1061
1089
  }
1062
1090
 
1063
1091
  /**