wallet-toolbox

MONITOR: BSV Wallet Toolbox API Documentation

The documentation is split into various pages, this page covers the Monitor and related API.

To function properly, a wallet must be able to perform a number of house keeping tasks:

  1. Ensure transactions are sent to the network without slowing application flow or when created while offline.
  2. Obtain and merge proofs when transactions are mined.
  3. Detect and propagate transactions that fail due to double-spend, reorgs, or other reasons.

These tasks are the responsibility of the Monitor class.

Return To Top

API

Links: API, Interfaces, Classes, Functions, Types, Variables

Interfaces

 
MonitorDaemonSetup
MonitorOptions
TaskPurgeParams

Links: API, Interfaces, Classes, Functions, Types, Variables


Interface: MonitorDaemonSetup
export interface MonitorDaemonSetup {
    chain?: sdk.Chain;
    sqliteFilename?: string;
    mySQLConnection?: string;
    knexConfig?: Knex.Config;
    knex?: Knex<any, any[]>;
    storageKnexOptions?: StorageKnexOptions;
    storageProvider?: StorageProvider;
    storageManager?: WalletStorageManager;
    servicesOptions?: sdk.WalletServicesOptions;
    services?: Services;
    monitor?: Monitor;
}

See also: Chain, Monitor, Services, StorageKnexOptions, StorageProvider, WalletServicesOptions, WalletStorageManager

Links: API, Interfaces, Classes, Functions, Types, Variables


Interface: MonitorOptions
export interface MonitorOptions {
    chain: sdk.Chain;
    services: Services;
    storage: MonitorStorage;
    chaintracks: ChaintracksServiceClient;
    msecsWaitPerMerkleProofServiceReq: number;
    taskRunWaitMsecs: number;
    abandonedMsecs: number;
    unprovenAttemptsLimitTest: number;
    unprovenAttemptsLimitMain: number;
}

See also: Chain, MonitorStorage, Services

Property msecsWaitPerMerkleProofServiceReq

How many msecs to wait after each getMerkleProof service request.

msecsWaitPerMerkleProofServiceReq: number

Links: API, Interfaces, Classes, Functions, Types, Variables


Interface: TaskPurgeParams

The database stores a variety of data that may be considered transient.

At one extreme, the data that must be preserved:

At the other extreme, everything can be preserved to fully log all transaction creation and processing actions.

The following purge actions are available to support sustained operation:

export interface TaskPurgeParams extends PurgeParams {
}

See also: PurgeParams

Links: API, Interfaces, Classes, Functions, Types, Variables


Classes

   
Monitor TaskPurge
MonitorDaemon TaskReviewStatus
TaskCheckForProofs TaskSendWaiting
TaskCheckNoSends TaskSyncWhenIdle
TaskClock TaskUnFail
TaskFailAbandoned WalletMonitorTask
TaskNewHeader  

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: Monitor

Background task to make sure transactions are processed, transaction proofs are received and propagated, and potentially that reorgs update proofs that were already received.

export class Monitor {
    static createDefaultWalletMonitorOptions(chain: sdk.Chain, storage: MonitorStorage, services?: Services): MonitorOptions 
    options: MonitorOptions;
    services: Services;
    chain: sdk.Chain;
    storage: MonitorStorage;
    chaintracks: ChaintracksServiceClient;
    constructor(options: MonitorOptions) 
    oneSecond = 1000;
    oneMinute = 60 * this.oneSecond;
    oneHour = 60 * this.oneMinute;
    oneDay = 24 * this.oneHour;
    oneWeek = 7 * this.oneDay;
    _tasks: WalletMonitorTask[] = [];
    _otherTasks: WalletMonitorTask[] = [];
    _tasksRunning = false;
    defaultPurgeParams: TaskPurgeParams = {
        purgeSpent: false,
        purgeCompleted: false,
        purgeFailed: true,
        purgeSpentAge: 2 * this.oneWeek,
        purgeCompletedAge: 2 * this.oneWeek,
        purgeFailedAge: 5 * this.oneDay
    };
    addAllTasksToOther(): void 
    addDefaultTasks(): void 
    addMultiUserTasks(): void 
    addTask(task: WalletMonitorTask): void 
    removeTask(name: string): void 
    async setupChaintracksListeners(): Promise<void> 
    async runTask(name: string): Promise<string> 
    async runOnce(): Promise<void> 
    _runAsyncSetup: boolean = true;
    async startTasks(): Promise<void> 
    async logEvent(event: string, details?: string): Promise<void> 
    stopTasks(): void 
    lastNewHeader: BlockHeader | undefined;
    lastNewHeaderWhen: Date | undefined;
    processNewBlockHeader(header: BlockHeader): void 
    processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader): void 
}

See also: BlockHeader, Chain, MonitorOptions, MonitorStorage, Services, TaskPurgeParams, WalletMonitorTask

Property _otherTasks

_otherTasks can be run by runTask but not by scheduler.

_otherTasks: WalletMonitorTask[] = []

See also: WalletMonitorTask

Property _tasks

_tasks are typically run by the scheduler but may also be run by runTask.

_tasks: WalletMonitorTask[] = []

See also: WalletMonitorTask

Method addDefaultTasks

Default tasks with settings appropriate for a single user storage possibly with sync’ing enabled

addDefaultTasks(): void 
Method addMultiUserTasks

Tasks appropriate for multi-user storage without sync’ing enabled.

addMultiUserTasks(): void 
Method processNewBlockHeader

Process new chain header event received from Chaintracks

Kicks processing ‘unconfirmed’ and ‘unmined’ request processing.

processNewBlockHeader(header: BlockHeader): void 

See also: BlockHeader

Method processReorg

Process reorg event received from Chaintracks

Reorgs can move recent transactions to new blocks at new index positions. Affected transaction proofs become invalid and must be updated.

It is possible for a transaction to become invalid.

Coinbase transactions always become invalid.

processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader): void 

See also: BlockHeader

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: MonitorDaemon
export class MonitorDaemon {
    setup?: MonitorDaemonSetup;
    doneListening?: Promise<void>;
    doneTasks?: Promise<void>;
    stopDaemon: boolean = false;
    constructor(public args: MonitorDaemonSetup, public noRunTasks?: boolean) 
    async createSetup(): Promise<void> 
    async start(): Promise<void> 
    async stop(): Promise<void> 
    async destroy(): Promise<void> 
    async runDaemon(): Promise<void> 
}

See also: MonitorDaemonSetup

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskCheckForProofs

TaskCheckForProofs is a WalletMonitor task that retreives merkle proofs for transactions.

It is normally triggered by the Chaintracks new block header event.

When a new block is found, cwi-external-services are used to obtain proofs for any transactions that are currently in the ‘unmined’ or ‘unknown’ state.

If a proof is obtained and validated, a new ProvenTx record is created and the original ProvenTxReq status is advanced to ‘notifying’.

export class TaskCheckForProofs extends WalletMonitorTask {
    static taskName = "CheckForProofs";
    static checkNow = false;
    constructor(monitor: Monitor, public triggerMsecs = 0) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, WalletMonitorTask

Property checkNow

An external service such as the chaintracks new block header listener can set this true to cause

static checkNow = false
Method trigger

Normally triggered by checkNow getting set by new block header found event from chaintracks

trigger(nowMsecsSinceEpoch: number): {
    run: boolean;
} 

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskCheckNoSends

TaskCheckNoSends is a WalletMonitor task that retreives merkle proofs for ‘nosend’ transactions that MAY have been shared externally.

Unlike intentionally processed transactions, ‘nosend’ transactions are fully valid transactions which have not been processed by the wallet.

By default, this task runs once a day to check if any ‘nosend’ transaction has managed to get mined by some external process.

If a proof is obtained and validated, a new ProvenTx record is created and the original ProvenTxReq status is advanced to ‘notifying’.

export class TaskCheckNoSends extends WalletMonitorTask {
    static taskName = "CheckNoSends";
    static checkNow = false;
    constructor(monitor: Monitor, public triggerMsecs = monitor.oneDay * 1) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, WalletMonitorTask

Property checkNow

An external service such as the chaintracks new block header listener can set this true to cause

static checkNow = false
Method trigger

Normally triggered by checkNow getting set by new block header found event from chaintracks

trigger(nowMsecsSinceEpoch: number): {
    run: boolean;
} 

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskClock
export class TaskClock extends WalletMonitorTask {
    static taskName = "Clock";
    nextMinute: number;
    constructor(monitor: Monitor, public triggerMsecs = 1 * monitor.oneSecond) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
    getNextMinute(): number 
}

See also: Monitor, WalletMonitorTask

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskFailAbandoned

Handles transactions which do not have terminal status and have not been updated for an extended time period.

Calls updateTransactionStatus to set status to failed. This returns inputs to spendable status and verifies that any outputs are not spendable.

export class TaskFailAbandoned extends WalletMonitorTask {
    static taskName = "FailAbandoned";
    constructor(monitor: Monitor, public triggerMsecs = 1000 * 60 * 5) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, WalletMonitorTask

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskNewHeader
export class TaskNewHeader extends WalletMonitorTask {
    static taskName = "NewHeader";
    header?: BlockHeader;
    constructor(monitor: Monitor, public triggerMsecs = 1 * monitor.oneMinute) 
    async getHeader(): Promise<BlockHeader> 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: BlockHeader, Monitor, WalletMonitorTask

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskPurge
export class TaskPurge extends WalletMonitorTask {
    static taskName = "Purge";
    static checkNow = false;
    constructor(monitor: Monitor, public params: TaskPurgeParams, public triggerMsecs = 0) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, TaskPurgeParams, WalletMonitorTask

Property checkNow

Set to true to trigger running this task

static checkNow = false

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskReviewStatus

Notify Transaction records of changes in ProvenTxReq records they may have missed.

The notified property flags reqs that do not need to be checked.

Looks for aged Transactions with provenTxId with status != ‘completed’, sets status to ‘completed’.

Looks for reqs with ‘invalid’ status that

export class TaskReviewStatus extends WalletMonitorTask {
    static taskName = "ReviewStatus";
    static checkNow = false;
    constructor(monitor: Monitor, public triggerMsecs = 1000 * 60 * 15, public agedMsecs = 1000 * 60 * 5) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, WalletMonitorTask

Property checkNow

Set to true to trigger running this task

static checkNow = false

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskSendWaiting
export class TaskSendWaiting extends WalletMonitorTask {
    static taskName = "SendWaiting";
    lastSendingRunMsecsSinceEpoch: number | undefined;
    includeSending: boolean = true;
    constructor(monitor: Monitor, public triggerMsecs = monitor.oneSecond * 8, public agedMsecs = monitor.oneSecond * 7, public sendingMsecs = monitor.oneMinute * 5) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
    async processUnsent(reqApis: TableProvenTxReq[], indent = 0): Promise<string> 
}

See also: Monitor, TableProvenTxReq, WalletMonitorTask

Method processUnsent

Process an array of ‘unsent’ status table.ProvenTxReq

Send rawTx to transaction processor(s), requesting proof callbacks when possible.

Set status ‘invalid’ if req is invalid.

Set status to ‘callback’ on successful network submission with callback service.

Set status to ‘unmined’ on successful network submission without callback service.

Add mapi responses to database table if received.

Increments attempts if sending was attempted.

async processUnsent(reqApis: TableProvenTxReq[], indent = 0): Promise<string> 

See also: TableProvenTxReq

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskSyncWhenIdle
export class TaskSyncWhenIdle extends WalletMonitorTask {
    static taskName = "SyncWhenIdle";
    constructor(monitor: Monitor, public triggerMsecs = 1000 * 60 * 1) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
}

See also: Monitor, WalletMonitorTask

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: TaskUnFail

Setting provenTxReq status to ‘unfail’ when ‘invalid’ will attempt to find a merklePath, and if successful:

  1. set the req status to ‘unmined’
  2. set the referenced txs to ‘unproven’
  3. determine if any inputs match user’s existing outputs and if so update spentBy and spendable of those outputs.
  4. set the txs outputs to spendable

If it fails (to find a merklePath), returns the req status to ‘invalid’.

export class TaskUnFail extends WalletMonitorTask {
    static taskName = "UnFail";
    static checkNow = false;
    constructor(monitor: Monitor, public triggerMsecs = monitor.oneMinute * 10) 
    trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    } 
    async runTask(): Promise<string> 
    async unfail(reqs: TableProvenTxReq[], indent = 0): Promise<{
        log: string;
    }> 
    async unfailReq(req: EntityProvenTxReq, indent: number): Promise<string> 
}

See also: EntityProvenTxReq, Monitor, TableProvenTxReq, WalletMonitorTask

Property checkNow

Set to true to trigger running this task

static checkNow = false
Method unfailReq
  1. set the referenced txs to ‘unproven’
  2. determine if any inputs match user’s existing outputs and if so update spentBy and spendable of those outputs.
  3. set the txs outputs to spendable
async unfailReq(req: EntityProvenTxReq, indent: number): Promise<string> 

See also: EntityProvenTxReq

Links: API, Interfaces, Classes, Functions, Types, Variables


Class: WalletMonitorTask

A monitor task performs some periodic or state triggered maintenance function on the data managed by a wallet (Bitcoin UTXO manager, aka wallet)

The monitor maintains a collection of tasks.

It runs each task’s non-asynchronous trigger to determine if the runTask method needs to run.

Tasks that need to be run are run consecutively by awaiting their async runTask override method.

The monitor then waits a fixed interval before repeating…

Tasks may use the monitor_events table to persist their execution history. This is done by accessing the wathman.storage object.

export abstract class WalletMonitorTask {
    lastRunMsecsSinceEpoch = 0;
    storage: MonitorStorage;
    constructor(public monitor: Monitor, public name: string) 
    async asyncSetup(): Promise<void> 
    abstract trigger(nowMsecsSinceEpoch: number): {
        run: boolean;
    };
    abstract runTask(): Promise<string>;
}

See also: Monitor, MonitorStorage

Property lastRunMsecsSinceEpoch

Set by monitor each time runTask completes

lastRunMsecsSinceEpoch = 0
Method asyncSetup

Override to handle async task setup configuration.

Called before first call to trigger

async asyncSetup(): Promise<void> 
Method trigger

Return true if runTask needs to be called now.

abstract trigger(nowMsecsSinceEpoch: number): {
    run: boolean;
}

Links: API, Interfaces, Classes, Functions, Types, Variables


Functions

Function: getProofs

Process an array of table.ProvenTxReq (typically with status ‘unmined’ or ‘unknown’)

If req is invalid, set status ‘invalid’

Verify the requests are valid, lookup proofs or updated transaction status using the array of getProofServices,

When proofs are found, create new ProvenTxApi records and transition the requests’ status to ‘unconfirmed’ or ‘notifying’, depending on chaintracks succeeding on proof verification.

Increments attempts if proofs where requested.

export async function getProofs(task: WalletMonitorTask, reqs: TableProvenTxReq[], indent = 0, countsAsAttempt = false, ignoreStatus = false): Promise<{
    proven: TableProvenTxReq[];
    invalid: TableProvenTxReq[];
    log: string;
}> 

See also: TableProvenTxReq, WalletMonitorTask

Returns

reqs partitioned by status

Links: API, Interfaces, Classes, Functions, Types, Variables


Types

Type: MonitorStorage
export type MonitorStorage = WalletStorageManager

See also: WalletStorageManager

Links: API, Interfaces, Classes, Functions, Types, Variables


Variables