@zebec-network/zebec-stake-sdk 1.2.2 → 1.3.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/README.md +661 -11
- package/dist/artifacts/zebec_stake_v1.d.ts +28 -2
- package/dist/artifacts/zebec_stake_v1.json +63 -35
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +5 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/pda.d.ts +1 -1
- package/dist/pda.js +8 -2
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -1
- package/dist/service.d.ts +5 -69
- package/dist/service.js +60 -25
- package/dist/types.d.ts +67 -0
- package/dist/types.js +2 -0
- package/dist/utils.js +4 -2
- package/package.json +46 -46
package/dist/service.js
CHANGED
|
@@ -4,12 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.StakeService = exports.StakeServiceBuilder = void 0;
|
|
7
|
-
const assert_1 = __importDefault(require("assert"));
|
|
8
|
-
const bignumber_js_1 = require("bignumber.js");
|
|
9
7
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
10
8
|
const web3_js_1 = require("@solana/web3.js");
|
|
11
9
|
const core_utils_1 = require("@zebec-network/core-utils");
|
|
12
10
|
const solana_common_1 = require("@zebec-network/solana-common");
|
|
11
|
+
const assert_1 = __importDefault(require("assert"));
|
|
12
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
13
13
|
const artifacts_1 = require("./artifacts");
|
|
14
14
|
const pda_1 = require("./pda");
|
|
15
15
|
const providers_1 = require("./providers");
|
|
@@ -89,7 +89,9 @@ class StakeServiceBuilder {
|
|
|
89
89
|
if (!this._provider) {
|
|
90
90
|
throw new Error("InvalidOperation: Provider is not set. Please set the provider before setting the program.");
|
|
91
91
|
}
|
|
92
|
-
this._program = !createProgram
|
|
92
|
+
this._program = !createProgram
|
|
93
|
+
? new anchor_1.Program(artifacts_1.ZEBEC_STAKE_IDL_V1, this._provider)
|
|
94
|
+
: createProgram(this._provider);
|
|
93
95
|
return this;
|
|
94
96
|
}
|
|
95
97
|
build() {
|
|
@@ -117,8 +119,8 @@ class StakeService {
|
|
|
117
119
|
}
|
|
118
120
|
async _createPayload(payerKey, instructions, signers, addressLookupTableAccounts) {
|
|
119
121
|
const errorMap = new Map();
|
|
120
|
-
this.program.idl.errors.
|
|
121
|
-
let signTransaction
|
|
122
|
+
this.program.idl.errors.map((error) => errorMap.set(error.code, error.msg));
|
|
123
|
+
let signTransaction;
|
|
122
124
|
const provider = this.provider;
|
|
123
125
|
if (provider instanceof anchor_1.AnchorProvider) {
|
|
124
126
|
signTransaction = async (tx) => {
|
|
@@ -193,7 +195,9 @@ class StakeService {
|
|
|
193
195
|
.instruction();
|
|
194
196
|
}
|
|
195
197
|
async initLockup(params) {
|
|
196
|
-
const creator = params.creator
|
|
198
|
+
const creator = params.creator
|
|
199
|
+
? (0, anchor_1.translateAddress)(params.creator)
|
|
200
|
+
: this.provider.publicKey;
|
|
197
201
|
if (!creator) {
|
|
198
202
|
throw new Error("MissingArgument: Please provide either creator address or publicKey in provider");
|
|
199
203
|
}
|
|
@@ -223,7 +227,9 @@ class StakeService {
|
|
|
223
227
|
return this._createPayload(creator, [instruction]);
|
|
224
228
|
}
|
|
225
229
|
async updateLockup(params) {
|
|
226
|
-
const updater = params.updater
|
|
230
|
+
const updater = params.updater
|
|
231
|
+
? (0, anchor_1.translateAddress)(params.updater)
|
|
232
|
+
: this.provider.publicKey;
|
|
227
233
|
if (!updater) {
|
|
228
234
|
throw new Error("MissingArgument: Please provide either updater address or publicKey in provider");
|
|
229
235
|
}
|
|
@@ -250,19 +256,23 @@ class StakeService {
|
|
|
250
256
|
return this._createPayload(updater, [instruction]);
|
|
251
257
|
}
|
|
252
258
|
async stake(params) {
|
|
253
|
-
const staker = params.staker
|
|
259
|
+
const staker = params.staker
|
|
260
|
+
? (0, anchor_1.translateAddress)(params.staker)
|
|
261
|
+
: this.provider.publicKey;
|
|
254
262
|
if (!staker) {
|
|
255
263
|
throw new Error("MissingArgument: Please provide either staker address or publicKey in provider");
|
|
256
264
|
}
|
|
257
|
-
const feePayer = params.feePayer
|
|
265
|
+
const feePayer = params.feePayer
|
|
266
|
+
? (0, anchor_1.translateAddress)(params.feePayer)
|
|
267
|
+
: staker;
|
|
258
268
|
const lockup = (0, pda_1.deriveLockupAddress)(params.lockupName, this.programId);
|
|
259
269
|
const lockupAccount = await this.program.account.lockup.fetchNullable(lockup, this.connection.commitment);
|
|
260
270
|
if (!lockupAccount) {
|
|
261
|
-
throw new Error(
|
|
271
|
+
throw new Error(`Lockup account does not exists for address: ${lockup}`);
|
|
262
272
|
}
|
|
263
273
|
const lockPeriods = lockupAccount.stakeInfo.durationMap.map((item) => item.duration.toNumber());
|
|
264
274
|
if (!lockPeriods.includes(params.lockPeriod)) {
|
|
265
|
-
throw new Error(
|
|
275
|
+
throw new Error(`Invalid lockperiod. Available options are: ${lockPeriods.map((l) => l.toString()).join(", ")}`);
|
|
266
276
|
}
|
|
267
277
|
const stakeToken = lockupAccount.stakedToken.tokenAddress;
|
|
268
278
|
const stakeVault = (0, pda_1.deriveStakeVaultAddress)(lockup, this.programId);
|
|
@@ -284,11 +294,15 @@ class StakeService {
|
|
|
284
294
|
return this._createPayload(feePayer, [instruction]);
|
|
285
295
|
}
|
|
286
296
|
async unstake(params) {
|
|
287
|
-
const staker = params.staker
|
|
297
|
+
const staker = params.staker
|
|
298
|
+
? (0, anchor_1.translateAddress)(params.staker)
|
|
299
|
+
: this.provider.publicKey;
|
|
288
300
|
if (!staker) {
|
|
289
301
|
throw new Error("MissingArgument: Please provide either staker address or publicKey in provider");
|
|
290
302
|
}
|
|
291
|
-
const feePayer = params.feePayer
|
|
303
|
+
const feePayer = params.feePayer
|
|
304
|
+
? (0, anchor_1.translateAddress)(params.feePayer)
|
|
305
|
+
: staker;
|
|
292
306
|
const lockup = (0, pda_1.deriveLockupAddress)(params.lockupName, this.programId);
|
|
293
307
|
const lockupAccount = await this.program.account.lockup.fetchNullable(lockup, this.connection.commitment);
|
|
294
308
|
if (!lockupAccount) {
|
|
@@ -315,7 +329,9 @@ class StakeService {
|
|
|
315
329
|
return {
|
|
316
330
|
address: lockupAddress.toString(),
|
|
317
331
|
feeInfo: {
|
|
318
|
-
fee: (0, bignumber_js_1.BigNumber)(lockupAccount.feeInfo.fee.toString())
|
|
332
|
+
fee: (0, bignumber_js_1.BigNumber)(lockupAccount.feeInfo.fee.toString())
|
|
333
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
334
|
+
.toFixed(),
|
|
319
335
|
feeVault: lockupAccount.feeInfo.feeVault.toString(),
|
|
320
336
|
},
|
|
321
337
|
rewardToken: {
|
|
@@ -323,7 +339,9 @@ class StakeService {
|
|
|
323
339
|
},
|
|
324
340
|
stakeToken: {
|
|
325
341
|
tokenAdress: lockupAccount.stakedToken.tokenAddress.toString(),
|
|
326
|
-
totalStaked: (0, bignumber_js_1.BigNumber)(lockupAccount.stakedToken.totalStaked.toString())
|
|
342
|
+
totalStaked: (0, bignumber_js_1.BigNumber)(lockupAccount.stakedToken.totalStaked.toString())
|
|
343
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
344
|
+
.toFixed(),
|
|
327
345
|
},
|
|
328
346
|
stakeInfo: {
|
|
329
347
|
name: lockupAccount.stakeInfo.name,
|
|
@@ -332,7 +350,9 @@ class StakeService {
|
|
|
332
350
|
duration: value.duration.toNumber(),
|
|
333
351
|
rewardRate: (0, core_utils_1.bpsToPercent)(value.reward.toString()),
|
|
334
352
|
})),
|
|
335
|
-
minimumStake: (0, bignumber_js_1.BigNumber)(lockupAccount.stakeInfo.minimumStake.toString())
|
|
353
|
+
minimumStake: (0, bignumber_js_1.BigNumber)(lockupAccount.stakeInfo.minimumStake.toString())
|
|
354
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
355
|
+
.toFixed(),
|
|
336
356
|
},
|
|
337
357
|
};
|
|
338
358
|
}
|
|
@@ -355,8 +375,12 @@ class StakeService {
|
|
|
355
375
|
address: stakeAddress.toString(),
|
|
356
376
|
nonce: BigInt(stakeAccount.nonce.toString()),
|
|
357
377
|
createdTime: stakeAccount.createdTime.toNumber(),
|
|
358
|
-
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
359
|
-
|
|
378
|
+
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
379
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
380
|
+
.toFixed(),
|
|
381
|
+
rewardAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.rewardAmount.toString())
|
|
382
|
+
.div(UNITS_PER_REWARD_TOKEN)
|
|
383
|
+
.toFixed(),
|
|
360
384
|
stakeClaimed: stakeAccount.stakeClaimed,
|
|
361
385
|
lockPeriod: stakeAccount.lockPeriod.toNumber(),
|
|
362
386
|
lockup: stakeAccount.lockup.toString(),
|
|
@@ -393,20 +417,27 @@ class StakeService {
|
|
|
393
417
|
const nonces = Array.from({ length: currentNonce }, (_, i) => BigInt(i));
|
|
394
418
|
const stakeAddresses = nonces.map((nonce) => (0, pda_1.deriveStakeAddress)(userAdress, lockupAddress, nonce, this.programId));
|
|
395
419
|
const stakeAddressesChunks = (0, utils_1.chunkArray)(stakeAddresses, 100);
|
|
396
|
-
|
|
420
|
+
const stakeWithHash2D = [];
|
|
397
421
|
for (const stakeAddresses of stakeAddressesChunks) {
|
|
398
422
|
const accountInfos = await this.connection.getMultipleAccountsInfo(stakeAddresses, {
|
|
399
423
|
commitment: this.connection.commitment,
|
|
400
424
|
});
|
|
401
425
|
const stakeAccountsInfo = accountInfos.map((value, i) => {
|
|
402
|
-
(0, assert_1.default)(value, "Account does not exists for stake address: " +
|
|
426
|
+
(0, assert_1.default)(value, "Account does not exists for stake address: " +
|
|
427
|
+
stakeAddresses[i] +
|
|
428
|
+
" at nonce: " +
|
|
429
|
+
nonces[i]);
|
|
403
430
|
const stakeAccount = this.program.coder.accounts.decode(this.program.idl.accounts[2].name, value.data);
|
|
404
431
|
const info = {
|
|
405
432
|
address: stakeAddresses[i].toString(),
|
|
406
433
|
nonce: BigInt(stakeAccount.nonce.toString()),
|
|
407
434
|
createdTime: stakeAccount.createdTime.toNumber(),
|
|
408
|
-
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
409
|
-
|
|
435
|
+
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
436
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
437
|
+
.toFixed(),
|
|
438
|
+
rewardAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.rewardAmount.toString())
|
|
439
|
+
.div(UNITS_PER_REWARD_TOKEN)
|
|
440
|
+
.toFixed(),
|
|
410
441
|
stakeClaimed: stakeAccount.stakeClaimed,
|
|
411
442
|
lockPeriod: stakeAccount.lockPeriod.toNumber(),
|
|
412
443
|
lockup: stakeAccount.lockup.toString(),
|
|
@@ -414,7 +445,7 @@ class StakeService {
|
|
|
414
445
|
};
|
|
415
446
|
return info;
|
|
416
447
|
});
|
|
417
|
-
|
|
448
|
+
const stakesWithHash = new Array(stakeAccountsInfo.length);
|
|
418
449
|
const { maxConcurrent = 3, minDelayMs = 400 } = options;
|
|
419
450
|
const queue = new rateLimitQueue_1.RateLimitedQueue(maxConcurrent, minDelayMs); // Max 3 concurrent, 300ms between requests
|
|
420
451
|
const promises = stakeAccountsInfo.map((stakeInfo, index) => queue.add(async () => {
|
|
@@ -492,8 +523,12 @@ class StakeService {
|
|
|
492
523
|
address: accountInfo.pubkey.toString(),
|
|
493
524
|
nonce: BigInt(stakeAccount.nonce.toString()),
|
|
494
525
|
createdTime: stakeAccount.createdTime.toNumber(),
|
|
495
|
-
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
496
|
-
|
|
526
|
+
stakedAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.stakedAmount.toString())
|
|
527
|
+
.div(UNITS_PER_STAKE_TOKEN)
|
|
528
|
+
.toFixed(),
|
|
529
|
+
rewardAmount: (0, bignumber_js_1.BigNumber)(stakeAccount.rewardAmount.toString())
|
|
530
|
+
.div(UNITS_PER_REWARD_TOKEN)
|
|
531
|
+
.toFixed(),
|
|
497
532
|
stakeClaimed: stakeAccount.stakeClaimed,
|
|
498
533
|
lockPeriod: stakeAccount.lockPeriod.toNumber(),
|
|
499
534
|
lockup: stakeAccount.lockup.toString(),
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import type BN from "bn.js";
|
|
3
|
+
export type InitLockupInstructionData = {
|
|
4
|
+
rewardSchemes: ParsedRewardScheme[];
|
|
5
|
+
fee: BN;
|
|
6
|
+
feeVault: PublicKey;
|
|
7
|
+
name: string;
|
|
8
|
+
minimumStake: BN;
|
|
9
|
+
};
|
|
10
|
+
export type UpdateLockupInstructionData = {
|
|
11
|
+
rewardSchemes: ParsedRewardScheme[];
|
|
12
|
+
fee: BN;
|
|
13
|
+
feeVault: PublicKey;
|
|
14
|
+
minimumStake: BN;
|
|
15
|
+
};
|
|
16
|
+
export type ParsedRewardScheme = {
|
|
17
|
+
duration: BN;
|
|
18
|
+
reward: BN;
|
|
19
|
+
};
|
|
20
|
+
export type Numeric = string | number;
|
|
21
|
+
export type RewardScheme = {
|
|
22
|
+
duration: number;
|
|
23
|
+
rewardRate: Numeric;
|
|
24
|
+
};
|
|
25
|
+
export type StakeInstructionData = {
|
|
26
|
+
amount: BN;
|
|
27
|
+
lockPeriod: BN;
|
|
28
|
+
nonce: BN;
|
|
29
|
+
};
|
|
30
|
+
export type LockupInfo = {
|
|
31
|
+
address: string;
|
|
32
|
+
feeInfo: {
|
|
33
|
+
fee: string;
|
|
34
|
+
feeVault: string;
|
|
35
|
+
};
|
|
36
|
+
rewardToken: {
|
|
37
|
+
tokenAddress: string;
|
|
38
|
+
};
|
|
39
|
+
stakeToken: {
|
|
40
|
+
tokenAdress: string;
|
|
41
|
+
totalStaked: string;
|
|
42
|
+
};
|
|
43
|
+
stakeInfo: {
|
|
44
|
+
name: string;
|
|
45
|
+
creator: string;
|
|
46
|
+
rewardSchemes: RewardScheme[];
|
|
47
|
+
minimumStake: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export type StakeInfo = {
|
|
51
|
+
address: string;
|
|
52
|
+
nonce: bigint;
|
|
53
|
+
createdTime: number;
|
|
54
|
+
stakedAmount: string;
|
|
55
|
+
rewardAmount: string;
|
|
56
|
+
stakeClaimed: boolean;
|
|
57
|
+
lockPeriod: number;
|
|
58
|
+
staker: string;
|
|
59
|
+
lockup: string;
|
|
60
|
+
};
|
|
61
|
+
export type UserNonceInfo = {
|
|
62
|
+
address: string;
|
|
63
|
+
nonce: bigint;
|
|
64
|
+
};
|
|
65
|
+
export type StakeInfoWithHash = StakeInfo & {
|
|
66
|
+
hash: string;
|
|
67
|
+
};
|
package/dist/types.js
ADDED
package/dist/utils.js
CHANGED
|
@@ -17,9 +17,11 @@ async function callWithEnhancedBackoff(fn, maxRetries = MAX_RETRIES, backoffFact
|
|
|
17
17
|
catch (error) {
|
|
18
18
|
if (attempt === maxRetries)
|
|
19
19
|
throw error;
|
|
20
|
-
let delay = Math.min(baseDelay *
|
|
20
|
+
let delay = Math.min(baseDelay * backoffFactor ** attempt, maxDelay);
|
|
21
21
|
// Handle 429 specifically with longer delays
|
|
22
|
-
if (error?.status === 429 ||
|
|
22
|
+
if (error?.status === 429 ||
|
|
23
|
+
error?.code === 429 ||
|
|
24
|
+
error?.message?.includes("429")) {
|
|
23
25
|
delay = Math.min(delay * backoffFactor, maxDelay); // Double delay for rate limits
|
|
24
26
|
console.warn(`Rate limit hit, waiting ${delay}ms before retry ${attempt + 1}/${maxRetries}`);
|
|
25
27
|
}
|
package/package.json
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
{
|
|
2
|
+
"author": "Zebec Network | Ashish Sapkota",
|
|
3
|
+
"dependencies": {
|
|
4
|
+
"@coral-xyz/anchor": "^0.31.1",
|
|
5
|
+
"@solana/web3.js": "^1.98.2",
|
|
6
|
+
"@zebec-network/core-utils": "^1.1.1",
|
|
7
|
+
"@zebec-network/solana-common": "^2.3.1",
|
|
8
|
+
"bignumber.js": "^9.3.1",
|
|
9
|
+
"buffer": "^6.0.3"
|
|
10
|
+
},
|
|
11
|
+
"description": "An SDK for zebec network stake solana program",
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/bn.js": "^5.2.0",
|
|
14
|
+
"@types/mocha": "^10.0.10",
|
|
15
|
+
"@types/node": "^25.0.3",
|
|
16
|
+
"dotenv": "^17.2.3",
|
|
17
|
+
"mocha": "^11.7.5",
|
|
18
|
+
"prettier": "^3.6.2",
|
|
19
|
+
"rimraf": "^6.1.2",
|
|
20
|
+
"ts-mocha": "^11.1.0",
|
|
21
|
+
"ts-node": "^10.9.2",
|
|
22
|
+
"typescript": "^5.9.2"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"keywords": [
|
|
28
|
+
"solana",
|
|
29
|
+
"zebec",
|
|
30
|
+
"zebec network",
|
|
31
|
+
"stake",
|
|
32
|
+
"staking"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"main": "dist/index.js",
|
|
36
|
+
"name": "@zebec-network/zebec-stake-sdk",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "npm run clean && tsc",
|
|
39
|
+
"clean": "rimraf ./dist",
|
|
40
|
+
"format": "npx @biomejs/biome format --write",
|
|
41
|
+
"start": "ts-node src/index.ts",
|
|
42
|
+
"test": "ts-mocha -p ./tsconfig.json -t 1000000000 test/**/*.test.ts",
|
|
43
|
+
"test:single": "ts-mocha -p ./tsconfig.json -t 1000000000"
|
|
44
|
+
},
|
|
45
|
+
"types": "dist/index.d.ts",
|
|
46
|
+
"version": "1.3.1"
|
|
47
47
|
}
|