dWallets
The on-chain unit of ownership in mpckit, and the local state you have to keep alongside it.
A dWallet is an MPC-key-pair anchored on Sui. The public key (and the addresses it derives) lives on chain; the secret has been split at DKG time between two parties and never reassembled.
The DWallet record
api.getDWallet(id) returns the DWallet shape exported from
@mpckit/sdk:
Prop
Type
The Sui record at suiDwalletId is the source of truth. The backend
row mirrors it for fast reads. You can read the on-chain state
directly via the SDK's lazy IkaClient if you need to bypass the
cache.
Zero-trust vs shared
Every dWallet has a kind:
zero_trust: the user share lives client-side, encrypted under a class-groups key derived from your seed. The high-levelonboardproduces this kind.shared: the user share is also escrowed on the network for multi-party scenarios. v1 of@mpckit/sdkexposes only zero-trust; shared support lands later.
For both kinds, the network share is held by ika validators and gated by the on-chain encryption key.
Lifecycle
A dWallet moves through status values in order:
submitting
The SDK has just posted the DKG message; the on-chain submission is in flight.
awaiting_user_share
The on-chain DKG completed. The user share is encrypted client-side and
needs to be accepted on chain. onboard polls for this state, then
finalizes.
active
The dWallet is signable. Both dkgTxDigest and acceptTxDigest are set.
failed
The DKG or accept call failed. Inspect the on-chain state for the cause.
What lives where
| Where | What |
|---|---|
| Sui (on chain) | dWallet record, encryption key public component, EncryptedUserSecretKeyShare, DKG tx, accept tx |
| Backend | DWallet row mirroring on-chain state, billing rows |
| Your storage | The seed (must keep). Optionally: userSecretKeyShareHex cache, userPublicOutputHex cache |
The split matters. mpckit can be down and your dWallets are still
recoverable from the chain, as long as you have the seed: the SDK
reads the encrypted share from Sui and decrypts it with the
seed-derived decryption key. The plaintext share you got from
onboard is a convenience cache, not a backup.
Listing & fetching
const { dwallets } = await api.listDWallets();
const { dwallet } = await api.getDWallet(dwallets[0].id);Both calls are simple HTTP reads against the backend's mirror of Sui
state. Use MPCKit.raw.get(...) if you want to call the backend
directly.