-
Notifications
You must be signed in to change notification settings - Fork 85
chore: rebase v2 support onto 0.21.0 #1746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
50985c6 to
0bc8e3e
Compare
0bc8e3e to
b9d6ee9
Compare
9c08675 to
7e607c0
Compare
* stateless.js add treeinfos * wip * add getTokenPoolInfos * wip * wip * wip - storageoptions * wip * wip * wip * wip - known bug in rpc-interop.test.ts if using random trees * debugged test-rpc in ctoken * all ctoken tests working * rm logs * clean * ctxs to infos, removed redundant getMintProgramId calls * rm deadcode, storageoptions * fix cli getMindProgramId use * fix tokenpool * fix test stateless.js add treeinfos wip add getTokenPoolInfos wip wip wip - storageoptions wip wip wip wip - known bug in rpc-interop.test.ts if using random trees debugged test-rpc in ctoken all ctoken tests working rm logs clean ctxs to infos, removed redundant getMintProgramId calls rm deadcode, storageoptions fix cli getMindProgramId use fix tokenpool fix test update CHANGELOG.md files update changelog update CHANGELOG.md export get-token-pool-infos.ts wip clean wip refactor merklecontext refactor StateTreeInfo wip wip debug test-rpc getCompressedTokenAccountsByOwner fix unit test wip wip wip debug .readUIntLE wip wip wip fix buffer conversion at test-rpc decode wip tests working compressedProof -> validityProof update changelog wip refactor: do not allow output trees for decompress, transfer fmt wip rename getCachedStateTreeInfos upd changelog use with getCachedStateTreeInfos getStateTreeInfos wip wip delegate test wip added transfer-delegated.test.ts added transfer-delegated test cases. all green add tests for decompress-delegated fix rm logs from program update changelog update err msg fix state-tree-luts wip getActiveStateTreeInfos -> getAllStateTreeInfos wip fix sigs for nullifyStateTree wip wip cleanup add getCachedActiveStateTreeInfos mock revert to compressedProof add tokenpools tests update comment update CHANGELOG.md update changelog 0.21.0 update changelog fix fix event parsing post rebase stateless js refactor dedupe types link to computebudgetprogram wip fix DX for instructions: add docstrings to call signatures wip dont break mergeTokenAccounts wip wip add v2 trees to test-rpc v1 mergeable test-rpc tests working rpc-interop tests working with v2 all stateless.js tests working with v2 compressed-token tests working rebase to main fixup cargo lock wip
7e607c0 to
d235ce2
Compare
chore: backport breaking api changes to v1 js SDKs (#1661) * stateless.js add treeinfos * wip * add getTokenPoolInfos * wip * wip * wip - storageoptions * wip * wip * wip * wip - known bug in rpc-interop.test.ts if using random trees * debugged test-rpc in ctoken * all ctoken tests working * rm logs * clean * ctxs to infos, removed redundant getMintProgramId calls * rm deadcode, storageoptions * fix cli getMindProgramId use * fix tokenpool * fix test stateless.js add treeinfos wip add getTokenPoolInfos wip wip wip - storageoptions wip wip wip wip - known bug in rpc-interop.test.ts if using random trees debugged test-rpc in ctoken all ctoken tests working rm logs clean ctxs to infos, removed redundant getMintProgramId calls rm deadcode, storageoptions fix cli getMindProgramId use fix tokenpool fix test update CHANGELOG.md files update changelog update CHANGELOG.md export get-token-pool-infos.ts wip clean wip refactor merklecontext refactor StateTreeInfo wip wip debug test-rpc getCompressedTokenAccountsByOwner fix unit test wip wip wip debug .readUIntLE wip wip wip fix buffer conversion at test-rpc decode wip tests working compressedProof -> validityProof update changelog wip refactor: do not allow output trees for decompress, transfer fmt wip rename getCachedStateTreeInfos upd changelog use with getCachedStateTreeInfos getStateTreeInfos wip wip delegate test wip added transfer-delegated.test.ts added transfer-delegated test cases. all green add tests for decompress-delegated fix rm logs from program update changelog update err msg fix state-tree-luts wip getActiveStateTreeInfos -> getAllStateTreeInfos wip fix sigs for nullifyStateTree wip wip cleanup add getCachedActiveStateTreeInfos mock revert to compressedProof add tokenpools tests update comment update CHANGELOG.md update changelog 0.21.0 update changelog fix fix event parsing post rebase stateless js refactor dedupe types link to computebudgetprogram wip fix DX for instructions: add docstrings to call signatures wip dont break mergeTokenAccounts wip wip add v2 trees to test-rpc v1 mergeable test-rpc tests working rpc-interop tests working with v2 all stateless.js tests working with v2 compressed-token tests working rebase to main fixup cargo lock wip chore: backport breaking api changes to v1 js SDKs (#1661) * stateless.js add treeinfos * wip * add getTokenPoolInfos * wip * wip * wip - storageoptions * wip * wip * wip * wip - known bug in rpc-interop.test.ts if using random trees * debugged test-rpc in ctoken * all ctoken tests working * rm logs * clean * ctxs to infos, removed redundant getMintProgramId calls * rm deadcode, storageoptions * fix cli getMindProgramId use * fix tokenpool * fix test stateless.js add treeinfos wip add getTokenPoolInfos wip wip wip - storageoptions wip wip wip wip - known bug in rpc-interop.test.ts if using random trees debugged test-rpc in ctoken all ctoken tests working rm logs clean ctxs to infos, removed redundant getMintProgramId calls rm deadcode, storageoptions fix cli getMindProgramId use fix tokenpool fix test update CHANGELOG.md files update changelog update CHANGELOG.md export get-token-pool-infos.ts wip clean wip refactor merklecontext refactor StateTreeInfo wip wip debug test-rpc getCompressedTokenAccountsByOwner fix unit test wip wip wip debug .readUIntLE wip wip wip fix buffer conversion at test-rpc decode wip tests working compressedProof -> validityProof update changelog wip refactor: do not allow output trees for decompress, transfer fmt wip rename getCachedStateTreeInfos upd changelog use with getCachedStateTreeInfos getStateTreeInfos wip wip delegate test wip added transfer-delegated.test.ts added transfer-delegated test cases. all green add tests for decompress-delegated fix rm logs from program update changelog update err msg fix state-tree-luts wip getActiveStateTreeInfos -> getAllStateTreeInfos wip fix sigs for nullifyStateTree wip wip cleanup add getCachedActiveStateTreeInfos mock revert to compressedProof add tokenpools tests update comment update CHANGELOG.md update changelog 0.21.0 update changelog fix fix event parsing post rebase stateless js refactor dedupe types link to computebudgetprogram wip fix DX for instructions: add docstrings to call signatures wip dont break mergeTokenAccounts wip wip add v2 trees to test-rpc v1 mergeable test-rpc tests working rpc-interop tests working with v2 all stateless.js tests working with v2 compressed-token tests working rebase to main fixup cargo lock wip wip rename statetreeinfo -> treeinfo wip wip wip cli test works wip wip wip wip wip wip wip wip wip wip wip wip rm logs fix lint clean upd comment
* stateless.js add treeinfos * wip * add getTokenPoolInfos * wip * wip * wip - storageoptions * wip * wip * wip * wip - known bug in rpc-interop.test.ts if using random trees * debugged test-rpc in ctoken * all ctoken tests working * rm logs * clean * ctxs to infos, removed redundant getMintProgramId calls * rm deadcode, storageoptions * fix cli getMindProgramId use * fix tokenpool * fix test stateless.js add treeinfos wip add getTokenPoolInfos wip wip wip - storageoptions wip wip wip wip - known bug in rpc-interop.test.ts if using random trees debugged test-rpc in ctoken all ctoken tests working rm logs clean ctxs to infos, removed redundant getMintProgramId calls rm deadcode, storageoptions fix cli getMindProgramId use fix tokenpool fix test update CHANGELOG.md files update changelog update CHANGELOG.md export get-token-pool-infos.ts wip clean wip refactor merklecontext refactor StateTreeInfo wip wip debug test-rpc getCompressedTokenAccountsByOwner fix unit test wip wip wip debug .readUIntLE wip wip wip fix buffer conversion at test-rpc decode wip tests working compressedProof -> validityProof update changelog wip refactor: do not allow output trees for decompress, transfer fmt wip rename getCachedStateTreeInfos upd changelog use with getCachedStateTreeInfos getStateTreeInfos wip wip delegate test wip added transfer-delegated.test.ts added transfer-delegated test cases. all green add tests for decompress-delegated fix rm logs from program update changelog update err msg fix state-tree-luts wip getActiveStateTreeInfos -> getAllStateTreeInfos wip fix sigs for nullifyStateTree wip wip cleanup add getCachedActiveStateTreeInfos mock revert to compressedProof add tokenpools tests update comment update CHANGELOG.md update changelog 0.21.0 update changelog fix fix event parsing post rebase stateless js refactor dedupe types link to computebudgetprogram wip fix DX for instructions: add docstrings to call signatures wip dont break mergeTokenAccounts wip wip add v2 trees to test-rpc v1 mergeable test-rpc tests working rpc-interop tests working with v2 all stateless.js tests working with v2 compressed-token tests working rebase to main fixup cargo lock wip chore: backport breaking api changes to v1 js SDKs (#1661) * stateless.js add treeinfos * wip * add getTokenPoolInfos * wip * wip * wip - storageoptions * wip * wip * wip * wip - known bug in rpc-interop.test.ts if using random trees * debugged test-rpc in ctoken * all ctoken tests working * rm logs * clean * ctxs to infos, removed redundant getMintProgramId calls * rm deadcode, storageoptions * fix cli getMindProgramId use * fix tokenpool * fix test stateless.js add treeinfos wip add getTokenPoolInfos wip wip wip - storageoptions wip wip wip wip - known bug in rpc-interop.test.ts if using random trees debugged test-rpc in ctoken all ctoken tests working rm logs clean ctxs to infos, removed redundant getMintProgramId calls rm deadcode, storageoptions fix cli getMindProgramId use fix tokenpool fix test update CHANGELOG.md files update changelog update CHANGELOG.md export get-token-pool-infos.ts wip clean wip refactor merklecontext refactor StateTreeInfo wip wip debug test-rpc getCompressedTokenAccountsByOwner fix unit test wip wip wip debug .readUIntLE wip wip wip fix buffer conversion at test-rpc decode wip tests working compressedProof -> validityProof update changelog wip refactor: do not allow output trees for decompress, transfer fmt wip rename getCachedStateTreeInfos upd changelog use with getCachedStateTreeInfos getStateTreeInfos wip wip delegate test wip added transfer-delegated.test.ts added transfer-delegated test cases. all green add tests for decompress-delegated fix rm logs from program update changelog update err msg fix state-tree-luts wip getActiveStateTreeInfos -> getAllStateTreeInfos wip fix sigs for nullifyStateTree wip wip cleanup add getCachedActiveStateTreeInfos mock revert to compressedProof add tokenpools tests update comment update CHANGELOG.md update changelog 0.21.0 update changelog fix fix event parsing post rebase stateless js refactor dedupe types link to computebudgetprogram wip fix DX for instructions: add docstrings to call signatures wip dont break mergeTokenAccounts wip wip add v2 trees to test-rpc v1 mergeable test-rpc tests working rpc-interop tests working with v2 all stateless.js tests working with v2 compressed-token tests working rebase to main fixup cargo lock wip wip rename statetreeinfo -> treeinfo wip wip wip cli test works wip wip wip wip wip wip wip wip wip wip wip wip rm logs fix lint clean upd comment wip stateless.js tests working ctoken tests working
js/compressed-token/src/program.ts
Outdated
| inputCompressedTokenAccounts, | ||
| ); | ||
|
|
||
| const CHANGE_INDEX = featureFlags.isV2() ? 1 : 0; // TODO: find better solution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the idea here?
are we always passing a tree and a queue in remaining accounts and are just switching the indices based on the version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't inputCompressedTokenAccounts include a TreeInfo that has a tree version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
featureFlags is for switching our sdk to v2 (endpoints, new instructions,..) so it's actually misused here. switched to treeInfo.treeType in all places where it should
WalkthroughThis update introduces substantial changes across the compressed token and stateless.js libraries, focusing on protocol scalability, multi-pool support, and enhanced state tree and proof management. Major refactors include new and updated types, batch and delegation instructions, migration to dynamic state tree/token pool selection, and V2 API support. Test suites and utilities are updated accordingly. Changes
Sequence Diagram(s)Compressed Token Minting and Compression (New Flow)sequenceDiagram
participant User
participant RPC
participant TokenPoolSelector
participant StateTreeSelector
participant CompressedTokenProgram
User->>RPC: getStateTreeInfos()
RPC-->>User: [TreeInfo...]
User->>StateTreeSelector: selectStateTreeInfo([TreeInfo...])
StateTreeSelector-->>User: stateTreeInfo
User->>RPC: getTokenPoolInfos(mint)
RPC-->>User: [TokenPoolInfo...]
User->>TokenPoolSelector: selectTokenPoolInfo([TokenPoolInfo...])
TokenPoolSelector-->>User: tokenPoolInfo
User->>CompressedTokenProgram: mintTo({stateTreeInfo, tokenPoolInfo, ...})
CompressedTokenProgram-->>User: TransactionInstruction
User->>RPC: sendAndConfirmTx(TransactionInstruction)
RPC-->>User: TransactionSignature
Delegated Transfer and DecompressionsequenceDiagram
participant Owner
participant Delegate
participant RPC
participant CompressedTokenProgram
Owner->>CompressedTokenProgram: approve({owner, delegate, amount, ...})
CompressedTokenProgram-->>Owner: TransactionInstruction
Owner->>RPC: sendAndConfirmTx(TransactionInstruction)
RPC-->>Owner: TransactionSignature
Delegate->>CompressedTokenProgram: transferDelegated({delegate, toAddress, amount, ...})
CompressedTokenProgram-->>Delegate: TransactionInstruction
Delegate->>RPC: sendAndConfirmTx(TransactionInstruction)
RPC-->>Delegate: TransactionSignature
Delegate->>CompressedTokenProgram: decompressDelegated({delegate, toAddress, amount, ...})
CompressedTokenProgram-->>Delegate: TransactionInstruction
Delegate->>RPC: sendAndConfirmTx(TransactionInstruction)
RPC-->>Delegate: TransactionSignature
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 25
🔭 Outside diff range comments (14)
js/stateless.js/tests/e2e/transfer.test.ts (1)
55-57: 🛠️ Refactor suggestion
bn(-transferAmount)may throw – construct negative BN via.neg()instead.Many BN helpers accept only unsigned input. Creating a negative number directly can fail on some runtimes.
- assert( - postSenderBalance.sub(preSenderBalance).eq(bn(-transferAmount)), + const expectedDelta = bn(transferAmount).neg(); // safer + assert( + postSenderBalance.sub(preSenderBalance).eq(expectedDelta),cli/src/commands/compress-spl/index.ts (2)
55-66:⚠️ Potential issueGuard against
undefinedtokenProgramId.
getMintProgramIdreturnsPromise<PublicKey | undefined>.
If the mint was initialized with the default SPL‐Token program the call will resolve toundefined; passing this straight intogetAssociatedTokenAddressSyncwill throw because that function expects a definedPublicKey, notundefined.const payer = defaultSolanaWalletKeypair(); - const tokenProgramId = await CompressedTokenProgram.getMintProgramId( + const tokenProgramId = await CompressedTokenProgram.getMintProgramId( mintPublicKey, rpc(), ); + + if (!tokenProgramId) { + throw new Error( + `Unable to determine token program for mint ${mintPublicKey.toBase58()}`, + ); + }
48-87: 🛠️ Refactor suggestionSpinner never stops on error.
loader.start()is called butloader.stop()is only executed on the happy path.
On failure the process exits viathis.error, leaving the TTY spinner running and
corrupting subsequent output.console.log("compress-spl successful"); } catch (error) { - console.log("compress-spl failed", txId); + loader.stop(true); + console.log("compress-spl failed", txId); this.error(`Failed to compress-spl!\n${error}`); }cli/src/commands/decompress-spl/index.ts (2)
60-69:⚠️ Potential issueIncorrect argument position in
getOrCreateAssociatedTokenAccount.
tokenProgramIdmust be the 8-th parameter (programId), not the 9-th
(associatedTokenProgramId).
Passing it in the wrong slot breaks accounts created under custom programs.- undefined, - undefined, - undefined, - tokenProgramId, + undefined, // allowOwnerOffCurve + undefined, // commitment + undefined, // confirmOptions + tokenProgramId, // <-- programId (8th argument)
48-90: 🛠️ Refactor suggestionStop loader on failure (same issue as compress command).
console.log("decompress-spl successful"); } catch (error) { - console.log("decompress-spl failed", txId); + loader.stop(true); + console.log("decompress-spl failed", txId); this.error(`Failed to decompress-spl!\n${error}`); }js/stateless.js/src/actions/decompress.ts (1)
32-41:⚠️ Potential issueGuard against empty input set before proceeding
rpc.getCompressedAccountsByOwnercan legitimately return an empty list (e.g. a brand-new payer).
InvokingsumUpLamportsandrpc.getValidityProofwith an empty array will either throw or produce a confusing “Not enough compressed lamports” error downstream. Bail out early with a clearer message.+ if (userCompressedAccountsWithMerkleContext.length === 0) { + throw new Error('Payer owns no compressed accounts – nothing to decompress'); + }js/stateless.js/tests/unit/utils/conversion.test.ts (2)
59-63: 🛠️ Refactor suggestionOut-of-date field name
queue_indexwill break once decoder is upgradedThe new layout renamed
queue_index→queuePubkeyIndex. Keeping the old
expectation will cause this test to fail after the corresponding implementation lands.- tree_index: 1, - queue_index: 1, + treeIndex: 1, + queuePubkeyIndex: 1,
71-78: 🛠️ Refactor suggestionSynchronise nullifier context field names with latest IDL
Similarly,
queue_indexshould bequeuePubkeyIndexandprove_by_indexis nowproveByIndex(camel-cased). Update to stay aligned with production structs.js/compressed-token/tests/e2e/merge-token-accounts.test.ts (1)
60-60:⚠️ Potential issue
it.onlywill cripple the entire Vitest suiteLeaving
.onlyin committed code means all other tests are skipped, masking regressions in unrelated areas.- it.only('should merge all token accounts', async () => { + it('should merge all token accounts', async () => {🧰 Tools
🪛 Biome (1.9.4)
[error] 60-60: Don't focus the test.
The 'only' method is often used for debugging or during implementation. It should be removed before deploying to production.
Consider removing 'only' to ensure all tests are executed.
Unsafe fix: Remove focus from test.(lint/suspicious/noFocusedTests)
js/stateless.js/src/utils/parse-validity-proof.ts (1)
64-78:⚠️ Potential issueIncorrect BN constructor usage – second arg should be endian string, not
32Passing
32as the base for aUint8Arrayinput is undefined behaviour inbn.js.
Use the endian parameter instead:-const aYElement = bn(proofA.slice(32, 64), 32, 'be'); +const aYElement = bn(proofA.slice(32, 64), undefined, 'be'); ... - bn(bYElement.slice(0, 32), 32, 'be'), - bn(bYElement.slice(32, 64), 32, 'be'), + bn(bYElement.slice(0, 32), undefined, 'be'), + bn(bYElement.slice(32, 64), undefined, 'be'), ... -const proofCIsPositive = yElementIsPositiveG1(bn(cYElement, 32, 'be')); +const proofCIsPositive = yElementIsPositiveG1( + bn(cYElement, undefined, 'be'), +);Without this fix the values are parsed as base-32 numbers, silently producing wrong proofs.
🧰 Tools
🪛 Biome (1.9.4)
[error] 68-68: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with(lint/complexity/noUselessTernary)
js/stateless.js/src/actions/transfer.ts (2)
80-83:⚠️ Potential issue
getValidityProofcall uses legacy signature – will reject on V2 clusters.API v2 expects
{hash, tree, queue}objects (getValidityProofV0). Passing bare hashes will lead toInvalid parametersRPC errors.- const proof = await rpc.getValidityProof( - inputAccounts.map(account => bn(account.hash)), - ); + const proof = await rpc.getValidityProofV0( + inputAccounts.map(a => ({ + hash: bn(a.hash), + tree: a.treeInfo.tree, + queue: a.treeInfo.queue, + })), + );
93-99:⚠️ Potential issueOwner is never added to
additionalSigners– tx will fail whenowner ≠ payer.- const signedTx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 350_000 }), ix], - payer, - blockhash, - ); + const additionalSigners = + owner.publicKey.equals(payer.publicKey) ? [] : [owner]; + + const signedTx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 350_000 }), ix], + payer, + blockhash, + additionalSigners, + );js/compressed-token/tests/e2e/compress-spl-token-account.test.ts (1)
359-367:⚠️ Potential issue
mintTocall missestokenPoolInfo– will throw after API upgradeAll other
mintToinvocations were updated to passtokenPoolInfo.
The Token-2022 branch still calls:await mintTo(..., bn(1000), stateTreeInfo);
tokenPoolInfois now mandatory for V2. Add the argument to keep the test green.- bn(1000), - stateTreeInfo, + bn(1000), + stateTreeInfo, + tokenPoolInfoT22,js/compressed-token/src/layout.ts (1)
49-64:⚠️ Potential issueBreaking change: Field renaming in InputTokenDataWithContextLayout
The renaming of
nullifierQueuePubkeyIndextoqueuePubkeyIndexand changingqueueIndexfrom a field to a booleanproveByIndexare breaking changes that could affect existing code using these layouts.Ensure that all code depending on these field names is updated accordingly, and document this breaking change in the migration guide or changelog.
♻️ Duplicate comments (2)
cli/src/commands/decompress-spl/index.ts (1)
55-59: Sameundefinedguard needed as incompress-spl.The code path is identical; protect against an unresolved token-program id.
js/compressed-token/src/types.ts (1)
76-81: Remove leftover development comments
🧹 Nitpick comments (55)
js/compressed-token/vitest.config.ts (1)
14-15: Consider keeping the default reporter alongsideverbose.Replacing the default reporter means the final pass/fail summary banner disappears ‒ useful in CI logs.
If you only need the detailed per-test output, ignore this. Otherwise, consider:- reporters: ['verbose'], + reporters: ['default', 'verbose'],js/stateless.js/tests/e2e/transfer.test.ts (1)
21-22: Optional: useawait Promise.allto speed upcompress+ airdrop.
compressis awaited serially; parallelising funding steps (if more accounts appear later) can shave test time.
Not critical, just a potential test-suite speed-up.cli/src/commands/start-prover/index.ts (1)
63-66: Prefer the null-coalescing (??) operator for clearer intent
||will treat an empty string passed via--redisUrl=""as falsy and silently fall back to the env-var orundefined, which may surprise users.
Using??preserves the “explicit empty means empty” contract and makes the|| undefinedsuffix redundant.-const redisUrl = flags["redisUrl"] || process.env.REDIS_URL || undefined; +const redisUrl = flags["redisUrl"] ?? process.env.REDIS_URL;examples/anchor/counter/tests/test.rs (1)
202-206: Field order is now inconsistent with sibling helpers
increment_counterbuildsCompressedAccountMetawithaddressfirst, whereasdecrement_counter,reset_counter, etc. still usetree_infofirst.
Although Rust struct literals ignore order, keeping a consistent layout across helpers avoids cognitive friction and reduces merge-conflict noise.Consider reverting to the common order or updating the others for uniformity.
js/compressed-token/rollup.config.js (1)
48-55: Leavingdrop_console: falsein production bundles may bloat size and leak internalsIf the intention is only to aid local debugging, gate this option on the build target (e.g. keep logs for dev builds, strip for prod).
A quick toggle:- terser({ - compress: { - drop_console: false, + terser({ + compress: { + drop_console: env !== 'browser', // strip in node/browser-prodor expose an explicit
--debugflag in your build script.js/compressed-token/src/utils/index.ts (1)
1-4: Public API surface widened – double-check versioningRe-exporting these helpers is handy, but it also freezes their current signatures in the public contract. Make sure semver expectations are clear (e.g. bump minor version) and add docs so downstream consumers know they’re supported.
js/compressed-token/src/utils/validation.ts (1)
11-21: Empty input array is silently accepted.
every()on an empty array returnstrue, socheckMint([])currently succeeds.
For symmetry withvalidateSameOwner(which guards against this) add an explicit
length check:export function checkMint( compressedTokenAccounts: ParsedTokenAccount[], mint: PublicKey, ): boolean { - if ( + if (compressedTokenAccounts.length === 0) { + throw new Error('No accounts provided for mint validation'); + } + + if ( !compressedTokenAccounts.every(account => account.parsed.mint.equals(mint), ) ) {js/stateless.js/package.json (1)
101-101: Suggest extracting composite script.
Thetest:e2e:allcommand is very long and hard to maintain. Consider moving it into a dedicated shell script or leveraging a task runner for better readability.js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts (1)
254-261: Add error handling around deserialization.
IfdeserializeAppendNullifyCreateAddressInputsIndexerthrows, it could abort the entire parsing loop. Wrap this call in atry/catchto log failures without dropping all events.js/compressed-token/tests/e2e/mint-to.test.ts (2)
104-115: Remove unusedtxId(or assert on it) to satisfy linters
txIdis assigned but never read. Either assert its truthiness or drop the variable.- const txId = await mintTo( + await mintTo(
160-170:txvariable is computed but never usedSame issue as above – consider asserting on
txor omitting the assignment.- const tx = await mintTo( + await mintTo(js/stateless.js/src/state/bn.ts (1)
3-12: Avoid forwardingbase/endianwhen cloning an existingBNPassing
basetonew BN(existingBn, base)is undocumented and may throw in
futurebn.jsversions. Strip the optional params when the argument is already
aBNinstance.- if (number instanceof Uint8Array && !(number instanceof Buffer)) { + if (number instanceof Uint8Array && !(number instanceof Buffer)) { return new BN(Buffer.from(number), base, endian); } - return new BN(number, base, endian); + return number instanceof BN + ? new BN(number) + : new BN(number, base, endian);js/compressed-token/src/actions/index.ts (1)
1-15: Alphabetise exports to make merge conflicts rarerMinor, but keeping exports sorted reduces churn when adding new actions.
No code change required if team disagrees.
js/stateless.js/src/state/BN254.ts (1)
46-49: Avoid the extra memory copy when convertingBuffer→Uint8Array
Bufferis already a subclass ofUint8Array; the cast is only required for the TS type-checker.
new Uint8Array(bn254Buffer)allocates a fresh copy every call, which is wasteful in a hot path such as encoding.- return bs58.encode(new Uint8Array(bn254Buffer)); + // Cast without copying – zero-alloc on Node ≥ 12 + return bs58.encode( + bn254Buffer as unknown as Uint8Array /* Buffer → Uint8Array cast */ + );js/compressed-token/src/constants.ts (1)
14-16: Discriminators look good – consider adding dev-docsThe new discriminators follow the existing 8-byte pattern and are unique.
For long-term maintainability, consider a short comment indicating which on-chain instruction each constant maps to (mirrors the IDL names).Also applies to: 24-32
js/compressed-token/tests/e2e/merge-token-accounts.test.ts (1)
3-11: Remove unused import to keep linter happy
defaultTestStateTreeAccountsis no longer referenced after moving to dynamicstateTreeInfoselection.- defaultTestStateTreeAccounts,js/compressed-token/tests/e2e/approve-and-mint-to.test.ts (2)
18-21: Remove unused import to avoid linter noise
defaultTestStateTreeAccountsis still imported but never referenced after the refactor to dynamic tree-selection.-import { - Rpc, - bn, - buildAndSignTx, - dedupeSigner, - newAccountWithLamports, - sendAndConfirmTx, - getTestRpc, - defaultTestStateTreeAccounts, - TreeInfo, - selectStateTreeInfo, -} from '@lightprotocol/stateless.js'; +import { + Rpc, + bn, + buildAndSignTx, + dedupeSigner, + newAccountWithLamports, + sendAndConfirmTx, + getTestRpc, + TreeInfo, + selectStateTreeInfo, +} from '@lightprotocol/stateless.js';Tidying this keeps CI/lint pipelines green.
113-127: Variable shadowing may confuse future maintainersInside the second
itblock a newconst payershadows the outer-scopepayer.
Although legal, it is easy to overlook and can lead to subtle bugs if the inner variable is later moved/used outside the block.Consider renaming (e.g.
localPayer) to make the scoping explicit.js/compressed-token/tests/e2e/rpc-token-interop.test.ts (1)
9-12: Drop the now-unused static tree import
defaultTestStateTreeAccountsis not referenced after the v2 migration.
Same pattern as in the previous test file – trim the import list.js/stateless.js/tests/unit/utils/tree-info.test.ts (1)
88-116: Test loops run 10k–100k iterations – they add seconds to CIRandomised selection can be validated with far fewer iterations (e.g. 500).
Reducing the loops keeps the suite fast without sacrificing confidence.js/stateless.js/src/utils/parse-validity-proof.ts (1)
98-103: Minor – small performance win
bn(...)already returns a Buffer when given a hex string; converting straight tobebytes avoids an interim BN:-const bN = bn(hexStr.startsWith('0x') ? hexStr.substring(2) : hexStr, 'hex'); -return new Uint8Array(bN.toArray('be', 32)); +return new Uint8Array( + bn( + hexStr.startsWith('0x') ? hexStr.substring(2) : hexStr, + 'hex', + ).toArray('be', 32), +);js/compressed-token/src/actions/create-token-program-lookup-table.ts (2)
43-43: Explicitly typetxIdsfor stronger compile-time guaranteesDeclare the variable with its intended type to avoid accidental misuse and make downstream intent clear.
- const txIds = []; + const txIds: TransactionSignature[] = [];
45-60: Sequential per-instruction round-trips are slow & blockhash calls are redundantEvery iteration fetches a fresh blockhash and awaits confirmation before moving on.
For large lookup tables this becomes noticeably slower and places unnecessary load on the RPC.
- Reuse one recent blockhash – a single hash is typically valid for ~150 blocks; signing several transactions with the same hash is fine.
- Fire transactions in parallel –
Promise.all(instructions.map(...))reduces wall-clock time and RPC latency.- Aggregate errors – if one tx fails you can still continue and return partial success (or bubble all errors).
Illustrative refactor:
-const txIds = []; -for (const instruction of instructions) { - const blockhashCtx = await rpc.getLatestBlockhash(); - const signedTx = buildAndSignTx([instruction], payer, blockhashCtx.blockhash, additionalSigners); - const txId = await sendAndConfirmTx(rpc, signedTx, { commitment: 'finalized' }, blockhashCtx); - txIds.push(txId); -} +const { blockhash, lastValidBlockHeight } = await rpc.getLatestBlockhash(); +const txIds = await Promise.all( + instructions.map(async ix => { + const signed = buildAndSignTx([ix], payer, blockhash, additionalSigners); + return sendAndConfirmTx( + rpc, + signed, + { commitment: 'finalized' }, + { blockhash, lastValidBlockHeight }, + ); + }), +);This keeps behaviour identical while greatly improving throughput.
js/stateless.js/tests/unit/instruction/pack-compressed-accounts.test.ts (2)
10-13: Remove dead variables to keep the test tidy
accA,accB, andaccCare no longer referenced after the refactor. Extra variables may trip linters or confuse future readers.- const accA: any = { treeInfo: { tree: treeA } }; - const accB: any = { treeInfo: { tree: treeB } }; - const accC: any = { treeInfo: { tree: treeC } };
14-17: Update description to match the new function contract
padOutputStateMerkleTreesno longer inspects “input state”.
A clearer spec title avoids cognitive dissonance.-it('should use the 0th state tree of input state if no output state trees are provided', () => { +it('should pad with the provided tree when only a single tree is given', () => {js/compressed-token/src/actions/approve.ts (2)
17-20: Drop unused import
selectMinCompressedTokenAccountsForTransferis imported but never used.-import { - selectMinCompressedTokenAccountsForTransfer, - selectTokenAccountsForApprove, -} from '../utils'; +import { selectTokenAccountsForApprove } from '../utils';
39-45: Avoid mutating theamountparameterShadowing the input with a different type can lead to subtle bugs and weakens type safety.
- amount = bn(amount); + const amountBn = bn(amount);Remember to pass
amountBnto subsequent calls.js/compressed-token/src/actions/transfer-delegated.ts (1)
36-42: Prefer immutable conversion foramountSame mutability issue as in
approve.ts.- amount = bn(amount); + const amountBn = bn(amount);Use
amountBndownstream.js/compressed-token/src/actions/merge-token-accounts.ts (2)
51-57: Repeatedslicecalls waste cycles and risk off-by-one errorsYou already cap to 8 accounts; compute that once and iterate on the trimmed array.
- for ( - let i = 0; - i < compressedTokenAccounts.items.slice(0, 8).length; - i += 4 - ) { - const batch = compressedTokenAccounts.items.slice(i, i + 4); + const capped = compressedTokenAccounts.items.slice(0, 8); + for (let i = 0; i < capped.length; i += 4) { + const batch = capped.slice(i, i + 4);This improves readability and eliminates redundant allocations.
48-49: 1 000 000 compute units may exceed the current network capRecent main-net limits cap at 800 000 units. Setting a higher value results in a failed simulation. Consider reducing to 500 000 or adding a try/catch that falls back to a lower limit.
js/stateless.js/tests/e2e/compress.test.ts (2)
69-76: Avoid randomness in tests – inject a deterministicTreeInfo.
selectStateTreeInfochooses a random active tree which can cause non-deterministic test failures when several trees are present. Prefer selecting a fixed element (e.g. first sorted entry) or mocking the selector for the test run.
95-111: Assertion relies on an exact error-string – brittle test.Matching the complete message
'Neither input accounts nor outputStateTreeInfo are available'will break the test on any wording tweak.
Compare against the error class/type or usetoThrow()with a partial / regex instead.js/stateless.js/src/actions/compress.ts (1)
41-44: Fetching state-tree infos inside every call adds unnecessary RPC latency.Consider injecting
outputStateTreeInfofrom the caller (tests already do this) or caching the result in the action to avoid an extra round-trip per compression.js/compressed-token/tests/e2e/decompress.test.ts (1)
1-13:defaultTestStateTreeAccountsimport is now unused.Tree selection is performed via
selectStateTreeInfo; remove the unused symbol to keep the test lint-clean.-import { - ParsedTokenAccount, - Rpc, - bn, - defaultTestStateTreeAccounts, - newAccountWithLamports, - getTestRpc, - selectStateTreeInfo, - TreeInfo, -} from '@lightprotocol/stateless.js'; +import { + ParsedTokenAccount, + Rpc, + bn, + newAccountWithLamports, + getTestRpc, + selectStateTreeInfo, + TreeInfo, +} from '@lightprotocol/stateless.js';js/compressed-token/tests/e2e/multi-pool.test.ts (1)
134-143: Random pool / tree selection makes the test flaky
selectStateTreeInfoandselectTokenPoolInfointentionally return a random active entry.
Because subsequent assertions expect fixed indices & counts, the test can pass or fail depending on RNG state and concurrent test order.Seed the selection deterministically, or pick by explicit index:
- const info = selectStateTreeInfo(stateTreeInfos); + const info = stateTreeInfos.find(i => i.treeType === expectedType)!;Same applies to
tokenPoolInfo.js/compressed-token/tests/e2e/delegate.test.ts (1)
122-134: Single globalstateTreeInforeused across tests
stateTreeInfois captured once inbeforeAll, but state-tree rotation can occur between tests (especially when compression/decompression is happening in the same suite).
Stale tree info will cause sporadicProof verification failederrors.Fetch a fresh tree snapshot in
beforeEachor just-in-time before each action.js/stateless.js/tests/e2e/rpc-multi-trees.test.ts (1)
41-46: Consider completing the TODO for V2 multi-tree testing.The code correctly handles V1/V2 differences, but there's a TODO comment about adding specific tests for multiple V2 trees. This might be important for comprehensive test coverage.
Would you like me to help implement the test for multiple V2 trees or create an issue to track this task?
js/compressed-token/tests/e2e/decompress-delegated.test.ts (1)
51-56: Consider using bigint for balance calculations.While the current BN implementation works, consider migrating to native bigint for better performance and cleaner syntax, especially since you're already using modern JavaScript features.
js/compressed-token/package.json (1)
103-103: Consider refactoring the long test:e2e:all script.The
test:e2e:allscript has become quite long and difficult to maintain. Consider refactoring it to use a shell script or breaking it into smaller logical groups.Example approach:
"test:e2e:all": "pnpm test:e2e:core && pnpm test:e2e:delegation && pnpm test:e2e:compression", "test:e2e:core": "pnpm test-validator && vitest run tests/e2e/create-mint.test.ts && vitest run tests/e2e/mint-to.test.ts && vitest run tests/e2e/transfer.test.ts", "test:e2e:delegation": "pnpm test-validator && vitest run tests/e2e/delegate.test.ts && vitest run tests/e2e/transfer-delegated.test.ts && vitest run tests/e2e/decompress-delegated.test.ts", "test:e2e:compression": "pnpm test-validator-skip-prover && vitest run tests/e2e/compress.test.ts && vitest run tests/e2e/compress-spl-token-account.test.ts && vitest run tests/e2e/decompress.test.ts"js/compressed-token/src/utils/pack-compressed-token-accounts.ts (1)
39-159: Well-structured refactoring with good error handling.The refactoring properly implements the new TreeInfo-based approach with excellent defensive programming:
- Clear mutual exclusivity validation
- Proper feature flag gating for V2 trees
- Logical precedence handling for nextTreeInfo
Consider extracting the tree resolution logic into a helper function for better testability:
+function resolveActiveTreeOrQueue(treeInfo: TreeInfo): PublicKey { + const activeTreeInfo = treeInfo.nextTreeInfo || treeInfo; + + if (activeTreeInfo.treeType === TreeType.StateV2) { + if (featureFlags.isV2()) { + return activeTreeInfo.queue; + } + throw new Error('V2 trees are not supported yet'); + } + + return activeTreeInfo.tree; +} // Use next tree if available, otherwise fall back to current tree. // `nextTreeInfo` always takes precedence. - const activeTreeInfo = treeInfo.nextTreeInfo || treeInfo; - let activeTreeOrQueue = activeTreeInfo.tree; - - if (activeTreeInfo.treeType === TreeType.StateV2) { - if (featureFlags.isV2()) { - activeTreeOrQueue = activeTreeInfo.queue; - } else throw new Error('V2 trees are not supported yet'); - } + const activeTreeOrQueue = resolveActiveTreeOrQueue(treeInfo);js/stateless.js/CHANGELOG.md (1)
65-68: Typo in sample code – wrong variable name passed toselectStateTreeInfo
infois not defined in the snippet; the earlier line stores the array ininfos. Readers copy-pasting this will hit a ReferenceError.-const selectedInfo = selectStateTreeInfo(info); +const selectedInfo = selectStateTreeInfo(infos);js/compressed-token/tests/e2e/transfer.test.ts (2)
147-156: Remove noisyconsole.login test suite
console.log('txid transfer ', txid);will spam CI logs and makes failures harder to read. The txid is rarely useful outside debugging.- console.log('txid transfer ', txid);
174-182:transferhelper already prints a txid – duplicate debug outputSame log duplication as above; please drop it for cleaner output.
- console.log('txid transfer 2 ', txid2);js/stateless.js/tests/unit/state/compressed-account.test.ts (1)
55-63:hashgeneration uses numbers > 255 – considerUint8Array
new Array(32).fill(1)creates an array of JS numbers, not bytes; anything above255would silently truncate when converted to BN/Buffer.
Using aUint8Array(32).fill(1)is safer and documents intent.No diff provided – applies to multiple occurrences.
js/compressed-token/tests/e2e/compress.test.ts (1)
211-223: Inefficient assertion loop – body ignores loop index
for (let i = 0; i < recipients.length; i++) { … }repeatedly executes the same assertion with identical data, adding ~15 × runtime.Recommend removing the loop and calling
assertCompressonce, or passing the current recipient slice to validate per-iteration.js/stateless.js/tests/e2e/rpc-interop.test.ts (3)
23-41: Debug helpers pollute global test output
log/logIndexedemit to stdout on every run. Wrap them behind an env flag or remove to keep CI logs concise.
123-133: Duplicate iteration overtreeInfosYou loop twice to compare
.treeand.queue; combine for clarity:validityProof.treeInfos.forEach((elem, idx) => { assert.isTrue(elem.tree.equals(validityProofTest.treeInfos[idx].tree)); assert.isTrue(elem.queue.equals(validityProofTest.treeInfos[idx].queue)); });
682-688: Dead code – results read but never used
allAccountsTestRpcandallAccountsRpcare fetched then discarded. Remove to avoid lint warnings and unnecessary RPC round-trips.js/compressed-token/CHANGELOG.md (1)
85-85: Add comma for improved readability.-When building a transaction you can now pick a random treeInfo via `selectStateTreeInfo(infos)`. +When building a transaction, you can now pick a random treeInfo via `selectStateTreeInfo(infos)`.🧰 Tools
🪛 LanguageTool
[uncategorized] ~85-~85: Possible missing comma found.
Context: ...ll active state trees. When building a transaction you can now pick a random treeInfo via ...(AI_HYDRA_LEO_MISSING_COMMA)
js/compressed-token/src/utils/get-token-pool-infos.ts (1)
42-44: Consider making the pool count configurableThe function is hardcoded to fetch exactly 5 token pools. Consider extracting this as a constant or making it a parameter for future flexibility.
+const MAX_TOKEN_POOLS = 5; + export async function getTokenPoolInfos( rpc: Rpc, mint: PublicKey, commitment?: Commitment, ): Promise<TokenPoolInfo[]> { - const addressesAndBumps = Array.from({ length: 5 }, (_, i) => + const addressesAndBumps = Array.from({ length: MAX_TOKEN_POOLS }, (_, i) => CompressedTokenProgram.deriveTokenPoolPdaWithIndex(mint, i), );js/stateless.js/src/state/compressed-account.ts (1)
226-236: Usebn()helper instead ofnew BN()for consistency.The codebase is migrating to use the
bn()helper function, but these deprecated functions still usenew BN(0).Apply this diff to maintain consistency:
- lamports: lamports ?? new BN(0), + lamports: lamports ?? bn(0),Also applies to: 240-253
js/stateless.js/src/rpc.ts (1)
633-636: Add deprecation notice to guide users.The deprecated method should inform users about the replacement.
- async getCachedActiveStateTreeInfos() {} + async getCachedActiveStateTreeInfos() { + console.warn('getCachedActiveStateTreeInfos is deprecated. Use getStateTreeInfos() instead.'); + return this.getStateTreeInfos(); + }js/compressed-token/src/layout.ts (1)
534-547: Technical debt: Optional proof supportThe comment indicates that approve and revoke instructions don't support optional proofs yet, requiring the use of an empty proof placeholder. This is a limitation that should be addressed in future updates.
Would you like me to create an issue to track adding optional proof support for approve and revoke instructions?
js/compressed-token/src/program.ts (1)
650-661: Consider making the token pool limit configurableThe
findTokenPoolIndexAndBumpmethod hardcodes a limit of 5 indices (0-4). Consider making this limit configurable or at least define it as a constant for easier maintenance.+ static readonly MAX_TOKEN_POOLS_PER_MINT = 5; + static findTokenPoolIndexAndBump( poolPda: PublicKey, mint: PublicKey, ): [number, number] { - for (let index = 0; index < 5; index++) { + for (let index = 0; index < CompressedTokenProgram.MAX_TOKEN_POOLS_PER_MINT; index++) {🧰 Tools
🪛 Biome (1.9.4)
[error] 655-655: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
js/stateless.js/src/utils/get-state-tree-infos.ts (1)
197-209: Consider adding documentation for the nullified tree linking logicThe logic for linking nullified trees to their next available tree is complex. While the implementation appears correct, it would benefit from additional inline comments explaining:
- Why
PublicKey.defaultis used as a placeholder- The relationship between nullified trees and their next tree assignments
- The assumption that there will always be an available tree to assign
/// for each context, check if the tree is in the nullifyLookupTable + // Link nullified trees to the next available active tree + // Trees marked with PublicKey.default placeholder need assignment for (const context of contexts) { if (context.nextTreeInfo?.tree.equals(PublicKey.default)) { + // Find an active tree (one without nextTreeInfo) to link to const nextAvailableTreeInfo = contexts.find( ctx => !ctx.nextTreeInfo, );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
Cargo.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (106)
Cargo.toml(1 hunks)cli/src/commands/compress-spl/index.ts(1 hunks)cli/src/commands/decompress-spl/index.ts(1 hunks)cli/src/commands/init/index.ts(1 hunks)cli/src/commands/start-prover/index.ts(1 hunks)examples/anchor/counter/tests/test.rs(1 hunks)examples/browser/nextjs/src/app/page.tsx(3 hunks)js/compressed-token/CHANGELOG.md(2 hunks)js/compressed-token/package.json(2 hunks)js/compressed-token/rollup.config.js(1 hunks)js/compressed-token/src/actions/approve-and-mint-to.ts(2 hunks)js/compressed-token/src/actions/approve.ts(1 hunks)js/compressed-token/src/actions/compress-spl-token-account.ts(2 hunks)js/compressed-token/src/actions/compress.ts(3 hunks)js/compressed-token/src/actions/create-mint.ts(2 hunks)js/compressed-token/src/actions/create-token-pool.ts(4 hunks)js/compressed-token/src/actions/create-token-program-lookup-table.ts(2 hunks)js/compressed-token/src/actions/decompress-delegated.ts(1 hunks)js/compressed-token/src/actions/decompress.ts(3 hunks)js/compressed-token/src/actions/index.ts(1 hunks)js/compressed-token/src/actions/merge-token-accounts.ts(4 hunks)js/compressed-token/src/actions/mint-to.ts(2 hunks)js/compressed-token/src/actions/revoke.ts(1 hunks)js/compressed-token/src/actions/transfer-delegated.ts(1 hunks)js/compressed-token/src/actions/transfer.ts(3 hunks)js/compressed-token/src/constants.ts(2 hunks)js/compressed-token/src/idl.ts(4 hunks)js/compressed-token/src/index.ts(1 hunks)js/compressed-token/src/instructions/index.ts(0 hunks)js/compressed-token/src/layout.ts(9 hunks)js/compressed-token/src/program.ts(26 hunks)js/compressed-token/src/types.ts(5 hunks)js/compressed-token/src/utils/get-token-pool-infos.ts(1 hunks)js/compressed-token/src/utils/index.ts(1 hunks)js/compressed-token/src/utils/pack-compressed-token-accounts.ts(5 hunks)js/compressed-token/src/utils/select-input-accounts.ts(1 hunks)js/compressed-token/src/utils/validation.ts(1 hunks)js/compressed-token/tests/e2e/approve-and-mint-to.test.ts(5 hunks)js/compressed-token/tests/e2e/compress-spl-token-account.test.ts(15 hunks)js/compressed-token/tests/e2e/compress.test.ts(14 hunks)js/compressed-token/tests/e2e/create-token-pool.test.ts(8 hunks)js/compressed-token/tests/e2e/decompress-delegated.test.ts(1 hunks)js/compressed-token/tests/e2e/decompress.test.ts(6 hunks)js/compressed-token/tests/e2e/delegate.test.ts(1 hunks)js/compressed-token/tests/e2e/layout.test.ts(14 hunks)js/compressed-token/tests/e2e/merge-token-accounts.test.ts(7 hunks)js/compressed-token/tests/e2e/mint-to.test.ts(10 hunks)js/compressed-token/tests/e2e/multi-pool.test.ts(1 hunks)js/compressed-token/tests/e2e/rpc-multi-trees.test.ts(6 hunks)js/compressed-token/tests/e2e/rpc-token-interop.test.ts(5 hunks)js/compressed-token/tests/e2e/select-accounts.test.ts(35 hunks)js/compressed-token/tests/e2e/transfer-delegated.test.ts(1 hunks)js/compressed-token/tests/e2e/transfer.test.ts(13 hunks)js/compressed-token/tsconfig.json(1 hunks)js/compressed-token/vitest.config.ts(1 hunks)js/stateless.js/CHANGELOG.md(2 hunks)js/stateless.js/package.json(2 hunks)js/stateless.js/src/actions/compress.ts(1 hunks)js/stateless.js/src/actions/create-account.ts(5 hunks)js/stateless.js/src/actions/decompress.ts(1 hunks)js/stateless.js/src/actions/index.ts(1 hunks)js/stateless.js/src/actions/transfer.ts(4 hunks)js/stateless.js/src/constants.ts(10 hunks)js/stateless.js/src/index.ts(1 hunks)js/stateless.js/src/instruction/index.ts(0 hunks)js/stateless.js/src/instruction/pack-compressed-accounts.ts(0 hunks)js/stateless.js/src/programs/index.ts(0 hunks)js/stateless.js/src/programs/system/idl.ts(2 hunks)js/stateless.js/src/programs/system/index.ts(1 hunks)js/stateless.js/src/programs/system/layout.ts(7 hunks)js/stateless.js/src/programs/system/pack.ts(1 hunks)js/stateless.js/src/programs/system/program.ts(13 hunks)js/stateless.js/src/programs/system/select-compressed-accounts.ts(1 hunks)js/stateless.js/src/rpc-interface.ts(17 hunks)js/stateless.js/src/rpc.ts(32 hunks)js/stateless.js/src/state/BN254.ts(1 hunks)js/stateless.js/src/state/bn.ts(1 hunks)js/stateless.js/src/state/compressed-account.ts(1 hunks)js/stateless.js/src/state/index.ts(1 hunks)js/stateless.js/src/state/types.ts(1 hunks)js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts(2 hunks)js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts(7 hunks)js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts(2 hunks)js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts(12 hunks)js/stateless.js/src/utils/address.ts(1 hunks)js/stateless.js/src/utils/calculate-compute-unit-price.ts(1 hunks)js/stateless.js/src/utils/conversion.ts(3 hunks)js/stateless.js/src/utils/get-state-tree-infos.ts(1 hunks)js/stateless.js/src/utils/index.ts(1 hunks)js/stateless.js/src/utils/parse-validity-proof.ts(5 hunks)js/stateless.js/src/utils/send-and-confirm.ts(0 hunks)js/stateless.js/src/utils/state-tree-lookup-table.ts(5 hunks)js/stateless.js/src/utils/validation.ts(2 hunks)js/stateless.js/tests/e2e/compress.test.ts(10 hunks)js/stateless.js/tests/e2e/layout.test.ts(3 hunks)js/stateless.js/tests/e2e/rpc-interop.test.ts(15 hunks)js/stateless.js/tests/e2e/rpc-multi-trees.test.ts(8 hunks)js/stateless.js/tests/e2e/test-rpc.test.ts(4 hunks)js/stateless.js/tests/e2e/testnet.test.ts(2 hunks)js/stateless.js/tests/e2e/transfer.test.ts(2 hunks)js/stateless.js/tests/unit/instruction/pack-compressed-accounts.test.ts(1 hunks)js/stateless.js/tests/unit/state/bn254.test.ts(1 hunks)js/stateless.js/tests/unit/state/compressed-account.test.ts(4 hunks)js/stateless.js/tests/unit/utils/conversion.test.ts(3 hunks)js/stateless.js/tests/unit/utils/tree-info.test.ts(1 hunks)js/stateless.js/vitest.config.ts(1 hunks)
💤 Files with no reviewable changes (5)
- js/stateless.js/src/programs/index.ts
- js/stateless.js/src/utils/send-and-confirm.ts
- js/compressed-token/src/instructions/index.ts
- js/stateless.js/src/instruction/index.ts
- js/stateless.js/src/instruction/pack-compressed-accounts.ts
🧰 Additional context used
🧬 Code Graph Analysis (35)
js/stateless.js/tests/e2e/transfer.test.ts (1)
js/stateless.js/src/actions/compress.ts (1)
compress(31-63)
js/compressed-token/src/utils/validation.ts (1)
js/stateless.js/src/rpc-interface.ts (1)
ParsedTokenAccount(236-239)
cli/src/commands/compress-spl/index.ts (1)
js/compressed-token/src/program.ts (1)
CompressedTokenProgram(599-1646)
js/stateless.js/src/utils/validation.ts (1)
js/stateless.js/src/state/types.ts (1)
CompressedAccountLegacy(146-163)
js/compressed-token/tests/e2e/decompress.test.ts (5)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/compressed-token/src/utils/get-token-pool-infos.ts (4)
TokenPoolInfo(104-141)getTokenPoolInfos(37-93)selectTokenPoolInfo(173-187)selectTokenPoolInfosForDecompression(201-229)js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts (1)
getTestRpc(91-110)js/stateless.js/src/test-helpers/test-utils.ts (1)
newAccountWithLamports(69-83)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)
js/stateless.js/src/utils/parse-validity-proof.ts (3)
js/stateless.js/src/state/types.ts (1)
ValidityProof(397-410)js/stateless.js/src/state/bn.ts (1)
bn(3-12)js/stateless.js/src/constants.ts (1)
FIELD_SIZE(29-31)
js/stateless.js/tests/unit/instruction/pack-compressed-accounts.test.ts (1)
js/stateless.js/src/programs/system/pack.ts (1)
padOutputStateMerkleTrees(52-63)
js/compressed-token/tests/e2e/merge-token-accounts.test.ts (3)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/compressed-token/src/actions/merge-token-accounts.ts (1)
mergeTokenAccounts(29-86)
js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts (3)
js/stateless.js/src/utils/get-state-tree-infos.ts (1)
getStateTreeInfoByPubkey(8-13)js/stateless.js/src/state/compressed-account.ts (3)
MerkleContext(80-97)CompressedAccountWithMerkleContext(14-17)createCompressedAccountWithMerkleContextLegacy(240-253)js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/compressed-token/src/actions/create-token-program-lookup-table.ts (1)
js/stateless.js/src/utils/send-and-confirm.ts (2)
buildAndSignTx(123-144)sendAndConfirmTx(51-62)
js/compressed-token/src/actions/revoke.ts (4)
js/stateless.js/src/rpc-interface.ts (1)
ParsedTokenAccount(236-239)js/compressed-token/src/program.ts (1)
CompressedTokenProgram(599-1646)js/stateless.js/src/utils/dedupe-signer.ts (1)
dedupeSigner(4-11)js/stateless.js/src/utils/send-and-confirm.ts (2)
buildAndSignTx(123-144)sendAndConfirmTx(51-62)
js/stateless.js/tests/e2e/layout.test.ts (2)
js/compressed-token/src/idl.ts (1)
IDL(1833-3669)js/stateless.js/src/constants.ts (1)
COMPRESSED_TOKEN_PROGRAM_ID(198-200)
js/stateless.js/tests/e2e/compress.test.ts (7)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts (1)
TestRpc(120-950)js/stateless.js/src/test-helpers/test-utils.ts (1)
newAccountWithLamports(69-83)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/stateless.js/src/actions/create-account.ts (1)
createAccountWithLamports(113-175)js/stateless.js/src/actions/compress.ts (1)
compress(31-63)js/stateless.js/src/actions/decompress.ts (1)
decompress(25-71)
js/compressed-token/src/utils/pack-compressed-token-accounts.ts (4)
js/stateless.js/src/state/types.ts (2)
TreeInfo(77-99)InputTokenDataWithContext(415-440)js/stateless.js/src/rpc-interface.ts (1)
ParsedTokenAccount(236-239)js/stateless.js/src/programs/system/pack.ts (2)
getIndexOrAdd(22-34)padOutputStateMerkleTrees(52-63)js/stateless.js/src/constants.ts (1)
featureFlags(16-19)
js/stateless.js/src/actions/transfer.ts (1)
js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/stateless.js/src/actions/compress.ts (4)
js/stateless.js/src/programs/system/program.ts (2)
compress(421-476)LightSystemProgram(171-537)js/stateless.js/src/rpc.ts (1)
Rpc(614-1938)js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)
js/compressed-token/tests/e2e/approve-and-mint-to.test.ts (5)
js/compressed-token/src/utils/get-token-pool-infos.ts (3)
TokenPoolInfo(104-141)selectTokenPoolInfo(173-187)getTokenPoolInfos(37-93)js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/compressed-token/src/program.ts (1)
approveAndMintTo(937-972)js/compressed-token/src/actions/approve-and-mint-to.ts (1)
approveAndMintTo(44-100)
js/compressed-token/src/actions/merge-token-accounts.ts (1)
js/stateless.js/src/utils/send-and-confirm.ts (1)
sendAndConfirmTx(51-62)
js/stateless.js/src/programs/system/layout.ts (2)
js/stateless.js/src/constants.ts (1)
INVOKE_DISCRIMINATOR(38-40)js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/compressed-token/src/actions/mint-to.ts (6)
js/compressed-token/src/program.ts (2)
mintTo(867-920)CompressedTokenProgram(599-1646)js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/compressed-token/src/utils/get-token-pool-infos.ts (3)
TokenPoolInfo(104-141)selectTokenPoolInfo(173-187)getTokenPoolInfos(37-93)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/stateless.js/src/utils/dedupe-signer.ts (1)
dedupeSigner(4-11)js/stateless.js/src/utils/send-and-confirm.ts (1)
sendAndConfirmTx(51-62)
js/stateless.js/tests/unit/state/compressed-account.test.ts (2)
js/stateless.js/src/state/compressed-account.ts (3)
createCompressedAccountLegacy(226-236)createMerkleContextLegacy(258-268)createCompressedAccountWithMerkleContextLegacy(240-253)js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/compressed-token/src/utils/select-input-accounts.ts (1)
js/stateless.js/src/rpc-interface.ts (1)
ParsedTokenAccount(236-239)
js/stateless.js/tests/e2e/rpc-multi-trees.test.ts (8)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/stateless.js/src/rpc.ts (1)
createRpc(232-265)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/stateless.js/src/constants.ts (1)
featureFlags(16-19)js/stateless.js/src/test-helpers/test-utils.ts (1)
newAccountWithLamports(69-83)js/stateless.js/src/actions/compress.ts (1)
compress(31-63)js/stateless.js/src/actions/transfer.ts (1)
transfer(30-102)js/stateless.js/src/actions/create-account.ts (1)
createAccountWithLamports(113-175)
js/stateless.js/src/utils/conversion.ts (1)
js/stateless.js/src/state/types.ts (2)
CompressedAccountLegacy(146-163)PackedMerkleContextLegacy(120-137)
js/compressed-token/tests/e2e/compress-spl-token-account.test.ts (4)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)js/compressed-token/src/utils/get-token-pool-infos.ts (3)
TokenPoolInfo(104-141)selectTokenPoolInfo(173-187)getTokenPoolInfos(37-93)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
selectStateTreeInfo(84-110)js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/compressed-token/src/types.ts (2)
js/stateless.js/src/state/types.ts (4)
PackedMerkleContextLegacy(120-137)ValidityProof(397-410)InputTokenDataWithContext(415-440)CompressedCpiContext(353-368)js/compressed-token/src/utils/get-token-pool-infos.ts (1)
TokenPoolInfo(104-141)
js/stateless.js/src/constants.ts (1)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)
js/stateless.js/src/state/compressed-account.ts (2)
js/stateless.js/src/state/types.ts (4)
CompressedAccountData(199-212)TreeInfo(77-99)CompressedAccountLegacy(146-163)PackedMerkleContextLegacy(120-137)js/stateless.js/src/state/BN254.ts (1)
BN254(12-12)
js/stateless.js/src/programs/system/program.ts (5)
js/stateless.js/src/utils/address.ts (1)
NewAddressParams(43-62)js/stateless.js/src/state/types.ts (3)
ValidityProof(397-410)TreeInfo(77-99)CompressedAccountLegacy(146-163)js/stateless.js/src/state/bn.ts (1)
bn(3-12)js/stateless.js/src/utils/validation.ts (2)
validateSufficientBalance(8-12)validateSameOwner(14-28)js/stateless.js/src/state/compressed-account.ts (2)
createCompressedAccountLegacy(226-236)CompressedAccountWithMerkleContext(14-17)
js/stateless.js/src/state/types.ts (3)
js/stateless.js/src/state/compressed-account.ts (1)
PackedCompressedAccountWithMerkleContext(204-221)js/stateless.js/src/utils/address.ts (1)
NewAddressParamsPacked(64-83)js/compressed-token/src/types.ts (2)
InputTokenDataWithContext(53-60)TokenData(139-165)
js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts (9)
js/stateless.js/src/constants.ts (2)
defaultTestStateTreeAccounts(178-186)localTestActiveStateTreeInfo(135-161)js/stateless.js/src/rpc-interface.ts (4)
CompressionApiInterface(756-861)CompressedTransaction(120-142)WithContext(241-248)ValidityProofWithContext(161-190)js/stateless.js/src/state/types.ts (2)
TreeInfo(77-99)PublicTransactionEvent(231-272)js/stateless.js/src/state/BN254.ts (1)
BN254(12-12)js/stateless.js/src/state/compressed-account.ts (1)
MerkleContextWithMerkleProof(102-115)js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts (1)
getParsedEvents(37-151)js/stateless.js/src/utils/get-state-tree-infos.ts (1)
getStateTreeInfoByPubkey(8-13)js/stateless.js/src/state/bn.ts (1)
bn(3-12)js/stateless.js/src/rpc.ts (4)
convertMerkleProofsWithContextToHex(425-443)proverRequest(337-391)MerkleContextWithNewAddressProof(403-413)convertNonInclusionMerkleProofInputsToHex(445-471)
js/compressed-token/src/layout.ts (3)
js/compressed-token/src/constants.ts (6)
MINT_TO_DISCRIMINATOR(11-13)BATCH_COMPRESS_DISCRIMINATOR(14-16)COMPRESS_SPL_TOKEN_ACCOUNT_DISCRIMINATOR(20-22)TRANSFER_DISCRIMINATOR(17-19)APPROVE_DISCRIMINATOR(24-26)REVOKE_DISCRIMINATOR(27-29)js/compressed-token/src/types.ts (5)
MintToInstructionData(82-86)BatchCompressInstructionData(67-74)CompressSplTokenAccountInstructionData(87-91)CompressedTokenInstructionDataApprove(167-177)CompressedTokenInstructionDataRevoke(179-185)js/stateless.js/src/state/types.ts (1)
ValidityProof(397-410)
js/stateless.js/src/rpc-interface.ts (3)
js/stateless.js/src/state/BN254.ts (1)
BN254(12-12)js/stateless.js/src/state/types.ts (3)
TreeInfo(77-99)AddressTreeInfo(107-115)ValidityProof(397-410)js/stateless.js/src/state/bn.ts (1)
bn(3-12)
js/stateless.js/src/rpc.ts (8)
js/stateless.js/src/constants.ts (5)
versionedEndpoint(26-27)featureFlags(16-19)localTestActiveStateTreeInfo(135-161)defaultStateTreeLookupTables(99-123)defaultTestStateTreeAccounts(178-186)js/stateless.js/src/rpc-interface.ts (17)
jsonRpcResultAndContext(362-371)CompressionApiInterface(756-861)CompressedAccountResultV2(408-425)CompressedAccountResult(390-406)MerkleProofResultV2(549-557)MerkleProofResult(537-544)MultipleCompressedAccountsResultV2(461-463)MultipleCompressedAccountsResult(454-456)CompressedAccountsByOwnerResultV2(476-479)CompressedAccountsByOwnerResult(468-471)jsonRpcResult(338-349)CompressedTransactionResultV2(736-754)CompressedTransactionResult(713-731)ValidityProofWithContext(161-190)WithContext(241-248)ValidityProofResultV2(619-623)ValidityProofResult(594-603)js/stateless.js/src/utils/get-state-tree-infos.ts (3)
getStateTreeInfoByPubkey(8-13)getAllStateTreeInfos(120-213)getTreeInfoByPubkey(15-35)js/stateless.js/src/state/compressed-account.ts (4)
CompressedAccountWithMerkleContext(14-17)createCompressedAccountWithMerkleContextLegacy(240-253)createMerkleContextLegacy(258-268)MerkleContextWithMerkleProof(102-115)js/stateless.js/src/state/types.ts (4)
ValidityProof(397-410)AddressTreeInfo(107-115)TokenData(445-471)TreeInfo(77-99)js/stateless.js/src/state/bn.ts (1)
bn(3-12)js/stateless.js/src/state/BN254.ts (2)
BN254(12-12)encodeBN254toBase58(43-49)js/stateless.js/src/utils/validation.ts (1)
validateNumbersForProof(31-50)
js/compressed-token/src/program.ts (9)
js/stateless.js/src/state/types.ts (3)
TreeInfo(77-99)ValidityProof(397-410)CompressedProof(373-386)js/compressed-token/src/utils/get-token-pool-infos.ts (2)
TokenPoolInfo(104-141)checkTokenPoolInfo(13-27)js/compressed-token/src/types.ts (6)
TokenTransferOutputData(11-28)DelegatedTransfer(62-65)CompressedTokenInstructionDataTransfer(99-137)BatchCompressInstructionData(67-74)CompressedTokenInstructionDataApprove(167-177)CompressedTokenInstructionDataRevoke(179-185)js/compressed-token/src/layout.ts (10)
createTokenPoolAccountsLayout(268-287)addTokenPoolAccountsLayout(289-310)encodeBatchCompressInstructionData(137-152)mintToAccountsLayout(312-365)encodeTransferInstructionData(193-213)transferAccountsLayout(367-424)encodeApproveInstructionData(549-574)approveAccountsLayout(426-462)encodeRevokeInstructionData(588-613)revokeAccountsLayout(464-464)js/stateless.js/src/constants.ts (4)
defaultStaticAccountsStruct(79-89)featureFlags(16-19)noopProgram(58-58)accountCompressionProgram(60-61)js/stateless.js/src/utils/conversion.ts (1)
toArray(28-29)js/stateless.js/src/programs/system/program.ts (2)
createTransferOutputState(198-223)createDecompressOutputState(225-249)js/compressed-token/src/utils/pack-compressed-token-accounts.ts (1)
packCompressedTokenAccounts(39-159)js/compressed-token/src/utils/validation.ts (1)
checkMint(11-24)
🪛 LanguageTool
js/compressed-token/CHANGELOG.md
[uncategorized] ~64-~64: Loose punctuation mark.
Context: ...Instruction Changes: - compress, mintTo, approveAndMintTo, `compress...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~66-~66: Loose punctuation mark.
Context: ...ore TokenPoolInfos. - decompress, transfer now do not allow state tree ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~66-~66: This verb does not appear to agree with the subject. Consider using a different form.
Context: ...s. - decompress, transfer now do not allow state tree overrides. - Ac...
(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)
[uncategorized] ~78-~78: Loose punctuation mark.
Context: ...ransfer support. - addTokenPools: you can now register additional token p...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~85-~85: Possible missing comma found.
Context: ...ll active state trees. When building a transaction you can now pick a random treeInfo via ...
(AI_HYDRA_LEO_MISSING_COMMA)
🪛 Biome (1.9.4)
js/compressed-token/src/program.ts
[error] 655-655: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 688-688: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 779-779: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 828-828: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 832-832: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 840-840: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 845-845: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 904-904: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1103-1103: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1180-1180: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1201-1201: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1207-1207: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1218-1218: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1264-1264: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1266-1266: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1275-1275: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1357-1357: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1363-1363: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1405-1405: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1562-1562: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1568-1568: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1575-1575: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1628-1628: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1634-1634: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1641-1641: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
🔇 Additional comments (113)
Cargo.toml (1)
115-117: Workspace-level serialization dependencies look correct.
Addingserde = "1.0"with thederivefeature andserde_json = "1.0"aligns with the new (de)serialization requirements across your Rust crates and complements the JS/TS updates.cli/src/commands/init/index.ts (1)
1-4: Approve removal of unused execSync import.
The unusedexecSyncimport was removed without affecting any functionality;executeCommandis now the sole mechanism for running subprocesses.js/stateless.js/tests/unit/state/bn254.test.ts (1)
2-2: Approve consolidated import from state module.
ImportingcreateBN254andencodeBN254toBase58from the unifiedstateentrypoint aligns with the recent refactors and maintains test consistency.js/stateless.js/src/utils/address.ts (2)
1-1: Approve removal of unusedAccountMetaimport.
The unusedAccountMetaimport has been cleaned up, reducing dead code.
4-4: Approve updated import path forgetIndexOrAdd.
Switching to../programs/system/packmatches the new code organization for packing utilities.js/stateless.js/src/utils/calculate-compute-unit-price.ts (1)
5-5: Approve JSDoc hyperlink enhancement.
Linking directly to the Solana Web3.js reference improves documentation clarity and developer navigation.js/compressed-token/tsconfig.json (1)
16-16: Approve explicit relativetypeRootspath.
Using"./types"ensures the custom types directory is correctly resolved alongside@types.js/stateless.js/src/state/index.ts (1)
2-3: Verify there is no naming collision betweenbnre-export and existing BN helpers.
export * from './BN254'already re-exports aBNclass. Re-exporting a helper calledbnis fine, but double-check:
./bndoes not also export a top-level identifier calledBNthat would shadow the previous one.- Down-stream imports such as
import { bn, BN } …still resolve unambiguously.A quick grep in the codebase for
export .*BN.* from './bn'will confirm.js/stateless.js/src/actions/index.ts (1)
4-5: API surface changed – ensure no consumers relied on./common.Switching the export from
./commonto../utils/dedupe-signerdrops any symbols that were previously re-exported from./common.
If external packages imported them through@lightprotocol/stateless.js/actions, this is a breaking change.Confirm that:
- All removed re-exports are now available elsewhere.
- Version bump (minor/major) reflects this potential break.
If nothing else was exported from
./common, feel free to ignore.js/stateless.js/vitest.config.ts (1)
7-10: Tightened timeouts – watch for flaky CI failures.Reducing
testTimeoutto 30 s and adding a 20 shookTimeoutis fine, but some e2e blockchain interactions (blockhash fetch, confirmation) occasionally exceed that, especially under load.If flakiness appears, bump these values or conditionally increase them in CI via env vars.
js/stateless.js/tests/e2e/testnet.test.ts (2)
5-6: Imported surface trimmed correctly – 👍The unused helpers were removed and tree-info utilities are no longer required. Import list is tidy.
21-22:✅ Verification successful
Ensure all
compresscall-sites were updated to the new 4-arg signatureThis test compiles, but any overlooked call elsewhere will now fail at runtime/compile-time.
Run a quick grep to confirm:
🏁 Script executed:
rg "compress\(.*\,\s*.*\,\s*.*\,\s*.*\,\s*" js | catLength of output: 171
Let’s list every
compress(invocation in your JS/TS files to ensure they all have four arguments:
🏁 Script executed:
#!/usr/bin/env bash # Find all compress call-sites in .js and .ts under js/ rg -n --color never "compress\(" --glob "*.{js,ts}" jsLength of output: 4722
Let’s inspect the
compresssignature to confirm its parameters:
🏁 Script executed:
#!/usr/bin/env bash # Locate and print the compress function signature grep -R "export async function compress" -n js/stateless.js/src/actions/compress.ts sed -n '1,60p' js/stateless.js/src/actions/compress.tsLength of output: 1951
All
compress()invocations match the new 4-arg signatureI’ve checked every call in
js/stateless.jsandjs/compressed-token—eachcompress(has at least the required
rpcpayerlamportstoAddressOptional
outputStateTreeInfoorconfirmOptionsare passed where needed. No call‐site is missing arguments.js/stateless.js/src/utils/validation.ts (1)
1-7: Import alias matches implementation – looks good.
Transitioning toCompressedAccountLegacyaligns this helper with the new state
type without behavioural change.js/stateless.js/package.json (4)
3-3: Confirm version bump consistency.
Ensure the bumped version0.21.0aligns with release notes, CHANGELOG, and any interdependent packages.
91-91: Approve new unit test script.
Thetest:unit:tree-infotarget follows existing naming conventions and integrates cleanly.
94-94: Verify skip-prover script behavior.
Double-check that--skip-proverintest-validator-skip-proverworks reliably in CI and doesn’t mask upstream failures.
97-98: Approve bail-on-first-failure flags.
Adding--bail=1totest-rpcandrpc-interopimproves feedback speed during end-to-end runs.js/compressed-token/src/index.ts (2)
1-2: Review export ordering.
Groupingactionsandutilsfirst enhances discoverability, but please verify no missing exports (e.g.,instructions) due to this reordering.
4-5: Approve reordered exports.
Relocatingidlandlayoutexports higher up provides clearer structure.js/compressed-token/tests/e2e/select-accounts.test.ts (2)
1-3: Approve BigNumber helper import.
Switching to the centralbnutility from@lightprotocol/stateless.jsstandardizes big-number usage across tests.
5-890: Remaining changes uniformly replaceBNwithbnacross multiple test cases—no additional issues detected.js/stateless.js/src/programs/system/index.ts (1)
1-5: Approve new system program barrel file.
The consolidated exports (IDL,layout,pack,program,select-compressed-accounts) align with the refactor and improve import ergonomics.js/stateless.js/src/test-helpers/test-rpc/get-parsed-events.ts (1)
26-26: Verify updated import path.
EnsuredecodePublicTransactionEventfrom../../programs/system/layoutresolves and matches the new module structure.js/stateless.js/src/actions/decompress.ts (1)
47-50: Explicit endianness forbn(x.hash)avoids silent mis-interpretation
x.hashis a 32-byte BE array.bn()defaults to LE when the input is aBuffer, which silently flips the value.
Pass the endianness explicitly so the proof hash matches the program expectation.- userCompressedAccountsWithMerkleContext.map(x => bn(x.hash)), + userCompressedAccountsWithMerkleContext.map(x => + bn(x.hash, undefined, 'be'), + ),js/compressed-token/tests/e2e/mint-to.test.ts (1)
91-93: Assert that environment selection did not returnundefined
selectStateTreeInfo/selectTokenPoolInfomay returnundefinedwhen the cluster
doesn’t have a ready tree or pool. All following tests will then fail with opaque
errors. Add an explicit assumption so failures surface immediately and with context.- stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); - tokenPoolInfo = selectTokenPoolInfo(await getTokenPoolInfos(rpc, mint)); + stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); + tokenPoolInfo = selectTokenPoolInfo(await getTokenPoolInfos(rpc, mint)); + + expect(stateTreeInfo, 'No state tree available').toBeDefined(); + expect(tokenPoolInfo, 'No token pool found for minted SPL').toBeDefined();js/stateless.js/tests/e2e/layout.test.ts (1)
16-21: Imports & renamed fields updated correctlyThe switch to
programs/system/layoutand the newCOMPRESSED_TOKEN_PROGRAM_IDconstant align with the refactor; renamed fields (queuePubkeyIndex,proveByIndex) match the updated IDL. No issues spotted.Also applies to: 38-39, 143-147
js/compressed-token/tests/e2e/merge-token-accounts.test.ts (1)
67-68: Signature change propagated correctly
mergeTokenAccountsno longer needsstateTreeInfo; the updated calls compile and behave as expected. No additional changes required.Also applies to: 85-87, 100-102
examples/browser/nextjs/src/app/page.tsx (1)
29-30: LGTM! Clean migration to dynamic state tree management.The changes properly implement the migration from static state tree accounts to dynamic RPC-fetched state tree information, aligning with the broader V2 protocol updates.
Also applies to: 39-42, 57-57
js/stateless.js/src/test-helpers/test-rpc/get-compressed-accounts.ts (1)
46-68: Well-implemented dynamic tree info retrieval.The code efficiently fetches state tree infos once and correctly maps each compressed account to its corresponding tree using the merkleTreeIndex. The comment about V2 trees having
proveByIndex = trueprovides helpful context.js/stateless.js/tests/e2e/test-rpc.test.ts (1)
32-33: Test updates correctly align with the new API.The changes appropriately adapt to the updated compressed token API:
- Fixed lamport values provide consistency
- Simplified
compresscalls reflect the removal of explicit tree parameters- Conditional proof length assertion (26 vs 32) properly handles V1/V2 differences
Also applies to: 36-36, 42-42, 85-85, 113-113
js/compressed-token/tests/e2e/rpc-multi-trees.test.ts (2)
51-58: Verify the V2 tree selection logic.When
featureFlags.isV2()is true, bothstateTreeInfoandstateTreeInfo2are set to the same tree. This might be intentional if V2 only supports single tree scenarios, but please confirm this is the expected behavior for multi-tree tests.
30-33: Clean refactoring to dynamic tree and token pool management.The test properly migrates from static tree references to dynamically fetched
TreeInfoandTokenPoolInfoobjects, with assertions correctly updated to use the new structure.Also applies to: 70-72, 92-98, 108-113, 124-125, 133-141
js/compressed-token/tests/e2e/rpc-token-interop.test.ts (2)
36-41: Creation of two RPC connections looks intentional – just verifyYou create both
rpc = createRpc()andtestRpc = await getTestRpc(lightWasm).
If this is to compare mainnet vs in-memory test RPC it’s fine; otherwise double-initialisation may slow the test suite.
266-279: Potential race between pool PDA discovery and pool initialisation
selectTokenPoolInfo(await getTokenPoolInfos(rpc, mint2))is executed immediately aftercreateMint, but before any explicitcreateTokenPoolformint2.
IfcreateMintdoesn’t implicitly initialise a pool,getTokenPoolInfoswill throw (as seen in its guard clause).
Please confirm the implicit behaviour or addawait createTokenPool(...)beforehand.js/stateless.js/src/programs/system/idl.ts (1)
697-713: IDL field rename changes binary layout – ensure deserialisers are updated
queuePubkeyIndexreplaces the previousnullifierQueuePubkeyIndexand newproveByIndex: boolis appended.
Confirm that:
- All off-chain serializers reflect the new order/size (the bool shifts subsequent fields).
- On-chain program is bumped/renamed to avoid incompatible account data parsing.
Also applies to: 1693-1713
js/compressed-token/src/actions/merge-token-accounts.ts (1)
58-60: API drift: usegetValidityProofV0for consistencyOther new actions switched to
getValidityProofV0(hash, tree, queue).
Sticking to the legacy method here may break once RPC deprecates it. Align with the rest of the codebase.- const proof = await rpc.getValidityProof( - batch.map(account => bn(account.compressedAccount.hash)), - ); + const proof = await rpc.getValidityProofV0( + batch.map(account => ({ + hash: account.compressedAccount.hash, + tree: account.compressedAccount.treeInfo.tree, + queue: account.compressedAccount.treeInfo.queue, + })), + );js/compressed-token/tests/e2e/decompress.test.ts (1)
120-126: Creating a freshTestRpcinside the loop resets cluster state.
getTestRpcinitialises an independent in-memory ledger, so later decompressions run against a cluster that never received the mint / compress operations executed inbeforeAll. Re-use the existingrpcinstance or move the compress/mint steps inside the loop.js/compressed-token/src/actions/transfer.ts (1)
76-77: Re-evaluate 500 k CU limitCutting the compute budget in half is great for fees, but a single transfer that spans several input accounts plus the proof-verification logic often goes north of 600 k CU on main-net settings.
Consider:
- Making the value configurable (env / param); or
- Falling back to a higher limit on
TransactionExpiredBlockheightExceededfailures.This will avoid sporadic “CU exhausted” errors when pools are busy.
js/compressed-token/tests/e2e/compress-spl-token-account.test.ts (1)
83-84:decompresssignature driftEarlier tests invoke
decompresswith the extratokenPoolInfosparameter, but this invocation still uses the old 5-arg form.
Confirm the overload still exists or update to the new signature to avoid a compilation error.js/compressed-token/src/actions/decompress.ts (3)
63-70: LGTM! Proper migration to V0 proof API.The change from
getValidityProoftogetValidityProofV0correctly includes the required tree and queue information for each account, aligning with the new multi-tree support architecture.
71-76: Good defensive programming with null coalescing.The code properly handles the optional
tokenPoolInfosparameter by fetching them if not provided, then selecting appropriate pools based on the amount. This maintains backward compatibility while supporting the new multi-pool architecture.
91-91:❓ Verification inconclusive
Verify the compute unit limit reduction is sufficient.
The compute unit limit has been reduced from 1,000,000 to 350,000 (65% reduction). Please ensure this is sufficient for all decompression scenarios, especially when dealing with multiple input accounts or complex proof verifications.
Run the following script to check for any compute unit related errors in tests:
🏁 Script executed:
#!/bin/bash # Description: Search for compute unit related errors or adjustments in decompress tests # Check for compute unit errors in test files rg -A 5 -B 5 "compute.*unit|ComputeBudget" js/compressed-token/tests/ # Check for any transaction failures related to compute budget rg -A 10 "Program failed to complete|exceeded.*compute|compute.*exceeded" js/compressed-token/tests/Length of output: 5021
🏁 Script executed:
#!/bin/bash # Verify if there are any decompress-specific tests and their compute unit limits # Search for any test files or mentions of 'decompress' rg -A 5 -B 5 "decompress" js/compressed-token/tests/ # Search for compute unit settings in any decompress-related tests rg -A 5 -B 5 "setComputeUnitLimit" js/compressed-token/tests/ | rg "decompress"Length of output: 20435
Verify compute unit limit sufficiency in
decompress.ts
File:js/compressed-token/src/actions/decompress.ts:91The compute unit limit was reduced from
1_000_000to350_000. Please confirm that all decompress scenarios still complete under 350 k CU, in particular:
- Multi‐pool decompress (up to 90 accounts) →
tests/e2e/multi-pool.test.ts- Repeated decompress loops →
tests/e2e/decompress.test.ts- Delegated decompress →
tests/e2e/decompress-delegated.test.ts- Decompress within compress‐spl‐token‐account flows →
tests/e2e/compress-spl-token-account.test.tsConsider measuring on‐chain compute usage (e.g. via
simulateTransactionor runtime logs) or adding CI/performance checks to catch any budget overruns.js/stateless.js/tests/e2e/rpc-multi-trees.test.ts (1)
126-135: Good test coverage for multi-tree transfers.The test properly validates that random output trees are selected and tracked correctly during transfers, ensuring the multi-tree functionality works as expected.
js/compressed-token/src/actions/decompress-delegated.ts (1)
1-99: Well-implemented delegated decompression functionality.The implementation correctly handles delegated token decompression with proper proof generation, token pool selection, and transaction building. The function follows established patterns and integrates well with the delegation feature set.
js/compressed-token/tests/e2e/decompress-delegated.test.ts (1)
160-207: Excellent test coverage with error case validation.The test comprehensively validates the delegated decompression flow, including:
- Proper balance updates for delegate, owner, and recipient
- No delegated remainder tokens left
- Appropriate error when attempting to decompress more than delegated
This provides good confidence in the implementation.
js/compressed-token/src/actions/compress-spl-token-account.ts (1)
53-58: Clean implementation of default selection logic.The null coalescing pattern for both
outputStateTreeInfoandtokenPoolInfoprovides good defaults while maintaining flexibility. This approach is consistent with other refactored actions.js/stateless.js/src/programs/system/layout.ts (4)
46-54: LGTM! Simplified MerkleContext structure.The renaming of
nullifierQueuePubkeyIndextoqueuePubkeyIndexand replacement of the optionalqueueIndexstruct with a booleanproveByIndexsimplifies the data structure while maintaining the same functionality. This change aligns with the protocol updates for v2 support.
100-108: Good improvement for consistent typed array usage.Wrapping all buffer components in
Uint8Arraybefore concatenation ensures consistent type handling and improves compatibility across different JavaScript environments. This is a best practice when dealing with binary data.
255-292: Excellent documentation improvements!The addition of comprehensive JSDoc comments for all fields in
invokeAccountsLayoutParamsgreatly improves code readability and developer experience. The newfeePayerfield appropriately separates fee payment responsibility from transaction authority.
537-591: Consistent and improved big number handling.The migration to the
bn()helper function throughout the conversion logic provides better type handling and edge case management. The simplifiedsequenceNumbersmapping that returns raw values instead of wrapping inPublicKeyorBNobjects reduces unnecessary object creation and improves performance.js/compressed-token/src/actions/create-mint.ts (1)
87-90: Clean helper function implementation.The
getPublicKeyhelper properly handles all input cases and provides a clean abstraction for extracting public keys from eitherPublicKeyorSignertypes.js/compressed-token/src/actions/mint-to.ts (2)
44-60: Well-structured parameter updates with sensible defaults.The migration from
merkleTreetooutputStateTreeInfoand addition oftokenPoolInfoaligns with the protocol's enhanced state management. The dynamic selection logic provides good defaults while maintaining flexibility for users to specify their preferred state tree and token pool.
62-82: Clean instruction creation and transaction handling.The instruction creation properly utilizes the new structured parameters, and the direct return of
sendAndConfirmTxresult simplifies the code while maintaining the same functionality.js/compressed-token/src/actions/compress.ts (2)
51-60: Consistent parameter updates across actions.The migration to
outputStateTreeInfoandtokenPoolInfoparameters maintains consistency with other actions in the codebase. The dynamic selection logic provides sensible defaults.
77-79: Smart compute unit optimization.The dynamic compute unit calculation (130,000 + 20,000 * array length) is more efficient than the fixed 1,000,000 units, allocating resources based on actual workload. This optimization reduces transaction costs for simple operations while ensuring sufficient compute for batch compressions.
js/compressed-token/package.json (1)
3-3: Appropriate version bump for breaking changes.The version bump to 0.21.0 correctly indicates breaking changes with the new delegation features, multi-pool support, and API modifications.
js/compressed-token/src/actions/create-token-pool.ts (1)
17-52: LGTM! Good improvements to the API.The changes improve the function interface:
- Parameter rename from
mintAddresstomintis more concise and consistent- Optional
tokenProgramIdparameter enables SPL Token 2022 support- Method rename to
getMintProgramIdfollows JavaScript naming conventionsjs/compressed-token/src/actions/approve-and-mint-to.ts (1)
27-100: Good refactoring to support the new multi-pool architecture.The changes properly integrate with the new state tree and token pool selection system. The dynamic compute unit calculation (
150,000 + toArray(amount).length * 20,000) is a smart improvement that scales with the complexity of the amount being minted.js/compressed-token/tests/e2e/transfer-delegated.test.ts (1)
1-411: Excellent test coverage for delegated transfers!The test suite is comprehensive and well-structured:
- The
assertPostTransferhelper provides thorough validation of post-transfer states- Good coverage of edge cases including partial transfers and error scenarios
- Clear error logging for debugging test failures
- Proper integration with the new state tree and token pool selection architecture
js/compressed-token/src/utils/select-input-accounts.ts (2)
9-54: Smart selection strategy for approval operations.The function implements an optimal two-tier selection strategy:
- First attempts exact match (most efficient for approvals)
- Falls back to minimum selection if no exact match exists
This approach minimizes transaction complexity and avoids unnecessary change outputs when possible.
56-84: Good API wrapper for decompression use cases.The function provides a cleaner object-based API for decompression operations while reusing the existing selection logic. This improves code readability at call sites through named destructuring.
js/compressed-token/tests/e2e/compress.test.ts (2)
118-131:stateTreeInfo/tokenPoolInfoselection done at test start – add existence guardIf the RPC returns an empty array the subsequent tests will throw cryptic errors. Guard early to make the failure obvious.
- stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); - tokenPoolInfo = selectTokenPoolInfo(await getTokenPoolInfos(rpc, mint)); + stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); + tokenPoolInfo = selectTokenPoolInfo(await getTokenPoolInfos(rpc, mint)); + + if (!stateTreeInfo || !tokenPoolInfo) { + throw new Error('No active StateTreeInfo / TokenPoolInfo found – check test RPC setup'); + }
286-296: Hard-coded compute unit limit is too low for max-batch compressEmpirically, a 15-recipient compress frequently exceeds 500 k CUs on devnet. Consider raising the limit or deriving it from
recipients.length.- [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], + [ComputeBudgetProgram.setComputeUnitLimit({ units: 800_000 }), ix],js/stateless.js/src/utils/state-tree-lookup-table.ts (2)
46-49: Good improvement: Proper type casting and deduplication.The replacement of
@ts-expect-errorwith properRpctype casting and the addition ofdedupeSignerare solid improvements that enhance type safety and prevent duplicate signers.Also applies to: 119-122, 208-215
170-172: Correct approach for address comparison.Using base58 string representations for address comparison is the proper approach to ensure reliable equality checks between PublicKey instances.
Also applies to: 191-195
js/stateless.js/src/actions/create-account.ts (2)
25-48: Well-structured parameter updates align with new abstractions.The consolidation of
addressTreeandaddressQueueinto a singleaddressTreeInfoparameter and the addition ofoutputStateTreeInfoproperly implements the new tree info abstractions for improved scalability.
142-142:❓ Verification inconclusive
Verify removal of bn() wrapper is intentional.
The code removes the
bn()wrapper when passing account hashes togetValidityProof. Ensure this change is compatible with the updated RPC method signature.
🏁 Script executed:
#!/bin/bash # Description: Verify the RPC getValidityProof method signature accepts plain hashes without bn() wrapper # Search for getValidityProof method definition and usage ast-grep --pattern 'getValidityProof($$$)' -A 10 # Also check for any bn() usage patterns with account.hash rg 'bn\(.*account.*hash\)' --type tsLength of output: 1527
🏁 Script executed:
#!/bin/bash # Locate all occurrences of getValidityProof in the stateless client rg -n "getValidityProof" -n js/stateless.js/srcLength of output: 2145
🏁 Script executed:
#!/bin/bash # Display the TypeScript signature for getValidityProof in the RPC interface sed -n '770,820p' js/stateless.js/src/rpc-interface.ts echo "-----" # Show implementation and parameter formatting for getValidityProofV0 in rpc.ts sed -n '1800,1850p' js/stateless.js/src/rpc.tsLength of output: 3990
🏁 Script executed:
#!/bin/bash # Display the context around inputAccounts in create-account.ts sed -n '1,120p' js/stateless.js/src/actions/create-account.ts echo "-----" sed -n '121,200p' js/stateless.js/src/actions/create-account.tsLength of output: 5720
🏁 Script executed:
#!/bin/bash # Show definition and properties of CompressedAccountWithMerkleContext rg -n "interface CompressedAccountWithMerkleContext" -n js/stateless.js/src/state/types.ts -A 20Length of output: 98
🏁 Script executed:
#!/bin/bash # Search for the CompressedAccountWithMerkleContext interface and confirm the type of `hash` rg -n "interface CompressedAccountWithMerkleContext" -A20 .Length of output: 61
Verify hash type before removing bn() wrapper
The
createAccountWithLamportshelper now does:const proof = await rpc.getValidityProof( inputAccounts.map(account => account.hash), [bn(address.toBytes())], );However,
getValidityProofis declared as:getValidityProof( hashes: BN254[], // expects BN instances newAddresses: BN254[], ): Promise<ValidityProofWithContext>;Please confirm that
CompressedAccountWithMerkleContext.hashis already aBN(alias BN254). If it’s not (e.g. a raw number, Buffer or string), you’ll need to re-introduce thebn(account.hash)wrapper. Also ensure the same pattern is applied consistently intransfer.tsso both actions align with the RPC signature.js/stateless.js/src/test-helpers/test-rpc/get-compressed-token-accounts.ts (3)
70-77: Good addition of error handling for token data decoding.The try-catch block properly handles potential decoding errors and provides helpful error logging.
175-177: Improved comparison using BN equality.Using BN's
eq()method is more efficient and type-safe than JSON stringification for comparing BigNumbers.
97-113:✅ Verification successful
Complex tree validation logic - ensure V2 handling is correct.
The conditional logic for V2 trees adds complexity. The nested conditions check both tree and queue equality based on feature flags. Ensure this aligns with the expected behavior for V2 trees.
🏁 Script executed:
#!/bin/bash # Description: Verify V2 tree handling logic is used consistently across the codebase # Search for similar V2 tree validation patterns rg 'featureFlags\.isV2\(\).*queue\.equals' --type ts -A 5 -B 5 # Check for TreeType.StateV2 usage ast-grep --pattern 'TreeType.StateV2'Length of output: 1320
V2 tree validation logic is correct
The condition correctly throws only when neither the Merkle tree nor (for V2) its queue matches—and for non-V2 it throws on tree mismatch alone. No other
featureFlags.isV2() … queue.equalspatterns exist, and this aligns with allTreeType.StateV2checks in tests and helpers. No changes required.js/compressed-token/src/idl.ts (2)
1092-1189: Well-structured delegation instruction types.The new
CompressedTokenInstructionDataRevokeandCompressedTokenInstructionDataApprovetypes properly support the delegation features mentioned in the changelog. The field structures are consistent with existing instruction data types.
1484-1494: Simplified PackedMerkleContext structure.The changes to
PackedMerkleContextappropriately simplify the structure:
- Renaming
nullifierQueuePubkeyIndextoqueuePubkeyIndexmakes it more generic- Replacing the optional
queueIndexstruct with a booleanproveByIndexflag reduces complexityjs/stateless.js/src/programs/system/pack.ts (2)
102-187: Well-structured tree info packing implementationThe function properly handles different tree versions with appropriate feature flag checks and clear error messages for unsupported configurations.
207-309: Robust compressed account packing with proper validationThe function correctly enforces mutual exclusivity between input accounts and output state tree info, and handles tree versioning appropriately.
js/stateless.js/src/programs/system/program.ts (1)
292-353: Correct implementation of mutual exclusivity for tree infoThe conditional passing of
outputStateTreeInfoonly when there are no input compressed accounts is consistent with the validation logic in the packing utilities.🧰 Tools
🪛 Biome (1.9.4)
[error] 302-302: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 349-349: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
js/stateless.js/src/constants.ts (2)
6-27: Well-designed versioning systemThe VERSION enum and feature flags provide a clean and maintainable way to manage protocol versions. The
versionedEndpointhelper is particularly useful for API compatibility.
254-267: Significant fee reduction in V2The state tree rollover fee drops from 300 (V1) to 1 (V2), which is a 99.7% reduction. Please confirm this dramatic fee reduction is intentional.
js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts (2)
256-446: Comprehensive refactor supporting multiple tree versionsThe method has been successfully refactored to support both V1 and V2 trees with appropriate proof generation strategies. The validation ensuring all requested hashes belong to the same tree type is a good safety check.
758-937: Proper handling of validity proofs for different tree versionsThe method correctly differentiates between V1 accounts that require actual proofs and other versions that use null proofs with zero roots. The inclusion of
treeInfosandproveByIndicesin the response structure supports the new protocol requirements.js/stateless.js/src/rpc-interface.ts (4)
285-296: Good use of thebnhelper function.The migration from
new BN()tobn()helper improves consistency and properly handles Uint8Array inputs.
537-544: Good typo fix.Fixed the typo from
MerkeProofResulttoMerkleProofResult.
155-190: Well-structured validity proof context type.The new
ValidityProofWithContexttype properly encapsulates validity proof data with comprehensive context including tree infos and prove-by-indices flags.
779-791: Correct interface updates for validity proof methods.The method signatures properly return
ValidityProofWithContextinstead of the deprecatedCompressedProofWithContext.js/stateless.js/src/state/compressed-account.ts (2)
25-97: Well-designed type evolution with proper documentation.The new
CompressedAccountandMerkleContexttypes provide better structure by usingTreeInfoobjects instead of rawPublicKeyvalues, enabling richer context and multi-tree support.
117-198: Good addition of packed types for instruction data.The new
PackedStateTreeInfo,PackedAddressTreeInfo, andCompressedAccountMetatypes properly support the V2 instruction formats with proof metadata.js/stateless.js/src/state/types.ts (4)
7-24: Good enum design for tree versioning.The updated
TreeTypeenum properly distinguishes between V1 and V2 trees for both state and address trees, enabling protocol versioning.
58-99: Excellent TreeInfo type design with comprehensive documentation.The
TreeInfotype properly encapsulates tree metadata with support for CPI contexts and tree chaining vianextTreeInfo. The documentation with usage examples is particularly helpful.
388-410: Clean ValidityProof interface with proper deprecation.Good replacement of
CompressedProofwithValidityProof, maintaining the same structure while improving naming clarity.
341-368: Good camelCase consistency in CompressedCpiContext.The interface properly uses camelCase for all fields, improving consistency with TypeScript conventions.
js/stateless.js/src/rpc.ts (5)
617-669: Well-implemented caching for state tree infos.The caching mechanism properly handles:
- TTL-based cache expiration (1 hour)
- Concurrent request deduplication via
fetchPromise- Proper error handling in the finally block
726-737: Consistent V2 support pattern.Good implementation of conditional parsing based on feature flags, enabling smooth migration to V2 while maintaining backward compatibility.
482-483: Consistent use ofbn()helper function.The file properly uses the
bn()helper throughout instead of directBNinstantiation.Also applies to: 796-796, 822-822
535-564: Good addition of nullifier metadata handling for V2.The
buildCompressedAccountWithMaybeTokenDataFromClosedAccountResultV2function properly extracts the additional nullifier metadata from V2 responses.
1878-1936: Comprehensive validity proof V2 handling.The implementation properly transforms V2 responses with separate
accountsandaddressesarrays into the unified format expected byValidityProofWithContext, while maintaining V1 backward compatibility.js/compressed-token/src/layout.ts (3)
95-160: LGTM! Well-structured batch compress implementationThe new
batchCompressLayoutstruct and its encoding/decoding functions are properly implemented with correct discriminator handling and length prefixing.
123-126: Good improvement: Consistent buffer handlingThe updates to use
Uint8Arraywrappers andsubarrayinstead ofsliceimprove consistency and efficiency across all encoding/decoding functions.Also applies to: 133-134, 175-177, 184-185, 206-211
289-310: Well-designed account layout functionsThe new account layout functions for
addTokenPool,approve,revoke,freeze, andthawoperations are properly structured with consistent patterns. The aliasing ofrevokeAccountsLayouttoapproveAccountsLayoutandthawAccountsLayouttofreezeAccountsLayoutis appropriate since they share identical account requirements.Also applies to: 426-464, 466-506
js/compressed-token/src/program.ts (5)
474-499: Well-implemented delegated transfer parsingThe
parseMaybeDelegatedTransferfunction correctly handles the detection and parsing of delegated transfers, with appropriate logic for determining the delegate change account index.
1179-1280: Excellent V2 feature flag implementationThe
compressmethod properly handles both V1 and V2 paths with clear separation of logic. The V2 path correctly uses the batch compress instruction while maintaining backward compatibility through the V1 path.🧰 Tools
🪛 Biome (1.9.4)
[error] 1180-1180: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1201-1201: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1207-1207: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1218-1218: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1264-1264: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1266-1266: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 1275-1275: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
1399-1403: Good validation in mergeTokenAccountsThe method properly validates that all accounts belong to the same mint and enforces a reasonable limit of 4 accounts per merge operation.
901-903: Consistent V2 tree/queue selectionThe code consistently uses
featureFlags.isV2()to determine whether to use the queue (V2) or tree (V1) for state insertion. This architectural change is properly implemented throughout the codebase.Also applies to: 1206-1206, 1445-1447
96-101: Excellent architectural improvement with structured typesThe migration from simple
PublicKeyparameters to structuredTreeInfoandTokenPoolInfotypes significantly improves type safety and provides better context throughout the API. The consistent use ofcheckTokenPoolInfofor validation ensures data integrity.Also applies to: 127-132, 162-163, 333-337, 408-413
js/stateless.js/src/index.ts (1)
1-10:✅ Verification successful
Verify backward compatibility for removed exports
The removal of the
'./instruction'export and the named exports (LightSystemProgramandIDL) from'./idl'could be breaking changes for consumers of this package. Based on the AI summary, these exports have been relocated to'./programs'.
🏁 Script executed:
#!/bin/bash # Description: Verify that the removed exports are still accessible through other paths # Check if LightSystemProgram and IDL are exported from programs module echo "Checking for LightSystemProgram and IDL exports in programs module..." rg -A 5 "export.*LightSystemProgram|export.*IDL" --glob "js/stateless.js/src/programs/**/*.ts" # Check if instruction exports have been moved to programs echo "Checking for instruction-related exports in programs..." fd -e ts . js/stateless.js/src/programs --exec grep -l "pack.*[Cc]ompressed.*[Aa]ccounts" {} \; # Check for any remaining references to the old paths in the codebase echo "Checking for imports from removed paths..." rg "from.*['\"].*\/instruction['\"]|from.*['\"].*\/idl['\"]" --glob "**/*.ts" --glob "**/*.js" -g "!node_modules"Length of output: 2545
🏁 Script executed:
#!/bin/bash # Verify relocated instruction exports in programs modules echo "Searching for any 'Instruction' exports in programs modules..." rg -i "export.*Instruction" --glob "js/stateless.js/src/programs/**/*.ts" # Check for leftover imports from the removed './instruction' path echo "Checking for imports from removed 'instruction' path..." rg "from .*\/instruction" --glob "**/*.ts" --glob "**/*.js" --glob "!node_modules/**" # Check for leftover imports from the removed named './idl' path echo "Checking for imports from removed 'idl' path..." rg "from .*\/idl" --glob "**/*.ts" --glob "**/*.js" --glob "!node_modules/**"Length of output: 1560
🏁 Script executed:
#!/bin/bash # Check for any remaining imports from the removed './instruction' path echo "Checking for imports from './instruction'..." rg --glob '**/*.ts' --glob '**/*.js' --glob '!node_modules/**' -n "from './instruction'" rg --glob '**/*.ts' --glob '**/*.js' --glob '!node_modules/**' -n 'from "./instruction"' # Check for any remaining imports from the removed './idl' path echo "Checking for imports from './idl'..." rg --glob '**/*.ts' --glob '**/*.js' --glob '!node_modules/**' -n "from './idl'" rg --glob '**/*.ts' --glob '**/*.js' --glob '!node_modules/**' -n 'from "./idl"'Length of output: 732
Backward compatibility verified – no changes required
LightSystemProgramandIDLare correctly re-exported fromjs/stateless.js/src/programs/system/index.ts(and thus available underprogramsin the root index).- No remaining imports from
./instructionor top-level./idlpaths were found.- All previously exported entities remain reachable via their new module paths.
js/compressed-token/tests/e2e/create-token-pool.test.ts (3)
28-61: LGTM! Proper support for multiple token programsThe addition of the optional
tokenProgramIdparameter with a sensible default maintains backward compatibility while enabling Token 2022 support.
225-299: Well-structured test for multi-pool functionalityThe test comprehensively validates the new multi-token-pool feature, including:
- Idempotent pool creation
- Proper pool indexing
- Initialization state verification
- Pool info retrieval
301-412: Consistent Token 2022 multi-pool test coverageThe test properly validates multi-pool functionality for Token 2022 mints, maintaining consistency with the standard token test while correctly using
TOKEN_2022_PROGRAM_IDthroughout.js/compressed-token/src/types.ts (2)
1-61: Proper migration to shared types from stateless.jsThe migration to use
ValidityProof,PackedMerkleContextLegacy, andCompressedCpiContextfrom the shared@lightprotocol/stateless.jspackage improves code organization and reusability.
67-97: Well-structured new types for enhanced functionalityThe new types properly support:
- Batch compress operations with
BatchCompressInstructionData- Delegation control with
CompressedTokenInstructionDataApproveandCompressedTokenInstructionDataRevoke- Type guard utility
isSingleTokenPoolInfofor clean type discriminationAlso applies to: 167-185
js/stateless.js/src/utils/get-state-tree-infos.ts (2)
5-13: Good backward compatibility with deprecation noticeThe deprecated wrapper properly maintains backward compatibility while directing users to the new
getTreeInfoByPubkeyfunction.
84-110: Well-designed tree selection with concurrency controlThe
selectStateTreeInfofunction properly implements:
- Active tree filtering
- Tree type filtering with sensible V2 default
- Concurrency limiting via MAX_HOTSPOTS to reduce contention
- Clear error messages
js/compressed-token/tests/e2e/layout.test.ts (3)
10-53: Good migration to shared constants and utilitiesUsing
COMPRESSED_TOKEN_PROGRAM_IDfrom the shared package instead of hardcoding improves maintainability.
164-169: Test data properly updated for new field namesThe field renames from
nullifierQueuePubkeyIndextoqueuePubkeyIndexand the change fromqueueIndextoproveByIndexcorrectly align with thePackedMerkleContextLegacytype structure.Also applies to: 265-270
761-877: Comprehensive test coverage for token pool selectionThe test thoroughly validates both
selectTokenPoolInfoandselectTokenPoolInfosForDecompression:
- Ensures uninitialized pools are never selected
- Validates balance-based pool selection for decompression
- Tests edge cases with exact balance thresholds
| const compressedTokenAccounts = await rpc.getCompressedTokenAccountsByOwner( | ||
| owner.publicKey, | ||
| { | ||
| mint, | ||
| }, | ||
| ); | ||
|
|
||
| const [inputAccounts] = selectTokenAccountsForApprove( | ||
| compressedTokenAccounts.items, | ||
| amount, | ||
| ); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Gracefully handle insufficient or empty balances
selectTokenAccountsForApprove will throw if compressedTokenAccounts.items is empty or the requested amount exceeds the owner’s balance, but the error message originates deep inside the selector.
Consider an explicit guard for clarity:
if (compressedTokenAccounts.items.length === 0) {
throw new Error(`Owner ${owner.publicKey.toBase58()} holds no compressed tokens for mint ${mint.toBase58()}`);
}🤖 Prompt for AI Agents
In js/compressed-token/src/actions/approve.ts around lines 45 to 56, add an
explicit check before calling selectTokenAccountsForApprove to verify if
compressedTokenAccounts.items is empty. If it is, throw a clear error indicating
that the owner holds no compressed tokens for the specified mint. This prevents
the selector from throwing a less clear error and improves error handling
clarity.
| export function selectTokenPoolInfosForDecompression( | ||
| infos: TokenPoolInfo[], | ||
| decompressAmount: number | BN, | ||
| ): TokenPoolInfo[] { | ||
| if (infos.length === 0) { | ||
| throw new Error('Please pass at least one token pool info.'); | ||
| } | ||
|
|
||
| infos = shuffleArray(infos); | ||
| // Find the first info where balance is 10x the requested amount | ||
| const sufficientBalanceInfo = infos.find(info => | ||
| info.balance.gte(bn(decompressAmount).mul(bn(10))), | ||
| ); | ||
|
|
||
| // filter only infos that are initialized | ||
| infos = infos | ||
| .filter(info => info.isInitialized) | ||
| .sort((a, b) => a.poolIndex - b.poolIndex); | ||
|
|
||
| const allBalancesZero = infos.every(info => info.balance.isZero()); | ||
| if (allBalancesZero) { | ||
| throw new Error( | ||
| 'All provided token pool balances are zero. Please pass recent token pool infos.', | ||
| ); | ||
| } | ||
|
|
||
| // If none found, return all infos | ||
| return sufficientBalanceInfo ? [sufficientBalanceInfo] : infos; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid mutating the input array
The function modifies the input infos array on line 209, which could cause unexpected side effects for callers. Consider creating a copy before shuffling.
export function selectTokenPoolInfosForDecompression(
infos: TokenPoolInfo[],
decompressAmount: number | BN,
): TokenPoolInfo[] {
if (infos.length === 0) {
throw new Error('Please pass at least one token pool info.');
}
- infos = shuffleArray(infos);
+ const shuffledInfos = shuffleArray([...infos]);
// Find the first info where balance is 10x the requested amount
- const sufficientBalanceInfo = infos.find(info =>
+ const sufficientBalanceInfo = shuffledInfos.find(info =>
info.balance.gte(bn(decompressAmount).mul(bn(10))),
);
// filter only infos that are initialized
- infos = infos
+ const filteredInfos = shuffledInfos
.filter(info => info.isInitialized)
.sort((a, b) => a.poolIndex - b.poolIndex);
- const allBalancesZero = infos.every(info => info.balance.isZero());
+ const allBalancesZero = filteredInfos.every(info => info.balance.isZero());
if (allBalancesZero) {
throw new Error(
'All provided token pool balances are zero. Please pass recent token pool infos.',
);
}
// If none found, return all infos
- return sufficientBalanceInfo ? [sufficientBalanceInfo] : infos;
+ return sufficientBalanceInfo ? [sufficientBalanceInfo] : filteredInfos;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export function selectTokenPoolInfosForDecompression( | |
| infos: TokenPoolInfo[], | |
| decompressAmount: number | BN, | |
| ): TokenPoolInfo[] { | |
| if (infos.length === 0) { | |
| throw new Error('Please pass at least one token pool info.'); | |
| } | |
| infos = shuffleArray(infos); | |
| // Find the first info where balance is 10x the requested amount | |
| const sufficientBalanceInfo = infos.find(info => | |
| info.balance.gte(bn(decompressAmount).mul(bn(10))), | |
| ); | |
| // filter only infos that are initialized | |
| infos = infos | |
| .filter(info => info.isInitialized) | |
| .sort((a, b) => a.poolIndex - b.poolIndex); | |
| const allBalancesZero = infos.every(info => info.balance.isZero()); | |
| if (allBalancesZero) { | |
| throw new Error( | |
| 'All provided token pool balances are zero. Please pass recent token pool infos.', | |
| ); | |
| } | |
| // If none found, return all infos | |
| return sufficientBalanceInfo ? [sufficientBalanceInfo] : infos; | |
| } | |
| export function selectTokenPoolInfosForDecompression( | |
| infos: TokenPoolInfo[], | |
| decompressAmount: number | BN, | |
| ): TokenPoolInfo[] { | |
| if (infos.length === 0) { | |
| throw new Error('Please pass at least one token pool info.'); | |
| } | |
| // avoid mutating the caller’s array | |
| const shuffledInfos = shuffleArray([...infos]); | |
| // Find the first info where balance is 10x the requested amount | |
| const sufficientBalanceInfo = shuffledInfos.find(info => | |
| info.balance.gte(bn(decompressAmount).mul(bn(10))), | |
| ); | |
| // filter only infos that are initialized | |
| const filteredInfos = shuffledInfos | |
| .filter(info => info.isInitialized) | |
| .sort((a, b) => a.poolIndex - b.poolIndex); | |
| const allBalancesZero = filteredInfos.every(info => info.balance.isZero()); | |
| if (allBalancesZero) { | |
| throw new Error( | |
| 'All provided token pool balances are zero. Please pass recent token pool infos.', | |
| ); | |
| } | |
| // If none found, return all initialized infos | |
| return sufficientBalanceInfo ? [sufficientBalanceInfo] : filteredInfos; | |
| } |
🤖 Prompt for AI Agents
In js/compressed-token/src/utils/get-token-pool-infos.ts around lines 201 to
229, the input array 'infos' is directly mutated by shuffling it, which can
cause side effects for callers. To fix this, create a shallow copy of the
'infos' array before shuffling it, ensuring the original input remains unchanged
throughout the function.
| export interface AddressWithTreeInfo { | ||
| /** | ||
| * Address. | ||
| */ | ||
| address: BN254; | ||
| /** | ||
| * Address tree info. | ||
| */ | ||
| addressTreeInfo: AddressTreeInfo; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix duplicate AddressWithTreeInfo interface definitions.
There are two conflicting definitions of AddressWithTreeInfo:
- Lines 92-101 with
addressTreeInfo: AddressTreeInfo - Lines 115-118 with
treeInfo: AddressTreeInfo
This will cause TypeScript compilation errors and type inconsistencies.
Consider renaming one of the interfaces or consolidating them:
-export interface AddressWithTreeInfo {
- address: BN254;
- treeInfo: AddressTreeInfo;
-}
+export interface AddressWithTreeInfoLegacy {
+ address: BN254;
+ treeInfo: AddressTreeInfo;
+}Also applies to: 115-118
🤖 Prompt for AI Agents
In js/stateless.js/src/rpc-interface.ts around lines 92-101 and 115-118, there
are two conflicting interface definitions named AddressWithTreeInfo with
different property names (addressTreeInfo vs treeInfo). To fix this, consolidate
these two interfaces into one consistent definition by choosing a single
property name for the tree info field, or rename one of the interfaces to avoid
duplication and type conflicts. Ensure the final interface is uniquely named and
used consistently throughout the code.
| if (poolIndex <= 0) { | ||
| throw new Error( | ||
| 'Pool index must be greater than 0. For 0, use CreateTokenPool instead.', | ||
| ); | ||
| } | ||
| if (poolIndex > 3) { | ||
| throw new Error( | ||
| `Invalid poolIndex ${poolIndex}. Max 4 pools per mint.`, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Clarify token pool index bounds
There's a potential confusion in the validation logic. The error message states "Max 4 pools per mint" but the code allows indices 0-3, which is indeed 4 pools. However, the method doesn't allow index 0 (handled by createTokenPool), so effectively only 3 additional pools can be added.
Consider updating the error message for clarity:
- `Invalid poolIndex ${poolIndex}. Max 4 pools per mint.`,
+ `Invalid poolIndex ${poolIndex}. Valid range is 1-3 (pool 0 is created via createTokenPool).`,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (poolIndex <= 0) { | |
| throw new Error( | |
| 'Pool index must be greater than 0. For 0, use CreateTokenPool instead.', | |
| ); | |
| } | |
| if (poolIndex > 3) { | |
| throw new Error( | |
| `Invalid poolIndex ${poolIndex}. Max 4 pools per mint.`, | |
| ); | |
| } | |
| if (poolIndex <= 0) { | |
| throw new Error( | |
| 'Pool index must be greater than 0. For 0, use CreateTokenPool instead.', | |
| ); | |
| } | |
| if (poolIndex > 3) { | |
| throw new Error( | |
| `Invalid poolIndex ${poolIndex}. Valid range is 1-3 (pool 0 is created via createTokenPool).`, | |
| ); | |
| } |
🤖 Prompt for AI Agents
In js/compressed-token/src/program.ts around lines 815 to 824, the error message
for poolIndex exceeding the allowed range is misleading because it states "Max 4
pools per mint" while index 0 is disallowed here, effectively allowing only
indices 1 to 3. Update the error message to clarify that only 3 additional pools
(indices 1 to 3) are allowed beyond the initial pool at index 0, to avoid
confusion.
js/stateless.js/src/constants.ts
Outdated
| 'Dk9mNkbiZXJZ4By8DfSP6HEE4ojZzRvucwpawLeuwq8q'; // '8n8rH2bFRVA6cSGNDpgqcKHCndbFCT1bXxAQG89ejVsh'; | ||
| export const nullifiedStateTreeLookupTableDevnet = | ||
| '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP'; | ||
| 'AXbHzp1NgjLvpfnD6JRTTovXZ7APUCdtWZFCRr5tCxse'; // '5dhaJLBjnVBQFErr8oiCJmcVsx3Zj6xDekGB2zULPsnP'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover?
| import { hashToBn254FieldSizeBe, hashvToBn254FieldSizeBe } from './conversion'; | ||
| import { defaultTestStateTreeAccounts } from '../constants'; | ||
| import { getIndexOrAdd } from '../instruction'; | ||
| import { getIndexOrAdd } from '../programs/system/pack'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we support V2 address derivation yet?
(Probably not necessary for this pr.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch will add in new pr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (2)
js/compressed-token/src/program.ts (2)
817-826: Error message still misleading about valid pool range
Same concern as raised previously: message says “Max 4 pools per mint” but indices1-3are the only valid additions here.
Consider clarifying to “Valid range is 1–3 (pool 0 is created via createTokenPool).”
1540-1545: Hard-codedCHANGE_INDEXTODO persistsThe index is still derived from a ternary instead of being computed from actual remaining-account packing logic; earlier review already flagged this.
🧹 Nitpick comments (4)
js/stateless.js/src/constants.ts (2)
63-77: Avoid double-wrappingPublicKeyreturned from helper
getRegisteredProgramPda()already returns aPublicKey; wrapping it again withnew PublicKey(...)is redundant and allocates an extra object.-export const defaultStaticAccounts = () => [ - new PublicKey(getRegisteredProgramPda()), +export const defaultStaticAccounts = () => [ + getRegisteredProgramPda(),Same pattern occurs in
defaultStaticAccountsStruct.
265-267: Redundant ternary – same value both branchesThe ternary expression always returns
new BN(392).-export const ADDRESS_QUEUE_ROLLOVER_FEE = featureFlags.isV2() - ? new BN(392) - : new BN(392); +export const ADDRESS_QUEUE_ROLLOVER_FEE = new BN(392);js/stateless.js/src/rpc.ts (1)
111-145: Duplicated validator selection patternSeveral places repeat:
let res; if (featureFlags.isV2()) { res = create(unsafeRes, jsonRpcResultAndContext(FooV2)); } else { res = create(unsafeRes, jsonRpcResultAndContext(Foo)); }Consider a helper:
function versionedStruct<T, U>(raw: any, v1: Struct<T>, v2: Struct<U>) { return create(raw, jsonRpcResultAndContext(featureFlags.isV2() ? v2 : v1)); }to DRY up ~20 such blocks.
js/compressed-token/src/program.ts (1)
678-688: Hard-coded seed string differs from canonical constant
deriveTokenPoolPdaWithIndexre-creates the seed withBuffer.from('pool')instead of re-using the already-exportedPOOL_SEED.
Besides stylistic inconsistency, a future change to the seed would silently break this path.- seeds = [Buffer.from('pool'), mint.toBuffer(), Buffer.from([])]; + seeds = [POOL_SEED, mint.toBuffer(), Buffer.from([])];Apply the same replacement to the
elsebranch.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
js/compressed-token/src/actions/create-mint.ts(2 hunks)js/compressed-token/src/program.ts(26 hunks)js/compressed-token/src/types.ts(5 hunks)js/stateless.js/src/actions/transfer.ts(4 hunks)js/stateless.js/src/constants.ts(10 hunks)js/stateless.js/src/rpc.ts(32 hunks)js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts(13 hunks)js/stateless.js/src/utils/conversion.ts(3 hunks)js/stateless.js/src/utils/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- js/stateless.js/src/utils/index.ts
- js/compressed-token/src/actions/create-mint.ts
- js/stateless.js/src/actions/transfer.ts
- js/compressed-token/src/types.ts
- js/stateless.js/src/utils/conversion.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
js/stateless.js/src/constants.ts (1)
js/stateless.js/src/state/types.ts (1)
TreeInfo(77-99)
js/compressed-token/src/program.ts (10)
js/stateless.js/src/state/types.ts (3)
TreeInfo(77-99)ValidityProof(397-410)CompressedProof(373-386)js/compressed-token/src/utils/get-token-pool-infos.ts (2)
TokenPoolInfo(104-141)checkTokenPoolInfo(13-27)js/stateless.js/src/rpc-interface.ts (1)
ParsedTokenAccount(236-239)js/compressed-token/src/types.ts (6)
TokenTransferOutputData(11-28)DelegatedTransfer(62-65)CompressedTokenInstructionDataTransfer(94-132)BatchCompressInstructionData(67-74)CompressedTokenInstructionDataApprove(162-172)CompressedTokenInstructionDataRevoke(174-180)js/compressed-token/src/layout.ts (8)
createTokenPoolAccountsLayout(268-287)addTokenPoolAccountsLayout(289-310)mintToAccountsLayout(312-365)encodeTransferInstructionData(193-213)encodeApproveInstructionData(549-574)approveAccountsLayout(426-462)encodeRevokeInstructionData(588-613)revokeAccountsLayout(464-464)js/stateless.js/src/constants.ts (4)
defaultStaticAccountsStruct(79-89)featureFlags(16-19)noopProgram(58-58)accountCompressionProgram(60-61)js/stateless.js/src/utils/conversion.ts (1)
toArray(28-29)js/stateless.js/src/programs/system/program.ts (1)
LightSystemProgram(171-537)js/compressed-token/src/utils/pack-compressed-token-accounts.ts (1)
packCompressedTokenAccounts(39-159)js/compressed-token/src/utils/validation.ts (1)
checkMint(11-24)
🪛 Biome (1.9.4)
js/compressed-token/src/program.ts
[error] 690-690: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 781-781: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 830-830: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 834-834: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 842-842: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 847-847: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 907-907: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1106-1106: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1183-1183: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1204-1204: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1210-1210: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1221-1221: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1267-1267: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1269-1269: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1278-1278: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1360-1360: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1366-1366: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1408-1408: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1570-1570: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1576-1576: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1583-1583: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1640-1640: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1646-1646: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 1653-1653: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
⏰ Context from checks skipped due to timeout of 90000ms (22)
- GitHub Check: system-programs (sdk-anchor-test-program, ["cargo-test-sbf -p sdk-anchor-test"])
- GitHub Check: system-programs (token-escrow-test, [ "cargo test-sbf -p token-escrow" ])
- GitHub Check: system-programs (counter-test, ["cargo test-sbf -p counter"])
- GitHub Check: system-programs (sdk-test-program, ["cargo-test-sbf -p sdk-test"])
- GitHub Check: Test sdk-libs
- GitHub Check: Test program-libs
- GitHub Check: Test concurrent-merkle-tree
- GitHub Check: stateless-js
- GitHub Check: test-double-registration
- GitHub Check: test-state-photon-batched
- GitHub Check: test-address-batched
- GitHub Check: test-state-batched
- GitHub Check: test-e2e
- GitHub Check: test-2-foresters
- GitHub Check: lint
- GitHub Check: system-programs (system-cpi-test-v2, ["cargo-test-sbf -p system-cpi-v2-test"])
- GitHub Check: system-programs (light-compressed-token, ["cargo-test-sbf -p compressed-token-test"])
- GitHub Check: system-programs (system-cpi-test, ["cargo-test-sbf -p system-cpi-test"])
- GitHub Check: system-programs (account-compression, ["cargo-test-sbf -p account-compression-test"])
- GitHub Check: system-programs (light-registry, ["cargo-test-sbf -p registry-test"])
- GitHub Check: system-programs (random-e2e-test, ["cargo-test-sbf -p e2e-test"])
- GitHub Check: system-programs (light-system-program, ["cargo-test-sbf -p system-test"])
🔇 Additional comments (3)
js/stateless.js/src/constants.ts (1)
254-257: Drastic fee change – confirm economic impact
STATE_MERKLE_TREE_ROLLOVER_FEEdrops from300to1lamport under V2.
Please confirm this isn’t accidental; a 300× reduction will materially alter funding assumptions.js/compressed-token/src/program.ts (2)
688-907: Replacethiswith class name in static context (Bi-ome warnings)Multiple static methods still reference
this.programId/this.deriveTokenPoolPda…which Biome rightfully flags as confusing.
Using the explicit class name (CompressedTokenProgram) makes the call-site unambiguous and prevents subtle bugs once the class is subclassed or its static context is rebound.A blanket find/replace is safe:
- PublicKey.findProgramAddressSync(seeds, this.programId) + PublicKey.findProgramAddressSync(seeds, CompressedTokenProgram.programId)…same for every
this.occurrence inside static methods.
[ suggest_essential_refactor ]Also applies to: 1104-1111, 1180-1211, 1260-1278, 1357-1366, 1570-1583, 1640-1655
🧰 Tools
🪛 Biome (1.9.4)
[error] 690-690: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 699-699: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 750-750: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 781-781: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 788-788: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 793-793: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 830-830: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 834-834: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 842-842: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 847-847: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 895-895: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
[error] 907-907: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.(lint/complexity/noThisInStatic)
475-500: Potentially wrongdelegateChangeAccountIndexcalculation
parseMaybeDelegatedTransferunconditionally setsdelegateChangeAccountIndex = 0whenever there is more than one output.
If the first output is the “change” back to the owner (as is the case for normal transfers), index0would point to the owner’s side not to the delegate’s change account, breaking proof reconstruction.Please double-check the expected ordering; it might need to be
1(or computed dynamically).
| tree: new PublicKey(batchMerkleTree), | ||
| queue: new PublicKey(batchQueue), | ||
| cpiContext: PublicKey.default, | ||
| treeType: TreeType.StateV2, | ||
| nextTreeInfo: null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential misuse of PublicKey.default
PublicKey.default is not part of the documented @solana/web3.js API (latest 1.104.x). Relying on a non-public static may break on library upgrades.
Consider PublicKey.defaultPublicKey (if available) or new PublicKey(0) instead.
🤖 Prompt for AI Agents
In js/stateless.js/src/constants.ts around lines 152 to 156, the code uses
PublicKey.default which is not part of the official @solana/web3.js API and may
break on upgrades. Replace PublicKey.default with a supported alternative such
as PublicKey.defaultPublicKey if it exists, or create a new PublicKey instance
with a zeroed value using new PublicKey(0) to ensure compatibility and
stability.
| } else if (treeInfo.treeType === TreeType.StateV2) { | ||
| const pathElements = merkleTree._zeros.slice(0, -1); | ||
| const bnPathElements = pathElements.map(value => | ||
| bn(value), | ||
| ); | ||
| const root = bn(merkleTree.root()); | ||
|
|
||
| /// get leafIndex from leavesByTree for the given hash | ||
| const leafIndex = leavesByTree | ||
| .get(tree.toBase58())! | ||
| .leafIndices.findIndex(index => | ||
| hashes[i].eq( | ||
| bn( | ||
| leavesByTree.get(tree.toBase58())! | ||
| .leaves[index], | ||
| ), | ||
| ), | ||
| ); | ||
|
|
||
| const merkleProof: MerkleContextWithMerkleProof = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect V2 leafIndex calculation
findIndex iterates over indices, but you compare the hash again inside:
const leafIndex = leavesByTree.get(tree.toBase58())!
.leafIndices.findIndex(index =>
hashes[i].eq(
bn(leavesByTree.get(tree.toBase58())!.leaves[index]),
),
);index is already the wanted leafIndex; dereferencing leaves[index] mixes two arrays and may return ‑1 for valid leaves.
-const leafIndex = leavesByTree.get(tree.toBase58())!
- .leafIndices.findIndex(index =>
- hashes[i].eq(bn(leavesByTree.get(tree.toBase58())!.leaves[index])),
- );
+const leafIndex = leavesByTree
+ .get(tree.toBase58())!
+ .leafIndices.find(idx => hashes[i].eq(bn(leaves[idx])));🤖 Prompt for AI Agents
In js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts around lines 364 to
383, the leafIndex calculation incorrectly uses findIndex on leafIndices and
then dereferences leaves with that index, mixing two arrays. To fix this,
directly find the index in the leaves array that matches the hash without using
leafIndices, or adjust the logic to correctly map leafIndices to leaves. Ensure
the comparison is done on the correct array elements so leafIndex reflects the
actual position of the hash in the leaves array.
| merkleTree = new MerkleTree( | ||
| this.depth, | ||
| this.lightWasm, | ||
| leaves.map(leaf => bn(leaf).toString()), | ||
| ); | ||
| } else if (treeInfo.treeType === TreeType.StateV2) { | ||
| /// In V2 State trees, The Merkle tree stays empty until the | ||
| /// first forester transaction. And since test-rpc is only used | ||
| /// for non-forested tests, we must return a tree with | ||
| /// zerovalues. | ||
| merkleTree = new MerkleTree(32, this.lightWasm, []); | ||
| } else { | ||
| throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaking implementation detail: relying on private _zeros
merkleTree._zeros is a private field. Accessing it will break when the MerkleTree implementation changes or when TypeScript’s #private fields are enabled.
Replace with the library’s public helper (e.g., merkleTree.getZeros(depth) or construct the zero path manually).
🤖 Prompt for AI Agents
In js/stateless.js/src/test-helpers/test-rpc/test-rpc.ts around lines 321 to
333, the code accesses the private field merkleTree._zeros, which is an
implementation detail and may break with future changes or TypeScript private
fields. To fix this, replace any usage of merkleTree._zeros with a public method
provided by the MerkleTree class, such as merkleTree.getZeros(depth), or
manually construct the zero path using public APIs. Avoid direct access to
private fields to ensure compatibility and maintainability.
| activeStateTreeInfo, | ||
| res.result.value.tree!, | ||
| tree, | ||
| ); | ||
| const item = res.result.value; | ||
| const account = createCompressedAccountWithMerkleContext( | ||
| createMerkleContext( | ||
| item.tree!, | ||
| associatedQueue, | ||
| item.hash.toArray('be', 32), | ||
| item.leafIndex, | ||
| ), | ||
|
|
||
| return createCompressedAccountWithMerkleContextLegacy( | ||
| createMerkleContextLegacy(stateTreeInfo, item.hash, item.leafIndex), | ||
| item.owner, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
proveByIndex flag dropped for V2 accounts
When featureFlags.isV2() is true, the RPC returns a proveByIndex boolean, but the context here ignores it:
createMerkleContextLegacy(stateTreeInfo, item.hash, item.leafIndex)
// should forward proveByIndex-createMerkleContextLegacy(stateTreeInfo, item.hash, item.leafIndex),
+createMerkleContextLegacy(
+ stateTreeInfo,
+ item.hash,
+ item.leafIndex,
+ featureFlags.isV2() ? item.proveByIndex : false,
+),Down-stream verification will fail for proofs obtained via index.
🤖 Prompt for AI Agents
In js/stateless.js/src/rpc.ts around lines 753 to 760, the call to
createMerkleContextLegacy does not forward the proveByIndex flag returned by the
RPC when featureFlags.isV2() is true. Modify the code to extract proveByIndex
from the RPC result and pass it as an additional argument to
createMerkleContextLegacy to ensure correct proof verification downstream.
| const compressedAccount: CompressedAccountWithMerkleContext = | ||
| createCompressedAccountWithMerkleContextLegacy( | ||
| createMerkleContextLegacy( | ||
| compressedAccountResult.treeInfo, | ||
| compressedAccountResult.hash.toArray('be', 32), | ||
| compressedAccountResult.leafIndex, | ||
| compressedAccountResult.proveByIndex, | ||
| ), | ||
| compressedAccountResult.owner, | ||
| bn(compressedAccountResult.lamports), | ||
| compressedAccountResult.data | ||
| ? parseAccountData(compressedAccountResult.data) | ||
| : undefined, | ||
| compressedAccountResult.address || undefined, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing bn() conversion – hash fed as byte array
createMerkleContextLegacy expects a BN, but compressedAccountResult.hash.toArray() supplies a number[].
- compressedAccountResult.hash.toArray('be', 32),
+ bn(compressedAccountResult.hash.toArray('be', 32)),Without the cast the hash becomes an unintended huge integer.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const compressedAccount: CompressedAccountWithMerkleContext = | |
| createCompressedAccountWithMerkleContextLegacy( | |
| createMerkleContextLegacy( | |
| compressedAccountResult.treeInfo, | |
| compressedAccountResult.hash.toArray('be', 32), | |
| compressedAccountResult.leafIndex, | |
| compressedAccountResult.proveByIndex, | |
| ), | |
| compressedAccountResult.owner, | |
| bn(compressedAccountResult.lamports), | |
| compressedAccountResult.data | |
| ? parseAccountData(compressedAccountResult.data) | |
| : undefined, | |
| compressedAccountResult.address || undefined, | |
| ); | |
| const compressedAccount: CompressedAccountWithMerkleContext = | |
| createCompressedAccountWithMerkleContextLegacy( | |
| createMerkleContextLegacy( | |
| compressedAccountResult.treeInfo, | |
| - compressedAccountResult.hash.toArray('be', 32), | |
| + bn(compressedAccountResult.hash.toArray('be', 32)), | |
| compressedAccountResult.leafIndex, | |
| compressedAccountResult.proveByIndex, | |
| ), | |
| compressedAccountResult.owner, | |
| bn(compressedAccountResult.lamports), | |
| compressedAccountResult.data | |
| ? parseAccountData(compressedAccountResult.data) | |
| : undefined, | |
| compressedAccountResult.address || undefined, | |
| ); |
🤖 Prompt for AI Agents
In js/stateless.js/src/rpc.ts around lines 578 to 592, the hash passed to
createMerkleContextLegacy is currently converted to a byte array using toArray,
but the function expects a BN instance. To fix this, convert
compressedAccountResult.hash to a BN before passing it to
createMerkleContextLegacy instead of passing the byte array, ensuring the hash
is correctly interpreted as a big number.
| for (let index = 0; index < 5; index++) { | ||
| const derivedPda = | ||
| CompressedTokenProgram.deriveTokenPoolPdaWithIndex(mint, index); | ||
| if (derivedPda[0].equals(poolPda)) { | ||
| return [index, derivedPda[1]]; | ||
| } | ||
| } | ||
| throw new Error('Token pool not found'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Inconsistent pool-count limits – off-by-one bug
findTokenPoolIndexAndBump iterates over indices 0…4 (< 5) while both the JSDoc above (supports 4 indexes) and the validation in addTokenPool reject any index > 3.
This desynchronisation risks returning an index (4) that other branches will later treat as invalid, leading to hard-to-trace runtime errors.
- for (let index = 0; index < 5; index++) {
+ // index range must stay in sync with addTokenPool() validation (0–3)
+ for (let index = 0; index < 4; index++) {Synchronise all three places (deriveTokenPoolPdaWithIndex doc, findTokenPoolIndexAndBump, addTokenPool guard) to avoid undefined behaviour.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (let index = 0; index < 5; index++) { | |
| const derivedPda = | |
| CompressedTokenProgram.deriveTokenPoolPdaWithIndex(mint, index); | |
| if (derivedPda[0].equals(poolPda)) { | |
| return [index, derivedPda[1]]; | |
| } | |
| } | |
| throw new Error('Token pool not found'); | |
| } | |
| // index range must stay in sync with addTokenPool() validation (0–3) | |
| for (let index = 0; index < 4; index++) { | |
| const derivedPda = | |
| CompressedTokenProgram.deriveTokenPoolPdaWithIndex(mint, index); | |
| if (derivedPda[0].equals(poolPda)) { | |
| return [index, derivedPda[1]]; | |
| } | |
| } | |
| throw new Error('Token pool not found'); | |
| } |
🤖 Prompt for AI Agents
In js/compressed-token/src/program.ts around lines 655 to 663, the loop in
findTokenPoolIndexAndBump iterates from 0 to 4 inclusive, but the JSDoc and
addTokenPool validation only allow indices up to 3. To fix this off-by-one
error, change the loop condition to iterate only up to 3 (i.e., index < 4) so it
matches the documented and validated index range, ensuring consistent pool-count
limits across the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SwenSchaeferjohann this one is probably valid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can ignore - TS has a guard that limits to 4 for now but the protocol supports up to 5
ananas-block
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice lgtm!
There is at least one new ai comment which is probably valid tagged you.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Refactor
Chores