UNPKG

@bsv/wallet-toolbox

Version:

BRC100 conforming wallet, wallet storage and wallet signer components

216 lines (180 loc) 7.73 kB
import { verifyOne, verifyOneOrNone, verifyTruthy, wait, Wallet, WalletStorageManager } from '../../../src/index.client' import { StorageKnex } from '../../../src/storage/StorageKnex' import { _tu, logger, TestWalletNoSetup } from '../../utils/TestUtilsWalletStorage' describe('Wallet sync tests', () => { jest.setTimeout(99999999) const env = _tu.getEnvFlags('test') beforeAll(async () => {}) afterAll(async () => {}) test('0 syncToWriter initial-no changes-1 change', async () => { const { identityKey, storage: storageManager, activeStorage: storage } = await _tu.createLegacyWalletSQLiteCopy('walletSyncTest1aSource') const localSQLiteFile = await _tu.newTmpFile('walleltSyncTest0tmp.sqlite', true, false, false) const knexSQLite = _tu.createLocalSQLite(localSQLiteFile) const tmpStore = new StorageKnex({ ...StorageKnex.defaultOptions(), chain: env.chain, knex: knexSQLite }) //await tmpStore.dropAllData() await tmpStore.migrate('walletSyncTest0tmp', '1'.repeat(64)) const dstSettings = await tmpStore.makeAvailable() const srcSettings = await storage.makeAvailable() const manager = new WalletStorageManager(identityKey, storage, [tmpStore]) const auth = await manager.getAuth() { const r = await manager.syncToWriter(auth, tmpStore) expect(r.inserts).toBeGreaterThan(1000) expect(r.updates).toBe(2) } { const r = await manager.syncToWriter(auth, tmpStore) expect(r.inserts).toBe(0) expect(r.updates).toBe(0) } { _tu.insertTestOutputBasket(storage, auth.userId) await wait(1000) const r = await manager.syncToWriter(auth, tmpStore) expect(r.inserts).toBe(1) expect(r.updates).toBe(0) } await tmpStore.destroy() await storageManager.destroy() }) test('1a setActive to backup and back to original without backup first', async () => { // wallet will be the original active wallet, a backup is added, then setActive is used to initiate backup in each direction. const ctx = await _tu.createLegacyWalletSQLiteCopy('walletSyncTest1aSource') const { activeStorage: backup, wallet: backupWallet } = await _tu.createSQLiteTestWallet({ databaseName: 'walletSyncTest1aBackup', rootKeyHex: ctx.rootKey.toHex(), dropAll: true }) await ctx.storage.addWalletStorageProvider(backup) await setActiveTwice(ctx, false, backup, backupWallet) await setActiveTwice(ctx, false, backup, backupWallet) await ctx.storage.destroy() }) test('1b setActive to backup and back to original with backup first', async () => { // wallet will be the original active wallet, a backup is added, then setActive is used to initiate backup in each direction. const ctx = await _tu.createLegacyWalletSQLiteCopy('walletSyncTest1bSource') const backup = ( await _tu.createSQLiteTestWallet({ databaseName: 'walletSyncTest1bBackup', dropAll: true }) ).activeStorage await ctx.storage.addWalletStorageProvider(backup) await setActiveTwice(ctx, true, backup) await setActiveTwice(ctx, true, backup) await ctx.storage.destroy() }) }) async function setActiveTwice( ctx: TestWalletNoSetup, withBackupFirst: boolean, backup: StorageKnex, backupWallet?: Wallet ) { const { storage: storageManager, activeStorage: original, userId: originalUserId } = ctx if (withBackupFirst) { if (storageManager.isActiveEnabled) await storageManager.updateBackups() else await expect(storageManager.updateBackups()).rejects.toThrow( `WalletStorageManager is not accessing user's active storage or there are conflicting active stores configured.` ) } const backupIdentityKey = (await backup.makeAvailable()).storageIdentityKey const originalIdentityKey = (await original.makeAvailable()).storageIdentityKey expect(backupIdentityKey).not.toBe(originalIdentityKey) const originalAuth = { ...(await storageManager.getAuth()) } expect(originalAuth.userId).toBe(originalUserId) const originalTransactions = await original.findTransactions({ partial: { userId: originalAuth.userId } }) const originalUserBefore = verifyTruthy(await original.findUserById(originalAuth.userId!)) const backupUserBefore = verifyOneOrNone( await backup.findUsers({ partial: { identityKey: originalAuth.identityKey } }) ) expect(originalUserBefore.activeStorage === undefined || originalUserBefore.activeStorage === originalIdentityKey) let now = Date.now() expect(originalUserBefore.updated_at.getTime()).toBeLessThan(now) expect(!backupUserBefore || backupUserBefore.updated_at.getTime() < now).toBe(true) expect(storageManager.getActiveStore()).toBe(originalIdentityKey) expect(storageManager.getActiveUser().activeStorage).toBe(originalIdentityKey) // sync to backup and make it active. const log = await storageManager.setActive(backupIdentityKey) logger(log) expect(storageManager.getActiveStore()).toBe(backupIdentityKey) expect(storageManager.getActiveUser().activeStorage).toBe(backupIdentityKey) expect(storageManager.getBackupStores()).toEqual([originalIdentityKey]) let originalUserAfter = verifyTruthy(await original.findUserById(originalAuth.userId!)) let backupUserAfter = verifyOne( await backup.findUsers({ partial: { identityKey: originalAuth.identityKey } }) ) expect(originalUserAfter.updated_at.getTime()).toBeGreaterThanOrEqual(now) expect(backupUserAfter.updated_at.getTime()).toBeGreaterThanOrEqual(now) expect(originalUserAfter.activeStorage).toBe(backupIdentityKey) expect(backupUserAfter.activeStorage).toBe(backupIdentityKey) await expect( ctx.wallet.relinquishOutput({ basket: 'xyzzy', output: `${'1'.repeat(64)}.42` }) ).rejects.toThrow('Result must exist and be unique.') if (backupWallet) { backupWallet.storage._isAvailable = false backupWallet.storage._active!.user = undefined await backupWallet.storage.makeAvailable() await expect( backupWallet.relinquishOutput({ basket: 'xyzzy', output: `${'1'.repeat(64)}.42` }) ).rejects.toThrow('Result must exist and be unique.') } const backupAuth = await storageManager.getAuth() const backupTransactions = await backup.findTransactions({ partial: { userId: backupAuth.userId } }) now = Date.now() // sync back to original and make it active. const log2 = await storageManager.setActive(original.getSettings().storageIdentityKey) logger(log2) originalUserAfter = verifyTruthy(await original.findUserById(originalAuth.userId!)) backupUserAfter = verifyOne( await backup.findUsers({ partial: { identityKey: originalAuth.identityKey } }) ) expect(originalUserAfter.updated_at.getTime()).toBeGreaterThanOrEqual(now) expect(backupUserAfter.updated_at.getTime()).toBeGreaterThanOrEqual(now) expect(originalUserAfter.activeStorage).toBe(originalIdentityKey) expect(backupUserAfter.activeStorage).toBe(originalIdentityKey) await expect( ctx.wallet.relinquishOutput({ basket: 'xyzzy', output: `${'1'.repeat(64)}.42` }) ).rejects.toThrow('Result must exist and be unique.') if (backupWallet) { backupWallet.storage._isAvailable = false backupWallet.storage._active!.user = undefined await backupWallet.storage.makeAvailable() await expect( backupWallet.relinquishOutput({ basket: 'xyzzy', output: `${'1'.repeat(64)}.42` }) ).rejects.toThrow( `WalletStorageManager is not accessing user's active storage or there are conflicting active stores configured.` ) } }