@bsv/wallet-toolbox
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
210 lines (191 loc) • 4.78 kB
text/typescript
import { sdk, StorageProvider } from '../../../index.client'
export type EntityStorage = StorageProvider
export abstract class EntityBase<T> {
api: T
constructor(api: T) {
this.api = api
}
/**
* Standard property for entity database Id
*/
abstract get id(): number
/**
* Name of derived entity class
*/
abstract get entityName(): string
/**
* Schema table name of entity
*/
abstract get entityTable(): string
/**
* On construction, an entity may decode properties of the `api` object,
* such as JSON stringified objects.
*
* The `updateApi` method must re-encode the current state of those decoded properties
* into the `api` object.
*
* Used by the `toApi` method to return an updated `api` object.
*/
abstract updateApi(): void
/**
* Tests for equality or 'merge' / 'convergent' equality if syncMap is provided.
*
* 'convergent' equality must satisfy (A sync B) equals (B sync A)
*
* @param ei
* @param syncMap
*/
abstract equals(ei: T, syncMap?: SyncMap): boolean
/**
* Perform a 'merge' / 'convergent' equality migration of state
* to this new local entity which was constructed
* as a copy of the external object.
*
* @param userId local userId
* @param syncMap
*/
abstract mergeNew(storage: EntityStorage, userId: number, syncMap: SyncMap, trx?: sdk.TrxToken): Promise<void>
/**
* Perform a 'merge' / 'convergent' equality migration of state
* from external `ei` to this existing local EntityUser
*
* @param ei
* @param syncMap
* @returns true iff entity state changed and was updated to storage
*/
abstract mergeExisting(
storage: EntityStorage,
since: Date | undefined,
ei: T,
syncMap: SyncMap,
trx?: sdk.TrxToken
): Promise<boolean>
/**
* An entity may decode properties of the underlying Api object on construction.
*
* The `toApi` method forces an `updateApi` before returning the underlying,
* now updated, Api object.
*
* @returns The underlying Api object with any entity decoded properties updated.
*/
toApi(): T {
this.updateApi()
return this.api
}
}
export interface EntitySyncMap {
entityName: string
/**
* Maps foreign ids to local ids
* Some entities don't have idMaps (CertificateField, TxLabelMap and OutputTagMap)
*/
idMap: Record<number, number>
/**
* the maximum updated_at value seen for this entity over chunks received
* during this udpate cycle.
*/
maxUpdated_at?: Date
/**
* The cummulative count of items of this entity type received over all the `SyncChunk`s
* since the `since` was last updated.
*
* This is the `offset` value to use for the next SyncChunk request.
*/
count: number
}
export interface SyncMap {
provenTx: EntitySyncMap
outputBasket: EntitySyncMap
transaction: EntitySyncMap
provenTxReq: EntitySyncMap
txLabel: EntitySyncMap
txLabelMap: EntitySyncMap
output: EntitySyncMap
outputTag: EntitySyncMap
outputTagMap: EntitySyncMap
certificate: EntitySyncMap
certificateField: EntitySyncMap
commission: EntitySyncMap
}
export function createSyncMap(): SyncMap {
const r: SyncMap = {
provenTx: {
entityName: 'provenTx',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
outputBasket: {
entityName: 'outputBasket',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
transaction: {
entityName: 'transaction',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
provenTxReq: {
entityName: 'provenTxReq',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
txLabel: {
entityName: 'txLabel',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
txLabelMap: {
entityName: 'txLabelMap',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
output: {
entityName: 'output',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
outputTag: {
entityName: 'outputTag',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
outputTagMap: {
entityName: 'outputTagMap',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
certificate: {
entityName: 'certificate',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
certificateField: {
entityName: 'certificateField',
idMap: {},
maxUpdated_at: undefined,
count: 0
},
commission: {
entityName: 'commission',
idMap: {},
maxUpdated_at: undefined,
count: 0
}
}
return r
}
export interface SyncError {
code: string
description: string
stack?: string
}