The ECDSA signer uses the Ownable Validator module to authorise transactions with standard Ethereum key pairs. It supports both single-owner and multisig (n/m threshold) configurations on the same account.
Single owner
To create an account owned by a single ECDSA key:
import { RhinestoneSDK } from '@rhinestone/sdk'
import { privateKeyToAccount } from 'viem/accounts'
const signer = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
const rhinestone = new RhinestoneSDK({
apiKey: process.env.RHINESTONE_API_KEY as string,
})
const account = await rhinestone.createAccount({
owners: {
type: 'ecdsa',
accounts: [signer],
},
})
Multisig
The Ownable Validator supports n/m multisig with multiple owners and a configurable signature threshold. This is useful for shared accounts, treasury management, or any scenario where unilateral control is a risk.
Setup
Pass multiple accounts and set a threshold. The threshold defines how many signatures are required to authorise a transaction.
const account = await rhinestone.createAccount({
owners: {
type: 'ecdsa',
accounts: [signerA, signerB, signerC],
threshold: 2, // 2-of-3
},
})
By default, threshold is 1, meaning any single owner can sign.
Signing with a subset of owners
For m-of-n setups, specify which signers to use when sending a transaction:
const result = await account.sendTransaction({
chain,
calls: [
// …
],
signers: {
type: 'owner',
kind: 'ecdsa',
accounts: [signerA, signerB],
},
})
Provide at least as many signers as the threshold requires, or the transaction will fail validation.
Add a signer
import { addOwner } from '@rhinestone/sdk/actions/ecdsa'
await account.sendTransaction({
chain,
calls: [addOwner(newSigner.address)],
})
Remove a signer
import { removeOwner } from '@rhinestone/sdk/actions/ecdsa'
await account.sendTransaction({
chain,
calls: [removeOwner(signerC.address)],
})
Change threshold
import { changeThreshold } from '@rhinestone/sdk/actions/ecdsa'
await account.sendTransaction({
chain,
calls: [changeThreshold(2)],
})
Get current owners
const owners = await account.getOwners(chain)
// → { accounts: ['0xaaa…', '0xbbb…', '0xccc…'], threshold: 2 }
Enable in a separate transaction
If you need to enable the ECDSA module on an existing account rather than at creation time:
import { enable as enableEcdsa } from '@rhinestone/sdk/actions/ecdsa'
await account.sendTransaction({
chain,
calls: [enableEcdsa([signer.address])],
tokenRequests: [],
})