Skip to main content
The Rust SDK is stateless. It does not hold wallet state between calls. After create_wallet_account(), you receive two distinct pieces of state — each belongs in a different storage tier: Both must be persisted from creation. The SDK provides no compatibility shim — every subsequent operation requires WalletProperties explicitly, and operations without cached Vec<ServerKeyShare> (and without backup fallback) will fail.

Persisting WalletProperties

WalletProperties is non-sensitive identity + backup-pointer metadata. It’s serde::Serialize / Deserialize, so cache it like any other per-user record:
Cache the full struct. The external_server_key_shares_backup_info field on WalletProperties is not recoverable via SDK-scoped endpoints — fetch_wallet_metadata(account_address) returns identity only. Operations that need it (password verification, share recovery) will fail with Error::StaleWalletProperties if it’s missing.

Storing Vec<ServerKeyShare>

When you set back_up_to_dynamic: false during wallet creation, you are responsible for securely storing the Vec<ServerKeyShare> returned by create_wallet_account. These key shares, combined with your Dynamic developer API key, provide signing authority and must be protected with defense-in-depth strategies. ServerKeyShare is serde::Serialize / Deserialize — serialize to JSON or your vault’s native format before persisting.
Use the google-cloud-secretmanager crate (or gcloud-sdk) — same pattern as AWS KMS, integrated with Google Cloud’s IAM and audit logging.
Use the azure_security_keyvault crate — Azure-managed secrets with Managed Identity auth.
Use the vaultrs crate to read/write secrets to a Vault KV mount. Works well if your stack already runs Vault.

Security Requirements Checklist

Regardless of your storage method, follow these requirements:
  • Never log plaintext key shares — redact external_server_key_shares from all logs, error messages, and monitoring. The SDK’s tracing instrumentation already skips these args; do the same in your own code.
  • Encrypt at rest — use AES-256-GCM or equivalent; ensure database/storage has encryption enabled
  • Encrypt in transit — all communication must use TLS 1.3
  • Implement access controls — restrict which services and roles can decrypt key shares
  • Enable audit logging — track all access to encrypted materials with timestamps and actor identity
  • Separate encryption keys — don’t reuse keys across environments (dev/staging/prod)
  • Use unique encryption per record — generate new IVs for each encryption operation
  • Implement key rotation — rotate encryption keys periodically (e.g., every 90 days)
  • Plan for key compromise — document incident response for key material exposure
  • Secure deletionzeroize::Zeroize your decrypted shares after use

Storage Schema Example

What NOT to Do

  • Never store plaintext key shares in databases, files, or environment variables
  • Never commit encryption keys or key shares to version control
  • Never use the same encryption key across all wallets
  • Never rely solely on database encryption without application-level encryption
  • Never expose key shares through APIs or logs
Last modified on May 19, 2026