Get started with a multisig Safe
Install Safe beta.1 and connect a seed-derived owner to an existing Safe.
Install the package, configure the account, then inspect its identity. See Need Help for support.
Prerequisites: Node.js with ESM, npm, an existing Safe using modules 0.2.0, its owner seed, and matching RPC, EntryPoint v0.6 bundler and coordinator. This example uses native gas mode; the Safe needs native funds before execution. Store seeds outside source code and logs.
Install the Package
Install the exact package used by this guide:
npm install --save-exact @tetherto/wdk-wallet-multisig-safe@1.0.0-beta.1Configure the Account
- Supply the RPC, chain ID, bundler URL, Safe address and Safe Transaction Service proxy URL through your application configuration.
- Load the owner's seed from secret storage. The environment variable below is a Node example, not a requirement to store browser secrets in environment files.
- Create a
WalletManagerMultisigSafeand derive the known owner path.
Save this setup as safe-account.mjs; subsequent guides import its account and configuration:
import WalletManagerMultisigSafe from '@tetherto/wdk-wallet-multisig-safe'
export function requiredEnv(name) {
const value = process.env[name]
if (!value) throw new Error(`Missing ${name}`)
return value
}
export const config = {
provider: requiredEnv('EVM_RPC_URL'),
chainId: BigInt(requiredEnv('CHAIN_ID')),
bundlerUrl: requiredEnv('BUNDLER_URL'),
txServiceUrl: requiredEnv('SAFE_TX_SERVICE_URL'),
safeModulesVersion: '0.2.0',
safeOptions: { safeAddress: requiredEnv('SAFE_ADDRESS') },
useNativeCoins: true
}
export const wallet = new WalletManagerMultisigSafe(
requiredEnv('WDK_SEED_PHRASE'), config
)
export const account = await wallet.getAccountByPath("0'/0/0")The full owner path is m/44'/60'/0'/0/0. Change the relative path if the Safe's owner uses a different one. Deriving an account does not add that address as a Safe owner.
Inspect Its Identity
Use getAddress() and getSignerAddress() to distinguish the asset-holding Safe from its owner:
import { account } from './safe-account.mjs'
console.log('Safe:', await account.getAddress())
console.log('Owner EOA:', await account.getSignerAddress())Before signing, check getMultisigInfo() and validateSignerIsOwner():
console.log(await account.getMultisigInfo())
await account.validateSignerIsOwner()The expected result is your agreed Safe address, owner EOA, owner list and threshold. Stop if any differ. Continue with proposal management.