wallet-storage
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
147 lines (110 loc) • 6.91 kB
text/typescript
import { verifyOne, verifyOneOrNone, verifyTruthy, wait, Wallet, WalletStorageManager } from "../../../src/index.client"
import { StorageKnex } from "../../../src/storage/StorageKnex";
import { _tu, TestWalletNoSetup } from "../../utils/TestUtilsWalletStorage"
describe('Wallet sync tests', () => {
jest.setTimeout(99999999)
const env = _tu.getEnv('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(0)
}
{
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) {
await storageManager.updateBackups()
}
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);
// sync to backup and make it active.
await storageManager.setActive(backupIdentityKey);
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)
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.
await storageManager.setActive(original.getSettings().storageIdentityKey);
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) {
expect(backupWallet?.storage.stores.length === 1)
expect(backupWallet?.storage.stores[0] === backup)
await expect(backupWallet.relinquishOutput({ basket: "xyzzy", output: `${'1'.repeat(64)}.42` })).rejects.toThrow(`WalletStorageManager is not accessing user's active storage.`);
}
}