@soltracer/nft-staking 0.2.1 → 0.2.4

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/dist/index.d.ts CHANGED
@@ -1,5 +1,9 @@
1
- export { NftStakingClient, type FeeParams } from "./client";
2
- export { NFT_STAKING_PROGRAM_ID } from "@soltracer/core";
1
+ export { NftStakingClient, type FeeParams, type NftRewardAmount, type NftRewardSummary, type NftRewardSummaryOptions, } from "./client";
2
+ export { NFT_STAKING_PROGRAM_ID, getStakeConfigPda, getStakePoolPda, getStakeEntryPda, getStakerAccountPda, getCollectionPda, getPoolAuthorityPda, getPoolSecondaryRewardsPda, getStakerSecondaryRewardsPda, StakingMode, NftStandard, RewardType, TraitBonusMode, } from "@soltracer/core";
3
3
  export { type NftStaking as NftStakingIDLType } from "./idl";
4
4
  export { default as NftStakingIDL } from "./idl.json";
5
+ export * from "./errors";
6
+ export * from "./helpers";
7
+ export { buildTraitProofMessage, TRAIT_PROOF_MSG_LEN } from "./traitProof";
8
+ export { GATE_TYPE_NONE, GATE_TYPE_WALLET, GATE_TYPE_TOKEN_MINT, type GateType, type MerkleTree, hashLeaf, hashPair, buildMerkleTree, getMerkleProof, proofToAnchorArg, rootToAnchorArg, } from "./merkle";
5
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,KAAK,UAAU,IAAI,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,WAAW,EACX,WAAW,EACX,UAAU,EACV,cAAc,GACf,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,KAAK,UAAU,IAAI,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,YAAY,CAAA;AACrD,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
- export { NftStakingClient } from "./client";
2
- export { NFT_STAKING_PROGRAM_ID } from "@soltracer/core";
1
+ export { NftStakingClient, } from "./client";
2
+ export { NFT_STAKING_PROGRAM_ID, getStakeConfigPda, getStakePoolPda, getStakeEntryPda, getStakerAccountPda, getCollectionPda, getPoolAuthorityPda, getPoolSecondaryRewardsPda, getStakerSecondaryRewardsPda, StakingMode, NftStandard, RewardType, TraitBonusMode, } from "@soltracer/core";
3
3
  export { default as NftStakingIDL } from "./idl.json";
4
+ export * from "./errors";
5
+ export * from "./helpers";
6
+ export { buildTraitProofMessage, TRAIT_PROOF_MSG_LEN } from "./traitProof";
7
+ export { GATE_TYPE_NONE, GATE_TYPE_WALLET, GATE_TYPE_TOKEN_MINT, hashLeaf, hashPair, buildMerkleTree, getMerkleProof, proofToAnchorArg, rootToAnchorArg, } from "./merkle";
4
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAkB,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,GAKjB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,WAAW,EACX,WAAW,EACX,UAAU,EACV,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,YAAY,CAAA;AACrD,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EAGpB,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,UAAU,CAAA"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Merkle-gate helpers for NFT-staking pool access control.
3
+ *
4
+ * On-chain verification (`programs/nft-staking/src/merkle.rs`) uses:
5
+ *
6
+ * - Leaf hash: sha256(leaf_data_bytes) where leaf_data_bytes is
7
+ * the 32-byte PublicKey of
8
+ * the gated entity (wallet
9
+ * for GATE_TYPE_WALLET,
10
+ * mint for GATE_TYPE_TOKEN_MINT).
11
+ * - Inner node: sha256(min(a, b) || max(a, b)) (canonical ordering — no
12
+ * position bits in the proof).
13
+ *
14
+ * Use `buildMerkleTree(leafKeys, gateType)` once when seeding the pool's
15
+ * `merkleRoot` via `updateStakePool`, then `getMerkleProof(tree, leafKey)`
16
+ * for each `stakeNft` / `stakeCnft` call.
17
+ */
18
+ import { PublicKey } from "@solana/web3.js";
19
+ import { type PkInput } from "@soltracer/core";
20
+ export declare const GATE_TYPE_NONE = 0;
21
+ export declare const GATE_TYPE_WALLET = 1;
22
+ export declare const GATE_TYPE_TOKEN_MINT = 2;
23
+ export type GateType = typeof GATE_TYPE_NONE | typeof GATE_TYPE_WALLET | typeof GATE_TYPE_TOKEN_MINT;
24
+ /** Leaf hash: `sha256(pubkeyBytes)`. Matches `hashv(&[leaf_data])` on-chain. */
25
+ export declare function hashLeaf(key: PkInput): Uint8Array;
26
+ /** Pair-hash two nodes with canonical ordering (`sha256(min || max)`). */
27
+ export declare function hashPair(a: Uint8Array, b: Uint8Array): Uint8Array;
28
+ export interface MerkleTree {
29
+ /** Layer 0 = leaf hashes (in original order); each subsequent layer is the parent layer. */
30
+ layers: Uint8Array[][];
31
+ /** 32-byte root — store on-chain via `updateStakePool({ merkleRoot })`. */
32
+ root: Uint8Array;
33
+ /** Original input keys (preserved for proof lookup by index). */
34
+ leafKeys: PublicKey[];
35
+ }
36
+ /**
37
+ * Build a canonical-ordering Merkle tree from a list of gated entity keys
38
+ * (wallets for `GATE_TYPE_WALLET`, mints for `GATE_TYPE_TOKEN_MINT`).
39
+ * Duplicate keys are de-duplicated before hashing.
40
+ */
41
+ export declare function buildMerkleTree(leafKeys: PkInput[]): MerkleTree;
42
+ /**
43
+ * Get the inclusion proof for `leafKey` in `tree`. Returns the proof as
44
+ * an array of 32-byte `Uint8Array`s — convert to `number[][]` for the
45
+ * Anchor instruction args via `proof.map(Array.from)`.
46
+ *
47
+ * Throws if `leafKey` is not present in the tree.
48
+ */
49
+ export declare function getMerkleProof(tree: MerkleTree, leafKey: PkInput): Uint8Array[];
50
+ /**
51
+ * Convert a `Uint8Array[]` proof to the `number[][]` shape Anchor expects
52
+ * for the `gate_proof: Vec<[u8; 32]>` argument.
53
+ */
54
+ export declare function proofToAnchorArg(proof: Uint8Array[]): number[][];
55
+ /** Convert the 32-byte root to the `number[]` shape Anchor expects. */
56
+ export declare function rootToAnchorArg(root: Uint8Array): number[];
57
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEpD,eAAO,MAAM,cAAc,IAAI,CAAA;AAC/B,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,MAAM,MAAM,QAAQ,GAAG,OAAO,cAAc,GAAG,OAAO,gBAAgB,GAAG,OAAO,oBAAoB,CAAA;AAwBpG,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAEjD;AAED,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,UAAU,CAEjE;AAED,MAAM,WAAW,UAAU;IACzB,4FAA4F;IAC5F,MAAM,EAAE,UAAU,EAAE,EAAE,CAAA;IACtB,2EAA2E;IAC3E,IAAI,EAAE,UAAU,CAAA;IAChB,iEAAiE;IACjE,QAAQ,EAAE,SAAS,EAAE,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CA6B/D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,EAAE,CAmB/E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,EAAE,CAEhE;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAE1D"}
package/dist/merkle.js ADDED
@@ -0,0 +1,110 @@
1
+ import { sha256 as nobleSha256 } from "@noble/hashes/sha256";
2
+ import { toPk } from "@soltracer/core";
3
+ export const GATE_TYPE_NONE = 0;
4
+ export const GATE_TYPE_WALLET = 1;
5
+ export const GATE_TYPE_TOKEN_MINT = 2;
6
+ function sha256(...parts) {
7
+ let total = 0;
8
+ for (const p of parts)
9
+ total += p.length;
10
+ const buf = new Uint8Array(total);
11
+ let off = 0;
12
+ for (const p of parts) {
13
+ buf.set(p, off);
14
+ off += p.length;
15
+ }
16
+ return nobleSha256(buf);
17
+ }
18
+ function compare(a, b) {
19
+ const len = Math.min(a.length, b.length);
20
+ for (let i = 0; i < len; i++) {
21
+ const av = a[i];
22
+ const bv = b[i];
23
+ if (av !== bv)
24
+ return av - bv;
25
+ }
26
+ return a.length - b.length;
27
+ }
28
+ /** Leaf hash: `sha256(pubkeyBytes)`. Matches `hashv(&[leaf_data])` on-chain. */
29
+ export function hashLeaf(key) {
30
+ return sha256(toPk(key).toBytes());
31
+ }
32
+ /** Pair-hash two nodes with canonical ordering (`sha256(min || max)`). */
33
+ export function hashPair(a, b) {
34
+ return compare(a, b) <= 0 ? sha256(a, b) : sha256(b, a);
35
+ }
36
+ /**
37
+ * Build a canonical-ordering Merkle tree from a list of gated entity keys
38
+ * (wallets for `GATE_TYPE_WALLET`, mints for `GATE_TYPE_TOKEN_MINT`).
39
+ * Duplicate keys are de-duplicated before hashing.
40
+ */
41
+ export function buildMerkleTree(leafKeys) {
42
+ if (leafKeys.length === 0) {
43
+ throw new Error("buildMerkleTree: at least one leaf is required");
44
+ }
45
+ // Stable de-dup preserving first occurrence.
46
+ const seen = new Set();
47
+ const uniqueKeys = [];
48
+ for (const k of leafKeys) {
49
+ const pk = toPk(k);
50
+ const b58 = pk.toBase58();
51
+ if (seen.has(b58))
52
+ continue;
53
+ seen.add(b58);
54
+ uniqueKeys.push(pk);
55
+ }
56
+ const leaves = uniqueKeys.map((k) => hashLeaf(k));
57
+ const layers = [leaves];
58
+ let current = leaves;
59
+ while (current.length > 1) {
60
+ const next = [];
61
+ for (let i = 0; i < current.length; i += 2) {
62
+ const left = current[i];
63
+ const right = (i + 1 < current.length ? current[i + 1] : current[i]);
64
+ next.push(hashPair(left, right));
65
+ }
66
+ layers.push(next);
67
+ current = next;
68
+ }
69
+ return { layers, root: current[0], leafKeys: uniqueKeys };
70
+ }
71
+ /**
72
+ * Get the inclusion proof for `leafKey` in `tree`. Returns the proof as
73
+ * an array of 32-byte `Uint8Array`s — convert to `number[][]` for the
74
+ * Anchor instruction args via `proof.map(Array.from)`.
75
+ *
76
+ * Throws if `leafKey` is not present in the tree.
77
+ */
78
+ export function getMerkleProof(tree, leafKey) {
79
+ const target = toPk(leafKey).toBase58();
80
+ const index = tree.leafKeys.findIndex((k) => k.toBase58() === target);
81
+ if (index < 0) {
82
+ throw new Error(`getMerkleProof: leaf ${target} not in tree`);
83
+ }
84
+ const proof = [];
85
+ let idx = index;
86
+ for (let depth = 0; depth < tree.layers.length - 1; depth++) {
87
+ const layer = tree.layers[depth];
88
+ const sibling = idx ^ 1;
89
+ if (sibling < layer.length) {
90
+ proof.push(layer[sibling]);
91
+ }
92
+ else {
93
+ proof.push(layer[idx]); // odd → sibling is self
94
+ }
95
+ idx = idx >> 1;
96
+ }
97
+ return proof;
98
+ }
99
+ /**
100
+ * Convert a `Uint8Array[]` proof to the `number[][]` shape Anchor expects
101
+ * for the `gate_proof: Vec<[u8; 32]>` argument.
102
+ */
103
+ export function proofToAnchorArg(proof) {
104
+ return proof.map((n) => Array.from(n));
105
+ }
106
+ /** Convert the 32-byte root to the `number[]` shape Anchor expects. */
107
+ export function rootToAnchorArg(root) {
108
+ return Array.from(root);
109
+ }
110
+ //# sourceMappingURL=merkle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Trait-bonus proof builder for NFT-staking `claim_rewards`.
3
+ *
4
+ * Audit 2026-05-11 F-H2: the on-chain Ed25519 message embeds
5
+ * `staker.total_claimed` (strictly monotonic) instead of `last_update_at`,
6
+ * eliminating same-second replay. Callers MUST read the live
7
+ * `StakerAccount.totalClaimed` immediately before signing.
8
+ *
9
+ * Message layout — 80 bytes, little-endian where applicable:
10
+ *
11
+ * [0..32] pool (PublicKey bytes)
12
+ * [32..64] staker wallet (PublicKey bytes)
13
+ * [64..72] trait_bonus_rate u64 (LE)
14
+ * [72..80] total_claimed u64 (LE)
15
+ *
16
+ * Sign this byte payload with the pool's trait-authority Ed25519 keypair
17
+ * (or the global trait authority) and prepend an Ed25519 instruction with
18
+ * the signature, expected pubkey, and message to the same transaction that
19
+ * invokes `claimRewards(..., traitBonusRate)`.
20
+ */
21
+ import { type PkInput, type BnInput } from "@soltracer/core";
22
+ /** Fixed message length consumed by the on-chain Ed25519 verifier. */
23
+ export declare const TRAIT_PROOF_MSG_LEN = 80;
24
+ /**
25
+ * Build the 80-byte trait-proof message exactly as the on-chain handler
26
+ * reconstructs it. `totalClaimed` must be the LIVE value of
27
+ * `StakerAccount.totalClaimed` (i.e. fetched within the same client tx
28
+ * preparation window — otherwise the signature will be rejected).
29
+ */
30
+ export declare function buildTraitProofMessage(params: {
31
+ pool: PkInput;
32
+ wallet: PkInput;
33
+ traitBonusRate: BnInput;
34
+ /** Strictly monotonic nonce — `StakerAccount.totalClaimed` */
35
+ totalClaimed: BnInput;
36
+ }): Buffer;
37
+ /**
38
+ * Example (off-chain trait-authority server):
39
+ *
40
+ * ```ts
41
+ * import nacl from "tweetnacl"
42
+ * import { Ed25519Program } from "@solana/web3.js"
43
+ * import { buildTraitProofMessage } from "@soltracer/nft-staking"
44
+ *
45
+ * const message = buildTraitProofMessage({
46
+ * pool,
47
+ * wallet: staker,
48
+ * traitBonusRate,
49
+ * totalClaimed: stakerAccount.totalClaimed,
50
+ * })
51
+ * const signature = nacl.sign.detached(message, traitAuthority.secretKey)
52
+ * const ed25519Ix = Ed25519Program.createInstructionWithPublicKey({
53
+ * publicKey: traitAuthority.publicKey.toBytes(),
54
+ * message,
55
+ * signature,
56
+ * })
57
+ * const claimIx = await client.claimRewards(poolId, { traitBonusRate })
58
+ * await provider.sendAndConfirm(new Transaction().add(ed25519Ix, claimIx))
59
+ * ```
60
+ */
61
+ //# sourceMappingURL=traitProof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traitProof.d.ts","sourceRoot":"","sources":["../src/traitProof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAQ,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAElE,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAcrC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,cAAc,EAAE,OAAO,CAAA;IACvB,8DAA8D;IAC9D,YAAY,EAAE,OAAO,CAAA;CACtB,GAAG,MAAM,CAOT;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Trait-bonus proof builder for NFT-staking `claim_rewards`.
3
+ *
4
+ * Audit 2026-05-11 F-H2: the on-chain Ed25519 message embeds
5
+ * `staker.total_claimed` (strictly monotonic) instead of `last_update_at`,
6
+ * eliminating same-second replay. Callers MUST read the live
7
+ * `StakerAccount.totalClaimed` immediately before signing.
8
+ *
9
+ * Message layout — 80 bytes, little-endian where applicable:
10
+ *
11
+ * [0..32] pool (PublicKey bytes)
12
+ * [32..64] staker wallet (PublicKey bytes)
13
+ * [64..72] trait_bonus_rate u64 (LE)
14
+ * [72..80] total_claimed u64 (LE)
15
+ *
16
+ * Sign this byte payload with the pool's trait-authority Ed25519 keypair
17
+ * (or the global trait authority) and prepend an Ed25519 instruction with
18
+ * the signature, expected pubkey, and message to the same transaction that
19
+ * invokes `claimRewards(..., traitBonusRate)`.
20
+ */
21
+ import { toPk } from "@soltracer/core";
22
+ /** Fixed message length consumed by the on-chain Ed25519 verifier. */
23
+ export const TRAIT_PROOF_MSG_LEN = 80;
24
+ function u64LE(value) {
25
+ const bi = typeof value === "bigint"
26
+ ? value
27
+ : typeof value === "number"
28
+ ? BigInt(value)
29
+ : BigInt(value.toString());
30
+ const buf = Buffer.alloc(8);
31
+ buf.writeBigUInt64LE(bi);
32
+ return buf;
33
+ }
34
+ /**
35
+ * Build the 80-byte trait-proof message exactly as the on-chain handler
36
+ * reconstructs it. `totalClaimed` must be the LIVE value of
37
+ * `StakerAccount.totalClaimed` (i.e. fetched within the same client tx
38
+ * preparation window — otherwise the signature will be rejected).
39
+ */
40
+ export function buildTraitProofMessage(params) {
41
+ const msg = Buffer.alloc(TRAIT_PROOF_MSG_LEN);
42
+ toPk(params.pool).toBuffer().copy(msg, 0);
43
+ toPk(params.wallet).toBuffer().copy(msg, 32);
44
+ u64LE(params.traitBonusRate).copy(msg, 64);
45
+ u64LE(params.totalClaimed).copy(msg, 72);
46
+ return msg;
47
+ }
48
+ /**
49
+ * Example (off-chain trait-authority server):
50
+ *
51
+ * ```ts
52
+ * import nacl from "tweetnacl"
53
+ * import { Ed25519Program } from "@solana/web3.js"
54
+ * import { buildTraitProofMessage } from "@soltracer/nft-staking"
55
+ *
56
+ * const message = buildTraitProofMessage({
57
+ * pool,
58
+ * wallet: staker,
59
+ * traitBonusRate,
60
+ * totalClaimed: stakerAccount.totalClaimed,
61
+ * })
62
+ * const signature = nacl.sign.detached(message, traitAuthority.secretKey)
63
+ * const ed25519Ix = Ed25519Program.createInstructionWithPublicKey({
64
+ * publicKey: traitAuthority.publicKey.toBytes(),
65
+ * message,
66
+ * signature,
67
+ * })
68
+ * const claimIx = await client.claimRewards(poolId, { traitBonusRate })
69
+ * await provider.sendAndConfirm(new Transaction().add(ed25519Ix, claimIx))
70
+ * ```
71
+ */
72
+ //# sourceMappingURL=traitProof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traitProof.js","sourceRoot":"","sources":["../src/traitProof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,IAAI,EAA8B,MAAM,iBAAiB,CAAA;AAElE,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAErC,SAAS,KAAK,CAAC,KAAc;IAC3B,MAAM,EAAE,GACN,OAAO,KAAK,KAAK,QAAQ;QACvB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACf,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC3B,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;IACxB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAMtC;IACC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;IAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC5C,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC1C,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACxC,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soltracer/nft-staking",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,7 +11,9 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@soltracer/core": "0.1.2"
14
+ "@noble/hashes": "^1.8.0",
15
+ "@soltracer/core": "0.2.0",
16
+ "@soltracer/cpi-accounts": "0.1.0"
15
17
  },
16
18
  "devDependencies": {
17
19
  "typescript": "^5.7.0"