Skip to main content
The @portal-hq/firebase-storage package provides FirebaseStorage, a Portal Storage adapter that stores and retrieves backup encryption material using Firebase ID tokens. Requests are made to Portal’s token backup service (TBS); the Portal Client API key and Firebase ID token are sent so the backend can authenticate your app and the signed-in Firebase user, consistent with native iOS and Android Firebase backup behavior.

Installation

npm install @portal-hq/firebase-storage
# or
yarn add @portal-hq/firebase-storage
You also need a configured Firebase project and a supported Firebase Auth integration (for example @react-native-firebase/auth) so getToken can obtain ID tokens for the current user.

The FirebaseStorage class

FirebaseStorage implements the Portal Storage contract from @portal-hq/utils. Portal injects its API client on the instance when you construct Portal (adapter.api = portal.api), which supplies the Client API key used in TBS requests.

Class definition

export class FirebaseStorage implements Storage

Constructor

constructor(opts: FirebaseStorageOptions)

FirebaseStorageOptions

PropertyTypeRequiredDefaultDescription
getToken(options?: { forceRefresh?: boolean }) => Promise<string | null>Yes-Returns a Firebase ID token for the signed-in user, or null if there is no user. Should call your Auth SDK’s token API (for example User#getIdToken). When options?.forceRefresh is true, request a refreshed token (used internally after a 401 from TBS).
tbsHoststringNo'backup.web.portalhq.io'Hostname or URL for the token backup service. Trailing slashes are stripped; localhost uses http, otherwise https is assumed if no scheme is present.
import { FirebaseStorage } from '@portal-hq/firebase-storage'
import auth from '@react-native-firebase/auth'

const firebaseStorage = new FirebaseStorage({
  getToken: async (options?: { forceRefresh?: boolean }) => {
    const user = auth().currentUser

    if (!user) {
      return null
    }

    return user.getIdToken(Boolean(options?.forceRefresh))
  },
})

The getToken callback

Portal invokes getToken before TBS traffic (including validateOperations). Implement it by delegating to Firebase Auth’s ID token API.
  • options.forceRefresh: When true, obtain a new token from Firebase (for example getIdToken(true)). The adapter sets this on the retry path after an unauthorized (401) response so a stale token can be replaced.
  • Return null: If there is no signed-in Firebase user, return null. Backup and recovery operations will fail until the user signs in and tokens are available.
Firebase ID tokens identify the end user to Portal’s backend for this backup method; they are sent as the X-Firebase-Token header together with the Portal Client API key (Authorization: Bearer … from the configured IPortalApi).

When no Firebase user is signed in

If getToken resolves to null, FirebaseStorage throws standard Error instances, including:
  • Firebase token is not available — Initial read/write/validate when no token could be obtained (for example no currentUser).
  • Firebase token is not available. Ensure Firebase Auth is initialized and user is signed in. — From validateOperations() when the token is missing.
  • Firebase token refresh failed — After a 401, the adapter retries once with getToken({ forceRefresh: true }); if that still yields null, this message is thrown.
If the storage instance is not wired into Portal, you may also see Portal API not configured when api has not been set (normally Portal sets this for adapters listed under backup). Other HTTP failures surface as messages such as Firebase account does not match this client (403), No encryption key found for Firebase backup method (404), TBS error <status>: …, or a timeout error if the request exceeds 30 seconds. delete() is not supported for this method; calling it throws Firebase backups cannot be deleted.

Portal integration

Pass the adapter on the firebase key of BackupOptions and use BackupMethods.Firebase with backupWallet and recoverWallet. For cloud-style Firebase backup, pass an empty ciphertext string for recoverWallet, matching other cloud backups in the React Native SDK.
import { BackupMethods, Portal } from '@portal-hq/core'
import { FirebaseStorage } from '@portal-hq/firebase-storage'
import auth from '@react-native-firebase/auth'

const firebaseStorage = new FirebaseStorage({
  getToken: async (options?: { forceRefresh?: boolean }) => {
    const user = auth().currentUser

    if (!user) {
      return null
    }

    return user.getIdToken(Boolean(options?.forceRefresh))
  },
})

const portal = new Portal({
  apiKey: 'YOUR_PORTAL_CLIENT_API_KEY',
  backup: {
    firebase: firebaseStorage,
  },
  gatewayConfig: 'https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
})

Backup

const cipherText = await portal.backupWallet(BackupMethods.Firebase)

Recovery

const addresses = await portal.recoverWallet('', BackupMethods.Firebase)