Repository navigation
feat(cli,sdk): authorization lock commands and helpers - #240
Conversation
00a1dac to
3f8bdcb
Compare
SDK: - add_sol_authorization_lock / add_token_authorization_lock helpers that resolve the wallet address or its ATA (SPL Token or Token-2022) - get_active_authorization_locks - display_swig shows ManageAuthorizationLocks and stored locks CLI: - add-authorization-lock, remove-authorization-lock and list-authorization-locks commands - manageAuthorizationLocks permission JSON and RemoveActionsByType support - interactive "Authorization Locks" menu and permission option - stop splitting --permissions on commas, which broke any permission JSON with more than one field Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3f8bdcb to
c5edad6
Compare
edo-chan
left a comment
There was a problem hiding this comment.
Approved with the inline NIT on lock ID correlation.
| let lock_id = wallet | ||
| .get_authorization_locks()? | ||
| .iter() | ||
| .filter(|lock| lock.role_id == role_id && lock.expiry_slot == expiry_slot) |
There was a problem hiding this comment.
[NIT] Could the create call expose a transaction-correlated lock_id and have the CLI use it instead of selecting the highest ID with the same role and expiry? If two similar holds confirm before this read, the earlier command can print the later hold's ID, making capture or release ambiguous.
ProgramExecClientRole now builds AddAuthorizationLockV1 and RemoveAuthorizationLockV1 with the new ProgramExec interface builders, so SwigWallet's lock helpers work with a ProgramExec role. The CLI only uses the wallet helpers, so the new account order needs no CLI changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follows the authlock-v3 change: other roles are held off a lock, the holder spends and captures it, and fully captured locks (amount 0) are inactive until pruned. The CLI and wallet displays show them as "fully captured", and an SDK test covers capture, the active filter, and pruning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`swig remove-authority --remove-authority <PUBKEY>` handed the string's raw bytes (44 base58 characters) to `remove_authority`, which looks roles up by their decoded key bytes, so it always reported the authority as not found. It now decodes the value the same way add-authority does: a base58 pubkey for Ed25519 roles, or a hex public key with the new `--remove-authority-type` for Secp256k1/Secp256r1 roles. The README showed the flag as `--authority` (the signing authority) and now shows `--remove-authority`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k-v3-cli-sdk Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
edo-chan
left a comment
There was a problem hiding this comment.
Approved the final head after independent review and green CI against main. The CLI/SDK diff is unchanged from the reviewed implementation. Standard 948, ProgramScope 266, SDK 416 (3 existing skips), and stake 957 passed. Parent #226 is merged; the accepted lock-ID NIT and unchanged CLI reporting/initialization follow-ups remain separate.
Final merge validation (2026-11-05): base
f9b14b769e73171d9c5a330d7952e0b50f741588, head499be63296a9ae5c2df360fe369c116db62c87b7. Retargeted to main after #226 merged. The CLI/SDK diff is unchanged from the independently reviewed implementation; the ancestry update changes no files.Final-head CI passed: standard 948, ProgramScope 266, SDK 416 (3 existing skips), stake 957. SBF/release builds, lint, release CLI and Test Results passed. Independent review passed; local CLI units: 2 passed; SDK test target compiled; formatting/diff checks passed.
The accepted lock-ID correlation NIT remains a follow-up. Review also recorded the unchanged CLI policies where listing may initialize a missing wallet and a post-confirmation read can fail before printing the add receipt; this merge does not claim to fix those behaviors.
Adds client support for authorization locks from merged #226.
Lock semantics (from #226)
Locks are card authorization holds. Other roles,
Allincluded, can spend only the balance minus the locks they don't hold. The holder can spend its held funds, and each SignV2 it signs lowers ("captures") its locks on the account by the net outflow, oldest first. A lock captured to 0 stays stored withamount == 0, is inactive, and can be pruned. Limits are charged on spend, not at lock time. For clients this means a lock'samountis what is still reserved and goes down over time, and a fully captured lock remains listed until it is removed.SDK (
swig-sdk)add_sol_authorization_lock(amount, expiry_slot)locks the wallet's SOL.add_token_authorization_lock(mint, amount, expiry_slot)locks the wallet's ATA formint. It reads the mint's owner to pick SPL Token or Token-2022.get_active_authorization_locks()returns only the locks that still bind: unexpired and not fully captured.get_authorization_locks()returns every stored lock, including expired and fully captured (amount == 0) ones.display_swignow shows theManageAuthorizationLockspermission (with its max duration) and an AUTHORIZATION LOCKS section, where each lock's status is active, expired or fully captured.ProgramExecClientRolenow supportsadd_authorization_lock_instructionandremove_authorization_lock_instruction, so the wallet lock helpers work with a ProgramExec role. This relies on feat: authorization locks (supersedes #132) #226's new lock account order (swig, wallet address, payer, system program, ...), which lets ProgramExec bind to the config and wallet address. Every remove builder now takes the wallet address, andSwigInstructionBuilderderives it for you.CLI
add-authorization-lock(--amount, optional--mint, and either--expiry-slotor--duration-slots),remove-authorization-lock --lock-id, andlist-authorization-locks [--all]. All new flags are long-only (see below).{"type":"manageAuthorizationLocks","maxDurationSlots":N}, andManageAuthorizationLocksforupdate-authority --operation RemoveActionsByType.--permissionsno longer splits on,. Splitting broke every permission JSON with more than one field (e.g.{"type":"sol","amount":1}). To pass several permissions, repeat the flag.list-authorization-locksshows the remaining (uncaptured) amount and marks captured locks as "fully captured".--allincludes expired and fully captured locks.remove-authority --remove-authority <PUBKEY>passed the base58 string's raw bytes toremove_authority, so it always reported "Authority not found". It now decodes the key asadd-authoritydoes: base58 for Ed25519 roles, or a hex public key with the new--remove-authority-type Secp256k1|Secp256r1. Unit tests cover both. The README showed the flag as--authority(the signing authority) and now shows--remove-authority.Merged with main's security sync
71d4af7merges the updated #226, which now includes main throughe17b7ca(the #245 security-review backports). The merge into this branch was clean with no SDK or CLI changes needed. Local results with the pinned verifiable build: standard 934/934, program_scope_test 255/255, rust_sdk_test 405 passed (3 skipped).Testing
4628591(in-place lock tail edits and compute tables; no client-visible change): standard 886/886, program_scope_test 229/229, and rust_sdk_test+program_scope_test 379 passed, 3 skipped. This still includes RemoveAuthority pruning a removed role's inactive lock records, soremove_authorityalso clears them fromget_authorization_locks().should_lock_sol_and_tokens_through_convenience_helperscovers the SOL and token helpers and the active-lock filter. New testtest_program_exec_adds_and_removes_authorization_locksadds and removes a SOL lock through a ProgramExec role. The fullswig-sdksuite passes withrust_sdk_test(151 passed, 3 skipped). After merging the updated feat: authorization locks (supersedes #132) #226: standard 854/854, program_scope_test 224/224, rust_sdk_test+program_scope_test 373 passed, 3 skipped.solana-test-validatorwith the release CLI:manageAuthorizationLocks(500 slots) and a 2 SOL limitInvalidAuthorizationLockExpiry(0x52)AuthorizationLockExceedsSpendLimit(0x55)AuthorizationLockNotOwner(0x57)ManageAuthorizationLockssucceeds, and the delegate can still release its lock afterwards--mintis created, and a second lock beyond the balance is rejected withAuthorizationLockExceedsBalance(0x54)viewshows the lock sectionExisting CLI bugs found (not fixed here)
-atoauthority_type,authorityandauthority_kp, so clap's debug asserts panic in debug builds (e.g.swig-cli balance --help). Release builds work. The new commands use long-only flags so they aren't affected.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.