Packages: core (BIP39/32/44/49/84/86 derivation, WIF), keystore (PBKDF2 + AES-GCM), psbt, p2p (BIP157/158 SPV daemon, Dandelion++ broadcast with relay-echo verification), blockbook, rpc, electrum, net, bns, web-ui (React/Vite), mobile (Expo). ops/ holds the nginx vhost, systemd unit and push.sh deploy script for digibyte.x/web.
51 lines
2.3 KiB
TypeScript
51 lines
2.3 KiB
TypeScript
// Storage adapter — an intentionally tiny surface so we can plug in
|
|
// whatever the host platform gives us for at-rest bytes:
|
|
// - browser → LocalStorageAdapter (uses window.localStorage)
|
|
// - RN → SecureStoreAdapter (expo-secure-store, wired later)
|
|
// - Node/CLI → NodeFsAdapter (writes JSON files under a dir)
|
|
// - tests → InMemoryAdapter (Map-backed)
|
|
//
|
|
// The keystore itself doesn't care which one it got — it just persists
|
|
// EncryptedBlob JSON strings keyed by user-chosen label.
|
|
|
|
export interface StorageAdapter {
|
|
readonly name: string;
|
|
get(key: string): Promise<string | null>;
|
|
put(key: string, value: string): Promise<void>;
|
|
delete(key: string): Promise<void>;
|
|
list(prefix?: string): Promise<string[]>;
|
|
}
|
|
|
|
// Pure in-memory adapter, for tests and CLIs that don't want to touch
|
|
// disk. Also useful as a default when a platform adapter isn't ready.
|
|
export class InMemoryAdapter implements StorageAdapter {
|
|
readonly name = 'memory';
|
|
private readonly map = new Map<string, string>();
|
|
async get(key: string): Promise<string | null> { return this.map.get(key) ?? null; }
|
|
async put(key: string, value: string): Promise<void> { this.map.set(key, value); }
|
|
async delete(key: string): Promise<void> { this.map.delete(key); }
|
|
async list(prefix = ''): Promise<string[]> {
|
|
return [...this.map.keys()].filter((k) => k.startsWith(prefix));
|
|
}
|
|
}
|
|
|
|
// Browser adapter over window.localStorage. Synchronous under the hood
|
|
// but we present the async interface so consumers can swap in a real
|
|
// async backend (IndexedDB, expo-secure-store) without rewrites.
|
|
export class LocalStorageAdapter implements StorageAdapter {
|
|
readonly name = 'localStorage';
|
|
constructor(private readonly ls: Storage = globalThis.localStorage) {
|
|
if (!this.ls) throw new Error('LocalStorageAdapter: no localStorage available in this environment');
|
|
}
|
|
async get(key: string): Promise<string | null> { return this.ls.getItem(key); }
|
|
async put(key: string, value: string): Promise<void> { this.ls.setItem(key, value); }
|
|
async delete(key: string): Promise<void> { this.ls.removeItem(key); }
|
|
async list(prefix = ''): Promise<string[]> {
|
|
const out: string[] = [];
|
|
for (let i = 0; i < this.ls.length; i++) {
|
|
const k = this.ls.key(i);
|
|
if (k && k.startsWith(prefix)) out.push(k);
|
|
}
|
|
return out;
|
|
}
|
|
}
|