Part of #4014.
Final, riskiest phase: migrate smartcontract/sdk/rs/src/commands/* to delegate to the pure builders so there is a single source of truth for account ordering.
Scope
- Add to the
DoubleZeroClient trait: send_transaction(Instruction) -> Result<Signature> (+ quiet variant). The permission cache (note_transaction_sent/invalidation) stays; since migrated builders derive the Permission PDA from the payer internally, the command layer no longer resolves or passes a permission pubkey.
client.rs::assemble_instructions stops appending payer/system (now in common::build); it only prepends the compute-budget prelude over a pre-built Instruction.
- Rewrite each
execute() to: validate → resolve RPC values → call the builder → send_transaction(ix).
- Add the
solana-program-test integration suite in programs/doublezero-serviceability/tests/: for each buildable variant, build via the builder and run against the real in-process program (catches account-order drift automatically).
Permission-rollout sequencing
- The builders' Permission-account append is deferred (ships commented out) until each instruction's
authorize() migration is activated. A migrated-but-not-activated builder therefore emits a shorter account list, and authorize() takes its no-permission path (legacy GlobalState allowlist) until the append is re-enabled.
- Activation of the per-instruction append must be sequenced against the permission-model rollout so no caller loses authorization mid-transition.
Acceptance
- No behavior change on the wire for the tag, borsh args, and instruction-specific account order (verified by existing command tests, now asserting on the built
Instruction, and by the program-test suite). The only intended moving part is the deferred Permission-account append.
- Only one place appends payer/system after this PR.
- May exceed the ~500-line norm; split per-domain if needed and note it in the PR.
Part of #4014.
Final, riskiest phase: migrate
smartcontract/sdk/rs/src/commands/*to delegate to the pure builders so there is a single source of truth for account ordering.Scope
DoubleZeroClienttrait:send_transaction(Instruction) -> Result<Signature>(+ quiet variant). The permission cache (note_transaction_sent/invalidation) stays; since migrated builders derive the Permission PDA from the payer internally, the command layer no longer resolves or passes a permission pubkey.client.rs::assemble_instructionsstops appending payer/system (now incommon::build); it only prepends the compute-budget prelude over a pre-builtInstruction.execute()to: validate → resolve RPC values → call the builder →send_transaction(ix).solana-program-testintegration suite inprograms/doublezero-serviceability/tests/: for each buildable variant, build via the builder and run against the real in-process program (catches account-order drift automatically).Permission-rollout sequencing
authorize()migration is activated. A migrated-but-not-activated builder therefore emits a shorter account list, andauthorize()takes its no-permission path (legacy GlobalState allowlist) until the append is re-enabled.Acceptance
Instruction, and by the program-test suite). The only intended moving part is the deferred Permission-account append.