Skip to content

Commit 5e14fe3

Browse files
authored
feat: expose reward pool clawbak (#346)
1 parent 135ed31 commit 5e14fe3

10 files changed

Lines changed: 71 additions & 8 deletions

File tree

lerna.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
2-
"packages": ["packages/*"],
3-
"version": "11.2.2",
2+
"packages": [
3+
"packages/*"
4+
],
5+
"version": "11.3.0",
46
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
57
"command": {
68
"run": {

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/common",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "Common utilities and types used by streamflow packages.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"type": "module",

packages/distributor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/distributor",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "JavaScript SDK to interact with Streamflow Airdrop protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/cjs/index.cjs",

packages/eslint-config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/eslint-config",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "ESLint configuration for Streamflow protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"engines": {

packages/launchpad/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/launchpad",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "JavaScript SDK to interact with Streamflow Launchpad protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/cjs/index.cjs",

packages/staking/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This package allows you to
88
- `stake`;
99
- `unstake`;
1010
- `fund rewards pools`;
11+
- `claw back unclaimed tokens from expired fixed reward pools`;
1112

1213
with the Streamflow Staking protocol.
1314

@@ -66,6 +67,7 @@ const client = new SolanaStakingClient({
6667
> - Withdraw/Unstake - staker's ATAs for stake mint and stake mint (see deriveStakeMintPDA fn)
6768
> - Claim rewards - staker's ATAs for reward mint
6869
> - Fund Reward Pool - signer creates Streamflow Treasury's ATA for holding fee if defined
70+
> - Clawback - authority's ATA for reward mint
6971
7072
#### Read operations
7173
```typescript
@@ -377,6 +379,26 @@ const { tokenAccount } = await client.createFundDelegate({
377379

378380
After creating the delegate, transfer reward tokens to the `tokenAccount`, which is an ATA for the fund delegate PDA address. The worker will periodically fund the reward pool from these tokens according to the schedule.
379381

382+
### Clawback fixed reward pool funds
383+
384+
`clawback` lets the reward pool authority recover any tokens still left in the reward pool vault after the stake pool has expired and the cooldown has passed.
385+
386+
- It is available only for the fixed reward pool program.
387+
- Dynamic reward pools do not support clawback.
388+
- The program enforces a 7 day delay after `stakePool.expiryTs` before clawback is allowed.
389+
- When it succeeds, the remaining reward tokens are transferred to the authority's ATA for the reward mint and the reward vault is closed.
390+
391+
```typescript
392+
await client.clawback({
393+
stakePool,
394+
stakePoolMint: mint,
395+
nonce: rewardPoolNonce,
396+
rewardMint,
397+
}, extParams);
398+
```
399+
400+
Use `prepareClawbackInstructions` if you want to include the clawback instruction in a larger custom transaction.
401+
380402
### Set Token Metadata
381403

382404
SolanaStakingClient also exposes original IDL of all programs, so you can use some additional instructions, that are not wrapped by the client. Currently there is no method to update Token Metadata of the Staking Mint that stakers get in return for their stake, but you can call the instructions from the original IDL like so:

packages/staking/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/staking",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "JavaScript SDK to interact with Streamflow Staking protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/cjs/index.cjs",

packages/staking/solana/client.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import {
5454
} from "./lib/derive-accounts.js";
5555
import type {
5656
ClaimRewardPoolArgs,
57+
ClawbackRewardPoolArgs,
5758
CloseRewardEntryArgs,
5859
CloseStakeEntryArgs,
5960
CreateFundDelegateArgs,
@@ -682,6 +683,39 @@ export class SolanaStakingClient {
682683
return { ixs: treasuryATA ? treasuryATA.concat([instruction]) : [instruction] };
683684
}
684685

686+
async clawback(data: ClawbackRewardPoolArgs, extParams: IInteractExt): Promise<ITransactionResult> {
687+
const { ixs } = await this.prepareClawbackInstructions(data, extParams);
688+
const { signature } = await this.execute(ixs, extParams);
689+
690+
return {
691+
ixs,
692+
txId: signature,
693+
};
694+
}
695+
696+
async prepareClawbackInstructions(
697+
{ nonce, rewardMint, stakePool, tokenProgramId = TOKEN_PROGRAM_ID }: ClawbackRewardPoolArgs,
698+
extParams: IInteractExt,
699+
) {
700+
const { rewardPoolProgram } = this.programs;
701+
const authority = extParams.invoker.publicKey;
702+
invariant(authority, "Undefined invoker publicKey");
703+
const rewardMintPk = pk(rewardMint);
704+
const tokenProgramPk = pk(tokenProgramId);
705+
const rewardPoolPda = deriveRewardPoolPDA(rewardPoolProgram.programId, pk(stakePool), rewardMintPk, nonce);
706+
const instruction = await rewardPoolProgram.methods
707+
.clawback()
708+
.accountsPartial({
709+
rewardPool: rewardPoolPda,
710+
authority,
711+
tokenProgram: tokenProgramId,
712+
to: getAssociatedTokenAddressSync(rewardMintPk, authority, true, tokenProgramPk),
713+
})
714+
.instruction();
715+
716+
return { ixs: [instruction] };
717+
}
718+
685719
async createRewardEntry(data: CreateRewardEntryArgs, extParams: IInteractExt): Promise<ITransactionResult> {
686720
const { ixs } = await this.prepareCreateRewardEntryInstructions(data, extParams);
687721
const { signature } = await this.execute(ixs, extParams);

packages/staking/solana/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ export interface FundPoolArgs extends BaseStakePoolArgs, TokenProgram, RewardPoo
7979
feeValue: Address | null;
8080
}
8181

82+
export interface ClawbackRewardPoolArgs extends BaseStakePoolArgs, TokenProgram {
83+
nonce: number;
84+
rewardMint: Address;
85+
}
86+
8287
export interface CreateRewardEntryArgs extends BaseStakePoolArgs, TokenProgram, RewardPoolProgram {
8388
depositNonce: number;
8489
rewardPoolNonce: number;

packages/stream/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/stream",
3-
"version": "11.2.2",
3+
"version": "11.3.0",
44
"description": "JavaScript SDK to interact with Streamflow protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/cjs/index.cjs",

0 commit comments

Comments
 (0)