wallet-storage
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
169 lines (157 loc) • 8 kB
text/typescript
/* eslint-disable @typescript-eslint/no-unused-vars */
import { MerklePath } from "@bsv/sdk"
import { arraysEqual, entity, optionalArraysEqual, sdk, table, verifyId, verifyOneOrNone } from "../../../index.client";
import { EntityBase } from ".";
export class Output extends EntityBase<table.Output> {
constructor(api?: table.Output) {
const now = new Date()
super(api || {
outputId: 0,
created_at: now,
updated_at: now,
userId: 0,
transactionId: 0,
spendable: false,
change: false,
satoshis: 0,
outputDescription: '',
vout: 0,
type: '',
providedBy: 'you',
purpose: '',
txid: undefined,
basketId: undefined,
spentBy: undefined,
derivationPrefix: undefined,
derivationSuffix: undefined,
senderIdentityKey: undefined,
customInstructions: undefined,
spendingDescription: undefined,
scriptLength: undefined,
scriptOffset: undefined,
lockingScript: undefined,
})
}
override updateApi(): void {
/* nothing needed yet... */
}
get outputId() { return this.api.outputId }
set outputId(v: number) { this.api.outputId = v }
get created_at() { return this.api.created_at }
set created_at(v: Date) { this.api.created_at = v }
get updated_at() { return this.api.updated_at }
set updated_at(v: Date) { this.api.updated_at = v }
get userId() { return this.api.userId }
set userId(v: number) { this.api.userId = v }
get transactionId() { return this.api.transactionId }
set transactionId(v: number) { this.api.transactionId = v }
get basketId() { return this.api.basketId }
set basketId(v: number | undefined) { this.api.basketId = v }
get spentBy() { return this.api.spentBy }
set spentBy(v: number | undefined) { this.api.spentBy = v }
get vout() { return this.api.vout }
set vout(v: number) { this.api.vout = v }
get satoshis() { return this.api.satoshis }
set satoshis(v: number) { this.api.satoshis = v }
get outputDescription() { return this.api.outputDescription }
set outputDescription(v: string) { this.api.outputDescription = v }
get spendable() { return this.api.spendable }
set spendable(v: boolean) { this.api.spendable = v }
get change() { return this.api.change }
set change(v: boolean) { this.api.change = v }
get txid() { return this.api.txid }
set txid(v: string | undefined) { this.api.txid = v }
get type() { return this.api.type }
set type(v: string) { this.api.type = v }
get providedBy() { return this.api.providedBy }
set providedBy(v: sdk.StorageProvidedBy) { this.api.providedBy = v }
get purpose() { return this.api.purpose }
set purpose(v: string) { this.api.purpose = v }
get spendingDescription() { return this.api.spendingDescription }
set spendingDescription(v: string | undefined) { this.api.spendingDescription = v }
get derivationPrefix() { return this.api.derivationPrefix }
set derivationPrefix(v: string | undefined) { this.api.derivationPrefix = v }
get derivationSuffix() { return this.api.derivationSuffix }
set derivationSuffix(v: string | undefined) { this.api.derivationSuffix = v }
get senderIdentityKey() { return this.api.senderIdentityKey }
set senderIdentityKey(v: string | undefined) { this.api.senderIdentityKey = v }
get customInstructions() { return this.api.customInstructions }
set customInstructions(v: string | undefined) { this.api.customInstructions = v }
get lockingScript() { return this.api.lockingScript }
set lockingScript(v: number[] | undefined) { this.api.lockingScript = v }
get scriptLength() { return this.api.scriptLength }
set scriptLength(v: number | undefined) { this.api.scriptLength = v }
get scriptOffset() { return this.api.scriptOffset }
set scriptOffset(v: number | undefined) { this.api.scriptOffset = v }
override get id(): number { return this.api.outputId }
override set id(v: number) { this.api.outputId = v }
override get entityName(): string { return 'Output' }
override get entityTable(): string { return 'outputs' }
override equals(ei: table.Output, syncMap?: entity.SyncMap | undefined): boolean {
if (
this.transactionId !== (syncMap ? syncMap.transaction.idMap[ei.transactionId] : ei.transactionId) ||
this.basketId !== (syncMap && ei.basketId ? syncMap.outputBasket.idMap[ei.basketId] : ei.basketId) ||
this.spentBy !== (syncMap && ei.spentBy ? syncMap.transaction.idMap[ei.spentBy] : ei.spentBy) ||
this.vout !== ei.vout ||
this.satoshis !== ei.satoshis ||
this.spendable !== ei.spendable ||
this.change !== ei.change ||
this.txid !== ei.txid ||
this.type !== ei.type ||
this.providedBy !== ei.providedBy ||
this.purpose !== ei.purpose ||
this.outputDescription !== ei.outputDescription ||
this.spendingDescription !== ei.spendingDescription ||
this.derivationPrefix !== ei.derivationPrefix ||
this.derivationSuffix !== ei.derivationSuffix ||
this.senderIdentityKey !== ei.senderIdentityKey ||
this.customInstructions !== ei.customInstructions ||
!optionalArraysEqual(this.lockingScript, ei.lockingScript) ||
this.scriptLength !== ei.scriptLength ||
this.scriptOffset !== ei.scriptOffset
)
return false
return true
}
static async mergeFind(storage: entity.EntityStorage, userId: number, ei: table.Output, syncMap: entity.SyncMap, trx?: sdk.TrxToken)
: Promise<{ found: boolean, eo: entity.Output, eiId: number }> {
const transactionId = syncMap.transaction.idMap[ei.transactionId]
const basketId = ei.basketId ? syncMap.outputBasket.idMap[ei.basketId] : null
const ef = verifyOneOrNone(await storage.findOutputs({ partial: { userId, transactionId, vout: ei.vout, }, trx }))
return {
found: !!ef,
eo: new entity.Output(ef || { ...ei }),
eiId: verifyId(ei.outputId)
}
}
override async mergeNew(storage: entity.EntityStorage, userId: number, syncMap: entity.SyncMap, trx?: sdk.TrxToken): Promise<void> {
this.userId = userId
this.basketId = this.basketId ? syncMap.outputBasket.idMap[this.basketId] : undefined
this.transactionId = syncMap.transaction.idMap[this.transactionId]
this.spentBy = this.spentBy ? syncMap.transaction.idMap[this.spentBy] : undefined
this.outputId = 0
this.outputId = await storage.insertOutput(this.toApi(), trx)
}
override async mergeExisting(storage: entity.EntityStorage, since: Date | undefined, ei: table.Output, syncMap: entity.SyncMap, trx?: sdk.TrxToken): Promise<boolean> {
let wasMerged = false
if (ei.updated_at > this.updated_at) {
this.spentBy = ei.spentBy ? syncMap.transaction.idMap[ei.spentBy] : undefined
this.spendable = ei.spendable
this.change = ei.change
this.type = ei.type
this.providedBy = ei.providedBy
this.purpose = ei.purpose
this.outputDescription = ei.outputDescription
this.spendingDescription = ei.spendingDescription
this.senderIdentityKey = ei.senderIdentityKey
this.customInstructions = ei.customInstructions
this.scriptLength = ei.scriptLength
this.scriptOffset = ei.scriptOffset
this.lockingScript = ei.lockingScript
this.updated_at = new Date()
await storage.updateOutput(this.id, this.toApi(), trx)
wasMerged = true
}
return wasMerged
}
}