Skip to content

Rework assetsigner tests#89

Open
MarkSackerberg wants to merge 6 commits intomainfrom
feat/core-execute-testing
Open

Rework assetsigner tests#89
MarkSackerberg wants to merge 6 commits intomainfrom
feat/core-execute-testing

Conversation

@MarkSackerberg
Copy link
Contributor

Test Wallet Modes

The test suite runs in two wallet modes to verify all commands work with both normal keypairs and asset-signer wallets.

npm test                    # Both modes sequentially
npm run test:normal         # Normal wallet mode only
npm run test:asset-signer   # Asset-signer wallet mode only

In asset-signer mode, a root hook (test/setup.asset-signer.ts) creates a signing asset, funds its PDA, and writes a temporary config. runCli then uses -c <config> instead of -k <keypair>, so all transactions are wrapped in MPL Core execute().

Infrastructure that can't be created via execute CPI (large account allocations) uses runCliDirect, which always uses the normal keypair.

Test Coverage by Wallet Mode

Legend:

  • Y = runs and passes
  • Skip = skipped (CPI limitation or authority mismatch)
  • Pending = pre-existing describe.skip (not related to asset-signer)

Core Commands

Test Normal Asset-Signer
core asset create (name/uri, collection, custom owner) Y Y
core asset transfer (standalone, collection, not-owner error) Y Y
core asset burn (standalone, collection) Y Y
core asset update Y Y
core collection create Y Y
core plugins (add/update on collection and asset) Y Y
core execute info (PDA address + balance) Y Y

Asset-Signer Specific

Test Normal Asset-Signer
Separate fee payer via -p Y Y
Mint cNFT into public tree as PDA Y Y

Toolbox

Test Normal Asset-Signer
sol balance (identity + specific address) Y Y
sol transfer Y Y
sol wrap Y Y
sol unwrap Y Y
token create Y Y
token mint Y Y
toolbox raw (execute + error) Y Y

Token Metadata

Test Normal Asset-Signer
tm transfer (NFT + pNFT) Y Y
tm transfer validation errors Y Y
tm update validation errors Y Y

Bubblegum

Test Normal Asset-Signer Notes
bg tree create (8 tests) Y Y Uses runCliDirect internally (CPI limitation)
bg collection create (9 tests) Y Y No trees involved
bg nft create (9 tests) Y Skip Tree authority mismatch — tree owned by wallet, PDA can't mint
bg integration (8 tests) Y Skip Tree authority mismatch
bg nft burn Pending Pending Pre-existing describe.skip
bg nft transfer Pending Pending Pre-existing describe.skip
bg nft update Pending Pending Pre-existing describe.skip

Candy Machine

Test Normal Asset-Signer Notes
cm create (3 on-chain tests) Y Skip CM creation is CPI-incompatible (large account)
cm create hasGuards (5 unit tests) Y Y Pure unit tests
cm full lifecycle (create → insert → withdraw) Y Skip CM authority mismatch
cm insert Y Skip CM authority mismatch
cm withdraw Y Skip CM authority mismatch
cm guard parsing (5 unit tests) Y Y Pure unit tests

Genesis

Test Normal Asset-Signer Notes
genesis create/fetch (7 tests) Y Y Setup uses runCliDirect for SOL wrap
genesis integration (19 tests) Y Skip Authority mismatch on deposits/finalize
genesis launch (12 tests) Y Y Setup uses runCliDirect for SOL wrap
genesis presale (6 tests) Y Skip Authority mismatch on deposits/claims
genesis withdraw (8 tests) Y Skip Authority mismatch on deposits/withdrawals

Distribution

Test Normal Asset-Signer Notes
distro deposit (6 tests) Y Skip Authority mismatch + token account mismatch
distro withdraw (8 tests) Y Skip Authority mismatch + token account mismatch

Lib (Unit Tests)

Test Normal Asset-Signer
deserializeInstruction roundtrip (6 tests) Y Y

Why Some Tests Skip in Asset-Signer Mode

CPI Limitations

These operations allocate large accounts, which fails when wrapped in execute():

  • Merkle tree creation
  • Candy machine creation

The createBubblegumTree helper and CM creation in test setup use runCliDirect to bypass this.

Authority Mismatch

Resources created with runCliDirect (normal wallet) have the wallet as authority. In asset-signer mode, commands run as the PDA, which isn't the authority. This affects:

  • bg nft minting (tree authority is wallet, not PDA)
  • CM insert/withdraw (CM authority is wallet)
  • Genesis deposits/finalize (genesis authority is wallet)
  • Distro deposits/withdrawals (distro authority is wallet)

What IS Tested in Asset-Signer Mode

The asset-signer specific test creates a public tree (anyone can mint) and verifies the PDA can mint a cNFT into it. This confirms bubblegum minting works through execute CPI when authority isn't an issue.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary by CodeRabbit

  • New Features

    • Added an asset-signer wallet mode alongside the existing keypair mode; CLI lets you choose per command which wallet to use.
  • Tests

    • Test runner now runs the suite in both wallet modes sequentially.
    • Tests adapted to run or skip based on active wallet mode; an alternate CLI execution path is used where asset-signer mode is incompatible.
    • Root test setup auto-initializes and cleans up asset-signer test state.
  • Documentation

    • Added user guidance on asset-signer wallets, usage patterns, limitations, and per-feature test coverage.

Walkthrough

Adds an asset-signer test mode: a Mocha root hook creates/funds an asset-signer PDA and writes a temp CLI config; test/runCli.ts gains runCliDirect, asset-signer-aware runCli, and helpers; many tests use runCliDirect and add conditional skips under MPLX_TEST_WALLET_MODE=asset-signer. Docs and npm/mocha scripts updated.

Changes

Cohort / File(s) Summary
Mocha config & npm scripts
\.mocharc\.json, package\.json
Mocha now requires test/setup.asset-signer.ts. package.json test script split into sequential test:normal and test:asset-signer runs (env-controlled).
Test CLI harness
test/runCli\.ts
Introduce assetSignerConfigPath, setAssetSignerConfig(), isAssetSignerMode(); add runCliDirect() (always keypair); make runCli() choose -k vs -c and error when config missing; improved child-process/stdin handling.
Asset-signer root hook
test/setup\.asset-signer\.ts
New Mocha root hook: builds Umi client, creates core asset, derives/funds asset-signer PDA, writes temp CLI config, calls setAssetSignerConfig(), and removes the temp file in afterAll.
Core asset-signer tests
test/commands/core/core.asset-signer\.test\.ts
Refactor to create signing asset and public tree inline, write config, add fee-payer keypair, replace some flows with runCliDirect, add compressed-NFT mint test, and remove older SOL/transfer suites.
Bubblegum / tree tests & helpers
test/commands/bg/..., test/commands/bg/bghelpers\.ts
Import runCliDirect; use runCliDirect for large-account setup (airdrops, tree create); extract treeAddress from CLI output; convert callbacks to function and add this.skip() guards for asset-signer mode.
Candy Machine tests
test/commands/cm/...
Add runCliDirect; use it for airdrop and cm create; convert to function callbacks and add asset-signer conditional skips.
Distribution tests
test/commands/distro/...
Use runCliDirect for airdrop/wrap/create; convert tests to function and add asset-signer skips; test execution commands remain runCli.
Genesis tests
test/commands/genesis/...
Use runCliDirect for airdrop/wrap setup; convert tests to function and add asset-signer skips; in-test runCli calls left unchanged.
Various tests (misc.)
test/commands/...
Multiple test files updated to import runCliDirect, switch describe/it to function form, and add MPLX_TEST_WALLET_MODE==='asset-signer' skip guards where appropriate.
Mocha root hook & setup file
test/setup\.asset-signer\.ts
New root-hook module added and loaded by Mocha to provision asset-signer config for tests.
Docs & test notes
docs/asset-signer-wallets\.md, test/WALLET_MODES\.md
New documentation on asset-signer wallets, CLI behavior, CPI limitations, and a test-mode coverage matrix.

Sequence Diagram

sequenceDiagram
    participant Mocha as Mocha Root Hook
    participant FS as File System
    participant Umi as Umi Client
    participant RPC as RPC / Blockchain
    participant CLI as Test CLI Runner

    Mocha->>FS: load test keypair
    Mocha->>Umi: build client (mplCore & mplToolbox)
    Umi->>Umi: register keypair identity
    Umi->>RPC: createCoreAsset()
    RPC-->>Umi: assetId
    Umi->>Umi: derive asset-signer PDA
    Umi->>RPC: transfer SOL to PDA
    RPC-->>Umi: confirm transfer
    Mocha->>FS: write temp CLI config (RPC, keypair, vault asset-signer)
    Mocha->>CLI: setAssetSignerConfig(configPath)
    CLI->>CLI: runCli() reads isAssetSignerMode()
    alt asset-signer mode
        CLI->>RPC: spawn CLI with `-c config` (execute via PDA)
    else normal mode
        CLI->>RPC: spawn CLI with `-k keypair`
    end
    Mocha->>FS: afterAll: delete temp config
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • blockiosaurus
  • tonyboylehub
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Rework assetsigner tests' accurately summarizes the main change: refactoring and reworking the asset-signer test suite to support two wallet modes.
Description check ✅ Passed The description clearly relates to the changeset by explaining the two-wallet-mode test architecture, setup flow, test coverage matrix, and rationale for test skips.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/core-execute-testing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Base automatically changed from feat/core-execute to main March 19, 2026 15:42
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
test/commands/bg/bg.tree.create.test.ts (2)

18-59: ⚠️ Potential issue | 🟠 Major

Missing asset-signer mode skip guards in tree creation tests.

These it blocks use createBubblegumTree helper but lack the if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip() guard present in other test files. Since tree creation allocates large accounts (CPI-incompatible), these tests will fail in asset-signer mode.

🐛 Proposed fix - add skip guards
     it('creates a basic Bubblegum tree with default configuration', async function () {
+        if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip()
         const { treeAddress, signature } = await createBubblegumTree()

         expect(treeAddress).to.match(/^[a-zA-Z0-9]{32,44}$/)
         expect(signature).to.match(/^[a-zA-Z0-9]{32,}$/)
     })

     it('creates a tree with custom depth and buffer size', async function () {
+        if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip()
         const { treeAddress, signature } = await createBubblegumTree({

Apply similar fix to all it blocks in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/commands/bg/bg.tree.create.test.ts` around lines 18 - 59, Each test that
calls createBubblegumTree must bail out when running in asset-signer mode to
avoid allocating large/CPI-incompatible accounts; at the top of every it(...)
block (the ones using createBubblegumTree, e.g., "creates a basic Bubblegum
tree...", "creates a tree with custom depth and buffer size", "creates a public
tree", and "creates a tree with a name for storage") add the guard: if
(process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip(); so
the tests skip in asset-signer mode.

100-137: ⚠️ Potential issue | 🟠 Major

Missing skip guards for remaining tree tests.

The tests at lines 100-137 (validates tree name format and prevents duplicate tree names) also use createBubblegumTree helper and need the asset-signer skip guard.

🐛 Proposed fix
     it('validates tree name format', async function () {
+        if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip()
         const validName = `test-tree-${Date.now()}`
         const { treeAddress } = await createBubblegumTree({
     it('prevents duplicate tree names on same network', async function () {
+        if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return this.skip()
         const treeName = `unique-tree-${Date.now()}`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/commands/bg/bg.tree.create.test.ts` around lines 100 - 137, Add the same
asset-signer skip guard to these two tests that use createBubblegumTree so they
are skipped when the asset signer isn't available: at the start of the
"validates tree name format" and "prevents duplicate tree names on same network"
it blocks, call the existing skip helper (e.g., skipIfNoAssetSigner() or if
(!hasAssetSigner()) this.skip()) before invoking createBubblegumTree so the test
early-exits when the asset-signer is missing.
test/commands/cm/cm.create.test.ts (1)

34-45: ⚠️ Potential issue | 🟠 Major

Keep the unit tests free of suite-level chain setup.

In asset-signer mode the three on-chain cases immediately skip, but this outer before still performs an airdrop and waits 10 seconds. That makes the remaining hasGuards tests depend on validator setup even though the matrix documents them as pure unit tests. Guard this hook or move it under the on-chain cases.

Suggested minimal fix
 describe('cm create commands', function () {
     before(async () => {
+        if (process.env.MPLX_TEST_WALLET_MODE === 'asset-signer') return
         const { stdout, stderr, code } = await runCliDirect(
             ["toolbox", 'sol', "airdrop", "100", "TESTfCYwTPxME2cAnPcKvvF5xdPah3PY7naYQEP2kkx"]
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/commands/cm/cm.create.test.ts` around lines 34 - 45, The suite-level
before hook in the "cm create commands" describe block runs an airdrop via
runCliDirect and waits 10s unconditionally which couples unit-only tests (like
the hasGuards cases) to on-chain setup; either move this airdrop/wait into the
on-chain test cases or guard the before hook so it only runs when executing
on-chain tests (e.g., check the same condition used to skip the three on-chain
cases or an environment flag such as asset-signer mode) and leave the unit tests
untouched; update the before hook around runCliDirect and the setTimeout so it
only executes when that condition is true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/commands/bg/bg.nft.create.test.ts`:
- Around line 9-22: The before hook always performs an airdrop and calls
createBubblegumTree (assigning testTree) even when running in asset-signer mode;
wrap the airdrop and createBubblegumTree call in a conditional that checks the
asset-signer mode (e.g., process.env.ASSET_SIGNER or an existing helper like
isAssetSignerMode()) so that when asset-signer mode is enabled the test setup
skips the runCliDirect airdrop and createBubblegumTree calls and avoids spending
SOL and time, but still retains any other setup steps and the testTree
assignment only when the tree is actually created.

In `@test/commands/core/core.asset-signer.test.ts`:
- Around line 84-90: The test currently writes a config that sets the
asset-signer wallet payer to 'owner' which masks whether the CLI -p override is
honored; update the test in core.asset-signer.test.ts to explicitly verify the
override payer is used by (a) recording the balance of the dedicated override
keypair (the key at KEYPAIR_PATH you pass via -p) before the transfer, invoking
the CLI transfer that uses -p, then asserting that that keypair's balance
decreased after the transfer (use the same balance-check helper used elsewhere
in tests), OR alternatively modify the config written to make the default payer
(owner) unusable (e.g. remove/fund owner with insufficient balance) so the test
will fail if the CLI ignores -p; target the fs.writeFileSync block that writes
rpcUrl, keypair, activeWallet, wallets and the test that asserts the transfer
success string (around the transfer invocation) to add the before/after balance
assertion.

In `@test/runCli.ts`:
- Around line 53-57: runCli currently falls back to keypair mode when
isAssetSignerMode() is true but assetSignerConfigPath is undefined, hiding
setup-ordering bugs; update runCli to fail fast: if isAssetSignerMode() is true
and assetSignerConfigPath is falsy, immediately reject (or throw) with a clear
error mentioning asset signer mode and missing assetSignerConfigPath instead of
building args with '-k'; keep runCliDirect as the intended keypair path and
reference isAssetSignerMode(), assetSignerConfigPath and runCliDirect in the
error message to guide correct usage.

In `@test/WALLET_MODES.md`:
- Around line 109-124: Add a blank line after each H3 heading (the lines
starting "### CPI Limitations", "### Authority Mismatch", and "### What IS
Tested in Asset-Signer Mode") to satisfy MD022, and hyphenate the phrase
"asset-signer specific" to "asset-signer-specific" in the paragraph under the
last heading so the term is grammatically correct; update those three headings
and the phrase accordingly in WALLET_MODES.md.

---

Outside diff comments:
In `@test/commands/bg/bg.tree.create.test.ts`:
- Around line 18-59: Each test that calls createBubblegumTree must bail out when
running in asset-signer mode to avoid allocating large/CPI-incompatible
accounts; at the top of every it(...) block (the ones using createBubblegumTree,
e.g., "creates a basic Bubblegum tree...", "creates a tree with custom depth and
buffer size", "creates a public tree", and "creates a tree with a name for
storage") add the guard: if (process.env.MPLX_TEST_WALLET_MODE ===
'asset-signer') return this.skip(); so the tests skip in asset-signer mode.
- Around line 100-137: Add the same asset-signer skip guard to these two tests
that use createBubblegumTree so they are skipped when the asset signer isn't
available: at the start of the "validates tree name format" and "prevents
duplicate tree names on same network" it blocks, call the existing skip helper
(e.g., skipIfNoAssetSigner() or if (!hasAssetSigner()) this.skip()) before
invoking createBubblegumTree so the test early-exits when the asset-signer is
missing.

In `@test/commands/cm/cm.create.test.ts`:
- Around line 34-45: The suite-level before hook in the "cm create commands"
describe block runs an airdrop via runCliDirect and waits 10s unconditionally
which couples unit-only tests (like the hasGuards cases) to on-chain setup;
either move this airdrop/wait into the on-chain test cases or guard the before
hook so it only runs when executing on-chain tests (e.g., check the same
condition used to skip the three on-chain cases or an environment flag such as
asset-signer mode) and leave the unit tests untouched; update the before hook
around runCliDirect and the setTimeout so it only executes when that condition
is true.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ac77270b-3214-4fef-9a6e-551609ec6f1b

📥 Commits

Reviewing files that changed from the base of the PR and between 922f3f8 and 3b5e0f2.

📒 Files selected for processing (21)
  • .mocharc.json
  • package.json
  • test/WALLET_MODES.md
  • test/commands/bg/bg.integration.test.ts
  • test/commands/bg/bg.nft.create.test.ts
  • test/commands/bg/bg.nft.transfer.test.ts
  • test/commands/bg/bg.tree.create.test.ts
  • test/commands/bg/bghelpers.ts
  • test/commands/cm/cm.create.test.ts
  • test/commands/cm/cm.full.test.ts
  • test/commands/cm/cm.insert.test.ts
  • test/commands/cm/cm.withdraw.test.ts
  • test/commands/core/core.asset-signer.test.ts
  • test/commands/distro/distro.deposit.test.ts
  • test/commands/distro/distro.withdraw.test.ts
  • test/commands/genesis/genesis.integration.test.ts
  • test/commands/genesis/genesis.launch.test.ts
  • test/commands/genesis/genesis.presale.test.ts
  • test/commands/genesis/genesis.withdraw.test.ts
  • test/runCli.ts
  • test/setup.asset-signer.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/commands/core/core.asset-signer.test.ts`:
- Around line 143-145: The test fails because balanceAfter.basisPoints and
balanceBefore.basisPoints are bigints while Chai's lessThan expects numbers;
update the assertion in the test (around the variables balanceAfter,
balanceBefore, payerPubkey retrieved via umi.rpc.getBalance) to use a compatible
comparison — either convert to numbers with Number(balanceAfter.basisPoints) and
Number(balanceBefore.basisPoints) inside expect(...).to.be.lessThan(...) or
perform a direct bigint comparison (e.g., expect(balanceAfter.basisPoints <
balanceBefore.basisPoints).to.be.true) so TypeScript no longer complains.
- Around line 44-47: The test defines a duplicate extractTreeAddress function;
remove this local implementation and import the shared extractTreeAddress helper
from the bghelpers module instead, using the shared function
(extractTreeAddress) in place of the local one so you get support for multiple
output formats; update any call sites in this test (core.asset-signer.test.ts)
to match the helper's signature and run tests to confirm no behavior/regression
issues.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a4eb3b17-257e-476c-ab63-2a8ea76546f9

📥 Commits

Reviewing files that changed from the base of the PR and between 3b5e0f2 and b0c9181.

📒 Files selected for processing (4)
  • test/WALLET_MODES.md
  • test/commands/bg/bg.nft.create.test.ts
  • test/commands/core/core.asset-signer.test.ts
  • test/runCli.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/asset-signer-wallets.md`:
- Line 123: The current line is ambiguous about SOL wrapping; update the
sentence to explicitly state that this limitation concerns creating/funding
wrapped SOL (wSOL) token accounts via the Token Program and that calling
transferSol in a CPI (cross-program invocation) context will fail to create or
fund a wSOL token account; reference the Token Program and the transferSol
helper so readers know this is about creating/funding wSOL in CPI rather than
general SOL transfers.
- Line 96: Clarify the "(public trees)" note next to "Bubblegum: `nft create`,
`nft transfer`, `nft burn`, `collection create`" by explaining that creating a
new Bubblegum tree requires using runCliDirect due to CPI account-allocation
limits (see CPI Limitations section), while performing `nft create` (and
transfers/burns) against pre-existing public trees works with asset-signer
wallets; update the line to include this brief distinction or add a
parenthetical/note referencing the CPI Limitations section for details.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 211aff50-6cbd-4d97-9f33-ccf09995d5db

📥 Commits

Reviewing files that changed from the base of the PR and between b0c9181 and 26e07e7.

📒 Files selected for processing (2)
  • docs/asset-signer-wallets.md
  • test/commands/core/core.asset-signer.test.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/asset-signer-wallets.md`:
- Line 92: The docs currently list the Toolbox SOL operations "wrap" and
"unwrap" as fully transparent but elsewhere note that wSOL wrapping fails in
CPI; update both the "Toolbox SOL" entry and the later description so they are
consistent: change the "wrap"/"unwrap" visibility from fully transparent to
"partially transparent" (or add a caveat) in the Toolbox SOL line and add a
short note next to the wrap/unwrap descriptions explaining that wSOL wrapping
cannot be performed inside CPIs and will fail, referencing the same wording used
in the other section to keep phrasing consistent (look for the "Toolbox SOL"
heading and the wrap/unwrap discussion to edit).
- Line 87: Replace the overbroad sentence "All CLI commands work with
asset-signer wallets. The transaction wrapping happens transparently in the send
layer." with a qualified statement that acknowledges exceptions—e.g., "Most CLI
commands work with asset-signer wallets; however, some CPI cases are not
supported and require manual handling." —and add a direct pointer or inline link
to the existing "Unsupported CPI cases" section (the documented limitations
around CPI) so readers know to consult lines describing unsupported cases (the
section currently documenting unsupported CPI scenarios).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 157df667-b18a-4198-b6dc-e11e3dd1b71e

📥 Commits

Reviewing files that changed from the base of the PR and between 26e07e7 and 95fb000.

📒 Files selected for processing (1)
  • docs/asset-signer-wallets.md


## Supported Commands

All CLI commands work with asset-signer wallets. The transaction wrapping happens transparently in the send layer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Overbroad support statement conflicts with documented limitations.

Line 87 says all commands work, but Lines 118–125 explicitly document unsupported CPI cases. Reword this to avoid promising universal compatibility.

Suggested doc fix
-All CLI commands work with asset-signer wallets. The transaction wrapping happens transparently in the send layer.
+Most CLI commands work with asset-signer wallets. Transaction wrapping happens transparently in the send layer, with exceptions listed in [CPI Limitations](`#cpi-limitations`).
📝 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.

Suggested change
All CLI commands work with asset-signer wallets. The transaction wrapping happens transparently in the send layer.
Most CLI commands work with asset-signer wallets. Transaction wrapping happens transparently in the send layer, with exceptions listed in [CPI Limitations](`#cpi-limitations`).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/asset-signer-wallets.md` at line 87, Replace the overbroad sentence "All
CLI commands work with asset-signer wallets. The transaction wrapping happens
transparently in the send layer." with a qualified statement that acknowledges
exceptions—e.g., "Most CLI commands work with asset-signer wallets; however,
some CPI cases are not supported and require manual handling." —and add a direct
pointer or inline link to the existing "Unsupported CPI cases" section (the
documented limitations around CPI) so readers know to consult lines describing
unsupported cases (the section currently documenting unsupported CPI scenarios).

### Fully Transparent (no special handling needed)

- **Core**: `asset create`, `asset transfer`, `asset burn`, `asset update`, `collection create`
- **Toolbox SOL**: `balance`, `transfer`, `wrap`, `unwrap`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

wrap/unwrap listed as transparent contradicts SOL wrapping limitation.

Line 92 includes wrap/unwrap as fully transparent, but Line 123 says wSOL wrapping fails in CPI. Keep these sections consistent to prevent false expectations.

Suggested doc fix
-- **Toolbox SOL**: `balance`, `transfer`, `wrap`, `unwrap`
+- **Toolbox SOL**: `balance`, `transfer`
- **SOL wrapping** — creating wrapped SOL (wSOL) token accounts fails in CPI context
+ **SOL wrapping** — `wrap`/`unwrap` flows that create or fund wSOL token accounts fail in CPI context

Also applies to: 123-123

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/asset-signer-wallets.md` at line 92, The docs currently list the Toolbox
SOL operations "wrap" and "unwrap" as fully transparent but elsewhere note that
wSOL wrapping fails in CPI; update both the "Toolbox SOL" entry and the later
description so they are consistent: change the "wrap"/"unwrap" visibility from
fully transparent to "partially transparent" (or add a caveat) in the Toolbox
SOL line and add a short note next to the wrap/unwrap descriptions explaining
that wSOL wrapping cannot be performed inside CPIs and will fail, referencing
the same wording used in the other section to keep phrasing consistent (look for
the "Toolbox SOL" heading and the wrap/unwrap discussion to edit).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
test/commands/core/core.asset-signer.test.ts (1)

51-52: ⚠️ Potential issue | 🟠 Major

The -p override is still masked by the default config payer.

Because this config leaves vault.payer as owner, the transfer can still pass if the CLI ignores -p and charges the owner instead. Please assert that the dedicated payer’s balance decreases, or make the default payer unusable, so this test actually guards the override path.

🔎 One way to make the test actually verify the override payer
 let payerKeypairPath: string
+let payerAddress: string
 let publicTreeAddress: string
@@
         // Generate and fund a separate fee payer keypair
         const newKp = generateSigner(umi)
+        payerAddress = newKp.publicKey.toString()
         payerKeypairPath = path.join(os.tmpdir(), `mplx-test-payer-${Date.now()}.json`)
         fs.writeFileSync(payerKeypairPath, JSON.stringify(Array.from(newKp.secretKey)))
         tempFiles.push(payerKeypairPath)
@@
     it('transfers SOL from PDA with a different wallet paying fees', async function () {
-        const { stdout, stderr, code } = await runCliWithConfig(
+        const umi = createUmi(TEST_RPC)
+        const balanceBefore = await umi.rpc.getBalance(publicKey(payerAddress))
+        const { stdout, stderr } = await runCliWithConfig(
             ['toolbox', 'sol', 'transfer', '0.01', ownerAddress, '-p', payerKeypairPath],
             configPath,
         )
+        const balanceAfter = await umi.rpc.getBalance(publicKey(payerAddress))
 
         const output = stripAnsi(stdout) + stripAnsi(stderr)
-        expect(code).to.equal(0)
         expect(output).to.contain('SOL transferred successfully')
+        expect(balanceAfter.basisPoints < balanceBefore.basisPoints).to.be.true
     })

Also applies to: 78-88, 91-98, 120-129

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/commands/core/core.asset-signer.test.ts` around lines 51 - 52, The test
currently lets the default vault.payer (owner) be charged, so fix the test that
uses payerKeypairPath and publicTreeAddress to ensure the CLI -p override is
exercised by either (a) asserting the dedicated payer's balance decreases after
the transfer (capture its pre- and post-balance and compare), or (b) make the
default payer unusable for this scenario (e.g., transfer funds out or set its
balance to zero) before invoking the command so only the override payer can pay;
update all related test blocks that use payerKeypairPath/publicTreeAddress
(including the other failing blocks) to follow the same pattern and assert the
dedicated payer was billed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/commands/core/core.asset-signer.test.ts`:
- Around line 97-111: The fixed 2s sleeps after umi.rpc.airdrop and after
creating the tree make tests slow and flaky; replace them with readiness checks:
after umi.rpc.airdrop(newKp.publicKey, ...) poll the chain (e.g., via
umi.connection.getBalance or a waitForBalance helper) until the expected
lamports are present for newKp.publicKey instead of setTimeout, and after
running runCliDirect(['bg','tree','create',...]) use a polling check (e.g., call
getAccountInfo/getProgramAccounts or a waitForTree helper) against the tree
address returned by extractTreeAddress(stdout+stderr) until the tree account
exists/has expected state before assigning publicTreeAddress; keep timeouts and
retry intervals configurable and fail with a clear error if readiness isn't
reached in a reasonable timeout.

---

Duplicate comments:
In `@test/commands/core/core.asset-signer.test.ts`:
- Around line 51-52: The test currently lets the default vault.payer (owner) be
charged, so fix the test that uses payerKeypairPath and publicTreeAddress to
ensure the CLI -p override is exercised by either (a) asserting the dedicated
payer's balance decreases after the transfer (capture its pre- and post-balance
and compare), or (b) make the default payer unusable for this scenario (e.g.,
transfer funds out or set its balance to zero) before invoking the command so
only the override payer can pay; update all related test blocks that use
payerKeypairPath/publicTreeAddress (including the other failing blocks) to
follow the same pattern and assert the dedicated payer was billed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ee5223c6-dff0-45be-9192-f07283889e8f

📥 Commits

Reviewing files that changed from the base of the PR and between 95fb000 and 8797156.

📒 Files selected for processing (1)
  • test/commands/core/core.asset-signer.test.ts

Comment on lines +97 to +111
await umi.rpc.airdrop(newKp.publicKey, { basisPoints: 2_000_000_000n, identifier: 'SOL', decimals: 9 })
await new Promise(resolve => setTimeout(resolve, 2000))

// Create a public tree (anyone can mint) for bg mint test
const { stdout, stderr } = await runCliDirect([
'bg', 'tree', 'create',
'--maxDepth', '3',
'--maxBufferSize', '8',
'--canopyDepth', '1',
'--public',
])
const treeAddr = extractTreeAddress(stripAnsi(stdout + '\n' + stderr))
if (!treeAddr) throw new Error('Could not create public tree')
publicTreeAddress = treeAddr
await new Promise(resolve => setTimeout(resolve, 2000))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Replace the new fixed sleeps with readiness checks.

The 2s waits after funding the payer and creating the tree slow every asset-signer run and still leave the suite timing-sensitive on slower CI/RPC. Waiting on observable chain state here will be faster and less flaky.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/commands/core/core.asset-signer.test.ts` around lines 97 - 111, The
fixed 2s sleeps after umi.rpc.airdrop and after creating the tree make tests
slow and flaky; replace them with readiness checks: after
umi.rpc.airdrop(newKp.publicKey, ...) poll the chain (e.g., via
umi.connection.getBalance or a waitForBalance helper) until the expected
lamports are present for newKp.publicKey instead of setTimeout, and after
running runCliDirect(['bg','tree','create',...]) use a polling check (e.g., call
getAccountInfo/getProgramAccounts or a waitForTree helper) against the tree
address returned by extractTreeAddress(stdout+stderr) until the tree account
exists/has expected state before assigning publicTreeAddress; keep timeouts and
retry intervals configurable and fail with a clear error if readiness isn't
reached in a reasonable timeout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant