@wireio/stake 1.1.0 → 2.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/lib/stake.browser.js +12958 -6707
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +7612 -639
- package/lib/stake.js +13324 -7073
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +12958 -6707
- package/lib/stake.m.js.map +1 -1
- package/package.json +4 -3
- package/src/assets/solana/{idl → devnet/idl}/liqsol_core.json +15 -3
- package/src/assets/solana/{types → devnet/types}/liqsol_core.ts +15 -3
- package/src/assets/solana/mainnet/idl/liqsol_core.json +6178 -0
- package/src/assets/solana/mainnet/idl/liqsol_token.json +183 -0
- package/src/assets/solana/mainnet/idl/transfer_hook.json +197 -0
- package/src/assets/solana/mainnet/idl/validator_leaderboard.json +574 -0
- package/src/assets/solana/mainnet/types/liqsol_core.ts +6184 -0
- package/src/assets/solana/mainnet/types/liqsol_token.ts +189 -0
- package/src/assets/solana/mainnet/types/transfer_hook.ts +203 -0
- package/src/assets/solana/mainnet/types/validator_leaderboard.ts +580 -0
- package/src/networks/ethereum/clients/convert.client.ts +30 -1
- package/src/networks/ethereum/clients/receipt.client.ts +81 -3
- package/src/networks/ethereum/clients/stake.client.ts +1 -0
- package/src/networks/ethereum/contract.ts +260 -222
- package/src/networks/ethereum/ethereum.ts +35 -30
- package/src/networks/ethereum/types.ts +17 -2
- package/src/networks/solana/clients/deposit.client.ts +294 -68
- package/src/networks/solana/clients/distribution.client.ts +15 -20
- package/src/networks/solana/clients/leaderboard.client.ts +11 -13
- package/src/networks/solana/clients/outpost.client.ts +13 -19
- package/src/networks/solana/clients/token.client.ts +13 -15
- package/src/networks/solana/constants.ts +44 -285
- package/src/networks/solana/program.ts +382 -28
- package/src/networks/solana/solana.ts +315 -92
- package/src/networks/solana/types.ts +4 -4
- package/src/networks/solana/utils.ts +16 -301
- package/src/staker.ts +10 -2
- package/src/types.ts +19 -6
- /package/src/assets/ethereum/{ABI → mainnet}/common/Base58.sol/Base58.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/Base58.sol/Base58.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/OpenZepArtifacts.sol/__Dummy_OZ_UUPS__.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/OpenZepArtifacts.sol/__Dummy_OZ_UUPS__.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/RestrictedCallers.sol/RestrictedCallers.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/RestrictedCallers.sol/RestrictedCallers.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/iodata.sol/iodata.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/iodata.sol/iodata.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/iodata_util.sol/iodata_util.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/iodata_util.sol/iodata_util.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_data.sol/sysio_data.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_data.sol/sysio_data.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_errors.sol/sysio_errors.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_errors.sol/sysio_errors.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_merkle.sol/sysio_merkle.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_merkle.sol/sysio_merkle.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_name.sol/sysio_name.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_name.sol/sysio_name.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_pubkey.sol/sysio_pubkey.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_pubkey.sol/sysio_pubkey.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_read.sol/sysio_read.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_read.sol/sysio_read.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_tester.sol/SysioTester.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_tester.sol/SysioTester.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_verify.sol/sysio_verify.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_verify.sol/sysio_verify.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_write.sol/sysio_write.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/common/sysio_write.sol/sysio_write.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/BeaconState.sol/BeaconState.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/BeaconState.sol/BeaconState.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/DepositManager.sol/DepositManager.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/DepositManager.sol/DepositManager.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthAuthority.sol/LiqEthAuthority.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthAuthority.sol/LiqEthAuthority.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IAccounting.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IAccounting.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IDepositContract.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IDepositContract.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IDepositManager.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IDepositManager.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/ILiqEthUpgradeable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/ILiqEthUpgradeable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IRewardsERC20.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IRewardsERC20.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IRewardsERC20Pausable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IRewardsERC20Pausable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IStakingModule.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IStakingModule.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IValidatorBalanceVerifier.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IValidatorBalanceVerifier.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IWithdrawalRecord.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/IWithdrawalRecord.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/LiqEthCommon.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthCommon.sol/LiqEthCommon.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthManaged.sol/LiqEthManaged.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/LiqEthManaged.sol/LiqEthManaged.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/RewardsERC20.sol/RewardsERC20Upgradeable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/RewardsERC20.sol/RewardsERC20Upgradeable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/RewardsERC20Pausable.sol/RewardsERC20PausableUpgradeable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/RewardsERC20Pausable.sol/RewardsERC20PausableUpgradeable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/Yield.sol/YieldOracle.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/Yield.sol/YieldOracle.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/accounting.sol/Accounting.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/accounting.sol/Accounting.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/liqEth.sol/LiqEthToken.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/liqEth.sol/LiqEthToken.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/stakingModule.sol/StakingModule.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/stakingModule.sol/StakingModule.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalQueue.sol/WithdrawalQueue.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalQueue.sol/WithdrawalQueue.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalVault.sol/Uint64BE.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalVault.sol/Uint64BE.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalVault.sol/WithdrawalVault.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/liqEth/withdrawalVault.sol/WithdrawalVault.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Aggregator.sol/Aggregator.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/BAR.sol/BAR.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/BAR.sol/BAR.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Depositor.sol/Depositor.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Depositor.sol/Depositor.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/EthUsdPriceConsumer.sol/AggregatorV3Interface.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/EthUsdPriceConsumer.sol/AggregatorV3Interface.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/EthUsdPriceConsumer.sol/EthUsdPriceConsumer.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/EthUsdPriceConsumer.sol/EthUsdPriceConsumer.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPP.sol/OPP.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPP.sol/OPP.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPP.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPP.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPEndpoint.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPEndpoint.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPInbound.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPInbound.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPReceiver.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPReceiver.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPSender.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/IOPPSender.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/OPPCommon.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPCommon.sol/OPPCommon.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpoint.sol/OPPEndpoint.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpoint.sol/OPPEndpoint.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpointManaged.sol/OPPEndpointManaged.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpointManaged.sol/OPPEndpointManaged.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpointOwnable.sol/OPPEndpointOwnable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPEndpointOwnable.sol/OPPEndpointOwnable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPErrors.sol/OPPErrors.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPErrors.sol/OPPErrors.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPInbound.sol/OPPInbound.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPInbound.sol/OPPInbound.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPReceiver.sol/OPPReceiver.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPReceiver.sol/OPPReceiver.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPSender.sol/OPPSender.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OPPSender.sol/OPPSender.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostErrors.sol/OutpostErrors.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostErrors.sol/OutpostErrors.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManaged.sol/OutpostManaged.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManaged.sol/OutpostManaged.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManager.sol/OutpostManager.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManager.sol/OutpostManager.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerAuthority.sol/OutpostManagerAuthority.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerAuthority.sol/OutpostManagerAuthority.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/IOutpostManager.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/IOutpostManager.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/IOutpostUpgradeable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/IOutpostUpgradeable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/OutpostManagerCommon.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostManagerCommon.sol/OutpostManagerCommon.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostOwnable.sol/OutpostOwnable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/OutpostOwnable.sol/OutpostOwnable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Pool.sol/Pool.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Pool.sol/Pool.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Pretoken.sol/Pretoken.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/Pretoken.sol/Pretoken.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/ReceiptNFT.sol/ReceiptNFT.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/ReceiptNFT.sol/ReceiptNFT.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/interfaces/IPretoken.sol/IPretoken.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/interfaces/IPretoken.sol/IPretoken.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/interfaces/IWarrant.sol/IWarrant.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/interfaces/IWarrant.sol/IWarrant.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/token/ERC721EthEquivalentVotesUpgradeable.sol/ERC721EthEquivalentVotesUpgradeable.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/token/ERC721EthEquivalentVotesUpgradeable.sol/ERC721EthEquivalentVotesUpgradeable.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/token/IERC721EthEquivalent.sol/IERC721EthEquivalent.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/outpost/token/IERC721EthEquivalent.sol/IERC721EthEquivalent.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC1155Token.sol/ERC1155Token.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC1155Token.sol/ERC1155Token.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC20Token.sol/ERC20Token.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC20Token.sol/ERC20Token.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC721Token.sol/ERC721Token.dbg.json +0 -0
- /package/src/assets/ethereum/{ABI → mainnet}/token/ERC721Token.sol/ERC721Token.json +0 -0
- /package/src/assets/solana/{idl → devnet/idl}/liqsol_token.json +0 -0
- /package/src/assets/solana/{idl → devnet/idl}/transfer_hook.json +0 -0
- /package/src/assets/solana/{idl → devnet/idl}/validator_leaderboard.json +0 -0
- /package/src/assets/solana/{types → devnet/types}/liqsol_token.ts +0 -0
- /package/src/assets/solana/{types → devnet/types}/transfer_hook.ts +0 -0
- /package/src/assets/solana/{types → devnet/types}/validator_leaderboard.ts +0 -0
|
@@ -4,20 +4,28 @@ import {
|
|
|
4
4
|
Connection,
|
|
5
5
|
ConnectionConfig,
|
|
6
6
|
PerfSample,
|
|
7
|
+
SendTransactionError,
|
|
7
8
|
PublicKey as SolPubKey,
|
|
8
9
|
SystemProgram,
|
|
9
10
|
Transaction,
|
|
11
|
+
TransactionInstruction,
|
|
12
|
+
TransactionMessage,
|
|
10
13
|
TransactionSignature,
|
|
14
|
+
VersionedTransaction,
|
|
11
15
|
} from '@solana/web3.js';
|
|
12
16
|
import { AnchorProvider, BN } from '@coral-xyz/anchor';
|
|
13
17
|
import { BaseSignerWalletAdapter } from '@solana/wallet-adapter-base';
|
|
14
18
|
import {
|
|
15
19
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
20
|
+
createAssociatedTokenAccountInstruction,
|
|
16
21
|
getAssociatedTokenAddressSync,
|
|
17
22
|
TOKEN_2022_PROGRAM_ID,
|
|
18
23
|
} from '@solana/spl-token';
|
|
19
24
|
|
|
25
|
+
import * as multisig from "@sqds/multisig";
|
|
26
|
+
|
|
20
27
|
import {
|
|
28
|
+
Base58,
|
|
21
29
|
ChainID,
|
|
22
30
|
ExternalNetwork,
|
|
23
31
|
KeyType,
|
|
@@ -28,6 +36,7 @@ import {
|
|
|
28
36
|
import {
|
|
29
37
|
IStakingClient,
|
|
30
38
|
Portfolio,
|
|
39
|
+
SquadsXConfig,
|
|
31
40
|
StakerConfig,
|
|
32
41
|
TrancheSnapshot,
|
|
33
42
|
} from '../../types';
|
|
@@ -39,10 +48,7 @@ import { OutpostClient } from './clients/outpost.client';
|
|
|
39
48
|
import { TokenClient } from './clients/token.client';
|
|
40
49
|
|
|
41
50
|
import {
|
|
42
|
-
|
|
43
|
-
deriveReservePoolPda,
|
|
44
|
-
deriveStakeMetricsPda,
|
|
45
|
-
deriveVaultPda,
|
|
51
|
+
DEFAULT_AVERAGE_PAY_RATE,
|
|
46
52
|
INDEX_SCALE,
|
|
47
53
|
PAY_RATE_SCALE_FACTOR,
|
|
48
54
|
} from './constants';
|
|
@@ -50,6 +56,7 @@ import {
|
|
|
50
56
|
import { buildSolanaTrancheSnapshot, ceilDiv } from './utils';
|
|
51
57
|
import { GlobalConfig, PayRateEntry, SolanaTransaction } from './types';
|
|
52
58
|
import { SolanaProgramService } from './program';
|
|
59
|
+
import bs58 from 'bs58';
|
|
53
60
|
|
|
54
61
|
const commitment: Commitment = 'confirmed';
|
|
55
62
|
|
|
@@ -78,6 +85,9 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
78
85
|
public tokenClient: TokenClient;
|
|
79
86
|
public program: SolanaProgramService
|
|
80
87
|
|
|
88
|
+
private smartAccount?: SolPubKey; // PDA (off-curve)
|
|
89
|
+
private signer?: SolPubKey; // on-curve signer
|
|
90
|
+
|
|
81
91
|
get solPubKey(): SolPubKey {
|
|
82
92
|
if (!this.pubKey) throw new Error('pubKey is undefined');
|
|
83
93
|
return new SolPubKey(this.pubKey.data.array);
|
|
@@ -87,6 +97,18 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
87
97
|
return this.config.network;
|
|
88
98
|
}
|
|
89
99
|
|
|
100
|
+
get feePayer(): SolPubKey {
|
|
101
|
+
if (this.signer) return this.signer;
|
|
102
|
+
// fallback for normal wallets
|
|
103
|
+
if (this.anchor.wallet.publicKey) return this.anchor.wallet.publicKey;
|
|
104
|
+
throw new Error('No signing authority available');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get squadsX(): SquadsXConfig | null {
|
|
108
|
+
const config = this.config.extras?.squadsX;
|
|
109
|
+
return config ?? null;
|
|
110
|
+
}
|
|
111
|
+
|
|
90
112
|
constructor(private config: StakerConfig) {
|
|
91
113
|
const adapter = config.provider as BaseSignerWalletAdapter | undefined;
|
|
92
114
|
|
|
@@ -185,18 +207,95 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
185
207
|
commitment,
|
|
186
208
|
});
|
|
187
209
|
|
|
188
|
-
this.
|
|
189
|
-
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
192
|
-
this.
|
|
193
|
-
this.
|
|
210
|
+
this.program = new SolanaProgramService(this.anchor, config.network.chainId as SolChainID);
|
|
211
|
+
|
|
212
|
+
this.depositClient = new DepositClient(this.anchor, this.program);
|
|
213
|
+
this.distributionClient = new DistributionClient(this.anchor, this.program);
|
|
214
|
+
this.leaderboardClient = new LeaderboardClient(this.anchor, this.program);
|
|
215
|
+
this.outpostClient = new OutpostClient(this.anchor, this.program);
|
|
216
|
+
this.tokenClient = new TokenClient(this.anchor, this.program);
|
|
194
217
|
}
|
|
195
218
|
|
|
196
219
|
// ---------------------------------------------------------------------
|
|
197
220
|
// IStakingClient core methods
|
|
198
221
|
// ---------------------------------------------------------------------
|
|
199
222
|
|
|
223
|
+
|
|
224
|
+
async createVaultLiqsolAtaOneShot(params: {
|
|
225
|
+
connection: Connection;
|
|
226
|
+
payer: SolPubKey; // user's wallet pubkey (signer)
|
|
227
|
+
vaultPda: SolPubKey; // squads vault PDA (off-curve owner)
|
|
228
|
+
}): Promise<{ tx: Transaction; vaultAta: SolPubKey } | null> {
|
|
229
|
+
const { connection, payer, vaultPda } = params;
|
|
230
|
+
|
|
231
|
+
const liqsolMint = this.program.deriveLiqsolMintPda();
|
|
232
|
+
|
|
233
|
+
const vaultAta = getAssociatedTokenAddressSync(
|
|
234
|
+
liqsolMint,
|
|
235
|
+
vaultPda,
|
|
236
|
+
true, // allowOwnerOffCurve
|
|
237
|
+
TOKEN_2022_PROGRAM_ID,
|
|
238
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// If it already exists, just no-op
|
|
242
|
+
const info = await connection.getAccountInfo(vaultAta, "confirmed");
|
|
243
|
+
|
|
244
|
+
if (info) return null;
|
|
245
|
+
|
|
246
|
+
const ix = createAssociatedTokenAccountInstruction(
|
|
247
|
+
payer, // payer = user
|
|
248
|
+
vaultAta, // ata address
|
|
249
|
+
vaultPda, // owner = vault
|
|
250
|
+
liqsolMint,
|
|
251
|
+
TOKEN_2022_PROGRAM_ID,
|
|
252
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const tx = new Transaction().add(ix);
|
|
256
|
+
return { tx, vaultAta };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private async prepSquadsIxs(ix: TransactionInstruction): Promise<TransactionInstruction[]> {
|
|
260
|
+
if (!this.squadsX) throw new Error('Attempting to wrap Squads instruction without SquadsX config');
|
|
261
|
+
|
|
262
|
+
const multisigPda = this.squadsMultisigPDA!;
|
|
263
|
+
const vaultPda = this.squadsVaultPDA!;
|
|
264
|
+
const vaultIndex = this.squadsX?.vaultIndex ?? 0;
|
|
265
|
+
const creator = this.solPubKey;
|
|
266
|
+
|
|
267
|
+
// compute next transactionIndex
|
|
268
|
+
const ms = await multisig.accounts.Multisig.fromAccountAddress(this.connection, multisigPda);
|
|
269
|
+
const current = BigInt(ms.transactionIndex?.toString() ?? 0);
|
|
270
|
+
const transactionIndex = current + BigInt(1);
|
|
271
|
+
|
|
272
|
+
// inner message uses vault as payer
|
|
273
|
+
// const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 });
|
|
274
|
+
const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
|
|
275
|
+
const transactionMessage = new TransactionMessage({
|
|
276
|
+
payerKey: vaultPda,
|
|
277
|
+
recentBlockhash: blockhash,
|
|
278
|
+
instructions: [ix],
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const createVaultTxIx = await multisig.instructions.vaultTransactionCreate({
|
|
282
|
+
multisigPda,
|
|
283
|
+
transactionIndex,
|
|
284
|
+
creator,
|
|
285
|
+
vaultIndex,
|
|
286
|
+
transactionMessage,
|
|
287
|
+
ephemeralSigners: 0,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const createProposalIx = await multisig.instructions.proposalCreate({
|
|
291
|
+
multisigPda,
|
|
292
|
+
transactionIndex,
|
|
293
|
+
creator,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
return [createVaultTxIx, createProposalIx];
|
|
297
|
+
}
|
|
298
|
+
|
|
200
299
|
/**
|
|
201
300
|
* Deposit native SOL into liqSOL (liqsol_core::deposit).
|
|
202
301
|
* Handles tx build, sign, send, and confirmation.
|
|
@@ -208,20 +307,54 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
208
307
|
}
|
|
209
308
|
|
|
210
309
|
try {
|
|
211
|
-
// Build compute budget increase instruction
|
|
212
310
|
const cuIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 });
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
//
|
|
218
|
-
|
|
311
|
+
// console.log('amountLamports', amountLamports);
|
|
312
|
+
|
|
313
|
+
// if (!!this.squadsX) {
|
|
314
|
+
|
|
315
|
+
// const createVaultTx = await this.createVaultLiqsolAtaOneShot({
|
|
316
|
+
// connection: this.connection,
|
|
317
|
+
// payer: this.solPubKey,
|
|
318
|
+
// vaultPda: this.squadsVaultPDA!,
|
|
319
|
+
// })
|
|
320
|
+
|
|
321
|
+
// if (createVaultTx !== null) {
|
|
322
|
+
// // console.log('need to create vault ata first...');
|
|
323
|
+
// const tx0 = new Transaction().add(createVaultTx.tx);
|
|
324
|
+
// const prepared0 = await this.prepareTx(tx0);
|
|
325
|
+
// const signed0 = await this.signTransaction(prepared0.tx);
|
|
326
|
+
// const sent0 = await this.sendAndConfirmHttp(signed0, prepared0);
|
|
327
|
+
// // console.log('create Vault ATA', sent0);
|
|
328
|
+
// }
|
|
329
|
+
|
|
330
|
+
// const ix = await this.depositClient.buildDepositTx(amountLamports, this.squadsVaultPDA!)
|
|
331
|
+
// const squadIxs = await this.prepSquadsIxs(ix)
|
|
332
|
+
|
|
333
|
+
// const tx1 = new Transaction().add(cuIx, squadIxs[0]);
|
|
334
|
+
// const prepared1 = await this.prepareTx(tx1);
|
|
335
|
+
// const signed1 = await this.signTransaction(prepared1.tx);
|
|
336
|
+
// const sent1 = await this.sendAndConfirmHttp(signed1, prepared1);
|
|
337
|
+
// console.log('SENT 1', sent1);
|
|
338
|
+
|
|
339
|
+
// const tx2 = new Transaction().add(cuIx, squadIxs[1]);
|
|
340
|
+
// const prepared2 = await this.prepareTx(tx2);
|
|
341
|
+
// const signed2 = await this.signTransaction(prepared2.tx);
|
|
342
|
+
// const sent2 = await this.sendAndConfirmHttp(signed2, prepared2);
|
|
343
|
+
// console.log('SENT 2', sent2);
|
|
344
|
+
|
|
345
|
+
// return sent2;
|
|
346
|
+
// }
|
|
347
|
+
// else {
|
|
348
|
+
const ix = await this.depositClient.buildDepositTx(amountLamports)
|
|
349
|
+
const tx = new Transaction().add(ix);
|
|
219
350
|
const prepared = await this.prepareTx(tx);
|
|
220
351
|
const signed = await this.signTransaction(prepared.tx);
|
|
221
352
|
|
|
222
353
|
return this.sendAndConfirmHttp(signed, prepared);
|
|
354
|
+
// }
|
|
223
355
|
} catch (err) {
|
|
224
|
-
|
|
356
|
+
console.log(`Failed to deposit Solana: ${err}`);
|
|
357
|
+
throw err;
|
|
225
358
|
}
|
|
226
359
|
}
|
|
227
360
|
|
|
@@ -255,7 +388,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
255
388
|
|
|
256
389
|
return this.sendAndConfirmHttp(signed, prepared);
|
|
257
390
|
} catch (err) {
|
|
258
|
-
|
|
391
|
+
console.log(`Failed to withdraw Solana: ${err}`);
|
|
392
|
+
throw err;
|
|
259
393
|
}
|
|
260
394
|
}
|
|
261
395
|
|
|
@@ -285,7 +419,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
285
419
|
|
|
286
420
|
return this.sendAndConfirmHttp(signed, prepared);
|
|
287
421
|
} catch (err) {
|
|
288
|
-
|
|
422
|
+
console.log(`Failed to stake Solana: ${err}`);
|
|
423
|
+
throw err;
|
|
289
424
|
}
|
|
290
425
|
}
|
|
291
426
|
|
|
@@ -316,7 +451,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
316
451
|
return this.sendAndConfirmHttp(signed, prepared);
|
|
317
452
|
}
|
|
318
453
|
catch (err) {
|
|
319
|
-
|
|
454
|
+
console.log(`Failed to unstake Solana: ${err}`);
|
|
455
|
+
throw err;
|
|
320
456
|
}
|
|
321
457
|
}
|
|
322
458
|
|
|
@@ -344,7 +480,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
344
480
|
return this.sendAndConfirmHttp(signed, prepared);
|
|
345
481
|
}
|
|
346
482
|
catch (err) {
|
|
347
|
-
|
|
483
|
+
console.log(`Failed to buy liqSOL pretokens: ${err}`);
|
|
484
|
+
throw err;
|
|
348
485
|
}
|
|
349
486
|
}
|
|
350
487
|
|
|
@@ -361,16 +498,16 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
361
498
|
if (!this.pubKey) throw new Error('User pubKey is undefined');
|
|
362
499
|
|
|
363
500
|
try {
|
|
364
|
-
const user = this.solPubKey;
|
|
501
|
+
const user = !!this.squadsX ? this.squadsVaultPDA! : this.solPubKey;
|
|
365
502
|
|
|
366
|
-
const reservePoolPDA = deriveReservePoolPda();
|
|
367
|
-
const vaultPDA = deriveVaultPda();
|
|
368
|
-
const liqsolMint = deriveLiqsolMintPda();
|
|
503
|
+
const reservePoolPDA = this.program.deriveReservePoolPda();
|
|
504
|
+
const vaultPDA = this.program.deriveVaultPda();
|
|
505
|
+
const liqsolMint = this.program.deriveLiqsolMintPda();
|
|
369
506
|
|
|
370
507
|
const userLiqsolAta = getAssociatedTokenAddressSync(
|
|
371
508
|
liqsolMint,
|
|
372
509
|
user,
|
|
373
|
-
|
|
510
|
+
true, //set to true to allow off curve (e.g. PDA for squadsx wallet)
|
|
374
511
|
TOKEN_2022_PROGRAM_ID,
|
|
375
512
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
376
513
|
);
|
|
@@ -497,7 +634,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
497
634
|
};
|
|
498
635
|
}
|
|
499
636
|
catch (err) {
|
|
500
|
-
|
|
637
|
+
console.log(`Failed to get Solana portfolio: ${err}`);
|
|
638
|
+
throw err;
|
|
501
639
|
}
|
|
502
640
|
}
|
|
503
641
|
|
|
@@ -510,6 +648,21 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
510
648
|
return this.distributionClient.getUserRecord(this.solPubKey);
|
|
511
649
|
}
|
|
512
650
|
|
|
651
|
+
// ---------------------------------------------------------------------
|
|
652
|
+
// SquadsX Helpers
|
|
653
|
+
// ---------------------------------------------------------------------
|
|
654
|
+
|
|
655
|
+
get squadsMultisigPDA(): SolPubKey | null {
|
|
656
|
+
if (!this.squadsX) return null;
|
|
657
|
+
return new SolPubKey(this.squadsX.multisigPDA);
|
|
658
|
+
}
|
|
659
|
+
get squadsVaultPDA(): SolPubKey | null {
|
|
660
|
+
if (!this.squadsX || !this.squadsMultisigPDA) return null;
|
|
661
|
+
const multisigPda = this.squadsMultisigPDA;
|
|
662
|
+
const index = this.squadsX.vaultIndex ?? 0;
|
|
663
|
+
const pda = multisig.getVaultPda({ multisigPda, index });
|
|
664
|
+
return pda[0];
|
|
665
|
+
}
|
|
513
666
|
|
|
514
667
|
// ---------------------------------------------------------------------
|
|
515
668
|
// READ-ONLY Public Methods
|
|
@@ -525,18 +678,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
525
678
|
*
|
|
526
679
|
* This is READ-ONLY and works even with no connected wallet.
|
|
527
680
|
*/
|
|
528
|
-
async getTrancheSnapshot(
|
|
529
|
-
chainID?: ChainID;
|
|
530
|
-
windowBefore?: number;
|
|
531
|
-
windowAfter?: number;
|
|
532
|
-
}): Promise<TrancheSnapshot> {
|
|
681
|
+
async getTrancheSnapshot(chainID: ChainID): Promise<TrancheSnapshot> {
|
|
533
682
|
try {
|
|
534
|
-
const {
|
|
535
|
-
chainID = SolChainID.WireTestnet,
|
|
536
|
-
windowBefore,
|
|
537
|
-
windowAfter,
|
|
538
|
-
} = options ?? {};
|
|
539
|
-
|
|
540
683
|
const [globalState, trancheState] = await Promise.all([
|
|
541
684
|
this.tokenClient.fetchGlobalState(),
|
|
542
685
|
this.tokenClient.fetchTrancheState(),
|
|
@@ -551,12 +694,11 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
551
694
|
trancheState,
|
|
552
695
|
solPriceUsd,
|
|
553
696
|
nativePriceTimestamp: timestamp,
|
|
554
|
-
ladderWindowBefore: windowBefore,
|
|
555
|
-
ladderWindowAfter: windowAfter,
|
|
556
697
|
});
|
|
557
698
|
}
|
|
558
699
|
catch (err) {
|
|
559
|
-
|
|
700
|
+
console.log(`Failed to build Solana tranche snapshot: ${err}`);
|
|
701
|
+
throw err;
|
|
560
702
|
}
|
|
561
703
|
}
|
|
562
704
|
|
|
@@ -578,7 +720,8 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
578
720
|
|
|
579
721
|
return apyPercent;
|
|
580
722
|
} catch (err) {
|
|
581
|
-
|
|
723
|
+
console.log(`Failed to compute Solana system APY: ${err}`);
|
|
724
|
+
throw err;
|
|
582
725
|
}
|
|
583
726
|
}
|
|
584
727
|
|
|
@@ -588,24 +731,27 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
588
731
|
* de-scaled using PAY_RATE_SCALE_FACTOR (1e12).
|
|
589
732
|
*/
|
|
590
733
|
private async getEpochRateDecimalFromProgram(): Promise<number> {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const liqSolCoreProgram = this.program.getProgram('liqsolCore');
|
|
594
|
-
const stakeMetricsPda = deriveStakeMetricsPda();
|
|
595
|
-
const stakeMetrics =
|
|
596
|
-
await liqSolCoreProgram.account.stakeMetrics.fetch(stakeMetricsPda);
|
|
734
|
+
const liqSolCoreProgram = this.program.getProgram('liqsolCore');
|
|
735
|
+
const payRateHistoryPda = this.program.derivePayRateHistoryPda();
|
|
597
736
|
|
|
598
|
-
|
|
599
|
-
|
|
737
|
+
const payRateHistory =
|
|
738
|
+
await liqSolCoreProgram.account.payRateHistory.fetch(payRateHistoryPda);
|
|
600
739
|
|
|
601
|
-
|
|
602
|
-
|
|
740
|
+
const totalEntriesAdded = Number(payRateHistory.totalEntriesAdded);
|
|
741
|
+
const maxEntries = Number(payRateHistory.maxEntries);
|
|
603
742
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
throw new Error(`Failed to read stakeMetrics from program: ${err}`);
|
|
743
|
+
if (totalEntriesAdded === 0) {
|
|
744
|
+
// No real entries yet, fall back to default
|
|
745
|
+
return Number(DEFAULT_AVERAGE_PAY_RATE) / Number(PAY_RATE_SCALE_FACTOR);
|
|
608
746
|
}
|
|
747
|
+
|
|
748
|
+
// Latest entry is at (currentIndex - 1 + maxEntries) % maxEntries
|
|
749
|
+
const currentIndex = Number(payRateHistory.currentIndex);
|
|
750
|
+
const latestIdx = (currentIndex - 1 + maxEntries) % maxEntries;
|
|
751
|
+
const latestEntry = payRateHistory.entries[latestIdx];
|
|
752
|
+
|
|
753
|
+
const raw = BigInt(latestEntry.scaledRate.toString());
|
|
754
|
+
return Number(raw) / Number(PAY_RATE_SCALE_FACTOR);
|
|
609
755
|
}
|
|
610
756
|
|
|
611
757
|
// Simple cache so we don’t hammer RPC
|
|
@@ -690,7 +836,7 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
690
836
|
return BigInt(0);
|
|
691
837
|
}
|
|
692
838
|
|
|
693
|
-
const [avgPayRate, globalConfig]: [BN, GlobalConfig] = await Promise.all([
|
|
839
|
+
const [avgPayRate, globalConfig]: [BN, GlobalConfig | null] = await Promise.all([
|
|
694
840
|
this.distributionClient.getAverageScaledPayRate(windowSize),
|
|
695
841
|
this.distributionClient.getGlobalConfig(),
|
|
696
842
|
]);
|
|
@@ -741,14 +887,12 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
741
887
|
}): Promise<bigint> {
|
|
742
888
|
this.ensureUser();
|
|
743
889
|
|
|
744
|
-
const payer = this.solPubKey;
|
|
745
|
-
|
|
746
890
|
// -------------------------------------------------------------
|
|
747
891
|
// 1) Current wallet balance (prefer caller override)
|
|
748
892
|
// -------------------------------------------------------------
|
|
749
893
|
const balanceLamports: bigint =
|
|
750
894
|
options?.balanceOverrideLamports ??
|
|
751
|
-
BigInt(await this.connection.getBalance(
|
|
895
|
+
BigInt(await this.connection.getBalance(this.feePayer, commitment));
|
|
752
896
|
|
|
753
897
|
if (balanceLamports <= BigInt(0)) {
|
|
754
898
|
return BigInt(0);
|
|
@@ -859,7 +1003,7 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
859
1003
|
return this.cachedTxFee.value;
|
|
860
1004
|
}
|
|
861
1005
|
|
|
862
|
-
const payer = this.
|
|
1006
|
+
const payer = this.feePayer;
|
|
863
1007
|
|
|
864
1008
|
const dummyIx = SystemProgram.transfer({
|
|
865
1009
|
fromPubkey: payer,
|
|
@@ -892,38 +1036,107 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
892
1036
|
/**
|
|
893
1037
|
* Send a signed transaction over HTTP RPC and wait for confirmation.
|
|
894
1038
|
* Throws if the transaction fails.
|
|
1039
|
+
*
|
|
1040
|
+
* - Handles benign "already processed" preflight errors.
|
|
1041
|
+
* - Uses getSignatureStatuses() instead of confirmTransaction()
|
|
1042
|
+
* so we don't care about blockheight expiry.
|
|
895
1043
|
*/
|
|
896
1044
|
private async sendAndConfirmHttp(
|
|
897
1045
|
signed: SolanaTransaction,
|
|
898
|
-
|
|
1046
|
+
_ctx: { blockhash: string; lastValidBlockHeight: number },
|
|
899
1047
|
): Promise<string> {
|
|
900
1048
|
this.ensureUser();
|
|
901
1049
|
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
1050
|
+
const rawTx = signed.serialize();
|
|
1051
|
+
let signature: string;
|
|
1052
|
+
|
|
1053
|
+
// -------------------------------------------------------------
|
|
1054
|
+
// 1) Send the raw transaction
|
|
1055
|
+
// Handle "already been processed" as a soft success.
|
|
1056
|
+
// -------------------------------------------------------------
|
|
1057
|
+
try {
|
|
1058
|
+
signature = await this.connection.sendRawTransaction(rawTx, {
|
|
905
1059
|
skipPreflight: false,
|
|
906
1060
|
preflightCommitment: commitment,
|
|
907
1061
|
maxRetries: 3,
|
|
908
|
-
}
|
|
909
|
-
)
|
|
1062
|
+
});
|
|
1063
|
+
} catch (e: any) {
|
|
1064
|
+
const msg = e?.message ?? '';
|
|
1065
|
+
|
|
1066
|
+
const isSendTxError =
|
|
1067
|
+
e instanceof SendTransactionError || e?.name === 'SendTransactionError';
|
|
1068
|
+
|
|
1069
|
+
if (isSendTxError && msg.includes('already been processed')) {
|
|
1070
|
+
// Preflight is telling us this exact txid already landed.
|
|
1071
|
+
// Derive the signature from the signed tx and continue to confirmation.
|
|
1072
|
+
console.warn(
|
|
1073
|
+
'sendRawTransaction preflight says "already been processed"; ' +
|
|
1074
|
+
'treating as success and deriving signature from signed tx.',
|
|
1075
|
+
);
|
|
910
1076
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
signature
|
|
914
|
-
blockhash: ctx.blockhash,
|
|
915
|
-
lastValidBlockHeight: ctx.lastValidBlockHeight,
|
|
916
|
-
},
|
|
917
|
-
commitment,
|
|
918
|
-
);
|
|
1077
|
+
// Assuming SolanaTransaction is a legacy Transaction here.
|
|
1078
|
+
const legacy = signed as unknown as Transaction;
|
|
1079
|
+
const first = legacy.signatures?.[0]?.signature;
|
|
919
1080
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1081
|
+
if (!first) {
|
|
1082
|
+
// No way to recover the txid → rethrow
|
|
1083
|
+
throw e;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
signature = bs58.encode(first);
|
|
1087
|
+
} else {
|
|
1088
|
+
// Any other send error is a real failure
|
|
1089
|
+
throw e;
|
|
1090
|
+
}
|
|
924
1091
|
}
|
|
925
1092
|
|
|
926
|
-
|
|
1093
|
+
// -------------------------------------------------------------
|
|
1094
|
+
// 2) Poll getSignatureStatuses until confirmed/finalized or timeout
|
|
1095
|
+
// -------------------------------------------------------------
|
|
1096
|
+
const start = Date.now();
|
|
1097
|
+
const timeoutMs = 30_000; // tune this if you want longer for devnet
|
|
1098
|
+
const pollIntervalMs = 500; // 0.5s between polls
|
|
1099
|
+
|
|
1100
|
+
// eslint-disable-next-line no-constant-condition
|
|
1101
|
+
while (true) {
|
|
1102
|
+
const { value } = await this.connection.getSignatureStatuses(
|
|
1103
|
+
[signature],
|
|
1104
|
+
{ searchTransactionHistory: true },
|
|
1105
|
+
);
|
|
1106
|
+
const status = value[0];
|
|
1107
|
+
|
|
1108
|
+
if (status) {
|
|
1109
|
+
if (status.err) {
|
|
1110
|
+
// On-chain error (instruction error, etc.)
|
|
1111
|
+
throw new Error(
|
|
1112
|
+
`Transaction failed: ${JSON.stringify(status.err)}`,
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
const confirmations = status.confirmations;
|
|
1117
|
+
const confirmationStatus = status.confirmationStatus;
|
|
1118
|
+
|
|
1119
|
+
const satisfied =
|
|
1120
|
+
confirmationStatus === 'confirmed' ||
|
|
1121
|
+
confirmationStatus === 'finalized' ||
|
|
1122
|
+
confirmations === null || // rooted
|
|
1123
|
+
(confirmations ?? 0) > 0; // at least 1 confirmation
|
|
1124
|
+
|
|
1125
|
+
if (satisfied) {
|
|
1126
|
+
// We consider this successfully confirmed
|
|
1127
|
+
return signature;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Timeout guard so we don't spin forever on a tx that never lands
|
|
1132
|
+
if (Date.now() - start > timeoutMs) {
|
|
1133
|
+
throw new Error(
|
|
1134
|
+
`Transaction confirmation timed out for ${signature}`,
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
1139
|
+
}
|
|
927
1140
|
}
|
|
928
1141
|
|
|
929
1142
|
/**
|
|
@@ -961,7 +1174,7 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
961
1174
|
const { blockhash, lastValidBlockHeight } =
|
|
962
1175
|
await this.connection.getLatestBlockhash('confirmed');
|
|
963
1176
|
tx.recentBlockhash = blockhash;
|
|
964
|
-
tx.feePayer = this.
|
|
1177
|
+
tx.feePayer = this.feePayer;
|
|
965
1178
|
return { tx, blockhash, lastValidBlockHeight };
|
|
966
1179
|
}
|
|
967
1180
|
|
|
@@ -970,17 +1183,27 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
970
1183
|
* Ensures we have a Wire pubKey and an Anchor wallet pubKey, and that they match.
|
|
971
1184
|
*/
|
|
972
1185
|
ensureUser() {
|
|
973
|
-
if (!this.pubKey
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
) {
|
|
980
|
-
throw new Error(
|
|
981
|
-
'Write access requires connected wallet to match pubKey',
|
|
982
|
-
);
|
|
1186
|
+
if (!this.pubKey) throw new Error('User pubKey is undefined');
|
|
1187
|
+
|
|
1188
|
+
const wallet = this.anchor?.wallet as any;
|
|
1189
|
+
const pk = wallet?.publicKey as SolPubKey | undefined;
|
|
1190
|
+
|
|
1191
|
+
if (!pk) throw new Error('Wallet not connected');
|
|
1192
|
+
if (typeof wallet.signTransaction !== 'function') {
|
|
1193
|
+
throw new Error('Wallet does not support signTransaction');
|
|
983
1194
|
}
|
|
1195
|
+
|
|
1196
|
+
// if (!this.pubKey || !this.anchor.wallet.publicKey) {
|
|
1197
|
+
// throw new Error('User Authorization required: pubKey is undefined');
|
|
1198
|
+
// }
|
|
1199
|
+
// if (
|
|
1200
|
+
// this.solPubKey.toBase58() !==
|
|
1201
|
+
// this.anchor.wallet.publicKey.toBase58()
|
|
1202
|
+
// ) {
|
|
1203
|
+
// throw new Error(
|
|
1204
|
+
// 'Write access requires connected wallet to match pubKey',
|
|
1205
|
+
// );
|
|
1206
|
+
// }
|
|
984
1207
|
}
|
|
985
1208
|
|
|
986
1209
|
}
|
|
@@ -262,7 +262,7 @@ export type GlobalState = {
|
|
|
262
262
|
roleWarmupDuration: BN;
|
|
263
263
|
|
|
264
264
|
/** Wire lifecycle state (preLaunch / postLaunch / refund) */
|
|
265
|
-
wireState: WireState;
|
|
265
|
+
wireState: WireState | any;
|
|
266
266
|
|
|
267
267
|
/** PDA bump */
|
|
268
268
|
bump: number;
|
|
@@ -615,7 +615,7 @@ export type LeaderboardState = {
|
|
|
615
615
|
* Per-validator scores (i64 on-chain).
|
|
616
616
|
* Index corresponds to `registryIndex` in ValidatorRecord.
|
|
617
617
|
*/
|
|
618
|
-
scores:
|
|
618
|
+
scores: number[];
|
|
619
619
|
|
|
620
620
|
/**
|
|
621
621
|
* Sorted indices into `scores[]` / `voteAccounts[]`,
|
|
@@ -628,7 +628,7 @@ export type LeaderboardState = {
|
|
|
628
628
|
* `voteAccounts[i]` is the vote account for validator with
|
|
629
629
|
* `registryIndex == i`.
|
|
630
630
|
*/
|
|
631
|
-
voteAccounts:
|
|
631
|
+
voteAccounts: { bytes: number[]; }[];
|
|
632
632
|
|
|
633
633
|
/**
|
|
634
634
|
* Number of active validators currently tracked in the leaderboard.
|
|
@@ -643,7 +643,7 @@ export type LeaderboardState = {
|
|
|
643
643
|
* Reserved padding / future-proofing on-chain (u64[8]).
|
|
644
644
|
* Not used by client logic, but surfaced for completeness.
|
|
645
645
|
*/
|
|
646
|
-
padding:
|
|
646
|
+
padding: number[];
|
|
647
647
|
};
|
|
648
648
|
|
|
649
649
|
/**
|