@wireio/stake 0.1.0 → 0.1.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/README.md +57 -0
- package/lib/stake.browser.js +11836 -4103
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +374 -556
- package/lib/stake.js +12089 -4303
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +11836 -4103
- package/lib/stake.m.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/ethereum/ABI/liqEth/DepositManager.sol/DepositManager.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/DepositManager.sol/DepositManager.json +1153 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IAccounting.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IAccounting.json +172 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IDepositContract.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IDepositContract.json +39 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IDepositManager.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IDepositManager.json +64 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/ILiqEthBurn.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/ILiqEthBurn.json +24 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/ILiqEthMint.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/ILiqEthMint.json +35 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IRewardsERC20.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IRewardsERC20.json +213 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IStakingModule.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IStakingModule.json +138 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IValidatorBalanceVerifier.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IValidatorBalanceVerifier.json +70 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IWithdrawalRecord.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/IWithdrawalRecord.json +64 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/LiqEthCommon.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/LiqEthCommon.sol/LiqEthCommon.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/RewardsERC20.sol/RewardsERC20.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/RewardsERC20.sol/RewardsERC20.json +749 -0
- package/src/assets/ethereum/ABI/liqEth/RewardsERC20Pausable.sol/RewardsERC20Pausable.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/RewardsERC20Pausable.sol/RewardsERC20Pausable.json +812 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/BeaconRoots.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/BeaconRoots.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/SSZ.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/SSZ.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/ValidatorBalanceVerifier.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/ValidatorBalanceVerifier.json +225 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/BeaconRoots.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/BeaconRoots.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/SSZ.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/SSZ.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/YieldOracle.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/Yield.sol/YieldOracle.json +813 -0
- package/src/assets/ethereum/ABI/liqEth/accounting.sol/Accounting.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/accounting.sol/Accounting.json +651 -0
- package/src/assets/ethereum/ABI/liqEth/liqEth.sol/LiqEthToken.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/liqEth.sol/LiqEthToken.json +1110 -0
- package/src/assets/ethereum/ABI/liqEth/liqEthBurn.sol/LiqEthBurn.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/liqEthBurn.sol/LiqEthBurn.json +391 -0
- package/src/assets/ethereum/ABI/liqEth/liqEthMint.sol/LiqEthMint.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/liqEthMint.sol/LiqEthMint.json +402 -0
- package/src/assets/ethereum/ABI/liqEth/stakingModule.sol/StakingModule.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/stakingModule.sol/StakingModule.json +1225 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalQueue.sol/WithdrawalQueue.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalQueue.sol/WithdrawalQueue.json +927 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalVault.sol/Uint64BE.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalVault.sol/Uint64BE.json +10 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalVault.sol/WithdrawalVault.dbg.json +4 -0
- package/src/assets/ethereum/ABI/liqEth/withdrawalVault.sol/WithdrawalVault.json +447 -0
- package/src/assets/solana/idl/liqsol_core.json +4239 -0
- package/src/assets/solana/idl/liqsol_token.json +183 -0
- package/src/assets/solana/idl/validator_leaderboard.json +270 -265
- package/src/assets/solana/types/liqsol_core.ts +4245 -0
- package/src/assets/solana/types/liqsol_token.ts +189 -0
- package/src/assets/solana/types/validator_leaderboard.ts +270 -265
- package/src/index.ts +1 -3
- package/src/networks/ethereum/contract.ts +101 -36
- package/src/networks/ethereum/ethereum.ts +141 -45
- package/src/networks/ethereum/types.ts +30 -2
- package/src/networks/solana/clients/deposit.client.ts +71 -109
- package/src/networks/solana/clients/distribution.client.ts +256 -383
- package/src/networks/solana/clients/leaderboard.client.ts +38 -133
- package/src/networks/solana/constants.ts +214 -130
- package/src/networks/solana/program.ts +25 -38
- package/src/networks/solana/solana.ts +120 -105
- package/src/networks/solana/types.ts +37 -47
- package/src/networks/solana/utils.ts +551 -0
- package/src/scripts/tsconfig.json +17 -0
- package/src/staker/staker.ts +10 -6
- package/src/staker/types.ts +14 -9
- package/src/assets/solana/idl/deposit.json +0 -296
- package/src/assets/solana/idl/distribution.json +0 -768
- package/src/assets/solana/idl/liq_sol_token.json +0 -298
- package/src/assets/solana/idl/mint_helper.json +0 -110
- package/src/assets/solana/idl/read_tracked_balance.json +0 -140
- package/src/assets/solana/idl/stake_controller.json +0 -2149
- package/src/assets/solana/idl/treasury.json +0 -110
- package/src/assets/solana/idl/validator_registry.json +0 -487
- package/src/assets/solana/idl/yield_oracle.json +0 -32
- package/src/assets/solana/types/deposit.ts +0 -302
- package/src/assets/solana/types/distribution.ts +0 -774
- package/src/assets/solana/types/liq_sol_token.ts +0 -304
- package/src/assets/solana/types/mint_helper.ts +0 -116
- package/src/assets/solana/types/read_tracked_balance.ts +0 -146
- package/src/assets/solana/types/stake_controller.ts +0 -2155
- package/src/assets/solana/types/stake_registry.ts +0 -441
- package/src/assets/solana/types/treasury.ts +0 -116
- package/src/assets/solana/types/validator_registry.ts +0 -493
- package/src/assets/solana/types/yield_oracle.ts +0 -38
- package/src/common/utils.ts +0 -9
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module EthereumContractService
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Provides a unified service for interacting with Ethereum smart contracts using ethers.js.
|
|
5
|
-
*
|
|
6
|
-
* This module includes:
|
|
7
|
-
* - ABI imports for ERC20, ERC721, and ERC1155 token standards.
|
|
8
|
-
* - Address book and contract configuration types.
|
|
9
|
-
* - A service class for managing contract instances, interfaces, and utility methods for read/write access.
|
|
10
|
-
* - Utility for decoding custom errors and events using a combined interface of all known ABIs.
|
|
11
|
-
*
|
|
12
|
-
* @remarks
|
|
13
|
-
* - Update the `ADDRESSES` and `CONTRACTS` objects to match your deployment.
|
|
14
|
-
* - The service supports both read-only and write-enabled contract handles, depending on the presence of a signer.
|
|
15
|
-
* - The `omniInterface` property allows decoding of errors and events across all included ABIs.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* const service = new EthereumContractService({ provider, signer });
|
|
20
|
-
* const stakeContract = service.getContract('Stake');
|
|
21
|
-
* const address = service.getAddress('Stake');
|
|
22
|
-
* ```
|
|
23
5
|
*/
|
|
6
|
+
import AccountingArtifact from '../../assets/ethereum/ABI/liqEth/accounting.sol/Accounting.json';
|
|
7
|
+
import DepositManagerArtifact from '../../assets/ethereum/ABI/liqEth/DepositManager.sol/DepositManager.json';
|
|
8
|
+
import LiqEthArtifact from '../../assets/ethereum/ABI/liqEth/liqEth.sol/LiqEthToken.json';
|
|
9
|
+
import LiqEthBurnArtifact from '../../assets/ethereum/ABI/liqEth/liqEthBurn.sol/LiqEthBurn.json';
|
|
10
|
+
// import LiqEthCommonArtifact from '../../assets/ethereum/ABI/liqEth/liqEthCommon.sol/liqEthCommon.json';
|
|
11
|
+
import LiqEthMintArtifact from '../../assets/ethereum/ABI/liqEth/liqEthMint.sol/LiqEthMint.json';
|
|
12
|
+
// import RewardsERC20Artifact from '../../assets/ethereum/ABI/liqEth/RewardsERC20.sol/RewardsERC20.json';
|
|
13
|
+
import StakingModuleArtifact from '../../assets/ethereum/ABI/liqEth/stakingModule.sol/StakingModule.json';
|
|
14
|
+
// import ValidatorBalanceArtifact from '../../assets/ethereum/ABI/liqEth/ValidatorBalanceVerifier.sol/ValidatorBalanceVerifier.json';
|
|
15
|
+
import WithdrawalQueueArtifact from '../../assets/ethereum/ABI/liqEth/withdrawalQueue.sol/WithdrawalQueue.json';
|
|
16
|
+
import WithdrawalVaultArtifact from '../../assets/ethereum/ABI/liqEth/withdrawalVault.sol/WithdrawalVault.json';
|
|
17
|
+
// import YieldArtifact from '../../assets/ethereum/ABI/liqEth/Yield.sol/YieldOracle.json';
|
|
24
18
|
|
|
25
19
|
import ERC20Artifact from '../../assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.json';
|
|
26
20
|
import ERC721Artifact from '../../assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.json';
|
|
27
21
|
import ERC1155Artifact from '../../assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.json';
|
|
22
|
+
|
|
28
23
|
import { AddressBook, ContractName } from './types';
|
|
29
24
|
import { Contract, ethers, providers, Signer } from 'ethers';
|
|
30
25
|
import { JsonFragment } from '@ethersproject/abi';
|
|
@@ -34,9 +29,20 @@ export const ERC20Abi = ERC20Artifact.abi;
|
|
|
34
29
|
export const ERC721Abi = ERC721Artifact.abi;
|
|
35
30
|
export const ERC1155Abi = ERC1155Artifact.abi;
|
|
36
31
|
|
|
37
|
-
//
|
|
32
|
+
// -----------------------------------------------------------------------------
|
|
33
|
+
// Address book
|
|
34
|
+
// -----------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
// Make sure ContractName in ./types includes all of these keys.
|
|
38
37
|
export const ADDRESSES: AddressBook = {
|
|
39
|
-
|
|
38
|
+
Accounting: "0xd51CC479c25dc7Cd23f568Ef5c1AdE1671a4D15b",
|
|
39
|
+
DepositManager: "0x2249D309f086363ABF5057Ae7f8057279162786B",
|
|
40
|
+
LiqEth: "0xd5bd3DC2fD86e917A46f7571708aBB88CbfCc197",
|
|
41
|
+
LiqEthMint: "0xdBAa1539eB7b80C29d825FCda76c0d7F8F0E6cFB",
|
|
42
|
+
LiqEthBurn: "0x02e0A02fE2311FAd661677B7117FDdc801c1216b",
|
|
43
|
+
StakingModule: "0x87047291c3b0D55A551C97B9194A02E1D84e06A9",
|
|
44
|
+
WithdrawalQueue: "0x7781368720294fE0bB6D97F14fE2E9275fFED071",
|
|
45
|
+
WithdrawalVault: "0x24457626938d4132556005ecA4d9e6F24F85297E",
|
|
40
46
|
};
|
|
41
47
|
|
|
42
48
|
export type Contracts<T extends string = ContractName> = Record<T, ContractConfig>;
|
|
@@ -44,12 +50,58 @@ export type Contracts<T extends string = ContractName> = Record<T, ContractConfi
|
|
|
44
50
|
export type ContractConfig = {
|
|
45
51
|
address: string;
|
|
46
52
|
abi: JsonFragment[];
|
|
47
|
-
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// -----------------------------------------------------------------------------
|
|
56
|
+
// Contract config
|
|
57
|
+
// -----------------------------------------------------------------------------
|
|
48
58
|
|
|
49
59
|
export const CONTRACTS: Contracts<ContractName> = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
Accounting: {
|
|
61
|
+
address: ADDRESSES.Accounting,
|
|
62
|
+
abi: AccountingArtifact.abi as JsonFragment[],
|
|
63
|
+
},
|
|
64
|
+
LiqEth: {
|
|
65
|
+
address: ADDRESSES.LiqEth,
|
|
66
|
+
abi: LiqEthArtifact.abi as JsonFragment[],
|
|
67
|
+
},
|
|
68
|
+
DepositManager: {
|
|
69
|
+
address: ADDRESSES.DepositManager,
|
|
70
|
+
abi: DepositManagerArtifact.abi as JsonFragment[],
|
|
71
|
+
},
|
|
72
|
+
LiqEthMint: {
|
|
73
|
+
address: ADDRESSES.LiqEthMint,
|
|
74
|
+
abi: LiqEthMintArtifact.abi as JsonFragment[],
|
|
75
|
+
},
|
|
76
|
+
LiqEthBurn: {
|
|
77
|
+
address: ADDRESSES.LiqEthBurn,
|
|
78
|
+
abi: LiqEthBurnArtifact.abi as JsonFragment[],
|
|
79
|
+
},
|
|
80
|
+
// RewardsERC20: {
|
|
81
|
+
// address: ADDRESSES.RewardsERC20,
|
|
82
|
+
// abi: RewardsERC20Artifact.abi as JsonFragment[],
|
|
83
|
+
// },
|
|
84
|
+
StakingModule: {
|
|
85
|
+
address: ADDRESSES.StakingModule,
|
|
86
|
+
abi: StakingModuleArtifact.abi as JsonFragment[],
|
|
87
|
+
},
|
|
88
|
+
// ValidatorBalance: {
|
|
89
|
+
// address: ADDRESSES.ValidatorBalance,
|
|
90
|
+
// abi: ValidatorBalanceArtifact.abi as JsonFragment[],
|
|
91
|
+
// },
|
|
92
|
+
WithdrawalQueue: {
|
|
93
|
+
address: ADDRESSES.WithdrawalQueue,
|
|
94
|
+
abi: WithdrawalQueueArtifact.abi as JsonFragment[],
|
|
95
|
+
},
|
|
96
|
+
WithdrawalVault: {
|
|
97
|
+
address: ADDRESSES.WithdrawalVault,
|
|
98
|
+
abi: WithdrawalVaultArtifact.abi as JsonFragment[],
|
|
99
|
+
},
|
|
100
|
+
// Yield: {
|
|
101
|
+
// address: ADDRESSES.Yield,
|
|
102
|
+
// abi: YieldArtifact.abi as JsonFragment[],
|
|
103
|
+
// },
|
|
104
|
+
};
|
|
53
105
|
|
|
54
106
|
export interface ContractOptions {
|
|
55
107
|
/** RPC endpoint or injected EIP-1193 provider */
|
|
@@ -58,7 +110,6 @@ export interface ContractOptions {
|
|
|
58
110
|
signer?: Signer;
|
|
59
111
|
}
|
|
60
112
|
|
|
61
|
-
|
|
62
113
|
export class EthereumContractService {
|
|
63
114
|
private provider?: providers.Provider;
|
|
64
115
|
private signer?: Signer;
|
|
@@ -73,7 +124,11 @@ export class EthereumContractService {
|
|
|
73
124
|
(Object.keys(CONTRACTS) as ContractName[]).forEach((name) => {
|
|
74
125
|
const { address, abi } = CONTRACTS[name];
|
|
75
126
|
this.iface[name] = new ethers.utils.Interface(abi);
|
|
76
|
-
this.contract[name] = new ethers.Contract(
|
|
127
|
+
this.contract[name] = new ethers.Contract(
|
|
128
|
+
address,
|
|
129
|
+
abi,
|
|
130
|
+
this.signer ?? this.provider
|
|
131
|
+
);
|
|
77
132
|
});
|
|
78
133
|
}
|
|
79
134
|
|
|
@@ -83,13 +138,13 @@ export class EthereumContractService {
|
|
|
83
138
|
}
|
|
84
139
|
|
|
85
140
|
/** Utility: get a read-only handle even if signer is present */
|
|
86
|
-
getReadOnly(name: ContractName): Contract {
|
|
141
|
+
public getReadOnly(name: ContractName): Contract {
|
|
87
142
|
const { address, abi } = CONTRACTS[name];
|
|
88
143
|
return new Contract(address, abi, this.provider);
|
|
89
144
|
}
|
|
90
145
|
|
|
91
146
|
/** Utility: get a write-enabled handle (throws if no signer) */
|
|
92
|
-
getWrite(name: ContractName): Contract {
|
|
147
|
+
public getWrite(name: ContractName): Contract {
|
|
93
148
|
if (!this.signer) throw new Error('No signer available for write calls');
|
|
94
149
|
const { address, abi } = CONTRACTS[name];
|
|
95
150
|
return new Contract(address, abi, this.signer);
|
|
@@ -119,27 +174,35 @@ export class EthereumContractService {
|
|
|
119
174
|
return ctr;
|
|
120
175
|
}
|
|
121
176
|
|
|
122
|
-
/** A unified Interface containing all ABIs
|
|
123
|
-
* to parse custom errors or events. */
|
|
177
|
+
/** A unified Interface containing all ABIs to parse custom errors or events. */
|
|
124
178
|
public get omniInterface(): ethers.utils.Interface {
|
|
125
179
|
const all: any[] = [];
|
|
126
180
|
|
|
127
|
-
// Add all artifacts to the interface
|
|
128
181
|
const allArtifacts = [
|
|
129
182
|
ERC20Artifact,
|
|
130
183
|
ERC721Artifact,
|
|
131
184
|
ERC1155Artifact,
|
|
132
|
-
|
|
185
|
+
|
|
186
|
+
// liqETH suite
|
|
187
|
+
AccountingArtifact,
|
|
188
|
+
DepositManagerArtifact,
|
|
189
|
+
LiqEthArtifact,
|
|
190
|
+
LiqEthBurnArtifact,
|
|
191
|
+
LiqEthMintArtifact,
|
|
192
|
+
// RewardsERC20Artifact,
|
|
193
|
+
StakingModuleArtifact,
|
|
194
|
+
// ValidatorBalanceArtifact,
|
|
195
|
+
WithdrawalQueueArtifact,
|
|
196
|
+
WithdrawalVaultArtifact,
|
|
197
|
+
// YieldArtifact,
|
|
133
198
|
];
|
|
134
199
|
|
|
135
|
-
// Add all ABIs to the omnibus interface
|
|
136
200
|
allArtifacts.forEach(artifact => {
|
|
137
201
|
if (artifact && artifact.abi) {
|
|
138
202
|
all.push(...artifact.abi);
|
|
139
203
|
}
|
|
140
204
|
});
|
|
141
205
|
|
|
142
|
-
// dedupe
|
|
143
206
|
const seen = new Set<string>();
|
|
144
207
|
const dedup: any[] = [];
|
|
145
208
|
for (const item of all) {
|
|
@@ -150,7 +213,9 @@ export class EthereumContractService {
|
|
|
150
213
|
seen.add(key);
|
|
151
214
|
dedup.push(item);
|
|
152
215
|
}
|
|
153
|
-
} catch {
|
|
216
|
+
} catch {
|
|
217
|
+
// ignore bad fragments
|
|
218
|
+
}
|
|
154
219
|
}
|
|
155
220
|
|
|
156
221
|
return new ethers.utils.Interface(dedup);
|
|
@@ -1,64 +1,160 @@
|
|
|
1
1
|
// src/networks/ethereum/ethereum.ts
|
|
2
2
|
|
|
3
|
-
import { ethers } from 'ethers';
|
|
4
|
-
import { IStakingClient, StakerConfig } from '../../staker/types';
|
|
3
|
+
import { BigNumber, BigNumberish, ethers } from 'ethers';
|
|
4
|
+
import { IStakingClient, Portfolio, StakerConfig } from '../../staker/types';
|
|
5
5
|
import { PublicKey as WirePubKey } from '@wireio/core';
|
|
6
|
-
import { ERC20Abi } from './contract'; // TODO replace with staking contract ABI
|
|
7
|
-
|
|
8
|
-
// — replace with your actual staking contract ABI & address —
|
|
9
|
-
const STAKING_CONTRACT_ADDRESS = '0xYourStakingContractAddress';
|
|
6
|
+
import { ERC20Abi, EthereumContractService } from './contract'; // TODO replace with staking contract ABI
|
|
7
|
+
import { DepositEvent, DepositResult } from './types';
|
|
10
8
|
|
|
11
9
|
// TODO extend to implement ISTAKINGCLIENT
|
|
12
|
-
export class EthereumStakingClient {
|
|
10
|
+
export class EthereumStakingClient implements IStakingClient {
|
|
13
11
|
public readonly pubKey: WirePubKey;
|
|
14
12
|
private readonly provider: ethers.providers.Web3Provider;
|
|
15
13
|
private readonly signer: ethers.Signer;
|
|
16
|
-
private readonly
|
|
14
|
+
private readonly contractService: EthereumContractService;
|
|
15
|
+
|
|
16
|
+
get contract() { return this.contractService.contract; }
|
|
17
|
+
get network() { return this.config.network; }
|
|
17
18
|
|
|
18
19
|
constructor(private config: StakerConfig) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
this.signer
|
|
34
|
-
);
|
|
20
|
+
try {
|
|
21
|
+
this.provider = config.provider as ethers.providers.Web3Provider;
|
|
22
|
+
this.signer = this.provider.getSigner();
|
|
23
|
+
this.pubKey = config.pubKey as WirePubKey;
|
|
24
|
+
|
|
25
|
+
this.contractService = new EthereumContractService({
|
|
26
|
+
provider: this.provider,
|
|
27
|
+
signer: this.signer,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
// console.error('Error initializing EthereumStakingClient:', error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
// ---------------------------------------------------------------------
|
|
37
|
+
// Public IStakingClient.deposit
|
|
38
|
+
// ---------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Deposit native ETH into the liqETH protocol via DepositManager.
|
|
42
|
+
* @param amount Amount in wei (or something convertible to BigNumber).
|
|
43
|
+
* Keep this as a bigint / string in the caller; avoid JS floats.
|
|
44
|
+
* @returns transaction hash
|
|
45
|
+
*/
|
|
46
|
+
async deposit(amount: number | string | bigint | BigNumber): Promise<string> {
|
|
47
|
+
const amountWei = BigNumber.isBigNumber(amount)
|
|
48
|
+
? amount
|
|
49
|
+
: BigNumber.from(amount);
|
|
50
|
+
|
|
51
|
+
const result = await this.performDeposit(amountWei);
|
|
52
|
+
// For now, IStakingClient contract is: just return tx hash.
|
|
53
|
+
// If/when you extend the interface, you can surface more here.
|
|
54
|
+
return result.txHash;
|
|
51
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Simulate a deposit via callStatic.
|
|
58
|
+
*
|
|
59
|
+
* Useful for pre-flight checks; will throw with the same revert
|
|
60
|
+
* reason as a real tx if it would fail.
|
|
61
|
+
*/
|
|
62
|
+
async simulateDeposit(amount: number | string | bigint | BigNumber): Promise<void> {
|
|
63
|
+
const amountWei = BigNumber.isBigNumber(amount)
|
|
64
|
+
? amount
|
|
65
|
+
: BigNumber.from(amount);
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
data: this.contract.interface.encodeFunctionData('deposit', [
|
|
58
|
-
ethers.BigNumber.from(amount)
|
|
59
|
-
]),
|
|
67
|
+
// callStatic executes the function locally without sending a tx.
|
|
68
|
+
// deposit() doesn't return anything, so we only care if it reverts.
|
|
69
|
+
await this.contract.DepositManager.callStatic.deposit({
|
|
70
|
+
value: amountWei,
|
|
60
71
|
});
|
|
61
72
|
}
|
|
62
73
|
|
|
74
|
+
private async performDeposit(amountWei: BigNumber): Promise<DepositResult> {
|
|
75
|
+
// Pre-check minDeposit
|
|
76
|
+
const minDeposit: BigNumber = await this.contract.DepositManager.minDeposit();
|
|
77
|
+
if (amountWei.lt(minDeposit)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Deposit amount below minDeposit: ` +
|
|
80
|
+
`amount=${ethers.utils.formatEther(amountWei)} ETH, ` +
|
|
81
|
+
`min=${ethers.utils.formatEther(minDeposit)} ETH`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Send the payable tx
|
|
86
|
+
const tx = await this.contract.DepositManager.deposit({
|
|
87
|
+
value: amountWei,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Wait for 1 confirmation
|
|
91
|
+
const receipt = await tx.wait(1);
|
|
92
|
+
|
|
93
|
+
// Parse Deposited event if present
|
|
94
|
+
let deposited: DepositEvent | undefined;
|
|
95
|
+
const ev = receipt.events?.find((e) => e.event === 'Deposited');
|
|
96
|
+
|
|
97
|
+
if (ev && ev.args) {
|
|
98
|
+
const { user, netEth, fee, shares } = ev.args;
|
|
99
|
+
deposited = {
|
|
100
|
+
user,
|
|
101
|
+
netEth: BigNumber.from(netEth),
|
|
102
|
+
fee: BigNumber.from(fee),
|
|
103
|
+
shares: BigNumber.from(shares),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
txHash: tx.hash,
|
|
109
|
+
receipt,
|
|
110
|
+
deposited,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resolve the user's ETH + liqETH balances.
|
|
116
|
+
*
|
|
117
|
+
* native = ETH in wallet
|
|
118
|
+
* actual = liqETH token balance (ERC-20)
|
|
119
|
+
* tracked = liqETH tracked balance (protocol/accounting view)
|
|
120
|
+
*/
|
|
121
|
+
async getPortfolio(): Promise<Portfolio> {
|
|
122
|
+
const walletAddress = await this.signer.getAddress();
|
|
123
|
+
|
|
124
|
+
// 1) Native ETH balance
|
|
125
|
+
const nativeBalance = await this.provider.getBalance(walletAddress);
|
|
126
|
+
// console.log('nativeBalance', nativeBalance);
|
|
127
|
+
const nativeDecimals = this.network?.nativeCurrency?.decimals ?? 18;
|
|
128
|
+
const nativeSymbol = this.network?.nativeCurrency?.symbol ?? 'ETH';
|
|
129
|
+
|
|
130
|
+
// 2) liqETH ERC-20 balance (actual)
|
|
131
|
+
const liqBalance: ethers.BigNumber = await this.contract.LiqEth.balanceOf(walletAddress);
|
|
132
|
+
// console.log('liqBalance', liqBalance);
|
|
133
|
+
|
|
134
|
+
const liqDecimals = this.network?.nativeCurrency?.decimals ?? 18;
|
|
135
|
+
const liqSymbol = 'Liq' + (this.network?.nativeCurrency?.symbol ?? 'ETH');
|
|
136
|
+
|
|
137
|
+
const portfolio: Portfolio = {
|
|
138
|
+
native: {
|
|
139
|
+
amount: nativeBalance,
|
|
140
|
+
decimals: nativeDecimals,
|
|
141
|
+
symbol: nativeSymbol,
|
|
142
|
+
},
|
|
143
|
+
liq: {
|
|
144
|
+
amount: liqBalance,
|
|
145
|
+
decimals: liqDecimals,
|
|
146
|
+
symbol: liqSymbol,
|
|
147
|
+
},
|
|
148
|
+
staked: { // TODO fetch staked balance from outpost
|
|
149
|
+
amount: BigNumber.from(0),
|
|
150
|
+
decimals: liqDecimals,
|
|
151
|
+
symbol: liqSymbol,
|
|
152
|
+
},
|
|
153
|
+
chainID: this.network.chainId
|
|
154
|
+
}
|
|
155
|
+
// console.log('ETH PORTFOLIO', portfolio);
|
|
156
|
+
return portfolio;
|
|
157
|
+
}
|
|
158
|
+
|
|
63
159
|
// TODO: implement withdraw, claimRewards, etc.
|
|
64
160
|
}
|
|
@@ -1,6 +1,34 @@
|
|
|
1
|
+
import { BigNumber, ethers } from 'ethers';
|
|
2
|
+
|
|
1
3
|
export const CONTRACT_NAMES = [
|
|
2
|
-
'
|
|
4
|
+
'Accounting',
|
|
5
|
+
'DepositManager',
|
|
6
|
+
'LiqEth',
|
|
7
|
+
'LiqEthBurn',
|
|
8
|
+
'LiqEthMint',
|
|
9
|
+
// 'RewardsERC20',
|
|
10
|
+
'StakingModule',
|
|
11
|
+
// 'ValidatorBalance',
|
|
12
|
+
'WithdrawalQueue',
|
|
13
|
+
'WithdrawalVault',
|
|
14
|
+
// 'Yield',
|
|
3
15
|
] as const;
|
|
4
16
|
|
|
5
17
|
export type ContractName = typeof CONTRACT_NAMES[number];
|
|
6
|
-
export type AddressBook = Record<ContractName, string>;
|
|
18
|
+
export type AddressBook = Record<ContractName, string>;
|
|
19
|
+
|
|
20
|
+
export interface DepositEvent {
|
|
21
|
+
user: string;
|
|
22
|
+
netEth: BigNumber;
|
|
23
|
+
fee: BigNumber;
|
|
24
|
+
shares: BigNumber;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface DepositResult {
|
|
28
|
+
/** EVM transaction hash */
|
|
29
|
+
txHash: string;
|
|
30
|
+
/** Full receipt, if you want it */
|
|
31
|
+
receipt: ethers.providers.TransactionReceipt;
|
|
32
|
+
/** Parsed Deposited event, if present */
|
|
33
|
+
deposited?: DepositEvent;
|
|
34
|
+
}
|