@wireio/stake 0.0.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.
- package/LICENSE.md +114 -0
- package/README.md +28 -0
- package/lib/stake.browser.js +6875 -0
- package/lib/stake.browser.js.map +1 -0
- package/lib/stake.d.ts +6759 -0
- package/lib/stake.js +7178 -0
- package/lib/stake.js.map +1 -0
- package/lib/stake.m.js +6875 -0
- package/lib/stake.m.js.map +1 -0
- package/package.json +102 -0
- package/src/assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.dbg.json +4 -0
- package/src/assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.json +472 -0
- package/src/assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.dbg.json +4 -0
- package/src/assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.json +330 -0
- package/src/assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.dbg.json +4 -0
- package/src/assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.json +449 -0
- package/src/assets/solana/idl/deposit.json +260 -0
- package/src/assets/solana/idl/distribution.json +736 -0
- package/src/assets/solana/idl/liq_sol_token.json +275 -0
- package/src/assets/solana/idl/stake_controller.json +1788 -0
- package/src/assets/solana/idl/stake_registry.json +435 -0
- package/src/assets/solana/idl/treasury.json +336 -0
- package/src/assets/solana/idl/validator_leaderboard.json +528 -0
- package/src/assets/solana/idl/validator_registry.json +418 -0
- package/src/assets/solana/idl/yield_oracle.json +32 -0
- package/src/assets/solana/types/deposit.ts +266 -0
- package/src/assets/solana/types/distribution.ts +742 -0
- package/src/assets/solana/types/liq_sol_token.ts +281 -0
- package/src/assets/solana/types/stake_controller.ts +1794 -0
- package/src/assets/solana/types/stake_registry.ts +441 -0
- package/src/assets/solana/types/treasury.ts +342 -0
- package/src/assets/solana/types/validator_leaderboard.ts +534 -0
- package/src/assets/solana/types/validator_registry.ts +424 -0
- package/src/assets/solana/types/yield_oracle.ts +38 -0
- package/src/index.ts +21 -0
- package/src/networks/ethereum/contract.ts +167 -0
- package/src/networks/ethereum/ethereum.ts +64 -0
- package/src/networks/ethereum/types.ts +6 -0
- package/src/networks/solana/clients/deposit.client.ts +178 -0
- package/src/networks/solana/clients/distribution.client.ts +230 -0
- package/src/networks/solana/clients/leaderboard.client.ts +179 -0
- package/src/networks/solana/constants.ts +73 -0
- package/src/networks/solana/program.ts +113 -0
- package/src/networks/solana/solana.ts +84 -0
- package/src/networks/solana/utils.ts +122 -0
- package/src/staker/staker.ts +38 -0
- package/src/staker/types.ts +26 -0
- package/src/utils.ts +9 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program IDL in camelCase format in order to be used in JS/TS.
|
|
3
|
+
*
|
|
4
|
+
* Note that this is only a type helper and is not the actual IDL. The original
|
|
5
|
+
* IDL can be found at `target/idl/validator_registry.json`.
|
|
6
|
+
*/
|
|
7
|
+
export type ValidatorRegistry = {
|
|
8
|
+
"address": "DqaNZkyhg6ASSkut8tyQGjwMtv35Yj5rA9JZvzmzZb3e",
|
|
9
|
+
"metadata": {
|
|
10
|
+
"name": "validatorRegistry",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"spec": "0.1.0",
|
|
13
|
+
"description": "Created with Anchor"
|
|
14
|
+
},
|
|
15
|
+
"instructions": [
|
|
16
|
+
{
|
|
17
|
+
"name": "addValidator",
|
|
18
|
+
"discriminator": [
|
|
19
|
+
250,
|
|
20
|
+
113,
|
|
21
|
+
53,
|
|
22
|
+
54,
|
|
23
|
+
141,
|
|
24
|
+
117,
|
|
25
|
+
215,
|
|
26
|
+
185
|
|
27
|
+
],
|
|
28
|
+
"accounts": [
|
|
29
|
+
{
|
|
30
|
+
"name": "authority",
|
|
31
|
+
"signer": true
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "validatorRegistry",
|
|
35
|
+
"writable": true
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"args": [
|
|
39
|
+
{
|
|
40
|
+
"name": "voteAccount",
|
|
41
|
+
"type": "pubkey"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "name",
|
|
45
|
+
"type": "string"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "performanceScore",
|
|
49
|
+
"type": "u32"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "getValidators",
|
|
55
|
+
"discriminator": [
|
|
56
|
+
74,
|
|
57
|
+
81,
|
|
58
|
+
116,
|
|
59
|
+
129,
|
|
60
|
+
224,
|
|
61
|
+
19,
|
|
62
|
+
17,
|
|
63
|
+
238
|
|
64
|
+
],
|
|
65
|
+
"accounts": [
|
|
66
|
+
{
|
|
67
|
+
"name": "validatorRegistry"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"args": []
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "initialize",
|
|
74
|
+
"discriminator": [
|
|
75
|
+
175,
|
|
76
|
+
175,
|
|
77
|
+
109,
|
|
78
|
+
31,
|
|
79
|
+
13,
|
|
80
|
+
152,
|
|
81
|
+
155,
|
|
82
|
+
237
|
|
83
|
+
],
|
|
84
|
+
"accounts": [
|
|
85
|
+
{
|
|
86
|
+
"name": "payer",
|
|
87
|
+
"writable": true,
|
|
88
|
+
"signer": true
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "validatorRegistry",
|
|
92
|
+
"writable": true,
|
|
93
|
+
"pda": {
|
|
94
|
+
"seeds": [
|
|
95
|
+
{
|
|
96
|
+
"kind": "const",
|
|
97
|
+
"value": [
|
|
98
|
+
118,
|
|
99
|
+
97,
|
|
100
|
+
108,
|
|
101
|
+
105,
|
|
102
|
+
100,
|
|
103
|
+
97,
|
|
104
|
+
116,
|
|
105
|
+
111,
|
|
106
|
+
114,
|
|
107
|
+
95,
|
|
108
|
+
114,
|
|
109
|
+
101,
|
|
110
|
+
103,
|
|
111
|
+
105,
|
|
112
|
+
115,
|
|
113
|
+
116,
|
|
114
|
+
114,
|
|
115
|
+
121
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "systemProgram",
|
|
123
|
+
"address": "11111111111111111111111111111111"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"args": [
|
|
127
|
+
{
|
|
128
|
+
"name": "authority",
|
|
129
|
+
"type": "pubkey"
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "syncValidatorsFromChain",
|
|
135
|
+
"discriminator": [
|
|
136
|
+
247,
|
|
137
|
+
11,
|
|
138
|
+
19,
|
|
139
|
+
18,
|
|
140
|
+
37,
|
|
141
|
+
20,
|
|
142
|
+
245,
|
|
143
|
+
232
|
|
144
|
+
],
|
|
145
|
+
"accounts": [
|
|
146
|
+
{
|
|
147
|
+
"name": "authority",
|
|
148
|
+
"signer": true
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "validatorRegistry",
|
|
152
|
+
"writable": true
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"name": "stakeControllerProgram"
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
"args": [
|
|
159
|
+
{
|
|
160
|
+
"name": "voteAccounts",
|
|
161
|
+
"type": {
|
|
162
|
+
"vec": "pubkey"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "validatorMetrics",
|
|
167
|
+
"type": {
|
|
168
|
+
"vec": {
|
|
169
|
+
"defined": {
|
|
170
|
+
"name": "validatorMetrics"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "updatePerformance",
|
|
179
|
+
"discriminator": [
|
|
180
|
+
11,
|
|
181
|
+
251,
|
|
182
|
+
66,
|
|
183
|
+
148,
|
|
184
|
+
20,
|
|
185
|
+
86,
|
|
186
|
+
149,
|
|
187
|
+
20
|
|
188
|
+
],
|
|
189
|
+
"accounts": [
|
|
190
|
+
{
|
|
191
|
+
"name": "authority",
|
|
192
|
+
"signer": true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "validatorRegistry",
|
|
196
|
+
"writable": true
|
|
197
|
+
}
|
|
198
|
+
],
|
|
199
|
+
"args": [
|
|
200
|
+
{
|
|
201
|
+
"name": "voteAccount",
|
|
202
|
+
"type": "pubkey"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"name": "performanceScore",
|
|
206
|
+
"type": "u32"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "activeStake",
|
|
210
|
+
"type": "u64"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "commission",
|
|
214
|
+
"type": "u64"
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"accounts": [
|
|
220
|
+
{
|
|
221
|
+
"name": "validatorRegistry",
|
|
222
|
+
"discriminator": [
|
|
223
|
+
168,
|
|
224
|
+
113,
|
|
225
|
+
195,
|
|
226
|
+
186,
|
|
227
|
+
62,
|
|
228
|
+
121,
|
|
229
|
+
163,
|
|
230
|
+
230
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
],
|
|
234
|
+
"events": [
|
|
235
|
+
{
|
|
236
|
+
"name": "validatorsSyncedEvent",
|
|
237
|
+
"discriminator": [
|
|
238
|
+
119,
|
|
239
|
+
121,
|
|
240
|
+
49,
|
|
241
|
+
120,
|
|
242
|
+
230,
|
|
243
|
+
132,
|
|
244
|
+
109,
|
|
245
|
+
214
|
|
246
|
+
]
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
"errors": [
|
|
250
|
+
{
|
|
251
|
+
"code": 6000,
|
|
252
|
+
"name": "unauthorized",
|
|
253
|
+
"msg": "Unauthorized access"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"code": 6001,
|
|
257
|
+
"name": "maxValidatorsReached",
|
|
258
|
+
"msg": "Maximum validators reached"
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"code": 6002,
|
|
262
|
+
"name": "validatorAlreadyExists",
|
|
263
|
+
"msg": "Validator already exists"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"code": 6003,
|
|
267
|
+
"name": "validatorNotFound",
|
|
268
|
+
"msg": "Validator not found"
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"code": 6004,
|
|
272
|
+
"name": "invalidStakeUpdateType",
|
|
273
|
+
"msg": "Invalid stake update type"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"code": 6005,
|
|
277
|
+
"name": "invalidVoteAccount",
|
|
278
|
+
"msg": "Invalid vote account provided"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"code": 6006,
|
|
282
|
+
"name": "invalidInputLength",
|
|
283
|
+
"msg": "Invalid input length - all vectors must have same length"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"code": 6007,
|
|
287
|
+
"name": "invalidStakeAccount",
|
|
288
|
+
"msg": "Invalid Stake Account"
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
"types": [
|
|
292
|
+
{
|
|
293
|
+
"name": "validatorInfo",
|
|
294
|
+
"type": {
|
|
295
|
+
"kind": "struct",
|
|
296
|
+
"fields": [
|
|
297
|
+
{
|
|
298
|
+
"name": "voteAccount",
|
|
299
|
+
"type": "pubkey"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"name": "name",
|
|
303
|
+
"type": {
|
|
304
|
+
"array": [
|
|
305
|
+
"u8",
|
|
306
|
+
32
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"name": "performanceScore",
|
|
312
|
+
"type": "u32"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"name": "activeStake",
|
|
316
|
+
"type": "u64"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"name": "activatingStake",
|
|
320
|
+
"type": "u64"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"name": "deactivatingStake",
|
|
324
|
+
"type": "u64"
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"name": "commission",
|
|
328
|
+
"type": "u64"
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"name": "lastUpdatedEpoch",
|
|
332
|
+
"type": "u64"
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "initialStake",
|
|
336
|
+
"type": "u64"
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"name": "previousEpochActiveStake",
|
|
340
|
+
"type": "u64"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"name": "previousEpochSnapshot",
|
|
344
|
+
"type": "u64"
|
|
345
|
+
}
|
|
346
|
+
]
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"name": "validatorMetrics",
|
|
351
|
+
"type": {
|
|
352
|
+
"kind": "struct",
|
|
353
|
+
"fields": [
|
|
354
|
+
{
|
|
355
|
+
"name": "commission",
|
|
356
|
+
"type": "u8"
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"name": "skipRateBps",
|
|
360
|
+
"type": "u32"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"name": "isDelinquent",
|
|
364
|
+
"type": "bool"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"name": "activatedStake",
|
|
368
|
+
"type": "u64"
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"name": "validatorRegistry",
|
|
375
|
+
"type": {
|
|
376
|
+
"kind": "struct",
|
|
377
|
+
"fields": [
|
|
378
|
+
{
|
|
379
|
+
"name": "authority",
|
|
380
|
+
"type": "pubkey"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "validators",
|
|
384
|
+
"type": {
|
|
385
|
+
"vec": {
|
|
386
|
+
"defined": {
|
|
387
|
+
"name": "validatorInfo"
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"name": "lastUpdateEpoch",
|
|
394
|
+
"type": "u64"
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"name": "bump",
|
|
398
|
+
"type": "u8"
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"name": "validatorsSyncedEvent",
|
|
405
|
+
"type": {
|
|
406
|
+
"kind": "struct",
|
|
407
|
+
"fields": [
|
|
408
|
+
{
|
|
409
|
+
"name": "updatedCount",
|
|
410
|
+
"type": "u32"
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"name": "notFoundCount",
|
|
414
|
+
"type": "u32"
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"name": "epoch",
|
|
418
|
+
"type": "u64"
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
]
|
|
424
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program IDL in camelCase format in order to be used in JS/TS.
|
|
3
|
+
*
|
|
4
|
+
* Note that this is only a type helper and is not the actual IDL. The original
|
|
5
|
+
* IDL can be found at `target/idl/yield_oracle.json`.
|
|
6
|
+
*/
|
|
7
|
+
export type YieldOracle = {
|
|
8
|
+
"address": "ABMUzgJCoJ17WPYvxZg4Biuo5oCaEbuD4svUVGFBTWCz",
|
|
9
|
+
"metadata": {
|
|
10
|
+
"name": "yieldOracle",
|
|
11
|
+
"version": "0.1.0",
|
|
12
|
+
"spec": "0.1.0",
|
|
13
|
+
"description": "Created with Anchor"
|
|
14
|
+
},
|
|
15
|
+
"instructions": [
|
|
16
|
+
{
|
|
17
|
+
"name": "calculateYieldPerSol",
|
|
18
|
+
"discriminator": [
|
|
19
|
+
51,
|
|
20
|
+
25,
|
|
21
|
+
150,
|
|
22
|
+
38,
|
|
23
|
+
173,
|
|
24
|
+
32,
|
|
25
|
+
27,
|
|
26
|
+
202
|
|
27
|
+
],
|
|
28
|
+
"accounts": [
|
|
29
|
+
{
|
|
30
|
+
"name": "systemProgram",
|
|
31
|
+
"address": "11111111111111111111111111111111"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"args": [],
|
|
35
|
+
"returns": "u64"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Export all utilities from the utils module
|
|
2
|
+
export * from './utils';
|
|
3
|
+
|
|
4
|
+
// Staker utilities
|
|
5
|
+
export * from './staker/staker';
|
|
6
|
+
export * from './staker/types';
|
|
7
|
+
|
|
8
|
+
// NETWORKS
|
|
9
|
+
|
|
10
|
+
// Ethereum
|
|
11
|
+
export * from './networks/ethereum/ethereum';
|
|
12
|
+
export * from './networks/ethereum/contract';
|
|
13
|
+
export * as ETH from './networks/ethereum/types';
|
|
14
|
+
|
|
15
|
+
export * from './networks/solana/solana';
|
|
16
|
+
export * from './networks/solana/constants';
|
|
17
|
+
export * from './networks/solana/utils';
|
|
18
|
+
|
|
19
|
+
export * from './networks/solana/clients/deposit.client';
|
|
20
|
+
export * from './networks/solana/clients/distribution.client';
|
|
21
|
+
export * from './networks/solana/clients/leaderboard.client';
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module EthereumContractService
|
|
3
|
+
*
|
|
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
|
+
*/
|
|
24
|
+
|
|
25
|
+
import ERC20Artifact from '../../assets/ethereum/ABI/token/ERC20Token.sol/ERC20Token.json';
|
|
26
|
+
import ERC721Artifact from '../../assets/ethereum/ABI/token/ERC721Token.sol/ERC721Token.json';
|
|
27
|
+
import ERC1155Artifact from '../../assets/ethereum/ABI/token/ERC1155Token.sol/ERC1155Token.json';
|
|
28
|
+
import { AddressBook, ContractName } from './types';
|
|
29
|
+
import { Contract, ethers, providers, Signer } from 'ethers';
|
|
30
|
+
import { JsonFragment } from '@ethersproject/abi';
|
|
31
|
+
import { ErrorDescription } from '@ethersproject/abi/lib/interface';
|
|
32
|
+
|
|
33
|
+
export const ERC20Abi = ERC20Artifact.abi;
|
|
34
|
+
export const ERC721Abi = ERC721Artifact.abi;
|
|
35
|
+
export const ERC1155Abi = ERC1155Artifact.abi;
|
|
36
|
+
|
|
37
|
+
// Update this to be your staking contract address book
|
|
38
|
+
export const ADDRESSES: AddressBook = {
|
|
39
|
+
Stake: '0xEeaCBa95852324eAc63fE2711aFe0283adf3bC93',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type Contracts<T extends string = ContractName> = Record<T, ContractConfig>;
|
|
43
|
+
|
|
44
|
+
export type ContractConfig = {
|
|
45
|
+
address: string;
|
|
46
|
+
abi: JsonFragment[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const CONTRACTS: Contracts<ContractName> = {
|
|
50
|
+
Stake: { address: ADDRESSES.Stake, abi: undefined as any }, // Replace with actual ABI artifact when available
|
|
51
|
+
// Stake: { address: ADDRESSES.Stake, abi: Stake.abi },
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ContractOptions {
|
|
55
|
+
/** RPC endpoint or injected EIP-1193 provider */
|
|
56
|
+
provider?: ethers.providers.Provider;
|
|
57
|
+
/** Only required if you need to send txns */
|
|
58
|
+
signer?: Signer;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
export class EthereumContractService {
|
|
63
|
+
private provider?: providers.Provider;
|
|
64
|
+
private signer?: Signer;
|
|
65
|
+
|
|
66
|
+
public readonly contract: { [N in ContractName]: ethers.Contract } = {} as any;
|
|
67
|
+
public readonly iface: { [N in ContractName]: ethers.utils.Interface } = {} as any;
|
|
68
|
+
|
|
69
|
+
constructor(opts: ContractOptions) {
|
|
70
|
+
this.provider = opts.provider;
|
|
71
|
+
this.signer = opts.signer;
|
|
72
|
+
|
|
73
|
+
(Object.keys(CONTRACTS) as ContractName[]).forEach((name) => {
|
|
74
|
+
const { address, abi } = CONTRACTS[name];
|
|
75
|
+
this.iface[name] = new ethers.utils.Interface(abi);
|
|
76
|
+
this.contract[name] = new ethers.Contract(address, abi, this.signer ?? this.provider);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Get raw address for a contract */
|
|
81
|
+
public getAddress(name: ContractName): string {
|
|
82
|
+
return CONTRACTS[name].address;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Utility: get a read-only handle even if signer is present */
|
|
86
|
+
getReadOnly(name: ContractName): Contract {
|
|
87
|
+
const { address, abi } = CONTRACTS[name];
|
|
88
|
+
return new Contract(address, abi, this.provider);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Utility: get a write-enabled handle (throws if no signer) */
|
|
92
|
+
getWrite(name: ContractName): Contract {
|
|
93
|
+
if (!this.signer) throw new Error('No signer available for write calls');
|
|
94
|
+
const { address, abi } = CONTRACTS[name];
|
|
95
|
+
return new Contract(address, abi, this.signer);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Expose network info */
|
|
99
|
+
async getNetwork() {
|
|
100
|
+
return this.provider?.getNetwork();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** List all known contract names */
|
|
104
|
+
public listContractNames(): ContractName[] {
|
|
105
|
+
return Object.keys(CONTRACTS) as ContractName[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Get Interface instance for a contract */
|
|
109
|
+
public getInterface(name: ContractName): ethers.utils.Interface {
|
|
110
|
+
const iface = this.iface[name];
|
|
111
|
+
if (!iface) throw new Error(`Interface not initialized for ${name}`);
|
|
112
|
+
return iface;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Get live Contract instance */
|
|
116
|
+
public getContract(name: ContractName): ethers.Contract {
|
|
117
|
+
const ctr = this.contract[name];
|
|
118
|
+
if (!ctr) throw new Error(`Contract not initialized for ${name}`);
|
|
119
|
+
return ctr;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** A unified Interface containing all ABIs (addresses + extra decoding-only)
|
|
123
|
+
* to parse custom errors or events. */
|
|
124
|
+
public get omniInterface(): ethers.utils.Interface {
|
|
125
|
+
const all: any[] = [];
|
|
126
|
+
|
|
127
|
+
// Add all artifacts to the interface
|
|
128
|
+
const allArtifacts = [
|
|
129
|
+
ERC20Artifact,
|
|
130
|
+
ERC721Artifact,
|
|
131
|
+
ERC1155Artifact,
|
|
132
|
+
// Add more artifacts as needed
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
// Add all ABIs to the omnibus interface
|
|
136
|
+
allArtifacts.forEach(artifact => {
|
|
137
|
+
if (artifact && artifact.abi) {
|
|
138
|
+
all.push(...artifact.abi);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// dedupe
|
|
143
|
+
const seen = new Set<string>();
|
|
144
|
+
const dedup: any[] = [];
|
|
145
|
+
for (const item of all) {
|
|
146
|
+
try {
|
|
147
|
+
const frag = ethers.utils.Fragment.from(item);
|
|
148
|
+
const key = `${frag.type}:${frag.format(ethers.utils.FormatTypes.full)}`.toLowerCase();
|
|
149
|
+
if (!seen.has(key)) {
|
|
150
|
+
seen.add(key);
|
|
151
|
+
dedup.push(item);
|
|
152
|
+
}
|
|
153
|
+
} catch { }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return new ethers.utils.Interface(dedup);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Decode a revert or custom error payload */
|
|
160
|
+
public parseError(revertData: string): ErrorDescription {
|
|
161
|
+
try {
|
|
162
|
+
return this.omniInterface.parseError(revertData);
|
|
163
|
+
} catch {
|
|
164
|
+
throw new Error(`Unable to parse error data: ${revertData}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/networks/ethereum/ethereum.ts
|
|
2
|
+
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import { IStakingClient, StakerConfig } from '../../staker/types';
|
|
5
|
+
import { PublicKey as WirePubKey } from '@wireio/core';
|
|
6
|
+
import { ERC20Abi } from './contract'; // TODO replace with staking contract ABI
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
|
|
9
|
+
// — replace with your actual staking contract ABI & address —
|
|
10
|
+
const STAKING_CONTRACT_ADDRESS = '0xYourStakingContractAddress';
|
|
11
|
+
|
|
12
|
+
export class EthereumStakingClient implements IStakingClient {
|
|
13
|
+
public readonly pubKey: WirePubKey;
|
|
14
|
+
private readonly provider: ethers.providers.Web3Provider;
|
|
15
|
+
private readonly signer: ethers.Signer;
|
|
16
|
+
private readonly contract: ethers.Contract;
|
|
17
|
+
|
|
18
|
+
constructor(private config: StakerConfig) {
|
|
19
|
+
// 1) unwrap & validate Ethers provider
|
|
20
|
+
if (!ethers.providers.Web3Provider.isProvider(config.provider as any)) {
|
|
21
|
+
throw new Error('Expected a Web3Provider for Ethereum');
|
|
22
|
+
}
|
|
23
|
+
this.provider = config.provider as ethers.providers.Web3Provider;
|
|
24
|
+
|
|
25
|
+
// 2) signer
|
|
26
|
+
this.signer = this.provider.getSigner();
|
|
27
|
+
this.pubKey = config.pubKey as WirePubKey;
|
|
28
|
+
|
|
29
|
+
// 4) instantiate your contract wrapper
|
|
30
|
+
this.contract = new ethers.Contract(
|
|
31
|
+
STAKING_CONTRACT_ADDRESS,
|
|
32
|
+
ERC20Abi,
|
|
33
|
+
this.signer
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Submit a deposit; returns the transaction hash */
|
|
38
|
+
async deposit(amount: number): Promise<string> {
|
|
39
|
+
// build & send in one go
|
|
40
|
+
const txResponse = await this.contract.deposit(
|
|
41
|
+
ethers.BigNumber.from(amount),
|
|
42
|
+
{
|
|
43
|
+
// if your contract needs ETH value:
|
|
44
|
+
// value: ethers.BigNumber.from(amount),
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// wait for on-chain confirmation (optional)
|
|
49
|
+
await txResponse.wait();
|
|
50
|
+
return txResponse.hash;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** (Optional) dry-run via eth_call */
|
|
54
|
+
async simulateDeposit(amount: number): Promise<any> {
|
|
55
|
+
return this.provider.call({
|
|
56
|
+
to: STAKING_CONTRACT_ADDRESS,
|
|
57
|
+
data: this.contract.interface.encodeFunctionData('deposit', [
|
|
58
|
+
ethers.BigNumber.from(amount)
|
|
59
|
+
]),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// TODO: implement withdraw, claimRewards, etc.
|
|
64
|
+
}
|