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:
These tasks are the responsibility of the Monitor class.
Links: API, Interfaces, Classes, Functions, Types, Variables
MonitorDaemonSetup |
MonitorOptions |
TaskPurgeParams |
Links: API, Interfaces, Classes, Functions, Types, Variables
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
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
How many msecs to wait after each getMerkleProof service request.
msecsWaitPerMerkleProofServiceReq: number
Links: API, Interfaces, Classes, Functions, Types, Variables
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
Monitor | TaskPurge |
MonitorDaemon | TaskReviewStatus |
TaskCheckForProofs | TaskSendWaiting |
TaskCheckNoSends | TaskSyncWhenIdle |
TaskClock | TaskUnFail |
TaskFailAbandoned | WalletMonitorTask |
TaskNewHeader |
Links: API, Interfaces, Classes, Functions, Types, Variables
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
_otherTasks can be run by runTask but not by scheduler.
_otherTasks: WalletMonitorTask[] = []
See also: WalletMonitorTask
_tasks are typically run by the scheduler but may also be run by runTask.
_tasks: WalletMonitorTask[] = []
See also: WalletMonitorTask
Default tasks with settings appropriate for a single user storage possibly with sync’ing enabled
addDefaultTasks(): void
Tasks appropriate for multi-user storage without sync’ing enabled.
addMultiUserTasks(): void
Process new chain header event received from Chaintracks
Kicks processing ‘unconfirmed’ and ‘unmined’ request processing.
processNewBlockHeader(header: BlockHeader): void
See also: BlockHeader
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
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
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
An external service such as the chaintracks new block header listener can set this true to cause
static checkNow = false
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
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
An external service such as the chaintracks new block header listener can set this true to cause
static checkNow = false
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
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
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
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
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
Set to true to trigger running this task
static checkNow = false
Links: API, Interfaces, Classes, Functions, Types, Variables
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
Set to true to trigger running this task
static checkNow = false
Links: API, Interfaces, Classes, Functions, Types, Variables
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
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
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
Setting provenTxReq status to ‘unfail’ when ‘invalid’ will attempt to find a merklePath, and if successful:
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
Set to true to trigger running this task
static checkNow = false
async unfailReq(req: EntityProvenTxReq, indent: number): Promise<string>
See also: EntityProvenTxReq
Links: API, Interfaces, Classes, Functions, Types, Variables
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
Set by monitor each time runTask completes
lastRunMsecsSinceEpoch = 0
Override to handle async task setup configuration.
Called before first call to trigger
async asyncSetup(): Promise<void>
Return true if runTask
needs to be called now.
abstract trigger(nowMsecsSinceEpoch: number): {
run: boolean;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
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
export type MonitorStorage = WalletStorageManager
See also: WalletStorageManager
Links: API, Interfaces, Classes, Functions, Types, Variables