LogoLogo
SupportGithubSign InGet Access
  • Introduction
  • GETTING STARTED
    • SDK Quick Start
    • API Quick Start
  • Guides
    • Web
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Web authentication methods
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Configure a custom subdomain
      • Eject a wallet
      • Using the EIP-1193 Provider
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • iOS
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Manage ERC20 tokens
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
          • Passkey + Enclave Storage
        • Recover a wallet
      • Troubleshooting Tips
      • Feature Flags
    • Android
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • React Native
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • Enclave MPC API
      • Create a client
      • Create a wallet
      • Send tokens
      • Sign Ethereum transactions
      • Sign Solana transactions
      • Sign Tron transactions
      • Sign Stellar Transaction
      • Concurrent Transactions
      • Back up a wallet
      • Eject a wallet
  • Reference
    • iOS
      • createWallet
      • backupWallet
      • recoverWallet
      • ejectPrivateKeys
      • registerBackupMethod
      • setGDriveConfiguration
      • setPasskeyConfiguration
      • setPasskeyAuthenticationAnchor
      • setPassword
      • availableRecoveryMethods
      • doesWalletExist
      • isWalletBackedUp
      • isWalletOnDevice
      • isWalletRecoverable
      • getBalances
      • getAssets
      • getNftAssets
      • getTransactions
      • sendSol
      • evaluateTransaction
      • buildEip155Transaction
      • buildSolanaTransaction
      • getWalletCapabilities
    • Android
      • Reference Documentation
    • React Native
      • @portal-hq/core
      • Storage adapters
        • Cloud storage
          • @portal-hq/gdrive-storage
          • @portal-hq/icloud-storage
        • Mobile storage
          • @portal-hq/keychain
          • @portal-hq/mobile-key-values
    • Enclave MPC API
      • V1 endpoints
    • Client API
      • V3 endpoints
      • V1 endpoints
    • Custodian API
      • V3 endpoints
      • V1 endpoints
    • Swaps API
      • V3 endpoints
      • V1 endpoints
  • Resources
    • Flutter
      • iOS
      • Android
    • Error codes
      • Overview
      • MPC errors
      • Network errors
      • General errors
      • Encryption errors
      • Portal Connect errors
    • Portal's MPC architecture
    • Authentication and API Keys
    • Self-Managed Backups
    • Alert Webhooks
    • Wallet lifecycle
    • Backup options
      • Password/PIN
      • GDrive
      • iCloud
      • Passkey + Enclave
    • WalletConnect metadata
    • Advanced security scanning
    • Account abstraction
    • Security firewall
    • Eject
    • Security
    • Blockchain support
    • Chain ID formatting
    • Testnet faucets
    • Going to Production
    • Rate Limits
    • Multi-backup migration guide
    • Multi-wallet migration guides
      • Migrating from Android SDK v3.x.x to v4.x.x
      • Migrating from iOS SDK v3.0.x to v3.2.x
  • Support
    • Changelog
      • Android
      • iOS
      • React Native
      • Web
      • Past Releases
        • 2024 Releases
        • 2023 Releases
    • Celo Hackathon Hub
    • Glossary
Powered by GitBook
On this page
  • Portal-Managed Backups
  • Self-Managed Backups
  • Implementing Backup

Was this helpful?

  1. Guides
  2. Enclave MPC API

Back up a wallet

This guide will walk you through how to create a backup of a Portal client's wallet using the Enclave MPC API.

PreviousConcurrent TransactionsNextEject a wallet

Last updated 28 days ago

Was this helpful?

Portal lets you securely back up your MPC wallets in order to recover them even if the signing share pairs are lost or damaged.

There are two configurations you can choose from when running backup: Portal-Managed Backups or Self-Managed Backups which alter where backup shares are stored.

Portal-Managed Backups

With Portal-Managed Backups, Portal will store the Custodian Backup Shares on our backend leaving the storage of the Client Backup Shares up to your application.

This means you do not need to build and maintain a webhook server that accepts Custodian Backup Shares from Portal.

The benefit of Portal-Managed Backups is that there is less integration work required. The tradeoff is that you are dependent on Portal for running backup & recovery.

When using Portal-Managed Backups with the Enclave MPC API you will save the Client Backup Share in your backend. Be sure to store the shares in a way that makes them resilient to failure scenarios of your Client Signing Shares.

This implementation means that for recovery or eject you will retrieve the Client Backup Share from your own backend while requesting the Custodian Backup Share from Portal.

Self-Managed Backups

With Self-Managed Backups, Portal will send the Custodian Backup Shares to a webhook server you're required to deploy and maintain while your application is responsible for storing the Client Backup Share.

See our guide for more details on implementation.

Implementing Backup

While using the SDKs provides 4 built in backup methods: GDrive, iCloud, Password/PIN, and Passkeys. However, when using the Enclave MPC API your application is responsible for its own backup method.

We recommend using a Key Management Service (KMS) like those in and paired with using AES 256 in GCM.

Example

// Step 1. Run backup by passing in the response from generate (the signing shares)
const backupResponse = await axios.post(
  `https://mpc-client.portalhq.io/v1/backup`,
  {
    generateResponse: JSON.stringify(signingShares),
  },
  {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${clientApiKey}`,
    },
  },
);
  
const { secp256k1Share, ed25519Share } = backupResponse.data;

// Step 2. Encrypt the client backup shares
const secp256k1Ciphertext = await YourEnvelopEncryptionService.encrypt(secp256k1Share)
const ed25519Ciphertext = await YourEnvelopEncryptionService.encrypt(ed25519Share)

// Step 3. Store the client ciphertexts with Portal or your backend [OPTIONAL]
await axios.post(
    `https://api.portalhq.io/api/v3/clients/me/backup-share-pairs/${secp256k1Share.id}`,
    {
      clientCipherText: secp256k1Ciphertext,
    },
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${clientApiKey}`,
      },
    },
  );
  
await axios.post(
     `https://api.portalhq.io/api/v3/clients/me/backup-share-pairs/${ed25519Share.id}`,
    {
      clientCipherText: ed25519Ciphertext,
    },
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${clientApiKey}`,
      },
    },
  );

// Step 4. Mark the backup process as complete by updating the backup share pairs status
await axios.patch(
  `https://api.portalhq.io/api/v3/clients/me/backup-share-pairs`,
  {
    status: 'STORED_CLIENT_BACKUP_SHARE',
    backupSharePairIds: [secp256k1Share.id, ed25519Share.id],
  },
  {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${clientApiKey}`,
    },
  },
);
// Step 1. Run backup by passing in the response from generate (the signing shares)
const backupResponse = await axios.post(
  `https://mpc-client.portalhq.io/v1/backup`,
  {
    generateResponse: JSON.stringify(signingShares),
  },
  {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${clientApiKey}`,
    },
  },
);
  
const { secp256k1Share, ed25519Share } = backupResponse.data;

// Step 2. Encrypt the client backup shares
const secp256k1Ciphertext = await YourEnvelopEncryptionService.encrypt(secp256k1Share)
const ed25519Ciphertext = await YourEnvelopEncryptionService.encrypt(ed25519Share)

// Step 3. Store the client ciphertexts on your own backend
await axios.post('{your_server}/users/[userId]/user-backup-share', {
  data: { secp256k1Ciphertext, ed25519Ciphertext }
})

// Step 4. Mark the backup process as complete by updating the backup share pairs status
await axios.patch(
  `https://api.portalhq.io/api/v3/clients/me/backup-share-pairs`,
  {
    status: 'STORED_CLIENT_BACKUP_SHARE',
    backupSharePairIds: [secp256k1Share.id, ed25519Share.id],
  },
  {
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${clientApiKey}`,
    },
  },
);
Self-Managed Backups
Google Cloud
AWS
envelope encryption