You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The SDK has no rpc.multisigChangeThreshold, although the instruction and transaction builders exist (added in #99) and the other controlled-multisig config instructions have all three:
$ node -e 'const m = require("@sqds/multisig"); console.log(typeof m.rpc.multisigChangeThreshold, typeof m.rpc.multisigSetTimeLock, typeof m.transactions.multisigChangeThreshold)'
undefined function function # @sqds/multisig 2.1.4
So changing the threshold of a controlled multisig through the SDK means building, signing and sending the transaction by hand, unlike multisigSetTimeLock, multisigAddMember, multisigRemoveMember and the rest.
Also, transactions.multisigChangeThreshold declares a required spendingLimit: PublicKey parameter that it never uses, so callers have to pass a placeholder key.
Noted the same gap from the builder side. Question on the dead param: is spendingLimit in the transaction builder's signature just leftover from the other config builders, or does anything downstream (serializers, IDL consumers) depend on the parameter list matching across builders? If it is pure leftover, dropping it in the same change as the rpc wrapper saves a second breaking release.
@exocognosis It's a leftover. Nothing downstream depends on it.
transactions.multisigChangeThreshold never reads spendingLimit, so it never reaches the serializer. The instruction has no such account either: its accounts are multisig, configAuthority, rentPayer and systemProgram, in the IDL and in the program's MultisigConfig struct. The other config builders, such as multisigSetTimeLock and multisigAddMember, don't take it. The file looks copied from multisigRemoveSpendingLimit, which was added in the same change (#97).
Dropping it is a one-line change, but it breaks TypeScript callers at compile time. Today they all have to pass it, and an inline { ..., spendingLimit, ... } fails with TS2345 once the property is gone. JavaScript callers aren't affected. #204 makes it optional so it can ship without a breaking release. If the maintainers would rather remove it outright, I can change #204 to do that.
How I checked
On main at af94153 and on #204 at 61d8b53, with the SDK built from source.
Serialized bytes. Built the transaction with transactions.multisigChangeThreshold four times, changing only spendingLimit: two random keys, PublicKey.default, and no key. The four serialized transactions are byte-identical, and identical to one built from instructions.multisigChangeThreshold. The spendingLimit key is not among the transaction's 4 account keys. The instruction's keys match the IDL's accounts for multisigChangeThreshold.
Types. Compiled three callers with tsc 4.9.4 against the SDK's built .d.ts: an inline object that passes spendingLimit, a prebuilt args object that passes it, and an inline object that omits it.
Property removed: only the inline caller that passes it fails, with TS2345 ('spendingLimit' does not exist in type).
yarn ts in sdk/multisig passes in all three states.
On chain. Built the program with cargo build-sbf --features testing, loaded it at the test program id in solana-test-validator 3.1.10 with the Anchor.toml fixture, and ran mocha tests/index.ts on a fresh ledger each run. feat(sdk): add rpc.multisigChangeThreshold #204's new test changes the threshold of a controlled multisig with a transaction built without spendingLimit, and it passes.
The 3 failures expect Transaction signature verification failure, while Solana 3.1 reports Transaction did not pass signature verification. feat(sdk): add rpc.multisigChangeThreshold #204 does not change programs/.
Activity
exocognosis commentedon Oct 15, 2026
Noted the same gap from the builder side. Question on the dead param: is spendingLimit in the transaction builder's signature just leftover from the other config builders, or does anything downstream (serializers, IDL consumers) depend on the parameter list matching across builders? If it is pure leftover, dropping it in the same change as the rpc wrapper saves a second breaking release.
aelmanaa commentedon Oct 15, 2026
@exocognosis It's a leftover. Nothing downstream depends on it.
transactions.multisigChangeThresholdnever readsspendingLimit, so it never reaches the serializer. The instruction has no such account either: its accounts aremultisig,configAuthority,rentPayerandsystemProgram, in the IDL and in the program'sMultisigConfigstruct. The other config builders, such asmultisigSetTimeLockandmultisigAddMember, don't take it. The file looks copied frommultisigRemoveSpendingLimit, which was added in the same change (#97).Dropping it is a one-line change, but it breaks TypeScript callers at compile time. Today they all have to pass it, and an inline
{ ..., spendingLimit, ... }fails with TS2345 once the property is gone. JavaScript callers aren't affected. #204 makes it optional so it can ship without a breaking release. If the maintainers would rather remove it outright, I can change #204 to do that.How I checked
On
mainataf94153and on #204 at61d8b53, with the SDK built from source.Serialized bytes. Built the transaction with
transactions.multisigChangeThresholdfour times, changing onlyspendingLimit: two random keys,PublicKey.default, and no key. The four serialized transactions are byte-identical, and identical to one built frominstructions.multisigChangeThreshold. ThespendingLimitkey is not among the transaction's 4 account keys. The instruction's keys match the IDL's accounts formultisigChangeThreshold.Types. Compiled three callers with
tsc4.9.4 against the SDK's built.d.ts: an inline object that passesspendingLimit, a prebuilt args object that passes it, and an inline object that omits it.main: only the caller that omits it fails.'spendingLimit' does not exist in type).yarn tsinsdk/multisigpasses in all three states.On chain. Built the program with
cargo build-sbf --features testing, loaded it at the test program id insolana-test-validator3.1.10 with theAnchor.tomlfixture, and ranmocha tests/index.tson a fresh ledger each run. feat(sdk): add rpc.multisigChangeThreshold #204's new test changes the threshold of a controlled multisig with a transaction built withoutspendingLimit, and it passes.main: 160 passing, 12 pending, 3 failing.The 3 failures expect
Transaction signature verification failure, while Solana 3.1 reportsTransaction did not pass signature verification. feat(sdk): add rpc.multisigChangeThreshold #204 does not changeprograms/.