@soltracer/nft-staking 0.3.1 → 0.4.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.
@@ -1,21 +1,36 @@
1
1
  /**
2
2
  * Trait-bonus proof builder for NFT-staking `claim_rewards`.
3
3
  *
4
- * The on-chain Ed25519 message embeds `staker.total_claimed` (a strictly
5
- * monotonic nonce). Callers MUST read the live `StakerAccount.totalClaimed`
6
- * immediately before signing.
7
- *
8
- * Message layout 80 bytes, little-endian where applicable:
4
+ * Design summary
5
+ * --------------
6
+ * The on-chain `claim_rewards` instruction accepts a SINGLE u64
7
+ * `traitBonusRate` per claim. When `pool.reward_config.trait_bonus_enabled`
8
+ * is `true`, that rate is added directly to the staker's effective rate for
9
+ * the accrual window. The chain has zero per-NFT or per-trait awareness —
10
+ * ALL bonus math (trait lookups, per-NFT multipliers, caps, etc.) happens
11
+ * off-chain in the project's trait-authority server, which signs the final
12
+ * aggregated rate.
13
+ *
14
+ * Why per-NFT (not per-staker) multipliers
15
+ * ----------------------------------------
16
+ * An older design exposed a `BaseMultiplier` mode on-chain that multiplied
17
+ * the staker's ENTIRE effective rate (all NFTs combined). That meant a
18
+ * single "Mythic 2x" NFT doubled rewards for every plain NFT in the same
19
+ * claim — cross-contamination across NFTs. The new model evaluates each
20
+ * NFT's bonuses independently, applies its own optional multiplier to its
21
+ * own bonus sum, then sums those isolated per-NFT bonuses into the single
22
+ * signed `u64`. One NFT's multiplier never touches another NFT's reward.
23
+ *
24
+ * Ed25519 message layout — 80 bytes (LE where applicable):
9
25
  *
10
26
  * [0..32] pool (PublicKey bytes)
11
27
  * [32..64] staker wallet (PublicKey bytes)
12
- * [64..72] trait_bonus_rate u64 (LE)
13
- * [72..80] total_claimed u64 (LE)
28
+ * [64..72] traitBonusRate u64 (LE)
29
+ * [72..80] totalClaimed u64 (LE — strictly monotonic replay nonce)
14
30
  *
15
- * Sign this byte payload with the pool's trait-authority Ed25519 keypair
16
- * (or the global trait authority) and prepend an Ed25519 instruction with
17
- * the signature, expected pubkey, and message to the same transaction that
18
- * invokes `claimRewards(..., traitBonusRate)`.
31
+ * Sign with the pool's trait-authority Ed25519 keypair (or the global
32
+ * `stakeConfig.authority` when the pool has no override) and prepend the
33
+ * Ed25519 precompile instruction in the same transaction as `claimRewards`.
19
34
  */
20
35
  import { type PkInput, type BnInput } from "@soltracer/core";
21
36
  /** Fixed message length consumed by the on-chain Ed25519 verifier. */
@@ -23,8 +38,8 @@ export declare const TRAIT_PROOF_MSG_LEN = 80;
23
38
  /**
24
39
  * Build the 80-byte trait-proof message exactly as the on-chain handler
25
40
  * reconstructs it. `totalClaimed` must be the LIVE value of
26
- * `StakerAccount.totalClaimed` (i.e. fetched within the same client tx
27
- * preparation window — otherwise the signature will be rejected).
41
+ * `StakerAccount.totalClaimed` (fetched within the same tx prep window —
42
+ * otherwise the signature is rejected once the nonce advances).
28
43
  */
29
44
  export declare function buildTraitProofMessage(params: {
30
45
  pool: PkInput;
@@ -34,262 +49,173 @@ export declare function buildTraitProofMessage(params: {
34
49
  totalClaimed: BnInput;
35
50
  }): Buffer;
36
51
  /**
37
- * Example (off-chain trait-authority server):
38
- *
39
- * ```ts
40
- * import nacl from "tweetnacl"
41
- * import { Ed25519Program } from "@solana/web3.js"
42
- * import { buildTraitProofMessage } from "@soltracer/nft-staking"
43
- *
44
- * const message = buildTraitProofMessage({
45
- * pool,
46
- * wallet: staker,
47
- * traitBonusRate,
48
- * totalClaimed: stakerAccount.totalClaimed,
49
- * })
50
- * const signature = nacl.sign.detached(message, traitAuthority.secretKey)
51
- * const ed25519Ix = Ed25519Program.createInstructionWithPublicKey({
52
- * publicKey: traitAuthority.publicKey.toBytes(),
53
- * message,
54
- * signature,
55
- * })
56
- * const claimIx = await client.claimRewards(poolId, { traitBonusRate })
57
- * await provider.sendAndConfirm(new Transaction().add(ed25519Ix, claimIx))
58
- * ```
59
- */
60
- /**
61
- * Mode-aware trait-bonus rate aggregator.
62
- *
63
- * The on-chain `claim_rewards` instruction accepts a **single** `u64`
64
- * `traitBonusRate` per claim — the chain knows nothing about per-trait
65
- * granularity. Aggregation across N staked NFTs (each with M traits) is the
66
- * trait-authority server's responsibility.
67
- *
68
- * Intended backend flow:
69
- *
70
- * 1. Client sends `{ wallet, poolId, mints: [..] }` to your API.
71
- * 2. API validates `mints` are currently staked by `wallet` in `pool`
72
- * (e.g. via `fetchStakeEntriesByOwner`) and DROPS any it cannot prove.
73
- * 3. API resolves each surviving NFT's trait list from its own metadata
74
- * source (off-chain JSON, on-chain metaplex data, indexer, etc.).
75
- * 4. API looks up each `(traitType, value)` pair in the project's bonus
76
- * catalog. Unmatched traits contribute nothing.
77
- * 5. API sums the matched bonuses according to the pool's
78
- * `rewardConfig.traitBonusMode` and signs the resulting `u64`.
79
- *
80
- * Modes:
81
- *
82
- * - `0` / `None` — proofs disabled. Always returns `0n`.
83
- * - `1` / `FixedExtra` — bonuses are **absolute reward per `rateInterval`**.
84
- * Summed and added on top of the staker's effective rate for the accrual
85
- * window. Catalog entries MUST use `fixedExtra`.
86
- * - `2` / `BaseMultiplier` — bonuses are **BPS over the staker's current
87
- * `effective_rate`** (which already includes lock-tier rates). `10_000`
88
- * means +100% (2x base). Summed BPS apply once to the staker rate.
89
- * Catalog entries MUST use `bonusBps`.
90
- *
91
- * Catalog entries with both `bonusBps` and `fixedExtra` set, or with the wrong
92
- * field for the active mode, are rejected. Mints can repeat the same trait
93
- * type/value — each NFT contributes independently.
94
- *
95
- * @returns `{ traitBonusRate, perNft }` where `perNft` is the per-mint
96
- * breakdown (useful for receipts, debugging, or surfacing a tooltip in the UI).
97
- *
98
- * @example
99
- * ```ts
100
- * // Backend after ownership validation:
101
- * const result = computeTraitBonusRate({
102
- * traitBonusMode: pool.rewardConfig.traitBonusMode as 0 | 1 | 2,
103
- * catalog: [
104
- * { traitType: "Background", value: "Mythic", bonusBps: 2500 },
105
- * { traitType: "Eyes", value: "Laser", bonusBps: 1000 },
106
- * { traitType: "Head", value: "Gold Crown", bonusBps: 500 },
107
- * ],
108
- * nfts: validatedStakedNfts, // [{ mint, traits: [{ traitType, value }] }, ..]
109
- * })
110
- *
111
- * const message = buildTraitProofMessage({
112
- * pool, wallet,
113
- * traitBonusRate: result.traitBonusRate,
114
- * totalClaimed: stakerAccount.totalClaimed,
115
- * })
116
- * ```
52
+ * One catalog row. Each `(traitType, value)` pair maps to ONE absolute bonus
53
+ * amount measured in the same units as `rewardConfig.baseRate` (raw token
54
+ * units per `rateInterval`). To express the catalog in human units, multiply
55
+ * by `10 ** rewardDecimals` before passing it in.
56
+ *
57
+ * Example: catalog row `{ traitType: "Rarity", value: "Mythic", bonus: 25n }`
58
+ * with a `rateInterval` of 86_400s means "this trait adds 25 raw reward
59
+ * units per day to the NFT that carries it".
117
60
  */
118
- export type TraitBonusCatalogEntry = {
61
+ export interface TraitBonusCatalogEntry {
119
62
  traitType: string;
120
63
  value: string;
121
- /** Bonus BPS required when `traitBonusMode === 2` (BaseMultiplier). */
122
- bonusBps?: number | bigint;
123
- /** Extra reward per `rateInterval` — required when `traitBonusMode === 1` (FixedExtra). */
124
- fixedExtra?: number | bigint;
125
- };
126
- export type NftTraitInput = {
127
- mint: PkInput | string;
128
- /** Ordered or unordered list of an NFT's traits, after ownership validation. */
129
- traits: ReadonlyArray<{
64
+ /** Raw reward units per `rateInterval` to add for this trait. */
65
+ bonus: bigint;
66
+ }
67
+ /**
68
+ * Storage-agnostic store interface — implement with Prisma, Drizzle, Firestore,
69
+ * in-memory, etc.
70
+ *
71
+ * Catalog rows are keyed by **NFT collection mint**, NOT by pool id. A single
72
+ * collection can be wired into many pools (e.g. a 30-day pool and a 90-day
73
+ * pool over the same collection) and they all share one set of trait bonuses.
74
+ * The pool only contributes the trait-bonus *enable flag* and the signing
75
+ * authority; the bonus values themselves are a property of the collection.
76
+ */
77
+ export interface TraitBonusStore {
78
+ /**
79
+ * Return every catalog entry that applies to an NFT collection.
80
+ *
81
+ * `collectionMint` is `pool.collectionMint` (base58). For pools with no
82
+ * configured collection (open-set pools), pass the empty string or call
83
+ * with `Pubkey::default().toBase58()` — the store can return `[]`.
84
+ */
85
+ listForCollection(collectionMint: string): Promise<TraitBonusCatalogEntry[]>;
86
+ }
87
+ /**
88
+ * In-memory catalog suitable for tests and small static configurations.
89
+ * Keys are collection mints (base58).
90
+ */
91
+ export declare class InMemoryTraitBonusStore implements TraitBonusStore {
92
+ private readonly entriesByCollection;
93
+ constructor(entriesByCollection: Map<string, TraitBonusCatalogEntry[]>);
94
+ static from(entries: Record<string, TraitBonusCatalogEntry[]>): InMemoryTraitBonusStore;
95
+ listForCollection(collectionMint: string): Promise<TraitBonusCatalogEntry[]>;
96
+ }
97
+ /** Traits attached to a single staked NFT. */
98
+ export interface NftTraitInput {
99
+ /** Mint of the staked NFT (string only used for diagnostics). */
100
+ mint: string;
101
+ /** Trait pairs in `[traitType, value]` form. */
102
+ traits: Array<{
130
103
  traitType: string;
131
104
  value: string;
132
105
  }>;
133
- };
134
- export type ComputeTraitBonusResult = {
135
- /** Aggregated u64 rate to sign and include in the claim. */
106
+ /**
107
+ * Optional per-NFT multiplier in BPS applied ONLY to this NFT's own bonus
108
+ * total. 10_000 = (no change). 20_000 = this NFT's bonus. Multipliers
109
+ * NEVER cross NFTs — they cannot inflate another NFT's reward.
110
+ *
111
+ * Leave undefined (or 10_000) for plain NFTs. Project teams that want to
112
+ * reward rare NFTs disproportionately apply it here.
113
+ */
114
+ multiplierBps?: number;
115
+ }
116
+ export interface PerNftBonus {
117
+ mint: string;
118
+ /** Sum of catalog bonuses matched on this NFT, after any per-NFT multiplier. */
119
+ bonus: bigint;
120
+ }
121
+ export interface TraitBonusComputation {
122
+ /** Final aggregated `u64` to feed into the signed message and `claimRewards`. */
136
123
  traitBonusRate: bigint;
137
- /** Per-NFT breakdown (mint total bonus contributed + matched-trait count). */
138
- perNft: Array<{
139
- mint: string;
140
- bonus: bigint;
141
- matchedTraits: number;
142
- }>;
143
- };
144
- export declare function computeTraitBonusRate(params: {
145
- traitBonusMode: 0 | 1 | 2;
146
- catalog: ReadonlyArray<TraitBonusCatalogEntry>;
147
- nfts: ReadonlyArray<NftTraitInput>;
148
- }): ComputeTraitBonusResult;
124
+ /** Per-NFT breakdown useful for surfacing "you earned X from this NFT" in UI. */
125
+ perNft: PerNftBonus[];
126
+ }
149
127
  /**
150
- * @deprecated Use `computeTraitBonusRate` instead it accepts the real per-NFT
151
- * trait input and a bonus catalog, mirroring the backend flow. Retained for
152
- * call sites that already pre-resolved a flat bonus array.
128
+ * Aggregate trait bonuses into a single absolute `u64` rate.
129
+ *
130
+ * Algorithm (per NFT, independently):
131
+ * 1. For every `(traitType, value)` on the NFT, look it up in `catalog`.
132
+ * 2. Sum every matched `bonus`. Unmatched traits contribute 0.
133
+ * 3. If `multiplierBps` is set, multiply the NFT's bonus sum by it / 10_000.
134
+ * (Floor division — bonuses are integer raw units.)
135
+ *
136
+ * Final result = sum of per-NFT bonuses. A multiplier on one NFT cannot
137
+ * touch another NFT's contribution, eliminating the cross-contamination bug
138
+ * present in the old on-chain `BaseMultiplier` mode.
153
139
  */
154
- export declare function aggregateTraitBonusRate(traits: ReadonlyArray<{
155
- bonusBps?: number | bigint;
156
- fixedExtra?: number | bigint;
157
- }>, traitBonusMode: 0 | 1 | 2): bigint;
140
+ export declare function computeTraitBonusRate(params: {
141
+ catalog: TraitBonusCatalogEntry[];
142
+ nfts: NftTraitInput[];
143
+ }): TraitBonusComputation;
158
144
  /**
159
- * Storage adapter for a project's trait-bonus catalog.
160
- *
161
- * The SDK does not care where you persist this data — Prisma, Drizzle, raw
162
- * Postgres, Mongo, KV, in-memory, REST — implement this interface against
163
- * whatever backs your admin UI. Each `(traitType, value)` row carries the
164
- * bonus for that pair.
145
+ * Resolve the trait list for a staked mint. Implementations typically read
146
+ * from off-chain metadata, an indexer, or a cached project DB.
165
147
  */
166
- export interface TraitBonusStore {
167
- /**
168
- * Return every catalog entry for a given pool. The orchestrator does not
169
- * filter by trait — it expects the full set so unmatched traits naturally
170
- * contribute nothing.
171
- */
172
- list(params: {
173
- poolId: number;
174
- projectId?: string | number;
175
- }): Promise<TraitBonusCatalogEntry[]>;
176
- }
148
+ export type NftTraitResolver = (mint: string) => Promise<{
149
+ traits: Array<{
150
+ traitType: string;
151
+ value: string;
152
+ }>;
153
+ multiplierBps?: number;
154
+ }>;
177
155
  /**
178
- * Resolves the on-chain trait list for a given NFT mint.
156
+ * Confirm that a given mint is currently staked by `wallet` in `poolId`.
179
157
  *
180
- * Wire this to whatever your project uses as a source of truth: an indexer,
181
- * Metaplex on-chain metadata, your own collection JSON, an internal DB, etc.
182
- * Returning an empty array is fine that NFT simply contributes no bonus.
158
+ * MUST return `false` for any mint not actively staked by the caller
159
+ * otherwise a malicious client could submit a list of NFTs they do not own
160
+ * and have your server sign a bonus rate that the on-chain pool will accept.
183
161
  */
184
- export type NftTraitResolver = (mint: string) => Promise<ReadonlyArray<{
185
- traitType: string;
186
- value: string;
187
- }>>;
188
- /** Validates which `requestedMints` are actually staked in `poolId` by `wallet`. */
189
162
  export type StakedOwnershipResolver = (params: {
190
163
  wallet: string;
191
- poolId: number;
192
- requestedMints: ReadonlyArray<string>;
193
- }) => Promise<ReadonlyArray<string>>;
194
- export type PreparedTraitProof = {
195
- /** Aggregated u64 rate ready to sign. */
164
+ poolId: number | bigint;
165
+ mint: string;
166
+ }) => Promise<boolean>;
167
+ export interface PrepareTraitProofInput {
168
+ /** Pool that will receive the claim. */
169
+ pool: PkInput;
170
+ /** Wallet doing the claim. */
171
+ wallet: PkInput;
172
+ /** Live `StakerAccount.totalClaimed` — read immediately before signing. */
173
+ totalClaimed: BnInput;
174
+ /** Pool id — only used for the ownership / stake-state lookup. */
175
+ poolId: number | bigint;
176
+ /**
177
+ * Collection mint configured on the pool (`StakePool.collectionMint`,
178
+ * base58). The catalog is fetched by this key so the same bonuses apply
179
+ * across every pool that stakes this collection. Pass an empty string for
180
+ * open-set pools (the store should return `[]`).
181
+ */
182
+ collectionMint: string;
183
+ /** Mints the client claims to be staking. Each is verified individually. */
184
+ mints: string[];
185
+ store: TraitBonusStore;
186
+ resolveTraits: NftTraitResolver;
187
+ isStakedBy: StakedOwnershipResolver;
188
+ }
189
+ export interface PrepareTraitProofResult {
190
+ /** The 80-byte message ready for Ed25519 signing. */
191
+ message: Buffer;
192
+ /** Aggregated `u64` rate — pass to `claimRewards({ traitBonusRate })`. */
196
193
  traitBonusRate: bigint;
197
- /** Mints the user requested that survived ownership validation. */
198
- validatedMints: string[];
199
- /** Mints the user requested that were rejected (not staked). */
194
+ /** Per-NFT breakdown, including mints that survived ownership verification. */
195
+ perNft: PerNftBonus[];
196
+ /** Mints that the client supplied but were rejected as not actively staked. */
200
197
  rejectedMints: string[];
201
- /** Per-NFT contribution breakdown (useful for UI tooltips / audit logs). */
202
- perNft: ComputeTraitBonusResult["perNft"];
203
- /** Convenience: the raw 80-byte message to feed into `nacl.sign.detached`. */
204
- message: Buffer;
205
- };
198
+ }
206
199
  /**
207
- * End-to-end backend orchestrator for the trait-proof flow.
200
+ * Full backend orchestration: ownership-verify each mint, resolve traits,
201
+ * aggregate via `computeTraitBonusRate`, and build the signed message.
208
202
  *
209
- * Combines the four user-supplied dependencies ownership validation, trait
210
- * resolution, the bonus-catalog store, and the on-chain staker nonce into
211
- * the single signable payload the on-chain claim instruction expects.
203
+ * The server is expected to sign `result.message` with the trait-authority
204
+ * Ed25519 keypair, return both the signature and `traitBonusRate` to the
205
+ * client, and the client forwards both into the `claimRewards` tx.
206
+ */
207
+ export declare function prepareTraitProof(input: PrepareTraitProofInput): Promise<PrepareTraitProofResult>;
208
+ /**
209
+ * Adapter — turn an `NftStakingClient.fetchStakeEntriesByOwner` style call
210
+ * into a `StakedOwnershipResolver`. Pass in your already-constructed client.
212
211
  *
213
- * @example
214
212
  * ```ts
215
- * import {
216
- * prepareTraitProof,
217
- * type TraitBonusStore,
218
- * } from "@soltracer/nft-staking"
219
- *
220
- * // 1) Implement the store against your DB once (any DB works).
221
- * const traitBonusStore: TraitBonusStore = {
222
- * async list({ poolId, projectId }) {
223
- * const rows = await prisma.traitBonusConfig.findMany({
224
- * where: { poolId, ...(projectId ? { projectId: String(projectId) } : {}) },
225
- * })
226
- * return rows.map((r) => ({
227
- * traitType: r.traitType,
228
- * value: r.traitValue,
229
- * // pool is BaseMultiplier? use bonusBps. FixedExtra? use fixedExtra.
230
- * bonusBps: r.bonusAmount,
231
- * }))
232
- * },
233
- * }
234
- *
235
- * // 2) Prepare the proof on each claim request.
236
- * const prepared = await prepareTraitProof({
237
- * client, // NftStakingClient
238
- * pool, // already-fetched StakePool (has rewardConfig + address)
239
- * wallet: req.wallet,
240
- * requestedMints: req.mints,
241
- * store: traitBonusStore,
242
- * resolveTraits: (mint) => catalog.getTraits(mint),
243
- * })
244
- *
245
- * // 3) Sign and respond.
246
- * const signature = nacl.sign.detached(prepared.message, traitAuthority.secretKey)
247
- * return {
248
- * traitBonusRate: prepared.traitBonusRate.toString(),
249
- * signature: Buffer.from(signature).toString("base64"),
250
- * perNft: prepared.perNft,
251
- * rejectedMints: prepared.rejectedMints,
252
- * }
213
+ * const isStakedBy = ownershipFromClient(client)
253
214
  * ```
254
215
  */
255
- export declare function prepareTraitProof(params: {
256
- /** Pool config — must expose `address` and `rewardConfig.traitBonusMode`. */
257
- pool: {
258
- address: PkInput;
259
- rewardConfig: {
260
- traitBonusMode: number;
261
- };
262
- };
263
- /** Project ID hint forwarded to the store (DB scoping, optional). */
264
- projectId?: string | number;
265
- poolId?: number;
266
- wallet: PkInput;
267
- requestedMints: ReadonlyArray<string>;
268
- /** Storage adapter for the bonus catalog. */
269
- store: TraitBonusStore;
270
- /** Resolves trait list for a single mint. */
271
- resolveTraits: NftTraitResolver;
272
- /**
273
- * Validates which `requestedMints` are actually staked in this pool by
274
- * `wallet`. If omitted, the orchestrator trusts the caller — DO NOT skip
275
- * this in production. The SDK can drive this for you when you pass a
276
- * `client` and `poolId` (see `ownershipFromClient`).
277
- */
278
- validateOwnership: StakedOwnershipResolver;
279
- /**
280
- * Current `StakerAccount.totalClaimed` nonce. MUST be the live value;
281
- * advance-then-sign in the same request to avoid same-second replay.
282
- */
283
- totalClaimed: BnInput;
284
- }): Promise<PreparedTraitProof>;
285
- /**
286
- * Convenience `StakedOwnershipResolver` that uses an `NftStakingClient` to
287
- * walk the wallet's stake entries and only allow mints currently staked in
288
- * `poolId`. Wire this into `prepareTraitProof({ validateOwnership })` if you
289
- * don't already have your own stake index.
290
- */
291
216
  export declare function ownershipFromClient(client: {
292
- fetchStakeEntriesByOwner: (poolId: number, wallet: PkInput) => Promise<Array<{
217
+ fetchStakeEntriesByOwner: (owner: PkInput, poolId?: number) => Promise<Array<{
218
+ poolId: number;
293
219
  nftMint: {
294
220
  toBase58(): string;
295
221
  };
@@ -1 +1 @@
1
- {"version":3,"file":"traitProof.d.ts","sourceRoot":"","sources":["../src/traitProof.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"traitProof.d.ts","sourceRoot":"","sources":["../src/traitProof.ts"],"names":[],"mappings":"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"}