@star-factory/sdk-staking 0.1.0

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 ADDED
@@ -0,0 +1,151 @@
1
+ ### sdk-staking
2
+
3
+ Typed client for the on-chain staking program. It mirrors PDA seeds and instruction accounts, and adds read and convenience helpers.
4
+
5
+ - **Entry**: `sdk-staking/index.ts`
6
+ - **Types**: `sdk-staking/types.ts`
7
+ - **Peer deps**: `@coral-xyz/anchor`, `@solana/spl-token`
8
+
9
+ ### Install
10
+
11
+ ```bash
12
+ yarn add @coral-xyz/anchor @solana/spl-token
13
+ ```
14
+
15
+ ### Quick start
16
+
17
+ ```ts
18
+ import { AnchorProvider, BN } from '@coral-xyz/anchor';
19
+ import { PublicKey } from '@solana/web3.js';
20
+ import { StakingSDK } from '.';
21
+
22
+ const provider = AnchorProvider.env();
23
+ const sdk = await StakingSDK.create(provider); // or pass custom programId
24
+
25
+ // Initialize pool (authority must sign)
26
+ await sdk.initialize(new PublicKey('...accepted_mint...'));
27
+
28
+ // Stake
29
+ await sdk.stake(new BN(1_000_000));
30
+
31
+ // Unstake (starts 30-day unlock)
32
+ await sdk.unstake(new BN(500_000));
33
+
34
+ // Claim when eligible
35
+ if (await sdk.canClaimUnstake()) {
36
+ await sdk.claimUnstake();
37
+ }
38
+ ```
39
+
40
+ ### API
41
+
42
+ ```ts
43
+ class StakingSDK {
44
+ constructor(program: Program<StakeProgram>, provider: AnchorProvider);
45
+ static create(provider: AnchorProvider, programId?: PublicKey): Promise<StakingSDK>;
46
+
47
+ // PDAs
48
+ getStakePoolPDA(): PDAWithBump; // [b"stake_pool"]
49
+ getUserStakePDA(user: Address): PDAWithBump; // [b"user_stake", user]
50
+ getStakeVaultPDA(stakePool: Address): PDAWithBump; // [b"stake_vault", stake_pool]
51
+
52
+ // Writes
53
+ initialize(acceptedMint: Address, authority?: Address): Promise<TransactionSignature>;
54
+ stake(amount: Amount, user?: Address): Promise<TransactionSignature>;
55
+ unstake(amount: Amount, user?: Address): Promise<TransactionSignature>;
56
+ claimUnstake(user?: Address): Promise<TransactionSignature>;
57
+
58
+ // Reads
59
+ getStakePool(): Promise<StakePoolAccount>;
60
+ getUserStake(user?: Address): Promise<UserStakeAccount | null>;
61
+
62
+ // Derived helpers
63
+ getUserPoolShare(user?: Address): Promise<number>; // percentage 0..100
64
+ canClaimUnstake(user?: Address): Promise<boolean>;
65
+ getTimeUntilClaim(user?: Address): Promise<number | null>; // seconds
66
+
67
+ // Events
68
+ onStakeEvent(cb: EventCallback<StakeEvent>): ListenerId;
69
+ onUnstakeEvent(cb: EventCallback<UnstakeEvent>): ListenerId;
70
+ onClaimUnstakeEvent(cb: EventCallback<ClaimUnstakeEvent>): ListenerId;
71
+ removeEventListener(listenerId: ListenerId): Promise<void>;
72
+ }
73
+ ```
74
+
75
+ ### Types (subset)
76
+
77
+ ```ts
78
+ type Address = web3.PublicKey;
79
+ type Amount = BN;
80
+
81
+ interface StakePoolAccount { acceptedMint: Address; totalStaked: BN }
82
+ interface UserStakeAccount { stakedAmount: BN; pendingUnstake: BN; unlockTimestamp: BN }
83
+ ```
84
+
85
+ ### Behavior notes
86
+
87
+ - Loads IDL from `../target/idl/stake_program.json`; use `StakingSDK.create(provider, programId)` to override address.
88
+ - Uses `.accountsPartial(...)` (Anchor v0.29+). If needed, switch to `.accounts(...)`.
89
+ - `getUserStake()` returns `null` if the PDA is not initialized.
90
+ - `getUserPoolShare()` computes `(stakedAmount / totalStaked) * 100` with two-decimal precision.
91
+
92
+ ---
93
+
94
+ ## Staker Snapshot Script
95
+
96
+ Creates a snapshot of all stakers for pro-rata reward distribution. Outputs CSV compatible with the airdrop script.
97
+
98
+ ### Usage
99
+
100
+ ```bash
101
+ # From sdk-staking directory
102
+ yarn snapshot --supply <AMOUNT> [options]
103
+
104
+ # Options:
105
+ # --supply <amount> Total reward tokens to distribute (whole tokens)
106
+ # --decimals <n> Reward token decimals (default: 6 for USDC)
107
+ # --output <path> Output CSV path (default: ./staker-snapshot.csv)
108
+ # --rpc <url> RPC endpoint (default: $RPC_URL or localhost)
109
+ ```
110
+
111
+ ### Examples
112
+
113
+ ```bash
114
+ # Distribute 1M USDC (6 decimals) to stakers
115
+ yarn snapshot --supply 1000000 --decimals 6 --output ./usdc-rewards.csv
116
+
117
+ # Distribute 500K tokens with 9 decimals on mainnet
118
+ yarn snapshot --supply 500000 --decimals 9 --rpc https://api.mainnet-beta.solana.com
119
+ ```
120
+
121
+ ### Output
122
+
123
+ Creates three files:
124
+ - `staker-snapshot.csv` - `wallet,amount` format for airdrop script
125
+ - `staker-snapshot-detailed.csv` - Full allocation details (staked amounts, percentages)
126
+ - `staker-snapshot-summary.json` - Verification data and audit trail
127
+
128
+ ### Features
129
+
130
+ - **100% integer arithmetic** - No floating point for token amounts
131
+ - **Verified math** - `sum(distributed) + remainder = total_supply`
132
+ - **Deterministic ordering** - Sorted by wallet address for reproducibility
133
+ - **Randomized output** - CSV is shuffled so whales aren't airdropped first
134
+
135
+ ### Programmatic Usage
136
+
137
+ ```ts
138
+ import { StakingSDK } from '@star-vault/sdk-staking';
139
+
140
+ const sdk = await StakingSDK.create(provider);
141
+
142
+ // Get all stakers
143
+ const { stakers, totalStaked, activeStakers } = await sdk.getAllStakers();
144
+
145
+ // Each staker has:
146
+ // - wallet: PublicKey
147
+ // - stakedAmount: BN
148
+ // - pendingUnstake: BN
149
+ // - unlockTimestamp: BN
150
+ ```
151
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=set-allowed-mint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-allowed-mint.d.ts","sourceRoot":"","sources":["../../src/cli/set-allowed-mint.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const anchor_1 = require("@coral-xyz/anchor");
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const fs_1 = require("fs");
6
+ const index_1 = require("../index");
7
+ function getFlagValue(flag, argv) {
8
+ const index = argv.indexOf(flag);
9
+ if (index === -1)
10
+ return undefined;
11
+ return argv[index + 1];
12
+ }
13
+ function parseArgs(argv) {
14
+ const mint = getFlagValue('--mint', argv);
15
+ const programId = getFlagValue('--program-id', argv);
16
+ const keypair = getFlagValue('--keypair', argv);
17
+ const url = getFlagValue('--url', argv);
18
+ if (!mint) {
19
+ throw new Error('--mint <ADDRESS> is required');
20
+ }
21
+ return { mint, programId, keypair, url };
22
+ }
23
+ function expandHome(path) {
24
+ if (path.startsWith('~')) {
25
+ const home = process.env.HOME || process.env.USERPROFILE;
26
+ return (home ? path.replace('~', home) : path);
27
+ }
28
+ if (path.startsWith('${HOME}')) {
29
+ const home = process.env.HOME || process.env.USERPROFILE;
30
+ return (home ? path.replace('${HOME}', home) : path);
31
+ }
32
+ return path;
33
+ }
34
+ function loadKeypairFromFile(filePath) {
35
+ const expanded = expandHome(filePath);
36
+ if (!(0, fs_1.existsSync)(expanded)) {
37
+ throw new Error(`Keypair file not found: ${expanded}`);
38
+ }
39
+ const raw = (0, fs_1.readFileSync)(expanded, { encoding: 'utf-8' });
40
+ const secret = JSON.parse(raw);
41
+ return web3_js_1.Keypair.fromSecretKey(Uint8Array.from(secret));
42
+ }
43
+ async function createProvider(args) {
44
+ if (!args.keypair && !args.url) {
45
+ return anchor_1.AnchorProvider.env();
46
+ }
47
+ const connection = new web3_js_1.Connection(args.url ?? (0, web3_js_1.clusterApiUrl)('devnet'), {
48
+ commitment: 'confirmed',
49
+ confirmTransactionInitialTimeout: 60_000,
50
+ });
51
+ const kp = args.keypair ? loadKeypairFromFile(args.keypair) : undefined;
52
+ const wallet = kp ? new anchor_1.Wallet(kp) : anchor_1.AnchorProvider.env().wallet;
53
+ return new anchor_1.AnchorProvider(connection, wallet, {
54
+ commitment: 'confirmed',
55
+ preflightCommitment: 'confirmed',
56
+ });
57
+ }
58
+ async function main() {
59
+ const argv = process.argv.slice(2);
60
+ const args = parseArgs(argv);
61
+ const acceptedMint = new web3_js_1.PublicKey(args.mint);
62
+ const programId = args.programId ? new web3_js_1.PublicKey(args.programId) : undefined;
63
+ const provider = await createProvider(args);
64
+ const sdk = await index_1.StakingSDK.create(provider, programId);
65
+ const { signature: sig } = await sdk.initialize({ acceptedMint });
66
+ // eslint-disable-next-line no-console
67
+ console.log('Set allowed mint via initialize:', sig);
68
+ // Verify and print resulting pool state
69
+ const pool = await sdk.getStakePool();
70
+ // eslint-disable-next-line no-console
71
+ console.log('Accepted mint:', pool.acceptedMint.toBase58());
72
+ }
73
+ main().catch((err) => {
74
+ // eslint-disable-next-line no-console
75
+ console.error(err?.stack || err?.message || String(err));
76
+ process.exit(1);
77
+ });
78
+ //# sourceMappingURL=set-allowed-mint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-allowed-mint.js","sourceRoot":"","sources":["../../src/cli/set-allowed-mint.ts"],"names":[],"mappings":";;AAAA,8CAA2D;AAC3D,6CAAgF;AAChF,2BAA8C;AAC9C,oCAAsC;AAStC,SAAS,YAAY,CAAC,IAAY,EAAE,IAAc;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACnC,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAExC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAW,CAAC;IAC3D,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAW,CAAC;IACjE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,GAAG,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IAC3C,OAAO,iBAAO,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAa;IACzC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,OAAO,uBAAc,CAAC,GAAG,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,oBAAU,CAAC,IAAI,CAAC,GAAG,IAAI,IAAA,uBAAa,EAAC,QAAQ,CAAC,EAAE;QACrE,UAAU,EAAE,WAAW;QACvB,gCAAgC,EAAE,MAAM;KACzC,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,eAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,uBAAc,CAAC,GAAG,EAAE,CAAC,MAAiB,CAAC;IAE7E,OAAO,IAAI,uBAAc,CAAC,UAAU,EAAE,MAAM,EAAE;QAC5C,UAAU,EAAE,WAAW;QACvB,mBAAmB,EAAE,WAAW;KACjC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,YAAY,GAAG,IAAI,mBAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,mBAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7E,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,kBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAEzD,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IAClE,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IAErD,wCAAwC;IACxC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;IACtC,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}