UNPKG

accounts

Version:

Tempo Accounts SDK

85 lines 3.27 kB
import { persist } from 'zustand/middleware'; import { subscribeWithSelector } from 'zustand/middleware'; import { createStore } from 'zustand/vanilla'; import * as Storage from './Storage.js'; /** * Creates a Zustand vanilla store with `subscribeWithSelector` and `persist` middleware. */ export function create(options) { const { chainId, maxAccounts, persistCredentials = true, storage = typeof window !== 'undefined' ? Storage.idb({ key: 'tempo' }) : Storage.memory({ key: 'tempo' }), } = options; return createStore(subscribeWithSelector(persist(() => ({ accessKeys: [], accounts: [], activeAccount: 0, chainId, requestQueue: [], }), { merge: hydrate, name: 'store', partialize: (state) => serialize(state, { maxAccounts, persistCredentials }), storage, version: 0, }))); } /** Converts runtime provider state into the persisted refresh snapshot. */ export function serialize(state, options = {}) { const { maxAccounts, persistCredentials = true } = options; const accounts = maxAccounts && state.accounts.length > maxAccounts ? state.accounts.slice(0, maxAccounts) : state.accounts; return { accounts, activeAccount: state.activeAccount, ...(persistCredentials ? { accessKeys: state.accessKeys } : {}), ...(state.auth ? { auth: state.auth } : {}), chainId: state.chainId, }; } /** Restores runtime provider state from a persisted refresh snapshot. */ export function hydrate(persisted, current) { const state = persisted && typeof persisted === 'object' ? persisted : {}; return { ...state, ...current, // Preserve in-memory credentials when persisted accounts only have addresses. accounts: state.accounts?.map((persisted) => { const account = current.accounts.find((a) => a.address.toLowerCase() === persisted.address.toLowerCase()); return account ?? persisted; }) ?? current.accounts, accessKeys: normalizeAccessKeys(state.accessKeys) ?? current.accessKeys, chainId: state.chainId ?? current.chainId, }; } function normalizeAccessKeys(accessKeys) { if (!accessKeys) return undefined; return accessKeys.filter((key) => { if (!key || typeof key !== 'object') return false; const value = key; return (typeof value.access === 'string' && typeof value.address === 'string' && typeof value.chainId === 'number' && (value.keyType === 'secp256k1' || value.keyType === 'p256' || value.keyType === 'webAuthn' || value.keyType === 'webCrypto')); }); } /** * Waits for the store to finish hydrating from storage. * * Returns immediately if the store has already hydrated. Otherwise, waits * for the `onFinishHydration` callback with a 100ms safety timeout fallback. */ export async function waitForHydration(store) { if (store.persist.hasHydrated()) return; await new Promise((resolve) => { store.persist.onFinishHydration(() => resolve()); setTimeout(() => resolve(), 100); }); } //# sourceMappingURL=Store.js.map