@streamflow/staking 7.0.0-alpha.6

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.
Files changed (38) hide show
  1. package/README.md +216 -0
  2. package/dist/cjs/index.js +39 -0
  3. package/dist/cjs/solana/client.js +315 -0
  4. package/dist/cjs/solana/constants.js +61 -0
  5. package/dist/cjs/solana/descriptor/fee_manager.js +2 -0
  6. package/dist/cjs/solana/descriptor/idl/fee_manager.json +284 -0
  7. package/dist/cjs/solana/descriptor/idl/reward_pool.json +905 -0
  8. package/dist/cjs/solana/descriptor/idl/stake_pool.json +734 -0
  9. package/dist/cjs/solana/descriptor/reward_pool.js +2 -0
  10. package/dist/cjs/solana/descriptor/stake_pool.js +2 -0
  11. package/dist/cjs/solana/lib/derive-accounts.js +46 -0
  12. package/dist/cjs/solana/lib/rewards.js +134 -0
  13. package/dist/cjs/solana/types.js +2 -0
  14. package/dist/cjs/solana/utils.js +61 -0
  15. package/dist/esm/index.d.ts +6 -0
  16. package/dist/esm/index.js +6 -0
  17. package/dist/esm/solana/client.d.ts +77 -0
  18. package/dist/esm/solana/client.js +313 -0
  19. package/dist/esm/solana/constants.d.ts +50 -0
  20. package/dist/esm/solana/constants.js +58 -0
  21. package/dist/esm/solana/descriptor/fee_manager.d.ts +290 -0
  22. package/dist/esm/solana/descriptor/fee_manager.js +1 -0
  23. package/dist/esm/solana/descriptor/idl/fee_manager.json +284 -0
  24. package/dist/esm/solana/descriptor/idl/reward_pool.json +905 -0
  25. package/dist/esm/solana/descriptor/idl/stake_pool.json +734 -0
  26. package/dist/esm/solana/descriptor/reward_pool.d.ts +939 -0
  27. package/dist/esm/solana/descriptor/reward_pool.js +1 -0
  28. package/dist/esm/solana/descriptor/stake_pool.d.ts +538 -0
  29. package/dist/esm/solana/descriptor/stake_pool.js +1 -0
  30. package/dist/esm/solana/lib/derive-accounts.d.ts +10 -0
  31. package/dist/esm/solana/lib/derive-accounts.js +31 -0
  32. package/dist/esm/solana/lib/rewards.d.ts +24 -0
  33. package/dist/esm/solana/lib/rewards.js +136 -0
  34. package/dist/esm/solana/types.d.ts +69 -0
  35. package/dist/esm/solana/types.js +1 -0
  36. package/dist/esm/solana/utils.d.ts +11 -0
  37. package/dist/esm/solana/utils.js +50 -0
  38. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # Streamflow Staking
2
+
3
+ ## JS SDK to interact with Streamflow Staking.
4
+
5
+ This package allows you to
6
+ - `create staking pools and rewards pools`;
7
+ - `claim rewards`;
8
+ - `stake`;
9
+ - `unstake`;
10
+ - `fund rewards pools`;
11
+
12
+ with the Streamflow Staking protocol.
13
+
14
+ This protocol is the complex of several programs which ensures flexibility and accountability for stakers and respective incentives for them.
15
+
16
+ aforementioned programs are:
17
+ - Stake Pools Program
18
+ - Reward Pools Program
19
+ - Fee Management Program (for streamflow usage, non-required and ommited from further docs)
20
+
21
+
22
+ ## API Reference
23
+ API Documentation available here: [docs site →](https://streamflow-finance.github.io/js-sdk/)
24
+
25
+ The Stake Pool Program entities:
26
+ 1. Stake Pool
27
+ 2. Stake Entry (PDA which stores info about current stakes, durations and rewards structure)
28
+
29
+ The Reward Pool Program entities:
30
+ 1. Reward Pool (must has a back-reference to a stake pool)
31
+ 2. Reward Entry (PDA stores claims information and time-bound params)
32
+
33
+ 1 Stake Pool can have N Reward Pools.
34
+
35
+ > [!NOTE]
36
+ > There is a limitation of 255 Reward Pools per a single token mint for a stake pool.
37
+
38
+
39
+ ## Installation
40
+
41
+ Install the sdk with npm
42
+
43
+ ```npm
44
+ npm install @streamflow/staking
45
+ ```
46
+ ```yarn
47
+ yarn install @streamflow/staking
48
+ ```
49
+ ```pnpm
50
+ pnpm add @streamflow/staking
51
+ ```
52
+
53
+ ## Usage/Examples
54
+
55
+ #### Create a client
56
+ ```typescript
57
+ const client = new SolanaStakingClient({
58
+ clusterUrl: "https://api.mainnet-beta.solana.com",
59
+ cluster: ICluster.Mainnet
60
+ });
61
+ ```
62
+
63
+ > [!WARNING]
64
+ > All operations expect ATAs to be created at the moment of execution and don't add these instructions.
65
+ > - Stake - staker's ATAs for stake mint and stake mint (see deriveStakeMintPDA fn)
66
+ > - Withdraw/Unstake - staker's ATAs for stake mint and stake mint (see deriveStakeMintPDA fn)
67
+ > - Claim rewards - staker's ATAs for reward mint
68
+ > - Fund Reward Pool - signer creates Streamflow Treasury's ATA for holding fee if defined
69
+
70
+ #### Read operations
71
+ ```typescript
72
+
73
+ await client.searchStakePools({ mint, creator }) // returns results of lookup, `mint` and `creator` both optional. Omit the argument to get all pools
74
+
75
+ await client.searchStakeEntries({ payer, stakePool }) // returns all stake entries. Omit the argument to get all.
76
+
77
+ await client.searchRewardPools({ stakePool, mint })
78
+
79
+ await client.searchRewardEntries({ stakeEntry, rewardPool })
80
+
81
+ ```
82
+
83
+ #### Create a staking pool
84
+
85
+ ```typescript
86
+ const client = new SolanaStakingClient({
87
+ clusterUrl: "https://api.mainnet-beta.solana.com",
88
+ cluster: ICluster.Mainnet
89
+ });
90
+ /*
91
+ Rewards Multiplier powered by 10^9.
92
+ Example: if multiplier is 2_000_000_000 than stakes for maxDuration will have 2x more rewards than stakes for minDuration
93
+ */
94
+ const multiplier = new BN(1_000_000_000);
95
+ /*
96
+ 30 days - Unix time in seconds
97
+ */
98
+ const maxDuration = new BN(2592000);
99
+ /*
100
+ 1 day - Unix time in seconds
101
+ */
102
+ const maxDuration = new BN(86400);
103
+ /*
104
+ Limits signers that can create/assign reward pools to this stake pool. True - anyone can
105
+ */
106
+ const permissionless = false;
107
+ /*
108
+ [0;256) derive stake pool PDA account address.
109
+ If stake pool with the same mint already exists, it is required to pick a vacant nonce
110
+ */
111
+ const nonce = 0;
112
+
113
+ const { metadataId: stakePoolPda } = await client.createStakePool({
114
+ maxWeight: multiplier,
115
+ maxDuration,
116
+ minDuration,
117
+ mint: MINT_ADDRESS,
118
+ permissionless,
119
+ nonce:
120
+ })
121
+
122
+ ```
123
+
124
+ #### Create a rewardPool pool
125
+ ```typescript
126
+ /*
127
+ [0;256) derive reward pool PDA account address.
128
+ If reward pool with the same mint already exists, it is required to pick a vacant nonce
129
+ */
130
+ const nonce = 0;
131
+ /*
132
+ Amount of rewarding tokens stakers get in return for staking exactly 1 token to the staking pool
133
+ */
134
+ const rewardAmount = new BN(100);
135
+ /*
136
+ 1 day - Unix time in seconds. Period for rewarding stakers. Period starts counting from the moment of staking
137
+ */
138
+ const rewardPeriod = new BN(86400);
139
+ const rewardMint = REWARD_MINT_ADDRESS; // rewarding token
140
+ /*
141
+ Whether to allow anyone to fund this reward pool. If true anyone can fund, otherwise only the creator can
142
+ */
143
+ const permissionless = true;
144
+
145
+ client.createRewardPool({
146
+ nonce,
147
+ rewardAmount,
148
+ rewardPeriod,
149
+ rewardMint,
150
+ permissionless = false,
151
+ stakePool: stakePoolPda,
152
+ stakePoolMint: MINT_ADDRESS,
153
+ })
154
+ ```
155
+
156
+
157
+ #### Deposit/Stake to a stake pool
158
+ ```typescript
159
+ /*
160
+ [0;256) derive stake entry PDA account address.
161
+ If stake entry with the same nonce already exists, it is required to pick a vacant one
162
+ */
163
+ const nonce = 0;
164
+ const amount = new BN(1000); // tokens to stake
165
+ const duration = new BN(86400 * 2) // 2 days, must be in the range of stakePool's min and max durations
166
+ await client.stake({ nonce, amount, duration, stakePool, stakePoolMint });
167
+ ```
168
+
169
+ #### Unstake/Withdraw to a stake pool
170
+ ```typescript
171
+ /*
172
+ Usually to achieve this the app already loaded available stakeEntries.
173
+ Stake Entry holds used `nonce`, so `nonce` below could be taken from the stake entry
174
+ */
175
+
176
+ /*
177
+ [0;256) derived stake entry PDA account address.
178
+ If stake entry with the same nonce already exists, it is required to pick a vacant one
179
+ */
180
+ const nonce = 0; //
181
+ await client.unstake({ stakePool, stakePoolMint, nonce });
182
+ ```
183
+
184
+ #### Claim a reward
185
+ Since each stake entry can produce multiple rewards (single claim per each reward pool linked to the staking pool) this operation
186
+ can be triggered for every reward pool separately.
187
+
188
+ ```typescript
189
+ await client.claimRewards({
190
+ rewardPoolNonce,
191
+ depositNonce,
192
+ stakePool,
193
+ rewardMint,
194
+ });
195
+ ```
196
+
197
+ > [!Note]
198
+ > All operations have accompanying APIs for manual transaction building. Consult with API docs to find respective calls.
199
+ > For instance, prepareClaimRewardsInstructions.
200
+ > These APIs allow to aggregate multiple operations in a single transaction according to the app needs.
201
+
202
+ ## Appendix
203
+
204
+ Streamflow Staking protocol program IDs
205
+
206
+ | Solana | |
207
+ | ------- | -------------------------------------------- |
208
+ | Staking Pools Mainnet | STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH |
209
+ | Reward Pools Mainnet | RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj |
210
+ | ---- | --- |
211
+ | Staking Pools Devnet | STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH |
212
+ | Reward Pools Devnet | RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj |
213
+
214
+ ### IDLs
215
+ For further details you can consult with IDLs of protocols available at:
216
+ `@streamflow/staking/dist/esm/solana/descriptor`
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ var __importStar = (this && this.__importStar) || function (mod) {
22
+ if (mod && mod.__esModule) return mod;
23
+ var result = {};
24
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
+ __setModuleDefault(result, mod);
26
+ return result;
27
+ };
28
+ var __importDefault = (this && this.__importDefault) || function (mod) {
29
+ return (mod && mod.__esModule) ? mod : { "default": mod };
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.constants = exports.SolanaStakingClient = void 0;
33
+ var client_js_1 = require("./solana/client.js");
34
+ Object.defineProperty(exports, "SolanaStakingClient", { enumerable: true, get: function () { return __importDefault(client_js_1).default; } });
35
+ __exportStar(require("./solana/utils.js"), exports);
36
+ __exportStar(require("./solana/types.js"), exports);
37
+ __exportStar(require("./solana/lib/derive-accounts.js"), exports);
38
+ __exportStar(require("./solana/lib/rewards.js"), exports);
39
+ exports.constants = __importStar(require("./solana/constants.js"));
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const anchor_1 = require("@coral-xyz/anchor");
7
+ const spl_token_1 = require("@solana/spl-token");
8
+ const web3_js_1 = require("@solana/web3.js");
9
+ const common_1 = require("@streamflow/common");
10
+ const solana_1 = require("@streamflow/common/solana");
11
+ const constants_js_1 = require("./constants.js");
12
+ const fee_manager_json_1 = __importDefault(require("./descriptor/idl/fee_manager.json"));
13
+ const reward_pool_json_1 = __importDefault(require("./descriptor/idl/reward_pool.json"));
14
+ const stake_pool_json_1 = __importDefault(require("./descriptor/idl/stake_pool.json"));
15
+ const derive_accounts_js_1 = require("./lib/derive-accounts.js");
16
+ class SolanaStakingClient {
17
+ constructor({ clusterUrl, cluster = common_1.ICluster.Mainnet, commitment = "confirmed", programIds, sendRate = 1, sendThrottler, }) {
18
+ this.commitment = commitment;
19
+ this.connection = new web3_js_1.Connection(clusterUrl, this.commitment);
20
+ this.sendThrottler = sendThrottler ?? (0, solana_1.buildSendThrottler)(sendRate);
21
+ const stakePoolIdl = {
22
+ ...stake_pool_json_1.default,
23
+ address: programIds?.stakePool ?? constants_js_1.STAKE_POOL_PROGRAM_ID[cluster] ?? stake_pool_json_1.default.address,
24
+ };
25
+ const rewardPoolIdl = {
26
+ ...reward_pool_json_1.default,
27
+ address: programIds?.rewardPool ?? constants_js_1.REWARD_POOL_PROGRAM_ID[cluster] ?? reward_pool_json_1.default.address,
28
+ };
29
+ const feeManagerIdl = {
30
+ ...fee_manager_json_1.default,
31
+ address: programIds?.feeManager ?? fee_manager_json_1.default.address,
32
+ };
33
+ this.programs = {
34
+ stakePoolProgram: new anchor_1.Program(stakePoolIdl, {
35
+ connection: this.connection,
36
+ }),
37
+ rewardPoolProgram: new anchor_1.Program(rewardPoolIdl, {
38
+ connection: this.connection,
39
+ }),
40
+ feeManagerProgram: new anchor_1.Program(feeManagerIdl, {
41
+ connection: this.connection,
42
+ }),
43
+ };
44
+ }
45
+ getCurrentProgramId(programKey) {
46
+ const program = this.programs[programKey];
47
+ invariant(program, `Program ${programKey} is not found`);
48
+ return program.programId;
49
+ }
50
+ getCommitment() {
51
+ return typeof this.commitment == "string" ? this.commitment : this.commitment.commitment;
52
+ }
53
+ async getStakePool(id) {
54
+ const { stakePoolProgram } = this.programs;
55
+ return stakePoolProgram.account.stakePool.fetch(id);
56
+ }
57
+ async searchStakePools(criteria = {}) {
58
+ const { stakePoolProgram } = this.programs;
59
+ return stakePoolProgram.account.stakePool.all(getFilters(criteria, constants_js_1.STAKE_POOL_BYTE_OFFSETS));
60
+ }
61
+ async getStakeEntry(id) {
62
+ const { stakePoolProgram } = this.programs;
63
+ return stakePoolProgram.account.stakeEntry.fetch(id);
64
+ }
65
+ async searchStakeEntries(criteria = {}) {
66
+ const { stakePoolProgram } = this.programs;
67
+ return stakePoolProgram.account.stakeEntry.all(getFilters(criteria, constants_js_1.STAKE_ENTRY_BYTE_OFFSETS));
68
+ }
69
+ async searchRewardPools(criteria = {}) {
70
+ const { rewardPoolProgram } = this.programs;
71
+ return rewardPoolProgram.account.rewardPool.all(getFilters(criteria, constants_js_1.REWARD_POOL_BYTE_OFFSETS));
72
+ }
73
+ async searchRewardEntries(criteria) {
74
+ const { rewardPoolProgram } = this.programs;
75
+ return rewardPoolProgram.account.rewardEntry.all(getFilters(criteria, constants_js_1.REWARD_ENTRY_BYTE_OFFSETS));
76
+ }
77
+ getFeeValueIfExists(target) {
78
+ const { feeManagerProgram } = this.programs;
79
+ const feeValueKey = (0, derive_accounts_js_1.deriveFeeValuePDA)(feeManagerProgram.programId, new web3_js_1.PublicKey(target));
80
+ return feeManagerProgram.account.feeValue.fetchNullable(feeValueKey);
81
+ }
82
+ async createStakePool(data, extParams) {
83
+ const { ixs, publicKey } = await this.prepareCreateStakePoolInstructions(data, extParams);
84
+ const { signature } = await this.execute(ixs, extParams);
85
+ return {
86
+ ixs,
87
+ txId: signature,
88
+ metadataId: publicKey,
89
+ };
90
+ }
91
+ async prepareCreateStakePoolInstructions({ maxWeight, maxDuration, minDuration, mint, permissionless = false, nonce, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID, }, extParams) {
92
+ const { stakePoolProgram } = this.programs;
93
+ const creator = extParams.invoker.publicKey;
94
+ invariant(creator, "Undefined invoker publicKey");
95
+ const createInstruction = await stakePoolProgram.methods
96
+ .createPool(nonce, maxWeight, minDuration, maxDuration, permissionless)
97
+ .accounts({
98
+ creator,
99
+ mint,
100
+ tokenProgram: tokenProgramId,
101
+ })
102
+ .instruction();
103
+ const stakePoolPDA = (0, derive_accounts_js_1.deriveStakePoolPDA)(stakePoolProgram.programId, pk(mint), creator, nonce);
104
+ return { ixs: [createInstruction], publicKey: stakePoolPDA };
105
+ }
106
+ async stake(data, extParams) {
107
+ const { ixs } = await this.prepareStakeInstructions(data, extParams);
108
+ const { signature } = await this.execute(ixs, extParams);
109
+ return {
110
+ ixs,
111
+ txId: signature,
112
+ };
113
+ }
114
+ async prepareStakeInstructions({ nonce, amount, duration, stakePool, stakePoolMint, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID }, extParams) {
115
+ const { stakePoolProgram } = this.programs;
116
+ const staker = extParams.invoker.publicKey;
117
+ invariant(staker, "Undefined invoker publicKey");
118
+ const mint = (0, derive_accounts_js_1.deriveStakeMintPDA)(stakePoolProgram.programId, pk(stakePool));
119
+ const stakeMintAccountKey = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, staker, false, pk(tokenProgramId));
120
+ const poolMintAccountKey = (0, spl_token_1.getAssociatedTokenAddressSync)(pk(stakePoolMint), staker, false, pk(tokenProgramId));
121
+ const instruction = await stakePoolProgram.methods
122
+ .stake(nonce, amount, duration)
123
+ .accounts({
124
+ stakePool: stakePool,
125
+ tokenProgram: tokenProgramId,
126
+ from: poolMintAccountKey,
127
+ to: stakeMintAccountKey,
128
+ authority: staker,
129
+ payer: staker,
130
+ })
131
+ .instruction();
132
+ return { ixs: [instruction] };
133
+ }
134
+ async unstake(data, extParams) {
135
+ const { ixs } = await this.prepareUnstakeInstructions(data, extParams);
136
+ const { signature } = await this.execute(ixs, extParams);
137
+ return {
138
+ ixs,
139
+ txId: signature,
140
+ };
141
+ }
142
+ async prepareUnstakeInstructions({ stakePool, stakePoolMint, nonce, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID }, extParams) {
143
+ const { stakePoolProgram } = this.programs;
144
+ const staker = extParams.invoker.publicKey;
145
+ invariant(staker, "Undefined invoker publicKey");
146
+ const stakeMintKey = (0, derive_accounts_js_1.deriveStakeMintPDA)(stakePoolProgram.programId, pk(stakePool));
147
+ const stakeEntryKey = (0, derive_accounts_js_1.deriveStakeEntryPDA)(stakePoolProgram.programId, pk(stakePool), staker, nonce);
148
+ const poolMintAccountKey = (0, spl_token_1.getAssociatedTokenAddressSync)(pk(stakePoolMint), staker, false, pk(tokenProgramId));
149
+ const stakeMintAccountKey = (0, spl_token_1.getAssociatedTokenAddressSync)(stakeMintKey, staker, false, pk(tokenProgramId));
150
+ const instruction = await stakePoolProgram.methods
151
+ .unstake()
152
+ .accounts({
153
+ stakeEntry: stakeEntryKey,
154
+ to: poolMintAccountKey,
155
+ from: stakeMintAccountKey,
156
+ authority: staker,
157
+ tokenProgram: tokenProgramId,
158
+ })
159
+ .instruction();
160
+ return { ixs: [instruction] };
161
+ }
162
+ async createRewardPool(data, extParams) {
163
+ const { ixs, publicKey } = await this.prepareCreateRewardPoolInstructions(data, extParams);
164
+ const { signature } = await this.execute(ixs, extParams);
165
+ return {
166
+ ixs,
167
+ txId: signature,
168
+ metadataId: publicKey,
169
+ };
170
+ }
171
+ async prepareCreateRewardPoolInstructions({ nonce, rewardAmount, rewardPeriod, rewardMint, permissionless = false, stakePool, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID, }, extParams) {
172
+ const { rewardPoolProgram } = this.programs;
173
+ const creator = extParams.invoker.publicKey;
174
+ invariant(creator, "Undefined invoker publicKey");
175
+ const instruction = await rewardPoolProgram.methods
176
+ .createPool(nonce, rewardAmount, rewardPeriod, permissionless)
177
+ .accounts({
178
+ creator,
179
+ stakePool,
180
+ mint: rewardMint,
181
+ tokenProgram: tokenProgramId,
182
+ })
183
+ .instruction();
184
+ const rewardPoolKey = (0, derive_accounts_js_1.deriveRewardPoolPDA)(rewardPoolProgram.programId, pk(stakePool), pk(rewardMint), nonce);
185
+ return { publicKey: rewardPoolKey, ixs: [instruction] };
186
+ }
187
+ async claimRewards(data, extParams) {
188
+ const { ixs } = await this.prepareClaimRewardsInstructions(data, extParams);
189
+ const { signature } = await this.execute(ixs, extParams);
190
+ return {
191
+ ixs,
192
+ txId: signature,
193
+ };
194
+ }
195
+ async prepareClaimRewardsInstructions({ rewardPoolNonce, depositNonce, stakePool, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID, rewardMint }, extParams) {
196
+ const { stakePoolProgram, rewardPoolProgram } = this.programs;
197
+ const staker = extParams.invoker.publicKey;
198
+ invariant(staker, "Undefined invoker publicKey");
199
+ const instruction = await rewardPoolProgram.methods
200
+ .claimRewards()
201
+ .accounts({
202
+ stakeEntry: (0, derive_accounts_js_1.deriveStakeEntryPDA)(stakePoolProgram.programId, pk(stakePool), staker, depositNonce),
203
+ rewardPool: (0, derive_accounts_js_1.deriveRewardPoolPDA)(rewardPoolProgram.programId, pk(stakePool), pk(rewardMint), rewardPoolNonce),
204
+ claimant: staker,
205
+ tokenProgram: tokenProgramId,
206
+ to: (0, spl_token_1.getAssociatedTokenAddressSync)(pk(rewardMint), staker, false, pk(tokenProgramId)),
207
+ })
208
+ .instruction();
209
+ return { ixs: [instruction] };
210
+ }
211
+ async fundPool(data, extParams) {
212
+ const { ixs } = await this.prepareFundPoolInstructions(data, extParams);
213
+ const { signature } = await this.execute(ixs, extParams);
214
+ return {
215
+ ixs,
216
+ txId: signature,
217
+ };
218
+ }
219
+ async prepareFundPoolInstructions({ amount, tokenProgramId = spl_token_1.TOKEN_PROGRAM_ID, rewardMint, stakePool, feeValue, nonce }, extParams) {
220
+ const { rewardPoolProgram } = this.programs;
221
+ const staker = extParams.invoker.publicKey;
222
+ invariant(staker, "Undefined invoker publicKey");
223
+ const existingFee = await this.getFeeValueIfExists(staker);
224
+ const rewardMintPk = pk(rewardMint);
225
+ const tokenProgramPk = pk(tokenProgramId);
226
+ const treasuryATA = !existingFee || existingFee.streamflowFee.gtn(0)
227
+ ? await (0, solana_1.checkOrCreateAtaBatch)(this.connection, [constants_js_1.STREAMFLOW_TREASURY_PUBLIC_KEY], rewardMintPk, extParams.invoker, tokenProgramPk)
228
+ : null;
229
+ const rewardPoolPda = (0, derive_accounts_js_1.deriveRewardPoolPDA)(rewardPoolProgram.programId, pk(stakePool), rewardMintPk, nonce);
230
+ const instruction = await rewardPoolProgram.methods
231
+ .fundPool(amount)
232
+ .accountsPartial({
233
+ funder: staker,
234
+ rewardPool: rewardPoolPda,
235
+ from: (0, spl_token_1.getAssociatedTokenAddressSync)(rewardMintPk, staker, false, tokenProgramPk),
236
+ tokenProgram: tokenProgramId,
237
+ vault: (0, derive_accounts_js_1.deriveRewardVaultPDA)(rewardPoolProgram.programId, rewardPoolPda),
238
+ mint: rewardMint,
239
+ feeValue,
240
+ })
241
+ .instruction();
242
+ return { ixs: treasuryATA ? treasuryATA.concat([instruction]) : [instruction] };
243
+ }
244
+ async createRewardEntry(data, extParams) {
245
+ const { ixs } = await this.prepareCreateRewardEntryInstructions(data, extParams);
246
+ const { signature } = await this.execute(ixs, extParams);
247
+ return {
248
+ ixs,
249
+ txId: signature,
250
+ };
251
+ }
252
+ async prepareCreateRewardEntryInstructions({ stakePoolMint, stakePool, rewardPoolNonce, depositNonce }, extParams) {
253
+ const { stakePoolProgram, rewardPoolProgram } = this.programs;
254
+ const staker = extParams.invoker.publicKey;
255
+ invariant(staker, "Undefined invoker publicKey");
256
+ const instruction = await rewardPoolProgram.methods
257
+ .createEntry()
258
+ .accounts({
259
+ payer: staker,
260
+ authority: staker,
261
+ stakeEntry: (0, derive_accounts_js_1.deriveStakeEntryPDA)(stakePoolProgram.programId, pk(stakePool), staker, depositNonce),
262
+ rewardPool: (0, derive_accounts_js_1.deriveRewardPoolPDA)(rewardPoolProgram.programId, pk(stakePool), pk(stakePoolMint), rewardPoolNonce),
263
+ })
264
+ .instruction();
265
+ return { ixs: [instruction] };
266
+ }
267
+ async execute(ixs, extParams) {
268
+ const { tx, hash, context } = await (0, solana_1.prepareTransaction)(this.connection, ixs, extParams.invoker.publicKey);
269
+ try {
270
+ const signature = await (0, solana_1.signAndExecuteTransaction)(this.connection, extParams.invoker, tx, {
271
+ hash,
272
+ context,
273
+ commitment: this.getCommitment(),
274
+ }, { sendThrottler: this.sendThrottler });
275
+ return { signature };
276
+ }
277
+ catch (err) {
278
+ if (err instanceof Error) {
279
+ const parsed = (0, anchor_1.translateError)(err, (0, anchor_1.parseIdlErrors)(this.programs.stakePoolProgram.idl));
280
+ if (parsed) {
281
+ throw new common_1.ContractError(err, parsed.name, parsed.message);
282
+ }
283
+ }
284
+ throw err;
285
+ }
286
+ }
287
+ }
288
+ exports.default = SolanaStakingClient;
289
+ function pk(address) {
290
+ return typeof address === "string" ? new web3_js_1.PublicKey(address) : address;
291
+ }
292
+ const prefix = "Assertion failed";
293
+ function invariant(condition, message) {
294
+ if (condition) {
295
+ return;
296
+ }
297
+ const provided = typeof message === "function" ? message() : message;
298
+ const value = provided ? `${prefix}: ${provided}` : prefix;
299
+ throw new Error(value);
300
+ }
301
+ function getFilters(criteria, byteOffsets) {
302
+ return Object.entries(criteria).reduce((acc, [key, value]) => {
303
+ const criteriaKey = key;
304
+ const effectiveByteOffset = byteOffsets[criteriaKey];
305
+ if (criteria[criteriaKey] && effectiveByteOffset) {
306
+ acc.push({
307
+ memcmp: {
308
+ offset: effectiveByteOffset,
309
+ bytes: value.toString(),
310
+ },
311
+ });
312
+ }
313
+ return acc;
314
+ }, []);
315
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REWARD_POOL_PROGRAM_ID = exports.STAKE_POOL_PROGRAM_ID = exports.REWARD_ENTRY_BYTE_OFFSETS = exports.REWARD_ENTRY_STAKE_ENTRY_OFFSET = exports.REWARD_ENTRY_REWARD_POOL_OFFSET = exports.REWARD_POOL_BYTE_OFFSETS = exports.REWARD_POOL_MINT_OFFSET = exports.REWARD_POOL_STAKE_POOL_OFFSET = exports.STAKE_POOL_BYTE_OFFSETS = exports.STAKE_POOL_CREATOR_OFFSET = exports.STAKE_POOL_MINT_OFFSET = exports.STAKE_ENTRY_BYTE_OFFSETS = exports.STAKE_ENTRY_OWNER_OFFSET = exports.STAKE_ENTRY_STAKE_POOL_OFFSET = exports.ANCHOR_DISCRIMINATOR_OFFSET = exports.STREAMFLOW_TREASURY_PUBLIC_KEY = exports.FEE_VALUE_PREFIX = exports.CONFIG_PREFIX = exports.REWARD_ENTRY_PREFIX = exports.REWARD_VAULT_PREFIX = exports.REWARD_POOL_PREFIX = exports.STAKE_VAULT_PREFIX = exports.STAKE_MINT_PREFIX = exports.STAKE_POOL_PREFIX = exports.STAKE_ENTRY_PREFIX = exports.STAKE_ENTRY_DISCRIMINATOR = exports.U64_MAX = exports.SCALE_PRECISION_FACTOR_BN = exports.SCALE_PRECISION_FACTOR = exports.DEFAULT_FEE_BN = exports.DEFAULT_FEE = exports.FEE_PRECISION_FACTOR_BN = exports.FEE_PRECISION_FACTOR = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const common_1 = require("@streamflow/common");
6
+ const web3_js_1 = require("@solana/web3.js");
7
+ exports.FEE_PRECISION_FACTOR = 10000;
8
+ exports.FEE_PRECISION_FACTOR_BN = new anchor_1.BN(exports.FEE_PRECISION_FACTOR);
9
+ exports.DEFAULT_FEE = 99;
10
+ exports.DEFAULT_FEE_BN = new anchor_1.BN(exports.DEFAULT_FEE);
11
+ exports.SCALE_PRECISION_FACTOR = 1000000000;
12
+ exports.SCALE_PRECISION_FACTOR_BN = new anchor_1.BN(exports.SCALE_PRECISION_FACTOR);
13
+ exports.U64_MAX = 18446744073709551615n;
14
+ exports.STAKE_ENTRY_DISCRIMINATOR = [187, 127, 9, 35, 155, 68, 86, 40];
15
+ exports.STAKE_ENTRY_PREFIX = Buffer.from("stake-entry", "utf-8");
16
+ exports.STAKE_POOL_PREFIX = Buffer.from("stake-pool", "utf-8");
17
+ exports.STAKE_MINT_PREFIX = Buffer.from("stake-mint", "utf-8");
18
+ exports.STAKE_VAULT_PREFIX = Buffer.from("stake-vault", "utf-8");
19
+ exports.REWARD_POOL_PREFIX = Buffer.from("reward-pool", "utf-8");
20
+ exports.REWARD_VAULT_PREFIX = Buffer.from("reward-vault", "utf-8");
21
+ exports.REWARD_ENTRY_PREFIX = Buffer.from("reward-entry", "utf-8");
22
+ exports.CONFIG_PREFIX = Buffer.from("config", "utf-8");
23
+ exports.FEE_VALUE_PREFIX = Buffer.from("fee-value", "utf-8");
24
+ exports.STREAMFLOW_TREASURY_PUBLIC_KEY = new web3_js_1.PublicKey("5SEpbdjFK5FxwTvfsGMXVQTD2v4M2c5tyRTxhdsPkgDw");
25
+ exports.ANCHOR_DISCRIMINATOR_OFFSET = 8;
26
+ exports.STAKE_ENTRY_STAKE_POOL_OFFSET = exports.ANCHOR_DISCRIMINATOR_OFFSET + 4;
27
+ exports.STAKE_ENTRY_OWNER_OFFSET = exports.STAKE_ENTRY_STAKE_POOL_OFFSET + 32;
28
+ exports.STAKE_ENTRY_BYTE_OFFSETS = {
29
+ payer: exports.STAKE_ENTRY_OWNER_OFFSET,
30
+ stakePool: exports.STAKE_ENTRY_STAKE_POOL_OFFSET,
31
+ };
32
+ exports.STAKE_POOL_MINT_OFFSET = exports.ANCHOR_DISCRIMINATOR_OFFSET + 8;
33
+ exports.STAKE_POOL_CREATOR_OFFSET = exports.STAKE_POOL_MINT_OFFSET + 32;
34
+ exports.STAKE_POOL_BYTE_OFFSETS = {
35
+ mint: exports.STAKE_POOL_MINT_OFFSET,
36
+ creator: exports.STAKE_POOL_CREATOR_OFFSET,
37
+ };
38
+ exports.REWARD_POOL_STAKE_POOL_OFFSET = exports.ANCHOR_DISCRIMINATOR_OFFSET + 2;
39
+ exports.REWARD_POOL_MINT_OFFSET = exports.REWARD_POOL_STAKE_POOL_OFFSET + 32;
40
+ exports.REWARD_POOL_BYTE_OFFSETS = {
41
+ stakePool: exports.REWARD_POOL_STAKE_POOL_OFFSET,
42
+ mint: exports.REWARD_POOL_MINT_OFFSET,
43
+ };
44
+ exports.REWARD_ENTRY_REWARD_POOL_OFFSET = exports.ANCHOR_DISCRIMINATOR_OFFSET;
45
+ exports.REWARD_ENTRY_STAKE_ENTRY_OFFSET = exports.REWARD_ENTRY_REWARD_POOL_OFFSET + 32;
46
+ exports.REWARD_ENTRY_BYTE_OFFSETS = {
47
+ stakeEntry: exports.REWARD_ENTRY_STAKE_ENTRY_OFFSET,
48
+ rewardPool: exports.REWARD_ENTRY_REWARD_POOL_OFFSET,
49
+ };
50
+ exports.STAKE_POOL_PROGRAM_ID = {
51
+ [common_1.ICluster.Mainnet]: "STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH",
52
+ [common_1.ICluster.Devnet]: "STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH",
53
+ [common_1.ICluster.Testnet]: "STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH",
54
+ [common_1.ICluster.Local]: "STAKEvGqQTtzJZH6BWDcbpzXXn2BBerPAgQ3EGLN2GH",
55
+ };
56
+ exports.REWARD_POOL_PROGRAM_ID = {
57
+ [common_1.ICluster.Mainnet]: "RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj",
58
+ [common_1.ICluster.Devnet]: "RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj",
59
+ [common_1.ICluster.Testnet]: "RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj",
60
+ [common_1.ICluster.Local]: "RWRDdfRbi3339VgKxTAXg4cjyniF7cbhNbMxZWiSKmj",
61
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });