The documentation is split into various pages, this page covers the Services and related API.
To function properly, a wallet makes use of a variety of services provided by the network:
These tasks are the responsibility of the Services class.
Links: API, Interfaces, Classes, Functions, Types, Variables
Links: API, Interfaces, Classes, Functions, Types, Variables
Configuration options for the ARC broadcaster.
export interface ArcConfig {
apiKey?: string;
httpClient?: HttpClient;
deploymentId?: string;
callbackUrl?: string;
callbackToken?: string;
headers?: Record<string, string>;
}
Authentication token for the ARC API
apiKey?: string
default access token for notification callback endpoint. It will be used as a Authorization header for the http callback
callbackToken?: string
notification callback endpoint for proofs and double spend notification
callbackUrl?: string
Deployment id used annotating api calls in XDeployment-ID header - this value will be randomly generated if not set
deploymentId?: string
additional headers to be attached to all tx submissions.
headers?: Record<string, string>
The HTTP client used to make requests to the ARC API.
httpClient?: HttpClient
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ArcMinerGetTxData {
status: number;
title: string;
blockHash: string;
blockHeight: number;
competingTxs: null | string[];
extraInfo: string;
merklePath: string;
timestamp: string;
txid: string;
txStatus: string;
}
See also: blockHash
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BitailsConfig {
apiKey?: string;
httpClient?: HttpClient;
}
Authentication token for BitTails API
apiKey?: string
The HTTP client used to make requests to the API.
httpClient?: HttpClient
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BitailsMerkleProof {
index: number;
txOrId: string;
target: string;
nodes: string[];
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkFileDataManagerMergeResult {
unchanged: BulkHeaderFileInfo[];
inserted: BulkHeaderFileInfo[];
updated: BulkHeaderFileInfo[];
dropped: BulkHeaderFileInfo[];
}
See also: BulkHeaderFileInfo
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkFileDataManagerOptions {
chain: Chain;
maxPerFile: number;
maxRetained?: number;
fetch?: ChaintracksFetchApi;
fromKnownSourceUrl?: string;
}
See also: Chain, ChaintracksFetchApi
Links: API, Interfaces, Classes, Functions, Types, Variables
Descriptive information about a single bulk header file.
export interface BulkHeaderFileInfo {
fileName: string;
firstHeight: number;
count: number;
prevChainWork: string;
lastChainWork: string;
prevHash: string;
lastHash: string | null;
fileHash: string | null;
chain?: Chain;
data?: Uint8Array;
validated?: boolean;
fileId?: number;
sourceUrl?: string;
}
See also: Chain
Which chain: ‘main’ or ‘test’
chain?: Chain
See also: Chain
count of how many headers the file contains. File size must be 80 * count.
count: number
file contents single sha256 hash as base64 string
fileHash: string | null
optional, used for database storage
fileId?: number
filename and extension, no path
fileName: string
chain height of first header in file
firstHeight: number
lastChainWork is the cummulative chain work including the last header in this file’s data, as a hex string.
lastChainWork: string
block hash of last header in the file in standard hex string block hash encoding
lastHash: string | null
prevChainWork is the cummulative chain work up to the first header in this file’s data, as a hex string.
prevChainWork: string
previousHash of first header in file in standard hex string block hash encoding
prevHash: string
optional, if valid ${sourceUrl}/${fileName}
is the source of this data.
sourceUrl?: string
true iff these properties should be considered pre-validated, including a valid required fileHash of data (when not undefined).
validated?: boolean
Links: API, Interfaces, Classes, Functions, Types, Variables
Describes a collection of bulk block header files.
export interface BulkHeaderFilesInfo {
rootFolder: string;
jsonFilename: string;
files: BulkHeaderFileInfo[];
headersPerFile: number;
}
See also: BulkHeaderFileInfo
Array of information about each bulk block header file.
files: BulkHeaderFileInfo[]
See also: BulkHeaderFileInfo
Maximum number of headers in a single file in this collection of files.
headersPerFile: number
Sub-path to this resource on rootFolder
jsonFilename: string
Where this file was fetched or read from.
rootFolder: string
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkIngestorApi {
shutdown(): Promise<void>;
getPresentHeight(): Promise<number | undefined>;
fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>;
synchronize(presentHeight: number, before: HeightRanges, priorLiveHeaders: BlockHeader[]): Promise<BulkSyncResult>;
setStorage(storage: ChaintracksStorageApi): Promise<void>;
storage(): ChaintracksStorageApi;
}
See also: BlockHeader, BulkSyncResult, ChaintracksStorageApi, HeightRange, HeightRanges
A BulkIngestor fetches and updates storage with bulk headers in bulkRange.
If it can, it must also fetch live headers in fetch range that are not in bulkRange and return them as an array.
The storage methods insertBulkFile
, updateBulkFile
, and addBulkHeaders
should be used to add bulk headers to storage.
fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
See also: BlockHeader, HeightRange, HeightRanges
Returns
new live headers: headers in fetchRange but not in bulkRange
Argument Details
If the bulk ingestor is capable, return the approximate present height of the actual chain being tracked. Otherwise, return undefined.
May not assume that setStorage has been called.
getPresentHeight(): Promise<number | undefined>
Called before first Synchronize with reference to storage. Components requiring asynchronous setup can override base class implementation.
setStorage(storage: ChaintracksStorageApi): Promise<void>
See also: ChaintracksStorageApi
Close and release all resources.
shutdown(): Promise<void>
A BulkIngestor has two potential goals:
synchronize(presentHeight: number, before: HeightRanges, priorLiveHeaders: BlockHeader[]): Promise<BulkSyncResult>
See also: BlockHeader, BulkSyncResult, HeightRanges
Returns
updated priorLiveHeaders including any accumulated by this ingestor
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkIngestorBaseOptions {
chain: Chain;
jsonResource: string | undefined;
bypassLiveEnabled: boolean;
}
See also: Chain
If true, and the bulk ingestor supports it, bypass the live database
up to liveHeightThreshold
of available headers remaining.
bypassLiveEnabled: boolean
The target chain: “main” or “test”
chain: Chain
See also: Chain
Required.
The name of the JSON resource to request from CDN which describes currently available bulk block header resources.
jsonResource: string | undefined
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkIngestorCDNOptions extends BulkIngestorBaseOptions {
jsonResource: string | undefined;
cdnUrl: string | undefined;
maxPerFile: number | undefined;
fetch: ChaintracksFetchApi;
}
See also: BulkIngestorBaseOptions, ChaintracksFetchApi
Required.
URL to CDN implementing the bulk ingestor CDN service protocol
cdnUrl: string | undefined
Required.
The name of the JSON resource to request from CDN which describes currently available bulk block header resources.
jsonResource: string | undefined
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkIngestorWhatsOnChainOptions extends BulkIngestorBaseOptions, WhatsOnChainServicesOptions {
idleWait: number | undefined;
chain: Chain;
apiKey?: string;
timeout: number;
userAgent: string;
enableCache: boolean;
chainInfoMsecs: number;
fetch?: ChaintracksFetchApi;
}
See also: BulkIngestorBaseOptions, Chain, ChaintracksFetchApi, WhatsOnChainServicesOptions
WhatsOnChain.com API Key https://docs.taal.com/introduction/get-an-api-key If unknown or empty, maximum request rate is limited. https://developers.whatsonchain.com/#rate-limits
apiKey?: string
Which chain is being tracked: main, test, or stn.
chain: Chain
See also: Chain
How long chainInfo is considered still valid before updating (msecs).
chainInfoMsecs: number
Enable WhatsOnChain client cache option.
enableCache: boolean
Maximum msces of “normal” pause with no new data arriving.
idleWait: number | undefined
Request timeout for GETs to https://api.whatsonchain.com/v1/bsv
timeout: number
User-Agent header value for requests to https://api.whatsonchain.com/v1/bsv
userAgent: string
Links: API, Interfaces, Classes, Functions, Types, Variables
Handles block header storage and retrieval older than the “live” portion of the chain. Height is the primary and only indexing field required. Only stores headers on the active chain; no orphans, no forks, no reorgs.
export interface BulkStorageApi {
shutdown(): Promise<void>;
getMaxHeight(): Promise<number>;
getHeightRange(): Promise<HeightRange>;
appendHeaders(minHeight: number, count: number, headers: Uint8Array): Promise<void>;
findHeaderForHeightOrUndefined(height: number): Promise<BlockHeader | undefined>;
findHeaderForHeight(height: number): Promise<BlockHeader>;
headersToBuffer(height: number, count: number): Promise<Uint8Array>;
exportBulkHeaders(rootFolder: string, jsonFilename: string, maxPerFile: number): Promise<void>;
setStorage(storage: ChaintracksStorageApi): Promise<void>;
}
See also: BlockHeader, ChaintracksStorageApi, HeightRange
Append new Block Headers to BulkStorage.
Requires that these headers directly extend existing headers.
maxHeight of existing plus one equals minHeight of headers
.
hash of last existing equals previousHash of first in headers
.
Checks that all headers
are valid (hash, previousHash)
Duplicate headers must be ignored.
appendHeaders(minHeight: number, count: number, headers: Uint8Array): Promise<void>
Argument Details
Exports current bulk headers, including all ingests, excluding live headers to static header files.
exportBulkHeaders(rootFolder: string, jsonFilename: string, maxPerFile: number): Promise<void>
Argument Details
Returns block header for a given block height on active chain. Throws if not found.
findHeaderForHeight(height: number): Promise<BlockHeader>
See also: BlockHeader
Argument Details
Returns block header for a given block height on active chain.
findHeaderForHeightOrUndefined(height: number): Promise<BlockHeader | undefined>
See also: BlockHeader
Argument Details
getHeightRange(): Promise<HeightRange>
See also: HeightRange
Returns
available bulk block header height range: (0, getMaxHeight())
getMaxHeight(): Promise<number>
Returns
the height of the most recent header in bulk storage or -1 if empty.
Adds headers in 80 byte serialized format to a buffer. Only adds active headers. returned array length divided by 80 is the actual number returned.
Returns the buffer.
headersToBuffer(height: number, count: number): Promise<Uint8Array>
Argument Details
Called before first Synchronize with reference to storage. Components requiring asynchronous setup can override base class implementation.
setStorage(storage: ChaintracksStorageApi): Promise<void>
See also: ChaintracksStorageApi
Close and release all resources.
shutdown(): Promise<void>
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkStorageBaseOptions {
chain: Chain;
fs: ChaintracksFsApi;
}
See also: Chain, ChaintracksFsApi
The target chain: “main” or “test”
chain: Chain
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface BulkSyncResult {
liveHeaders: BlockHeader[];
liveRange: HeightRange;
done: boolean;
log: string;
}
See also: BlockHeader, HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
Full Chaintracks API including startListening with callbacks
export interface ChaintracksApi extends ChaintracksClientApi {
startListening(listening?: () => void): Promise<void>;
}
See also: ChaintracksClientApi
Start or resume listening for new headers.
Calls synchronize
to catch up on headers that were found while not listening.
Begins listening to any number of configured new header notification services.
Begins sending notifications to subscribed listeners only after processing any previously found headers.
May be called if already listening or synchronizing to listen.
listening
callback will be called after listening for new live headers has begun.
Alternatively, the listening
API function which returns a Promise can be awaited.
startListening(listening?: () => void): Promise<void>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Supports access and appending data to new or existing named data storage. New data is always appended to the end of existing data.
export interface ChaintracksAppendableFileApi extends ChaintracksReadableFileApi {
append(data: Uint8Array): Promise<void>;
}
See also: ChaintracksReadableFileApi
append(data: Uint8Array): Promise<void>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksChainTrackerOptions {
maxRetries?: number;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
Chaintracks client API excluding events and callbacks
export interface ChaintracksClientApi extends ChainTracker {
getChain(): Promise<Chain>;
getInfo(): Promise<ChaintracksInfoApi>;
getPresentHeight(): Promise<number>;
getHeaders(height: number, count: number): Promise<string>;
findChainTipHeader(): Promise<BlockHeader>;
findChainTipHash(): Promise<string>;
findHeaderForHeight(height: number): Promise<BlockHeader | undefined>;
findHeaderForBlockHash(hash: string): Promise<BlockHeader | undefined>;
addHeader(header: BaseBlockHeader): Promise<void>;
startListening(): Promise<void>;
listening(): Promise<void>;
isListening(): Promise<boolean>;
isSynchronized(): Promise<boolean>;
subscribeHeaders(listener: HeaderListener): Promise<string>;
subscribeReorgs(listener: ReorgListener): Promise<string>;
unsubscribe(subscriptionId: string): Promise<boolean>;
isValidRootForHeight(root: string, height: number): Promise<boolean>;
currentHeight: () => Promise<number>;
}
See also: BaseBlockHeader, BlockHeader, Chain, ChaintracksInfoApi, HeaderListener, ReorgListener
Submit a possibly new header for adding
If the header is invalid or a duplicate it will not be added.
This header will be ignored if the previous header has not already been inserted when this header is considered for insertion.
addHeader(header: BaseBlockHeader): Promise<void>
See also: BaseBlockHeader
Returns
immediately
Returns the block hash of the active chain tip.
findChainTipHash(): Promise<string>
Returns the active chain tip header
findChainTipHeader(): Promise<BlockHeader>
See also: BlockHeader
Returns block header for a given recent block hash or undefined.
findHeaderForBlockHash(hash: string): Promise<BlockHeader | undefined>
See also: BlockHeader
Returns block header for a given block height on active chain.
findHeaderForHeight(height: number): Promise<BlockHeader | undefined>
See also: BlockHeader
Confirms the chain
getChain(): Promise<Chain>
See also: Chain
Adds headers in 80 byte serialized format to an array. Only adds active headers. array length divided by 80 is the actual number returned.
getHeaders(height: number, count: number): Promise<string>
Returns
array of headers as serialized hex string
Argument Details
getInfo(): Promise<ChaintracksInfoApi>
See also: ChaintracksInfoApi
Returns
Summary of configuration and state.
Return the latest chain height from configured bulk ingestors.
getPresentHeight(): Promise<number>
Returns true if actively listening for new headers and client api is enabled.
isListening(): Promise<boolean>
Returns true if synchronize
has completed at least once.
isSynchronized(): Promise<boolean>
Returns a Promise that will resolve when the previous call to startListening enters the listening-for-new-headers state.
listening(): Promise<void>
Start or resume listening for new headers.
Calls synchronize
to catch up on headers that were found while not listening.
Begins listening to any number of configured new header notification services.
Begins sending notifications to subscribed listeners only after processing any previously found headers.
May be called if already listening or synchronizing to listen.
The listening
API function which returns a Promise can be awaited.
startListening(): Promise<void>
Subscribe to “header” events.
subscribeHeaders(listener: HeaderListener): Promise<string>
See also: HeaderListener
Returns
identifier for this subscription
Throws
ERR_NOT_IMPLEMENTED if callback events are not supported
Subscribe to “reorganization” events.
subscribeReorgs(listener: ReorgListener): Promise<string>
See also: ReorgListener
Returns
identifier for this subscription
Throws
ERR_NOT_IMPLEMENTED if callback events are not supported
Cancels all subscriptions with the given subscriptionId
which was previously returned
by a subscribe
method.
unsubscribe(subscriptionId: string): Promise<boolean>
Returns
true if a subscription was canceled
Argument Details
Throws
ERR_NOT_IMPLEMENTED if callback events are not supported
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksFetchApi {
httpClient: HttpClient;
download(url: string): Promise<Uint8Array>;
fetchJson<R>(url: string): Promise<R>;
pathJoin(baseUrl: string, subpath: string): string;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
Supports file-like access to named data storage.
Only minimal functionality required by Chaintracks is supported.
export interface ChaintracksFsApi {
delete(path: string): Promise<void>;
writeFile(path: string, data: Uint8Array): Promise<void>;
readFile(path: string): Promise<Uint8Array>;
openReadableFile(path: string): Promise<ChaintracksReadableFileApi>;
openWritableFile(path: string): Promise<ChaintracksWritableFileApi>;
openAppendableFile(path: string): Promise<ChaintracksAppendableFileApi>;
pathJoin(...parts: string[]): string;
}
See also: ChaintracksAppendableFileApi, ChaintracksReadableFileApi, ChaintracksWritableFileApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksInfoApi {
chain: Chain;
heightBulk: number;
heightLive: number;
storage: string;
bulkIngestors: string[];
liveIngestors: string[];
packages: ChaintracksPackageInfoApi[];
}
See also: Chain, ChaintracksPackageInfoApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksManagementApi extends ChaintracksApi {
destroy(): Promise<void>;
validate(): Promise<boolean>;
exportBulkHeaders(toFolder: string, toFs: ChaintracksFsApi, sourceUrl?: string, toHeadersPerFile?: number, maxHeight?: number): Promise<void>;
}
See also: ChaintracksApi, ChaintracksFsApi
close and release all resources
destroy(): Promise<void>
Exports current bulk headers, including all ingests, excluding live headers to static header files.
Useful for bulk ingestors such as those derived from BulkIngestorCDN.
exportBulkHeaders(toFolder: string, toFs: ChaintracksFsApi, sourceUrl?: string, toHeadersPerFile?: number, maxHeight?: number): Promise<void>
See also: ChaintracksFsApi
Argument Details
Verifies that all headers from the tip back to genesis can be retrieved, in order, by height, and that they obey previousHash constraint.
Additional validations may be addeded.
This is a slow operation.
validate(): Promise<boolean>
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksOptions {
chain: Chain;
storage?: ChaintracksStorageApi;
bulkIngestors: BulkIngestorApi[];
liveIngestors: LiveIngestorApi[];
addLiveRecursionLimit: number;
logging: undefined | "all";
readonly: boolean;
}
See also: BulkIngestorApi, Chain, ChaintracksStorageApi, LiveIngestorApi
Maximum number of missing headers to pursue when listening for new headers. Normally, large numbers of missing headers are handled by bulk ingestors.
addLiveRecursionLimit: number
Event logging level
logging: undefined | "all"
If true, this chaintracks instance will only service read requests for existing data. Shared storage only requires one readonly false instance to manage and update storage.
readonly: boolean
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksPackageInfoApi {
name: string;
version: string;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
Supports access to named data storage (file like).
export interface ChaintracksReadableFileApi {
path: string;
close(): Promise<void>;
getLength(): Promise<number>;
read(length?: number, offset?: number): Promise<Uint8Array>;
}
Returns the length of the data storage in bytes.
getLength(): Promise<number>
read(length?: number, offset?: number): Promise<Uint8Array>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksServiceClientOptions {
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksServiceOptions {
chain: Chain;
routingPrefix: string;
chaintracks?: Chaintracks;
services?: Services;
port?: number;
}
See also: Chain, Chaintracks, Services
Defaults to default configured Chaintracks instance with NoDb storage.
chaintracks?: Chaintracks
See also: Chaintracks
prepended to the path of each registered service endpoint
routingPrefix: string
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageApi extends ChaintracksStorageQueryApi, ChaintracksStorageIngestApi {
bulkManager: BulkFileDataManager;
destroy(): Promise<void>;
}
See also: BulkFileDataManager, ChaintracksStorageIngestApi, ChaintracksStorageQueryApi
Close and release all resources.
destroy(): Promise<void>
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageBaseOptions {
chain: Chain;
liveHeightThreshold: number;
reorgHeightThreshold: number;
bulkMigrationChunkSize: number;
batchInsertLimit: number;
bulkFileDataManager: BulkFileDataManager | undefined;
}
See also: BulkFileDataManager, Chain
Maximum number of headers per call to batchInsert
batchInsertLimit: number
Controls in memory caching and retrieval of missing bulk header data.
bulkFileDataManager: BulkFileDataManager | undefined
See also: BulkFileDataManager
How many excess “live” headers to accumulate before migrating them as a chunk to the bulk header storage.
bulkMigrationChunkSize: number
Which chain is being tracked: main, test, or stn.
chain: Chain
See also: Chain
How much of recent history is required to be kept in “live” block header storage.
Headers with height less than active chain tip height minus liveHeightThreshold
are not required to be kept in “live” storage and may be migrated to “bulk” storage.
As no forks, orphans, or reorgs can affect “bulk” block header storage, an aggressively high number is recommended: At least an order of magnitude more than the deepest actual reorg you can imagine.
liveHeightThreshold: number
How much of recent history must be processed with full validation and reorg support.
Must be less than or equal to liveHeightThreshold
.
Headers with height older than active chain tip height minus reorgHeightThreshold
may use batch processing when ingesting headers.
reorgHeightThreshold: number
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageBulkFileApi {
insertBulkFile(file: BulkHeaderFileInfo): Promise<number>;
updateBulkFile(fileId: number, file: BulkHeaderFileInfo): Promise<number>;
deleteBulkFile(fileId: number): Promise<number>;
getBulkFiles(): Promise<BulkHeaderFileInfo[]>;
getBulkFileData(fileId: number, offset?: number, length?: number): Promise<Uint8Array | undefined>;
}
See also: BulkHeaderFileInfo
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageIngestApi {
insertHeader(header: BlockHeader, prev?: LiveBlockHeader): Promise<InsertHeaderResult>;
pruneLiveBlockHeaders(activeTipHeight: number): Promise<void>;
migrateLiveToBulk(count: number): Promise<void>;
deleteOlderLiveBlockHeaders(maxHeight: number): Promise<number>;
makeAvailable(): Promise<void>;
migrateLatest(): Promise<void>;
dropAllData(): Promise<void>;
destroy(): Promise<void>;
getLiveHeightRange(): Promise<HeightRange>;
}
See also: BlockHeader, HeightRange, InsertHeaderResult, LiveBlockHeader
Delete live headers with height less or equal to maxHeight
after they have been migrated to bulk storage.
deleteOlderLiveBlockHeaders(maxHeight: number): Promise<number>
Argument Details
height
Release all resources. Makes the instance unusable.
destroy(): Promise<void>
getLiveHeightRange(): Promise<HeightRange>
See also: HeightRange
Returns
min, max height range in live database or empty (0, -1)
Attempts to insert a block header into the chain.
Returns ‘added’ false and ‘dupe’ true if header’s hash already exists in the live database Returns ‘added’ false and ‘dupe’ false if header’s previousHash wasn’t found in the live database, or height doesn’t increment previous’ height.
Computes the header’s chainWork from its bits and the previous header’s chainWork.
Returns ‘added’ true if the header was added to the live database. Returns ‘isActiveTip’ true if header’s chainWork is greater than current active chain tip’s chainWork.
If the addition of this header caused a reorg (did not directly extend old active chain tip): Returns ‘reorgDepth’ the minimum height difference of the common ancestor to the two chain tips. Returns ‘priorTip’ the old active chain tip. If not a reorg: Returns ‘reorgDepth’ of zero. Returns ‘priorTip’ the active chain tip before this insert. May be unchanged.
Implementation must call pruneLiveBlockHeaders
after adding new header.
insertHeader(header: BlockHeader, prev?: LiveBlockHeader): Promise<InsertHeaderResult>
See also: BlockHeader, InsertHeaderResult, LiveBlockHeader
Argument Details
Async initialization method.
May be called prior to other async methods to control when initialization occurs.
makeAvailable(): Promise<void>
Migrate storage schema to latest schema changes.
Typically invoked automatically by makeAvailable
.
migrateLatest(): Promise<void>
Migrates the oldest count
LiveBlockHeaders to BulkStorage.
BulkStorage must be configured.
count
must not exceed bulkMigrationChunkSize
.
count
must leave at least liveHeightThreshold
LiveBlockHeaders.
migrateLiveToBulk(count: number): Promise<void>
Argument Details
Must be called after the addition of new LiveBlockHeaders.
Checks the StorageEngine
configuration options to see
if BulkStorage is configured and if there is at least one
bulkMigrationChunkSize
woth of headers in excess of
liveHeightThreshold
available.
If yes, then calls migrateLiveToBulk
one or more times.
pruneLiveBlockHeaders(activeTipHeight: number): Promise<void>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageKnexOptions extends ChaintracksStorageBaseOptions {
knex: Knex | undefined;
headerTableName: string;
bulkBlockHashTableName: string;
bulkMerkleRootTableName: string;
}
See also: ChaintracksStorageBaseOptions
Required.
The table name for the block header hash to height index.
bulkBlockHashTableName: string
Required.
The table name for the block header merkleRoot to height index.
bulkMerkleRootTableName: string
Required.
The table name for live block headers.
headerTableName: string
Required.
Knex.js database interface initialized with valid connection configuration.
knex: Knex | undefined
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageMemoryOptions extends ChaintracksStorageKnexOptions {
sqliteClient: "sqlite3" | "better-sqlite3" | undefined;
}
See also: ChaintracksStorageKnexOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageNoDbOptions extends ChaintracksStorageBaseOptions {
}
See also: ChaintracksStorageBaseOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ChaintracksStorageQueryApi {
findChainTipHeader(): Promise<LiveBlockHeader>;
findChainTipHash(): Promise<string>;
findChainTipHeaderOrUndefined(): Promise<LiveBlockHeader | undefined>;
findChainTipWork(): Promise<string>;
findHeaderForHeight(height: number): Promise<LiveBlockHeader | BlockHeader>;
findHeaderForHeightOrUndefined(height: number): Promise<LiveBlockHeader | BlockHeader | undefined>;
findCommonAncestor(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<LiveBlockHeader>;
findReorgDepth(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<number>;
isMerkleRootActive(merkleRoot: string): Promise<boolean>;
getHeaders(height: number, count: number): Promise<number[]>;
findLiveHeaderForHeight(height: number): Promise<LiveBlockHeader | null>;
findLiveHeaderForHeaderId(headerId: number): Promise<LiveBlockHeader>;
findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | null>;
findLiveHeaderForMerkleRoot(merkleRoot: string): Promise<LiveBlockHeader | null>;
getAvailableHeightRanges(): Promise<{
bulk: HeightRange;
live: HeightRange;
}>;
findLiveHeightRange(): Promise<{
minHeight: number;
maxHeight: number;
}>;
findMaxHeaderId(): Promise<number>;
chain: Chain;
liveHeightThreshold: number;
reorgHeightThreshold: number;
bulkMigrationChunkSize: number;
batchInsertLimit: number;
}
See also: BlockHeader, Chain, HeightRange, LiveBlockHeader
Maximum number of headers per call to batchInsert
batchInsertLimit: number
How many excess “live” headers to accumulate before migrating them as a chunk to the bulk header storage.
bulkMigrationChunkSize: number
Which chain is being tracked: “main” or “test”.
chain: Chain
See also: Chain
How much of recent history is required to be kept in “live” block header storage.
Headers with height older than active chain tip height minus liveHeightThreshold
are not required to be kept in “live” storage and may be migrated to “bulk” storage.
liveHeightThreshold: number
How much of recent history must be processed with full validation and reorg support.
May be less than liveHeightThreshold
.
Headers with height older than active chain tip height minus `` may use batch processing when ingesting headers.
reorgHeightThreshold: number
Returns the block hash of the active chain tip.
findChainTipHash(): Promise<string>
Returns the active chain tip header Throws an error if there is no tip.
findChainTipHeader(): Promise<LiveBlockHeader>
See also: LiveBlockHeader
Returns the active chain tip header or undefined if there is no tip.
findChainTipHeaderOrUndefined(): Promise<LiveBlockHeader | undefined>
See also: LiveBlockHeader
Returns the chainWork value of the active chain tip
findChainTipWork(): Promise<string>
Given two chain tip headers in a chain reorg scenario, return their common ancestor header.
findCommonAncestor(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<LiveBlockHeader>
See also: LiveBlockHeader
Argument Details
Returns block header for a given block height on active chain.
findHeaderForHeight(height: number): Promise<LiveBlockHeader | BlockHeader>
See also: BlockHeader, LiveBlockHeader
Argument Details
Returns block header for a given block height on active chain.
findHeaderForHeightOrUndefined(height: number): Promise<LiveBlockHeader | BlockHeader | undefined>
See also: BlockHeader, LiveBlockHeader
Argument Details
Returns block header for a given block hash. Only from the “live” portion of the chain. Returns null if not found.
findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | null>
See also: LiveBlockHeader
Argument Details
Returns block header for a given headerId.
Only from the “live” portion of the chain.
findLiveHeaderForHeaderId(headerId: number): Promise<LiveBlockHeader>
See also: LiveBlockHeader
Returns block header for a given block height on active chain.
findLiveHeaderForHeight(height: number): Promise<LiveBlockHeader | null>
See also: LiveBlockHeader
Argument Details
Returns block header for a given merkleRoot. Only from the “live” portion of the chain.
findLiveHeaderForMerkleRoot(merkleRoot: string): Promise<LiveBlockHeader | null>
See also: LiveBlockHeader
findLiveHeightRange(): Promise<{
minHeight: number;
maxHeight: number;
}>
Returns
The current minimum and maximum height active LiveBlockHeaders in the “live” database.
findMaxHeaderId(): Promise<number>
Returns
The maximum headerId value used by existing records or -1 if there are none.
This is an original API. Proposed deprecation in favor of findCommonAncestor
Given two headers that are both chain tips in a reorg scenario, returns
the depth of the reorg (the greater of the heights of the two provided
headers, minus the height of their last common ancestor)
findReorgDepth(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<number>
See also: LiveBlockHeader
Returns the height range of both bulk and live storage. Verifies that the ranges meet these requirements:
getAvailableHeightRanges(): Promise<{
bulk: HeightRange;
live: HeightRange;
}>
See also: HeightRange
Adds headers in 80 byte serialized format to a buffer. Only adds active headers. Buffer length divided by 80 is the actual number returned.
This function supports the ChaintracksClientApi
getHeaders(height: number, count: number): Promise<number[]>
Argument Details
Returns true if the given merkleRoot is found in a block header on the active chain.
isMerkleRootActive(merkleRoot: string): Promise<boolean>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Supports creation or re-creation of named data storage from position 0. Any pre-existing data is initially removed. Does not support reading existing data.
export interface ChaintracksWritableFileApi {
path: string;
close(): Promise<void>;
append(data: Uint8Array): Promise<void>;
}
append(data: Uint8Array): Promise<void>
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ExchangeRatesIoApi {
success: boolean;
timestamp: number;
base: "EUR" | "USD";
date: string;
rates: Record<string, number>;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface GetHeaderByteFileLinksResult {
sourceUrl: string;
fileName: string;
range: HeightRange;
data: Uint8Array | undefined;
}
See also: HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface HeightRangeApi {
minHeight: number;
maxHeight: number;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface HeightRanges {
bulk: HeightRange;
live: HeightRange;
}
See also: HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
The “live” portion of the block chain is recent history that can conceivably be subject to reorganizations. The additional fields support tracking orphan blocks, chain forks, and chain reorgs.
export interface LiveBlockHeader extends BlockHeader {
chainWork: string;
isChainTip: boolean;
isActive: boolean;
headerId: number;
previousHeaderId: number | null;
}
See also: BlockHeader
The cummulative chainwork achieved by the addition of this block to the chain. Chainwork only matters in selecting the active chain.
chainWork: string
As there may be more than one header with identical height values due to orphan tracking, headers are assigned a unique headerId while part of the “live” portion of the block chain.
headerId: number
True only if this header is currently on the active chain.
isActive: boolean
True only if this header is currently a chain tip. e.g. There is no header that follows it by previousHash or previousHeaderId.
isChainTip: boolean
Every header in the “live” portion of the block chain is linked to an ancestor header through both its previousHash and previousHeaderId properties.
Due to forks, there may be multiple headers with identical previousHash
and previousHeaderId
values.
Of these, only one (the header on the active chain) will have isActive
=== true.
previousHeaderId: number | null
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface LiveIngestorApi {
shutdown(): Promise<void>;
getHeaderByHash(hash: string): Promise<BlockHeader | undefined>;
setStorage(storage: ChaintracksStorageApi): Promise<void>;
storage(): ChaintracksStorageApi;
startListening(liveHeaders: BlockHeader[]): Promise<void>;
stopListening(): void;
}
See also: BlockHeader, ChaintracksStorageApi
Called before first Synchronize with reference to storage. Components requiring asynchronous setup can override base class implementation.
setStorage(storage: ChaintracksStorageApi): Promise<void>
See also: ChaintracksStorageApi
Close and release all resources.
shutdown(): Promise<void>
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface LiveIngestorBaseOptions {
chain: Chain;
}
See also: Chain
The target chain: “main” or “test”
chain: Chain
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface LiveIngestorWhatsOnChainOptions extends LiveIngestorBaseOptions, WhatsOnChainServicesOptions {
idleWait: number | undefined;
chain: Chain;
apiKey?: string;
timeout: number;
userAgent: string;
enableCache: boolean;
chainInfoMsecs: number;
}
See also: Chain, LiveIngestorBaseOptions, WhatsOnChainServicesOptions
WhatsOnChain.com API Key https://docs.taal.com/introduction/get-an-api-key If unknown or empty, maximum request rate is limited. https://developers.whatsonchain.com/#rate-limits
apiKey?: string
Which chain is being tracked: main, test, or stn.
chain: Chain
See also: Chain
How long chainInfo is considered still valid before updating (msecs).
chainInfoMsecs: number
Enable WhatsOnChain client cache option.
enableCache: boolean
Maximum msces of “normal” time with no ping received from connected WoC service.
idleWait: number | undefined
Request timeout for GETs to https://api.whatsonchain.com/v1/bsv
timeout: number
User-Agent header value for requests to https://api.whatsonchain.com/v1/bsv
userAgent: string
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ServiceCall {
when: Date | string;
msecs: number;
success: boolean;
result?: string;
error?: {
message: string;
code: string;
};
}
Error code and message iff success is false and a exception was thrown.
error?: {
message: string;
code: string;
}
Simple text summary of result. e.g. not a valid utxo
or valid utxo
result?: string
true iff service provider successfully processed the request false iff service provider failed to process the request which includes thrown errors.
success: boolean
string value must be Date’s toISOString format.
when: Date | string
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface ServiceToCall<T> {
providerName: string;
serviceName: string;
service: T;
call: ServiceCall;
}
See also: ServiceCall
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface WhatsOnChainServicesOptions {
chain: Chain;
apiKey?: string;
timeout: number;
userAgent: string;
enableCache: boolean;
chainInfoMsecs: number;
}
See also: Chain
WhatsOnChain.com API Key https://docs.taal.com/introduction/get-an-api-key If unknown or empty, maximum request rate is limited. https://developers.whatsonchain.com/#rate-limits
apiKey?: string
Which chain is being tracked: main, test, or stn.
chain: Chain
See also: Chain
How long chainInfo is considered still valid before updating (msecs).
chainInfoMsecs: number
Enable WhatsOnChain client cache option.
enableCache: boolean
Request timeout for GETs to https://api.whatsonchain.com/v1/bsv
timeout: number
User-Agent header value for requests to https://api.whatsonchain.com/v1/bsv
userAgent: string
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface WocChainInfo {
chain: string;
blocks: number;
headers: number;
bestblockhash: string;
difficulty: number;
mediantime: number;
verificationprogress: number;
pruned: boolean;
chainwork: string;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface WocGetHeaderByteFileLinks {
files: string[];
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface WocGetHeadersHeader {
hash: string;
confirmations: number;
size: number;
height: number;
version: number;
versionHex: string;
merkleroot: string;
time: number;
mediantime: number;
nonce: number;
bits: string;
difficulty: number;
chainwork: string;
previousblockhash: string;
nextblockhash: string;
nTx: number;
num_tx: number;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export interface WocHeader {
hash: string;
size: number;
height: number;
version: number;
versionHex: string;
merkleroot: string;
time: number;
mediantime: number;
nonce: number;
bits: number | string;
difficulty: number;
chainwork: string;
previousblockhash: string;
confirmations: number;
txcount: number;
nextblockhash: string;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
Links: API, Interfaces, Classes, Functions, Types, Variables
Represents an ARC transaction broadcaster.
export class ARC {
readonly name: string;
readonly URL: string;
readonly apiKey: string | undefined;
readonly deploymentId: string;
readonly callbackUrl: string | undefined;
readonly callbackToken: string | undefined;
readonly headers: Record<string, string> | undefined;
constructor(URL: string, config?: ArcConfig, name?: string);
constructor(URL: string, apiKey?: string, name?: string);
constructor(URL: string, config?: string | ArcConfig, name?: string)
async postRawTx(rawTx: HexString, txids?: string[]): Promise<PostTxResultForTxid>
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
async getTxData(txid: string): Promise<ArcMinerGetTxData>
}
See also: ArcConfig, ArcMinerGetTxData, PostBeefResult, PostTxResultForTxid
Constructs an instance of the ARC broadcaster.
constructor(URL: string, config?: ArcConfig, name?: string)
See also: ArcConfig
Argument Details
Constructs an instance of the ARC broadcaster.
constructor(URL: string, apiKey?: string, name?: string)
Argument Details
This seems to only work for recently submitted txids…but that’s all we need to complete postBeef!
async getTxData(txid: string): Promise<ArcMinerGetTxData>
See also: ArcMinerGetTxData
ARC does not natively support a postBeef end-point aware of multiple txids of interest in the Beef.
It does process multiple new transactions, however, which allows results for all txids of interest
to be collected by the /v1/tx/${txid}
endpoint.
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
See also: PostBeefResult
The ARC ‘/v1/tx’ endpoint, as of 2025-02-17 supports all of the following hex string formats:
The ARC ‘/v1/tx’ endpoint, as of 2025-02-17 DOES NOT support the following hex string formats:
async postRawTx(rawTx: HexString, txids?: string[]): Promise<PostTxResultForTxid>
See also: PostTxResultForTxid
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BHServiceClient implements ChaintracksServiceClient {
bhs: BlockHeadersService;
cache: Record<number, string>;
chain: Chain;
serviceUrl: string;
options: ChaintracksServiceClientOptions;
apiKey: string;
constructor(chain: Chain, url: string, apiKey: string)
async currentHeight(): Promise<number>
async isValidRootForHeight(root: string, height: number): Promise<boolean>
async getPresentHeight(): Promise<number>
async findHeaderForHeight(height: number): Promise<BlockHeader | undefined>
async findHeaderForBlockHash(hash: string): Promise<BlockHeader | undefined>
async getHeaders(height: number, count: number): Promise<string>
async findChainWorkForBlockHash(hash: string): Promise<string | undefined>
async findChainTipHeader(): Promise<BlockHeader>
async getJsonOrUndefined<T>(path: string): Promise<T | undefined>
async getJson<T>(path: string): Promise<T>
async postJsonVoid<T>(path: string, params: T): Promise<void>
async addHeader(header: any): Promise<void>
async findHeaderForMerkleRoot(merkleRoot: string, height?: number): Promise<undefined>
async startListening(): Promise<void>
async listening(): Promise<void>
async isSynchronized(): Promise<boolean>
async getChain(): Promise<Chain>
async isListening(): Promise<boolean>
async getChainTipHeader(): Promise<BlockHeader>
async findChainTipHash(): Promise<string>
async subscribeHeaders(listener: HeaderListener): Promise<string>
async subscribeReorgs(listener: ReorgListener): Promise<string>
async unsubscribe(subscriptionId: string): Promise<boolean>
async getInfo(): Promise<ChaintracksInfoApi>
}
See also: BlockHeader, Chain, ChaintracksInfoApi, ChaintracksServiceClient, ChaintracksServiceClientOptions, HeaderListener, ReorgListener
Links: API, Interfaces, Classes, Functions, Types, Variables
export class Bitails {
readonly chain: Chain;
readonly apiKey: string;
readonly URL: string;
readonly httpClient: HttpClient;
constructor(chain: Chain = "main", config: BitailsConfig = {})
getHttpHeaders(): Record<string, string>
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
async postRaws(raws: HexString[], txids?: string[]): Promise<PostBeefResult>
async getMerklePath(txid: string, services: WalletServices): Promise<GetMerklePathResult>
}
See also: BitailsConfig, Chain, GetMerklePathResult, PostBeefResult, WalletServices
Bitails does not natively support a postBeef end-point aware of multiple txids of interest in the Beef.
Send rawTx in txids
order from beef.
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
See also: PostBeefResult
async postRaws(raws: HexString[], txids?: string[]): Promise<PostBeefResult>
See also: PostBeefResult
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Manages bulk file data (typically 8MB chunks of 100,000 headers each).
If not cached in memory,
optionally fetches data by sourceUrl
from CDN on demand,
optionally finds data by fileId
in a database on demand,
and retains a limited number of files in memory,
subject to the optional maxRetained
limit.
export class BulkFileDataManager {
static createDefaultOptions(chain: Chain): BulkFileDataManagerOptions
readonly chain: Chain;
readonly maxPerFile: number;
readonly fetch?: ChaintracksFetchApi;
readonly maxRetained?: number;
readonly fromKnownSourceUrl?: string;
constructor(options: BulkFileDataManagerOptions | Chain)
async createReader(range?: HeightRange, maxBufferSize?: number): Promise<BulkFileDataReader>
async updateFromUrl(cdnUrl: string): Promise<void>
async setStorage(storage: ChaintracksStorageBulkFileApi): Promise<void>
async deleteBulkFiles(): Promise<void>
async merge(files: BulkHeaderFileInfo[]): Promise<BulkFileDataManagerMergeResult>
toLogString(what?: BulkFileDataManagerMergeResult | BulkFileData[] | BulkHeaderFileInfo[]): string
async mergeIncrementalBlockHeaders(newBulkHeaders: BlockHeader[], incrementalChainWork?: string): Promise<void>
async getBulkFiles(keepData?: boolean): Promise<BulkHeaderFileInfo[]>
async getHeightRange(): Promise<HeightRange>
async getDataFromFile(file: BulkHeaderFileInfo, offset?: number, length?: number): Promise<Uint8Array | undefined>
async findHeaderForHeightOrUndefined(height: number): Promise<BlockHeader | undefined>
async getFileForHeight(height: number): Promise<BulkHeaderFileInfo | undefined>
async getLastFile(fromEnd = 1): Promise<BulkHeaderFileInfo | undefined>
async ReValidate(): Promise<void>
async exportHeadersToFs(toFs: ChaintracksFsApi, toHeadersPerFile: number, toFolder: string, sourceUrl?: string, maxHeight?: number): Promise<void>
}
See also: BlockHeader, BulkFileDataManagerMergeResult, BulkFileDataManagerOptions, BulkFileDataReader, BulkHeaderFileInfo, Chain, ChaintracksFetchApi, ChaintracksFsApi, ChaintracksStorageBulkFileApi, HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkFileDataReader {
readonly manager: BulkFileDataManager;
readonly range: HeightRange;
readonly maxBufferSize: number;
nextHeight: number;
constructor(manager: BulkFileDataManager, range: HeightRange, maxBufferSize: number)
async read(): Promise<Uint8Array | undefined>
}
See also: BulkFileDataManager, HeightRange
async read(): Promise<Uint8Array | undefined>
Returns
an array containing the next maxBufferSize
bytes of headers from the files.
Links: API, Interfaces, Classes, Functions, Types, Variables
Breaks available bulk headers stored in multiple files into a sequence of buffers with limited maximum size.
export class BulkFilesReader {
files: BulkHeaderFile[];
range: HeightRange;
maxBufferSize = 400 * 80;
nextHeight: number | undefined;
constructor(files: BulkHeaderFile[], range?: HeightRange, maxBufferSize?: number)
protected setRange(range?: HeightRange)
setMaxBufferSize(maxBufferSize: number | undefined)
get heightRange(): HeightRange
async readBufferForHeightOrUndefined(height: number): Promise<Uint8Array | undefined>
async readBufferForHeight(height: number): Promise<Uint8Array>
async readHeaderForHeight(height: number): Promise<BaseBlockHeader>
async readHeaderForHeightOrUndefined(height: number): Promise<BaseBlockHeader | undefined>
async read(): Promise<Uint8Array | undefined>
resetRange(range: HeightRange, maxBufferSize?: number)
async validateFiles(): Promise<void>
async exportHeadersToFs(toFs: ChaintracksFsApi, toHeadersPerFile: number, toFolder: string): Promise<void>
}
See also: BaseBlockHeader, BulkHeaderFile, ChaintracksFsApi, HeightRange
Previously validated bulk header files which may pull data from backing storage on demand.
files: BulkHeaderFile[]
See also: BulkHeaderFile
Maximum buffer size returned from read()
in bytes.
maxBufferSize = 400 * 80
“Read pointer”, the next height to be “read”.
nextHeight: number | undefined
Subset of headers currently being “read”.
range: HeightRange
See also: HeightRange
async read(): Promise<Uint8Array | undefined>
Returns
an array containing the next maxBufferSize
bytes of headers from the files.
Reset the reading process and adjust the range to be read to a new subset of what’s available…
resetRange(range: HeightRange, maxBufferSize?: number)
See also: HeightRange
Argument Details
read
calls to return.read
to returnLinks: API, Interfaces, Classes, Functions, Types, Variables
export class BulkFilesReaderFs extends BulkFilesReader {
constructor(public fs: ChaintracksFsApi, files: BulkHeaderFileFs[], range?: HeightRange, maxBufferSize?: number)
static async fromFs(fs: ChaintracksFsApi, rootFolder: string, jsonFilename: string, range?: HeightRange, maxBufferSize?: number): Promise<BulkFilesReaderFs>
static async writeEmptyJsonFile(fs: ChaintracksFsApi, rootFolder: string, jsonFilename: string): Promise<string>
static async readJsonFile(fs: ChaintracksFsApi, rootFolder: string, jsonFilename: string, failToEmptyRange: boolean = true): Promise<BulkHeaderFilesInfo>
}
See also: BulkFilesReader, BulkHeaderFileFs, BulkHeaderFilesInfo, ChaintracksFsApi, HeightRange
Return a BulkFilesReader configured to access the intersection of range
and available headers.
static async fromFs(fs: ChaintracksFsApi, rootFolder: string, jsonFilename: string, range?: HeightRange, maxBufferSize?: number): Promise<BulkFilesReaderFs>
See also: BulkFilesReaderFs, ChaintracksFsApi, HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkFilesReaderStorage extends BulkFilesReader {
constructor(storage: ChaintracksStorageBase, files: BulkHeaderFileStorage[], range?: HeightRange, maxBufferSize?: number)
static async fromStorage(storage: ChaintracksStorageBase, fetch: ChaintracksFetchApi, range?: HeightRange, maxBufferSize?: number): Promise<BulkFilesReaderStorage>
}
See also: BulkFilesReader, BulkHeaderFileStorage, ChaintracksFetchApi, ChaintracksStorageBase, HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class BulkHeaderFile implements BulkHeaderFileInfo {
chain?: Chain | undefined;
count: number;
data?: Uint8Array<ArrayBufferLike> | undefined;
fileHash: string | null;
fileId?: number | undefined;
fileName: string;
firstHeight: number;
lastChainWork: string;
lastHash: string | null;
prevChainWork: string;
prevHash: string;
sourceUrl?: string | undefined;
validated?: boolean | undefined;
constructor(info: BulkHeaderFileInfo)
abstract readDataFromFile(length: number, offset: number): Promise<Uint8Array | undefined>;
get heightRange(): HeightRange
async ensureData(): Promise<Uint8Array>
async computeFileHash(): Promise<string>
async releaseData(): Promise<void>
toCdnInfo(): BulkHeaderFileInfo
toStorageInfo(): BulkHeaderFileInfo
}
See also: BulkHeaderFileInfo, Chain, HeightRange
Whenever reloading data from a backing store, validated fileHash must be re-verified
async computeFileHash(): Promise<string>
Returns
the sha256 hash of the file’s data as base64 string.
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkHeaderFileFs extends BulkHeaderFile {
constructor(info: BulkHeaderFileInfo, public fs: ChaintracksFsApi, public rootFolder: string)
override async readDataFromFile(length: number, offset: number): Promise<Uint8Array | undefined>
override async ensureData(): Promise<Uint8Array>
}
See also: BulkHeaderFile, BulkHeaderFileInfo, ChaintracksFsApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkHeaderFileStorage extends BulkHeaderFile {
constructor(info: BulkHeaderFileInfo, public storage: ChaintracksStorageBase, public fetch: ChaintracksFetchApi)
override async readDataFromFile(length: number, offset: number): Promise<Uint8Array | undefined>
override async ensureData(): Promise<Uint8Array>
}
See also: BulkHeaderFile, BulkHeaderFileInfo, ChaintracksFetchApi, ChaintracksStorageBase
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class BulkHeaderFiles implements BulkHeaderFilesInfo {
constructor(public rootFolder: string, public jsonFilename: string, public files: BulkHeaderFileInfo[], public headersPerFile: number)
}
See also: BulkHeaderFileInfo, BulkHeaderFilesInfo
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class BulkIngestorBase implements BulkIngestorApi {
static createBulkIngestorBaseOptions(chain: Chain)
chain: Chain;
jsonFilename: string;
bypassLiveEnabled: boolean;
constructor(options: BulkIngestorBaseOptions)
async setStorage(storage: ChaintracksStorageBase): Promise<void>
async shutdown(): Promise<void>
storageOrUndefined(): ChaintracksStorageApi | undefined
storage(): ChaintracksStorageBase
filesInfo: BulkHeaderFilesInfo | undefined;
async getPresentHeight(): Promise<number | undefined>
abstract fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>;
async synchronize(presentHeight: number, before: HeightRanges, priorLiveHeaders: BlockHeader[]): Promise<BulkSyncResult>
}
See also: BlockHeader, BulkHeaderFilesInfo, BulkIngestorApi, BulkIngestorBaseOptions, BulkSyncResult, Chain, ChaintracksStorageApi, ChaintracksStorageBase, HeightRange, HeightRanges
information about locally cached bulk header files managed by this bulk ingestor
filesInfo: BulkHeaderFilesInfo | undefined
See also: BulkHeaderFilesInfo
static createBulkIngestorBaseOptions(chain: Chain)
See also: Chain
Argument Details
A BulkIngestor fetches and updates storage with bulk headers in bulkRange.
If it can, it must also fetch live headers in fetch range that are not in bulkRange and return them as an array.
The storage methods insertBulkFile
, updateBulkFile
, and addBulkHeaders
should be used to add bulk headers to storage.
abstract fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
See also: BlockHeader, HeightRange, HeightRanges
Returns
new live headers: headers in fetchRange but not in bulkRange
Argument Details
At least one derived BulkIngestor must override this method to provide the current height of the active chain tip.
async getPresentHeight(): Promise<number | undefined>
Returns
undefined unless overridden
A BulkIngestor has two potential goals:
async synchronize(presentHeight: number, before: HeightRanges, priorLiveHeaders: BlockHeader[]): Promise<BulkSyncResult>
See also: BlockHeader, BulkSyncResult, HeightRanges
Returns
updated priorLiveHeaders including any accumulated by this ingestor
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkIngestorCDN extends BulkIngestorBase {
static createBulkIngestorCDNOptions(chain: Chain, cdnUrl: string, fetch: ChaintracksFetchApi, maxPerFile?: number): BulkIngestorCDNOptions
fetch: ChaintracksFetchApi;
jsonResource: string;
cdnUrl: string;
maxPerFile: number | undefined;
availableBulkFiles: BulkHeaderFilesInfo | undefined;
selectedFiles: BulkHeaderFileInfo[] | undefined;
currentRange: HeightRange | undefined;
constructor(options: BulkIngestorCDNOptions)
override async getPresentHeight(): Promise<number | undefined>
getJsonHttpHeaders(): Record<string, string>
async fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
}
See also: BlockHeader, BulkHeaderFileInfo, BulkHeaderFilesInfo, BulkIngestorBase, BulkIngestorCDNOptions, Chain, ChaintracksFetchApi, HeightRange, HeightRanges
static createBulkIngestorCDNOptions(chain: Chain, cdnUrl: string, fetch: ChaintracksFetchApi, maxPerFile?: number): BulkIngestorCDNOptions
See also: BulkIngestorCDNOptions, Chain, ChaintracksFetchApi
Argument Details
A BulkFile CDN serves a JSON BulkHeaderFilesInfo resource which lists all the available binary bulk header files available and associated metadata.
The term “CDN file” is used for a local bulk file that has a sourceUrl. (Not undefined) The term “incremental file” is used for the local bulk file that holds all the non-CDN bulk headers and must chain to the live headers if there are any.
Bulk ingesting from a CDN happens in one of three contexts:
Context Cold Start:
Context Incremental:
Context Replace:
async fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
See also: BlockHeader, HeightRange, HeightRanges
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkIngestorCDNBabbage extends BulkIngestorCDN {
static createBulkIngestorCDNBabbageOptions(chain: Chain, fetch: ChaintracksFetchApi): BulkIngestorCDNOptions
}
See also: BulkIngestorCDN, BulkIngestorCDNOptions, Chain, ChaintracksFetchApi
static createBulkIngestorCDNBabbageOptions(chain: Chain, fetch: ChaintracksFetchApi): BulkIngestorCDNOptions
See also: BulkIngestorCDNOptions, Chain, ChaintracksFetchApi
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkIngestorWhatsOnChainCdn extends BulkIngestorBase {
static createBulkIngestorWhatsOnChainOptions(chain: Chain): BulkIngestorWhatsOnChainOptions
fetch: ChaintracksFetchApi;
idleWait: number;
woc: WhatsOnChainServices;
stopOldListenersToken: StopListenerToken = { stop: undefined };
constructor(options: BulkIngestorWhatsOnChainOptions)
override async getPresentHeight(): Promise<number | undefined>
async fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
}
See also: BlockHeader, BulkIngestorBase, BulkIngestorWhatsOnChainOptions, Chain, ChaintracksFetchApi, HeightRange, HeightRanges, StopListenerToken, WhatsOnChainServices
static createBulkIngestorWhatsOnChainOptions(chain: Chain): BulkIngestorWhatsOnChainOptions
See also: BulkIngestorWhatsOnChainOptions, Chain
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class BulkIngestorWhatsOnChainWs extends BulkIngestorBase {
static createBulkIngestorWhatsOnChainOptions(chain: Chain): BulkIngestorWhatsOnChainOptions
idleWait: number;
woc: WhatsOnChainServices;
stopOldListenersToken: StopListenerToken = { stop: undefined };
constructor(options: BulkIngestorWhatsOnChainOptions)
override async getPresentHeight(): Promise<number | undefined>
async fetchHeaders(before: HeightRanges, fetchRange: HeightRange, bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
}
See also: BlockHeader, BulkIngestorBase, BulkIngestorWhatsOnChainOptions, Chain, HeightRange, HeightRanges, StopListenerToken, WhatsOnChainServices
static createBulkIngestorWhatsOnChainOptions(chain: Chain): BulkIngestorWhatsOnChainOptions
See also: BulkIngestorWhatsOnChainOptions, Chain
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class BulkStorageBase implements BulkStorageApi {
static createBulkStorageBaseOptions(chain: Chain, fs: ChaintracksFsApi): BulkStorageBaseOptions
chain: Chain;
fs: ChaintracksFsApi;
constructor(options: BulkStorageBaseOptions)
async shutdown(): Promise<void>
abstract appendHeaders(minHeight: number, count: number, newBulkHeaders: Uint8Array): Promise<void>;
abstract getMaxHeight(): Promise<number>;
abstract headersToBuffer(height: number, count: number): Promise<Uint8Array>;
abstract findHeaderForHeightOrUndefined(height: number): Promise<BlockHeader | undefined>;
async findHeaderForHeight(height: number): Promise<BlockHeader>
async getHeightRange(): Promise<HeightRange>
async setStorage(storage: ChaintracksStorageBase): Promise<void>
async exportBulkHeaders(rootFolder: string, jsonFilename: string, maxPerFile: number): Promise<void>
}
See also: BlockHeader, BulkStorageApi, BulkStorageBaseOptions, Chain, ChaintracksFsApi, ChaintracksStorageBase, HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export class Chaintracks implements ChaintracksManagementApi {
static createOptions(chain: Chain): ChaintracksOptions
log: (...args: any[]) => void = () => { };
readonly chain: Chain;
readonly readonly: boolean;
constructor(public options: ChaintracksOptions)
async getChain(): Promise<Chain>
async getPresentHeight(): Promise<number>
async currentHeight(): Promise<number>
async subscribeHeaders(listener: HeaderListener): Promise<string>
async subscribeReorgs(listener: ReorgListener): Promise<string>
async unsubscribe(subscriptionId: string): Promise<boolean>
async addHeader(header: BaseBlockHeader): Promise<void>
async makeAvailable(): Promise<void>
async startPromises(): Promise<void>
async destroy(): Promise<void>
async listening(): Promise<void>
async isListening(): Promise<boolean>
async isSynchronized(): Promise<boolean>
async findHeaderForHeight(height: number): Promise<BlockHeader | undefined>
async findHeaderForBlockHash(hash: string): Promise<BlockHeader | undefined>
async findHeaderForBlockHashNoLock(hash: string): Promise<BlockHeader | undefined>
async isValidRootForHeight(root: string, height: number): Promise<boolean>
async getInfo(): Promise<ChaintracksInfoApi>
async getHeaders(height: number, count: number): Promise<string>
async findChainTipHeader(): Promise<BlockHeader>
async findChainTipHash(): Promise<string>
async findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | undefined>
async findChainWorkForBlockHash(hash: string): Promise<string | undefined>
async validate(): Promise<boolean>
async exportBulkHeaders(toFolder: string, toFs: ChaintracksFsApi, sourceUrl?: string, toHeadersPerFile?: number, maxHeight?: number): Promise<void>
async startListening(): Promise<void>
private async syncBulkStorageNoLock(presentHeight: number, initialRanges: HeightRanges): Promise<void> {
let newLiveHeaders: BlockHeader[] = [];
let bulkDone = false;
let before = initialRanges;
let after = before;
let added = HeightRange.empty;
let done = false;
for (; !done;) {
for (const bulk of this.bulkIngestors) {
try {
const r = await bulk.synchronize(presentHeight, before, newLiveHeaders);
newLiveHeaders = r.liveHeaders;
after = await this.storage.getAvailableHeightRanges();
added = after.bulk.above(before.bulk);
before = after;
this.log(`Bulk Ingestor: ${added.length} added with ${newLiveHeaders.length} live headers from ${bulk.constructor.name}`);
if (r.done) {
done = true;
break;
}
}
catch (uerr: unknown) {
console.log(uerr);
}
}
if (bulkDone)
break;
}
this.liveHeaders.unshift(...newLiveHeaders);
added = after.bulk.above(initialRanges.bulk);
this.log(`syncBulkStorage done
Before sync: bulk ${initialRanges.bulk}, live ${initialRanges.live}
After sync: bulk ${after.bulk}, live ${after.live}
${added.length} headers added to bulk storage
${this.liveHeaders.length} headers forwarded to live header storage
`);
}
private async mainThreadShiftLiveHeaders(): Promise<void> {
this.stopMainThread = false;
let lastSyncCheck = Date.now();
let lastBulkSync = Date.now();
const cdnSyncRepeatMsecs = 24 * 60 * 60 * 1000;
const syncCheckRepeatMsecs = 30 * 60 * 1000;
while (!this.stopMainThread) {
const now = Date.now();
lastSyncCheck = now;
const presentHeight = await this.getPresentHeight();
const before = await this.storage.getAvailableHeightRanges();
let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
if (skipBulkSync && now - lastSyncCheck > cdnSyncRepeatMsecs) {
skipBulkSync = false;
}
this.log(`Chaintracks Update Services: Bulk Header Sync Review
presentHeight=${presentHeight} addLiveRecursionLimit=${this.addLiveRecursionLimit}
Before synchronize: bulk ${before.bulk}, live ${before.live}
${skipBulkSync ? "Skipping" : "Starting"} syncBulkStorage.
`);
if (!skipBulkSync) {
lastBulkSync = now;
if (this.available)
await this.syncBulkStorage(presentHeight, before);
else
await this.syncBulkStorageNoLock(presentHeight, before);
}
let count = 0;
let liveHeaderDupes = 0;
let needSyncCheck = false;
for (; !needSyncCheck && !this.stopMainThread;) {
let header = this.liveHeaders.shift();
if (header) {
let recursions = this.addLiveRecursionLimit;
for (; !needSyncCheck && !this.stopMainThread;) {
const ihr = await this.addLiveHeader(header);
if (this.invalidInsertHeaderResult(ihr)) {
this.log(`Ignoring liveHeader ${header.height} ${header.hash} due to invalid insert result.`);
needSyncCheck = true;
}
else if (ihr.noPrev) {
if (recursions-- <= 0) {
this.log(`Ignoring liveHeader ${header.height} ${header.hash} addLiveRecursionLimit=${this.addLiveRecursionLimit} exceeded.`);
needSyncCheck = true;
}
else {
const hash = header.previousHash;
const prevHeader = await this.getMissingBlockHeader(hash);
if (!prevHeader) {
this.log(`Ignoring liveHeader ${header.height} ${header.hash} failed to find previous header by hash ${asString(hash)}`);
needSyncCheck = true;
}
else {
this.liveHeaders.unshift(header);
header = prevHeader;
}
}
}
else {
if (this.subscriberCallbacksEnabled)
this.log(`addLiveHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
if (ihr.dupe) {
liveHeaderDupes++;
}
if (ihr.added) {
count++;
}
break;
}
}
}
else {
const bheader = this.baseHeaders.shift();
if (bheader) {
const prev = await this.storage.findLiveHeaderForBlockHash(bheader.previousHash);
if (!prev) {
this.log(`Ignoring header with unknown previousHash ${bheader.previousHash} in live storage.`);
}
else {
const header: BlockHeader = {
...bheader,
height: prev.height + 1,
hash: blockHash(bheader)
};
const ihr = await this.addLiveHeader(header);
if (this.invalidInsertHeaderResult(ihr)) {
this.log(`Ignoring invalid baseHeader ${header.height} ${header.hash}.`);
}
else {
if (this.subscriberCallbacksEnabled)
this.log(`addBaseHeader ${header.height}${ihr.added ? " added" : ""}${ihr.dupe ? " dupe" : ""}${ihr.isActiveTip ? " isActiveTip" : ""}${ihr.reorgDepth ? " reorg depth " + ihr.reorgDepth : ""}${ihr.noPrev ? " noPrev" : ""}${ihr.noActiveAncestor || ihr.noTip || ihr.badPrev ? " error" : ""}`);
if (ihr.added) {
count++;
}
}
}
}
else {
if (count > 0) {
if (liveHeaderDupes > 0) {
this.log(`${liveHeaderDupes} duplicate headers ignored.`);
liveHeaderDupes = 0;
}
const updated = await this.storage.getAvailableHeightRanges();
this.log(`${count} live headers added: bulk ${updated.bulk}, live ${updated.live}`);
count = 0;
}
if (!this.subscriberCallbacksEnabled) {
const live = await this.storage.getLiveHeightRange();
if (!live.isEmpty) {
this.subscriberCallbacksEnabled = true;
this.log(`listening at height of ${live.maxHeight}`);
}
}
if (!this.available) {
this.available = true;
}
needSyncCheck = Date.now() - lastSyncCheck > syncCheckRepeatMsecs;
if (!needSyncCheck)
await wait(1000);
}
}
}
}
}
}
See also: BaseBlockHeader, BlockHeader, Chain, ChaintracksFsApi, ChaintracksInfoApi, ChaintracksManagementApi, ChaintracksOptions, HeaderListener, HeightRange, HeightRanges, LiveBlockHeader, ReorgListener, Services, asString, blockHash, wait
Queues a potentially new, unknown header for consideration as an addition to the chain.
When the header is considered, if the prior header is unknown, recursive calls to the
bulk ingestors will be attempted to resolve the linkage up to a depth of addLiveRecursionLimit
.
Headers are considered in the order they were added.
async addHeader(header: BaseBlockHeader): Promise<void>
See also: BaseBlockHeader
Caches and returns most recently sourced value if less than one minute old.
async getPresentHeight(): Promise<number>
Returns
the current externally available chain height (via bulk ingestors).
If not already available, takes a writer lock to queue calls until available.
Becoming available starts by initializing ingestors and main thread,
and ends when main thread sets available
.
Note that the main thread continues running and takes additional write locks
itself when already available.
async makeAvailable(): Promise<void>
Returns
when available for client requests
async validate(): Promise<boolean>
Returns
true iff all headers from height zero through current chainTipHeader height can be retreived and form a valid chain.
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksAppendableFile extends ChaintracksReadableFile implements ChaintracksAppendableFileApi {
foldersEnsured: boolean = false;
static async openAsAppendable(path: string): Promise<ChaintracksAppendableFile>
async ensureFoldersExist(): Promise<void>
async append(data: Uint8Array): Promise<void>
}
See also: ChaintracksAppendableFileApi, ChaintracksReadableFile
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksChainTracker implements ChainTracker {
chaintracks: ChaintracksServiceClient;
cache: Record<number, string>;
options: ChaintracksChainTrackerOptions;
constructor(chain?: Chain, chaintracks?: ChaintracksServiceClient, options?: ChaintracksChainTrackerOptions)
async currentHeight(): Promise<number>
async isValidRootForHeight(root: string, height: number): Promise<boolean>
}
See also: Chain, ChaintracksChainTrackerOptions, ChaintracksServiceClient
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksFetch implements ChaintracksFetchApi {
httpClient: HttpClient = defaultHttpClient();
constructor()
async download(url: string): Promise<Uint8Array>
async fetchJson<R>(url: string): Promise<R>
pathJoin(baseUrl: string, subpath: string): string
}
See also: ChaintracksFetchApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class ChaintracksFsStatics {
static async delete(path: string): Promise<void>
static async writeFile(path: string, data: Uint8Array): Promise<void>
static async readFile(path: string): Promise<Uint8Array>
static async openReadableFile(path: string): Promise<ChaintracksReadableFileApi>
static async openWritableFile(path: string): Promise<ChaintracksWritableFileApi>
static async openAppendableFile(path: string): Promise<ChaintracksAppendableFileApi>
static async ensureFoldersExist(path: string): Promise<void>
static pathJoin(...parts: string[]): string
}
See also: ChaintracksAppendableFileApi, ChaintracksReadableFileApi, ChaintracksWritableFileApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksKnexMigrations implements MigrationSource<string> {
migrations: Record<string, Migration> = {};
constructor(public chain: Chain)
async getMigrations(): Promise<string[]>
getMigrationName(migration: string)
async getMigration(migration: string): Promise<Migration>
async getLatestMigration(): Promise<string>
static async latestMigration(): Promise<string>
setupMigrations(): Record<string, Migration>
}
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksReadableFile implements ChaintracksReadableFileApi {
path: string;
parsedPath: Path.ParsedPath;
f: fs.FileHandle;
protected constructor(path: string, f: fs.FileHandle)
async close(): Promise<void>
async getLength(): Promise<number>
async read(length?: number, offset?: number): Promise<Uint8Array>
static async openAsReadable(path: string): Promise<ChaintracksReadableFile>
}
See also: ChaintracksReadableFileApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksService {
static createChaintracksServiceOptions(chain: Chain): ChaintracksServiceOptions
chain: Chain;
options: ChaintracksServiceOptions;
port?: number;
chaintracks: Chaintracks;
services: Services;
server?: Server<typeof IncomingMessage, typeof ServerResponse>;
constructor(options: ChaintracksServiceOptions)
async stopJsonRpcServer(): Promise<void>
async startJsonRpcServer(port?: number): Promise<void>
}
See also: Chain, Chaintracks, ChaintracksServiceOptions, Services
Links: API, Interfaces, Classes, Functions, Types, Variables
Connects to a ChaintracksService to implement ‘ChaintracksClientApi’
export class ChaintracksServiceClient implements ChaintracksClientApi {
static createChaintracksServiceClientOptions(): ChaintracksServiceClientOptions
options: ChaintracksServiceClientOptions;
constructor(public chain: Chain, public serviceUrl: string, options?: ChaintracksServiceClientOptions)
subscribeHeaders(listener: HeaderListener): Promise<string>
subscribeReorgs(listener: ReorgListener): Promise<string>
unsubscribe(subscriptionId: string): Promise<boolean>
async currentHeight(): Promise<number>
async isValidRootForHeight(root: string, height: number): Promise<boolean>
async getJsonOrUndefined<T>(path: string): Promise<T | undefined>
async getJson<T>(path: string): Promise<T>
async postJsonVoid<T>(path: string, params: T): Promise<void>
async addHeader(header: BaseBlockHeader): Promise<void>
async startListening(): Promise<void>
async listening(): Promise<void>
async getChain(): Promise<Chain>
async isListening(): Promise<boolean>
async isSynchronized(): Promise<boolean>
async getPresentHeight(): Promise<number>
async getInfo(): Promise<ChaintracksInfoApi>
async findChainTipHeader(): Promise<BlockHeader>
async findChainTipHash(): Promise<string>
async getHeaders(height: number, count: number): Promise<string>
async findHeaderForHeight(height: number): Promise<BlockHeader | undefined>
async findHeaderForBlockHash(hash: string): Promise<BlockHeader | undefined>
}
See also: BaseBlockHeader, BlockHeader, Chain, ChaintracksClientApi, ChaintracksInfoApi, ChaintracksServiceClientOptions, HeaderListener, ReorgListener
Links: API, Interfaces, Classes, Functions, Types, Variables
Required interface methods of a Chaintracks Storage Engine implementation.
export abstract class ChaintracksStorageBase implements ChaintracksStorageQueryApi, ChaintracksStorageIngestApi {
static createStorageBaseOptions(chain: Chain): ChaintracksStorageBaseOptions
chain: Chain;
liveHeightThreshold: number;
reorgHeightThreshold: number;
bulkMigrationChunkSize: number;
batchInsertLimit: number;
isAvailable: boolean = false;
hasMigrated: boolean = false;
bulkManager: BulkFileDataManager;
constructor(options: ChaintracksStorageBaseOptions)
async shutdown(): Promise<void>
async makeAvailable(): Promise<void>
async migrateLatest(): Promise<void>
async dropAllData(): Promise<void>
abstract deleteLiveBlockHeaders(): Promise<void>;
abstract deleteOlderLiveBlockHeaders(maxHeight: number): Promise<number>;
abstract findChainTipHeader(): Promise<LiveBlockHeader>;
abstract findChainTipHeaderOrUndefined(): Promise<LiveBlockHeader | undefined>;
abstract findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | null>;
abstract findLiveHeaderForHeaderId(headerId: number): Promise<LiveBlockHeader>;
abstract findLiveHeaderForHeight(height: number): Promise<LiveBlockHeader | null>;
abstract findLiveHeaderForMerkleRoot(merkleRoot: string): Promise<LiveBlockHeader | null>;
abstract findLiveHeightRange(): Promise<{
minHeight: number;
maxHeight: number;
}>;
abstract findMaxHeaderId(): Promise<number>;
abstract getLiveHeightRange(): Promise<HeightRange>;
abstract liveHeadersForBulk(count: number): Promise<LiveBlockHeader[]>;
abstract getHeaders(height: number, count: number): Promise<number[]>;
abstract insertHeader(header: BlockHeader): Promise<InsertHeaderResult>;
abstract destroy(): Promise<void>;
async deleteBulkBlockHeaders(): Promise<void>
async getAvailableHeightRanges(): Promise<{
bulk: HeightRange;
live: HeightRange;
}>
async pruneLiveBlockHeaders(activeTipHeight: number): Promise<void>
async findChainTipHash(): Promise<string>
async findChainTipWork(): Promise<string>
async findChainWorkForBlockHash(hash: string): Promise<string>
async findBulkFilesHeaderForHeightOrUndefined(height: number): Promise<BlockHeader | undefined>
async findHeaderForHeightOrUndefined(height: number): Promise<LiveBlockHeader | BlockHeader | undefined>
async findHeaderForHeight(height: number): Promise<LiveBlockHeader | BlockHeader>
async isMerkleRootActive(merkleRoot: string): Promise<boolean>
async findCommonAncestor(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<LiveBlockHeader>
async findReorgDepth(header1: LiveBlockHeader, header2: LiveBlockHeader): Promise<number>
async migrateLiveToBulk(count: number, ignoreLimits = false): Promise<void>
async addBulkHeaders(headers: BlockHeader[], bulkRange: HeightRange, priorLiveHeaders: BlockHeader[]): Promise<BlockHeader[]>
}
See also: BlockHeader, BulkFileDataManager, Chain, ChaintracksStorageBaseOptions, ChaintracksStorageIngestApi, ChaintracksStorageQueryApi, HeightRange, InsertHeaderResult, LiveBlockHeader
abstract insertHeader(header: BlockHeader): Promise<InsertHeaderResult>
See also: BlockHeader, InsertHeaderResult
Returns
details of conditions found attempting to insert header
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Implements the ChaintracksStorageApi using Knex.js for both MySql and Sqlite support.
Also see chaintracksStorageMemory
which leverages Knex support for an in memory database.
export class ChaintracksStorageKnex extends ChaintracksStorageBase implements ChaintracksStorageBulkFileApi {
static createStorageKnexOptions(chain: Chain, knex?: Knex): ChaintracksStorageKnexOptions
knex: Knex;
_dbtype?: DBType;
headerTableName: string;
bulkFilesTableName: string = "bulk_files";
bulkBlockHashTableName: string;
bulkMerkleRootTableName: string;
constructor(options: ChaintracksStorageKnexOptions)
get dbtype(): DBType
override async shutdown(): Promise<void>
override async makeAvailable(): Promise<void>
override async migrateLatest(): Promise<void>
override async dropAllData(): Promise<void>
override async destroy(): Promise<void>
async findLiveHeightRange(): Promise<{
minHeight: number;
maxHeight: number;
}>
async findLiveHeaderForHeaderId(headerId: number): Promise<LiveBlockHeader>
async findChainTipHeader(): Promise<LiveBlockHeader>
async findChainTipHeaderOrUndefined(): Promise<LiveBlockHeader | undefined>
async findLiveHeaderForHeight(height: number): Promise<LiveBlockHeader | null>
async findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | null>
async findLiveHeaderForMerkleRoot(merkleRoot: string): Promise<LiveBlockHeader | null>
async deleteBulkFile(fileId: number): Promise<number>
async insertBulkFile(file: BulkHeaderFileInfo): Promise<number>
async updateBulkFile(fileId: number, file: BulkHeaderFileInfo): Promise<number>
async getBulkFiles(): Promise<BulkHeaderFileInfo[]>
dbTypeSubstring(source: string, fromOffset: number, forLength?: number)
async getBulkFileData(fileId: number, offset?: number, length?: number): Promise<Uint8Array | undefined>
async insertHeader(header: BlockHeader): Promise<InsertHeaderResult>
async findMaxHeaderId(): Promise<number>
async getLiveHeightRange(): Promise<HeightRange>
async appendToIndexTable(table: string, index: string, buffers: string[], minHeight: number): Promise<void>
async appendToIndexTableChunked(table: string, index: string, buffers: string[], minHeight: number, chunkSize: number): Promise<void>
override async deleteLiveBlockHeaders(): Promise<void>
override async deleteBulkBlockHeaders(): Promise<void>
async deleteOlderLiveBlockHeaders(maxHeight: number): Promise<number>
async getHeaders(height: number, count: number): Promise<number[]>
concatSerializedHeaders(bufs: number[][]): number[]
async liveHeadersForBulk(count: number): Promise<LiveBlockHeader[]>
}
See also: BlockHeader, BulkHeaderFileInfo, Chain, ChaintracksStorageBase, ChaintracksStorageBulkFileApi, ChaintracksStorageKnexOptions, DBType, HeightRange, InsertHeaderResult, LiveBlockHeader
async insertHeader(header: BlockHeader): Promise<InsertHeaderResult>
See also: BlockHeader, InsertHeaderResult
Returns
details of conditions found attempting to insert header
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksStorageNoDb extends ChaintracksStorageBase {
static mainData: ChaintracksNoDbData = {
chain: "main",
liveHeaders: new Map<number, LiveBlockHeader>(),
maxHeaderId: 0,
tipHeaderId: 0,
hashToHeaderId: new Map<string, number>()
};
static testData: ChaintracksNoDbData = {
chain: "test",
liveHeaders: new Map<number, LiveBlockHeader>(),
maxHeaderId: 0,
tipHeaderId: 0,
hashToHeaderId: new Map<string, number>()
};
constructor(options: ChaintracksStorageNoDbOptions)
override async destroy(): Promise<void>
async getData(): Promise<ChaintracksNoDbData>
override async deleteLiveBlockHeaders(): Promise<void>
override async deleteOlderLiveBlockHeaders(maxHeight: number): Promise<number>
override async findChainTipHeader(): Promise<LiveBlockHeader>
override async findChainTipHeaderOrUndefined(): Promise<LiveBlockHeader | undefined>
override async findLiveHeaderForBlockHash(hash: string): Promise<LiveBlockHeader | null>
override async findLiveHeaderForHeaderId(headerId: number): Promise<LiveBlockHeader>
override async findLiveHeaderForHeight(height: number): Promise<LiveBlockHeader | null>
override async findLiveHeaderForMerkleRoot(merkleRoot: string): Promise<LiveBlockHeader | null>
override async findLiveHeightRange(): Promise<{
minHeight: number;
maxHeight: number;
}>
override async findMaxHeaderId(): Promise<number>
override async getLiveHeightRange(): Promise<HeightRange>
override async liveHeadersForBulk(count: number): Promise<LiveBlockHeader[]>
override async getHeaders(height: number, count: number): Promise<number[]>
override async insertHeader(header: BlockHeader, prev?: LiveBlockHeader): Promise<InsertHeaderResult>
}
See also: BlockHeader, ChaintracksStorageBase, ChaintracksStorageNoDbOptions, HeightRange, InsertHeaderResult, LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ChaintracksWritableFile implements ChaintracksWritableFileApi {
path: string;
parsedPath: Path.ParsedPath;
f: fs.FileHandle;
foldersEnsured: boolean = false;
static async openAsWritable(path: string): Promise<ChaintracksWritableFile>
async close(): Promise<void>
async ensureFoldersExist(): Promise<void>
async append(data: Uint8Array): Promise<void>
}
See also: ChaintracksWritableFileApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export class HeightRange implements HeightRangeApi {
constructor(public minHeight: number, public maxHeight: number)
static readonly empty = new HeightRange(0, -1);
static from(headers: BlockHeader[]): HeightRange
get length()
get isEmpty()
toString(): string
contains(range: HeightRange | number)
intersect(range: HeightRange)
union(range: HeightRange)
subtract(range: HeightRange)
above(range: HeightRange)
copy(): HeightRange
}
See also: BlockHeader, HeightRangeApi
If range
is not empty and this is not empty, returns a new range minHeight
replaced by to range.maxHeight + 1.
Otherwise returns a copy of this range.
This returns the portion of this range that is strictly above range
.
above(range: HeightRange)
See also: HeightRange
contains(range: HeightRange | number)
See also: HeightRange
Returns
true if range
is entirely within this range.
Argument Details
Return a copy of this range.
copy(): HeightRange
See also: HeightRange
static from(headers: BlockHeader[]): HeightRange
See also: BlockHeader, HeightRange
Returns
range of height values from the given headers, or the empty range if there are no headers.
Return the intersection with another height range.
Intersection with an empty range is always empty.
The result is always a single, possibly empty, range.
intersect(range: HeightRange)
See also: HeightRange
Returns range
subtracted from this range.
Throws an error if the subtraction would create two disjoint ranges.
subtract(range: HeightRange)
See also: HeightRange
function toString() { [native code] }
toString(): string
Return the union with another height range.
Only valid if the two ranges overlap or touch, or one is empty.
Throws an error if the union would create two disjoint ranges.
union(range: HeightRange)
See also: HeightRange
Links: API, Interfaces, Classes, Functions, Types, Variables
export abstract class LiveIngestorBase implements LiveIngestorApi {
static createLiveIngestorBaseOptions(chain: Chain)
chain: Chain;
constructor(options: LiveIngestorBaseOptions)
async shutdown(): Promise<void>
async setStorage(storage: ChaintracksStorageApi): Promise<void>
storage(): ChaintracksStorageApi
abstract getHeaderByHash(hash: string): Promise<BlockHeader | undefined>;
abstract startListening(liveHeaders: BlockHeader[]): Promise<void>;
abstract stopListening(): void;
}
See also: BlockHeader, Chain, ChaintracksStorageApi, LiveIngestorApi, LiveIngestorBaseOptions
Called to retrieve a missing block header, when the previousHash of a new header is unknown.
abstract getHeaderByHash(hash: string): Promise<BlockHeader | undefined>
See also: BlockHeader
Argument Details
Allocate resources.
async setStorage(storage: ChaintracksStorageApi): Promise<void>
See also: ChaintracksStorageApi
Argument Details
Release resources. Override if required.
async shutdown(): Promise<void>
Begin retrieving new block headers.
New headers are pushed onto the liveHeaders array.
Continue waiting for new headers.
Return only when either stopListening
or shutdown
are called.
Be prepared to resume listening after stopListening
but not
after shutdown
.
abstract startListening(liveHeaders: BlockHeader[]): Promise<void>
See also: BlockHeader
Causes startListening
to stop listening for new block headers and return.
abstract stopListening(): void
storage(): ChaintracksStorageApi
See also: ChaintracksStorageApi
Returns
coordinating storage engine.
Links: API, Interfaces, Classes, Functions, Types, Variables
Reports new headers by polling periodically.
export class LiveIngestorWhatsOnChainPoll extends LiveIngestorBase {
static createLiveIngestorWhatsOnChainOptions(chain: Chain): LiveIngestorWhatsOnChainOptions
idleWait: number;
woc: WhatsOnChainServices;
done: boolean = false;
constructor(options: LiveIngestorWhatsOnChainOptions)
async getHeaderByHash(hash: string): Promise<BlockHeader | undefined>
async startListening(liveHeaders: BlockHeader[]): Promise<void>
stopListening(): void
override async shutdown(): Promise<void>
}
See also: BlockHeader, Chain, LiveIngestorBase, LiveIngestorWhatsOnChainOptions, WhatsOnChainServices
Links: API, Interfaces, Classes, Functions, Types, Variables
export class LiveIngestorWhatsOnChainWs extends LiveIngestorBase {
static createLiveIngestorWhatsOnChainOptions(chain: Chain): LiveIngestorWhatsOnChainOptions
idleWait: number;
woc: WhatsOnChainServices;
stopNewListenersToken: StopListenerToken = { stop: undefined };
constructor(options: LiveIngestorWhatsOnChainOptions)
async getHeaderByHash(hash: string): Promise<BlockHeader | undefined>
async startListening(liveHeaders: BlockHeader[]): Promise<void>
stopListening(): void
}
See also: BlockHeader, Chain, LiveIngestorBase, LiveIngestorWhatsOnChainOptions, StopListenerToken, WhatsOnChainServices
Links: API, Interfaces, Classes, Functions, Types, Variables
Represents a chain tracker based on What’s On Chain .
export default class SdkWhatsOnChain implements ChainTracker {
readonly network: string;
readonly apiKey: string;
protected readonly URL: string;
protected readonly httpClient: HttpClient;
constructor(network: "main" | "test" | "stn" = "main", config: WhatsOnChainConfig = {})
async isValidRootForHeight(root: string, height: number): Promise<boolean>
async currentHeight(): Promise<number>
protected getHttpHeaders(): Record<string, string>
}
Constructs an instance of the WhatsOnChain ChainTracker.
constructor(network: "main" | "test" | "stn" = "main", config: WhatsOnChainConfig = {})
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class ServiceCollection<T> {
services: {
name: string;
service: T;
}[];
_index: number;
readonly since: Date;
_historyByProvider: Record<string, ProviderCallHistory> = {};
constructor(public serviceName: string, services?: {
name: string;
service: T;
}[])
add(s: {
name: string;
service: T;
}): ServiceCollection<T>
remove(name: string): void
get name()
get service()
getServiceToCall(i: number): ServiceToCall<T>
get serviceToCall(): ServiceToCall<T>
get allServicesToCall(): ServiceToCall<T>[]
moveServiceToLast(stc: ServiceToCall<T>)
get allServices()
get count()
get index()
reset()
next(): number
clone(): ServiceCollection<T>
_addServiceCall(providerName: string, call: ServiceCall): ProviderCallHistory
getDuration(since: Date | string): number
addServiceCallSuccess(stc: ServiceToCall<T>, result?: string): void
addServiceCallFailure(stc: ServiceToCall<T>, result?: string): void
addServiceCallError(stc: ServiceToCall<T>, error: WalletError): void
getServiceCallHistory(reset?: boolean): ServiceCallHistory
}
See also: ProviderCallHistory, ServiceCall, ServiceCallHistory, ServiceToCall, WalletError
Start of currentCounts interval. Initially instance construction time.
readonly since: Date
getServiceCallHistory(reset?: boolean): ServiceCallHistory
See also: ServiceCallHistory
Returns
A copy of current service call history
Used to de-prioritize a service call by moving it to the end of the list.
moveServiceToLast(stc: ServiceToCall<T>)
See also: ServiceToCall
Links: API, Interfaces, Classes, Functions, Types, Variables
export class Services implements WalletServices {
static createDefaultOptions(chain: Chain): WalletServicesOptions
options: WalletServicesOptions;
whatsonchain: WhatsOnChain;
arcTaal: ARC;
arcGorillaPool?: ARC;
bitails: Bitails;
getMerklePathServices: ServiceCollection<GetMerklePathService>;
getRawTxServices: ServiceCollection<GetRawTxService>;
postBeefServices: ServiceCollection<PostBeefService>;
getUtxoStatusServices: ServiceCollection<GetUtxoStatusService>;
getStatusForTxidsServices: ServiceCollection<GetStatusForTxidsService>;
getScriptHashHistoryServices: ServiceCollection<GetScriptHashHistoryService>;
updateFiatExchangeRateServices: ServiceCollection<UpdateFiatExchangeRateService>;
chain: Chain;
constructor(optionsOrChain: Chain | WalletServicesOptions)
getServicesCallHistory(reset?: boolean): ServicesCallHistory
async getChainTracker(): Promise<ChainTracker>
async getBsvExchangeRate(): Promise<number>
async getFiatExchangeRate(currency: "USD" | "GBP" | "EUR", base?: "USD" | "GBP" | "EUR"): Promise<number>
get getProofsCount()
get getRawTxsCount()
get postBeefServicesCount()
get getUtxoStatsCount()
async getStatusForTxids(txids: string[], useNext?: boolean): Promise<GetStatusForTxidsResult>
hashOutputScript(script: string): string
async isUtxo(output: TableOutput): Promise<boolean>
async getUtxoStatus(output: string, outputFormat?: GetUtxoStatusOutputFormat, outpoint?: string, useNext?: boolean): Promise<GetUtxoStatusResult>
async getScriptHashHistory(hash: string, useNext?: boolean): Promise<GetScriptHashHistoryResult>
postBeefMode: "PromiseAll" | "UntilSuccess" = "UntilSuccess";
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult[]>
async getRawTx(txid: string, useNext?: boolean): Promise<GetRawTxResult>
async invokeChaintracksWithRetry<R>(method: () => Promise<R>): Promise<R>
async getHeaderForHeight(height: number): Promise<number[]>
async getHeight(): Promise<number>
async hashToHeader(hash: string): Promise<BlockHeader>
async getMerklePath(txid: string, useNext?: boolean): Promise<GetMerklePathResult>
targetCurrencies = ["USD", "GBP", "EUR"];
async updateFiatExchangeRates(rates?: FiatExchangeRates, updateMsecs?: number): Promise<FiatExchangeRates>
async nLockTimeIsFinal(tx: string | number[] | BsvTransaction | number): Promise<boolean>
async getBeefForTxid(txid: string): Promise<Beef>
}
See also: ARC, Bitails, BlockHeader, Chain, FiatExchangeRates, GetMerklePathResult, GetMerklePathService, GetRawTxResult, GetRawTxService, GetScriptHashHistoryResult, GetScriptHashHistoryService, GetStatusForTxidsResult, GetStatusForTxidsService, GetUtxoStatusOutputFormat, GetUtxoStatusResult, GetUtxoStatusService, PostBeefResult, PostBeefService, ServiceCollection, ServicesCallHistory, TableOutput, UpdateFiatExchangeRateService, WalletServices, WalletServicesOptions, WhatsOnChain, getBeefForTxid
hashOutputScript(script: string): string
Returns
script hash in ‘hashLE’ format, which is the default.
Argument Details
getUtxoStatus
default outputFormat
Links: API, Interfaces, Classes, Functions, Types, Variables
A reader-writer lock to manage concurrent access. Allows multiple readers or one writer at a time.
export class SingleWriterMultiReaderLock {
async withReadLock<T>(fn: () => Promise<T>): Promise<T>
async withWriteLock<T>(fn: () => Promise<T>): Promise<T>
}
Links: API, Interfaces, Classes, Functions, Types, Variables
export class WhatsOnChain extends WhatsOnChainNoServices {
services: Services;
constructor(chain: Chain = "main", config: WhatsOnChainConfig = {}, services?: Services)
async getMerklePath(txid: string, services: WalletServices): Promise<GetMerklePathResult>
}
See also: Chain, GetMerklePathResult, Services, WalletServices, WhatsOnChainNoServices
Links: API, Interfaces, Classes, Functions, Types, Variables
export class WhatsOnChainNoServices extends SdkWhatsOnChain {
constructor(chain: Chain = "main", config: WhatsOnChainConfig = {})
async getStatusForTxids(txids: string[]): Promise<GetStatusForTxidsResult>
async getTxPropagation(txid: string): Promise<number>
async getRawTx(txid: string): Promise<string | undefined>
async getRawTxResult(txid: string): Promise<GetRawTxResult>
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
async postRawTx(rawTx: HexString): Promise<PostTxResultForTxid>
async updateBsvExchangeRate(rate?: BsvExchangeRate, updateMsecs?: number): Promise<BsvExchangeRate>
async getUtxoStatus(output: string, outputFormat?: GetUtxoStatusOutputFormat, outpoint?: string): Promise<GetUtxoStatusResult>
async getScriptHashConfirmedHistory(hash: string): Promise<GetScriptHashHistoryResult>
async getScriptHashUnconfirmedHistory(hash: string): Promise<GetScriptHashHistoryResult>
async getScriptHashHistory(hash: string): Promise<GetScriptHashHistoryResult>
async getBlockHeaderByHash(hash: string): Promise<BlockHeader | undefined>
async getChainInfo(): Promise<WocChainInfo>
}
See also: BlockHeader, BsvExchangeRate, Chain, GetRawTxResult, GetScriptHashHistoryResult, GetStatusForTxidsResult, GetUtxoStatusOutputFormat, GetUtxoStatusResult, PostBeefResult, PostTxResultForTxid, SdkWhatsOnChain, WocChainInfo
{ “hash”: “000000000000000004a288072ebb35e37233f419918f9783d499979cb6ac33eb”, “confirmations”: 328433, “size”: 14421, “height”: 575045, “version”: 536928256, “versionHex”: “2000e000”, “merkleroot”: “4ebcba09addd720991d03473f39dce4b9a72cc164e505cd446687a54df9b1585”, “time”: 1553416668, “mediantime”: 1553414858, “nonce”: 87914848, “bits”: “180997ee”, “difficulty”: 114608607557.4425, “chainwork”: “000000000000000000000000000000000000000000ddf5d385546872bab7dc01”, “previousblockhash”: “00000000000000000988156c7075dc9147a5b62922f1310862e8b9000d46dd9b”, “nextblockhash”: “00000000000000000112b36a37c10235fa0c991f680bc5482ba9692e0ae697db”, “nTx”: 0, “num_tx”: 5 }
async getBlockHeaderByHash(hash: string): Promise<BlockHeader | undefined>
See also: BlockHeader
May return undefined for unmined transactions that are in the mempool.
async getRawTx(txid: string): Promise<string | undefined>
Returns
raw transaction as hex string or undefined if txid not found in mined block.
POST https://api.whatsonchain.com/v1/bsv/main/txs/status Content-Type: application/json data: “{"txids":["6815f8014db74eab8b7f75925c68929597f1d97efa970109d990824c25e5e62b"]}”
result for a mined txid: [{ “txid”:”294cd1ebd5689fdee03509f92c32184c0f52f037d4046af250229b97e0c8f1aa”, “blockhash”:”000000000000000004b5ce6670f2ff27354a1e87d0a01bf61f3307f4ccd358b5”, “blockheight”:612251, “blocktime”:1575841517, “confirmations”:278272 }]
result for a valid recent txid: [{“txid”:”6815f8014db74eab8b7f75925c68929597f1d97efa970109d990824c25e5e62b”}]
result for an unknown txid: [{“txid”:”6815f8014db74eab8b7f75925c68929597f1d97efa970109d990824c25e5e62c”,”error”:”unknown”}]
async getStatusForTxids(txids: string[]): Promise<GetStatusForTxidsResult>
See also: GetStatusForTxidsResult
2025-02-16 throwing internal server error 500.
async getTxPropagation(txid: string): Promise<number>
WhatsOnChain does not natively support a postBeef end-point aware of multiple txids of interest in the Beef.
Send rawTx in txids
order from beef.
async postBeef(beef: Beef, txids: string[]): Promise<PostBeefResult>
See also: PostBeefResult
async postRawTx(rawTx: HexString): Promise<PostTxResultForTxid>
See also: PostTxResultForTxid
Returns
txid returned by transaction processor of transaction broadcast
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export class WhatsOnChainServices {
static createWhatsOnChainServicesOptions(chain: Chain): WhatsOnChainServicesOptions
static chainInfo: (WocChainInfo | undefined)[] = [];
static chainInfoTime: (Date | undefined)[] = [];
static chainInfoMsecs: number[] = [];
chain: Chain;
woc: WhatsOnChain;
constructor(public options: WhatsOnChainServicesOptions)
async getHeaderByHash(hash: string): Promise<BlockHeader | undefined>
async getChainInfo(): Promise<WocChainInfo>
async getChainTipHeight(): Promise<number>
async getChainTipHash(): Promise<string>
async getHeaders(fetch?: ChaintracksFetchApi): Promise<WocGetHeadersHeader[]>
async getHeaderByteFileLinks(neededRange: HeightRange, fetch?: ChaintracksFetchApi): Promise<GetHeaderByteFileLinksResult[]>
}
See also: BlockHeader, Chain, ChaintracksFetchApi, GetHeaderByteFileLinksResult, HeightRange, WhatsOnChain, WhatsOnChainServicesOptions, WocChainInfo, WocGetHeadersHeader
async getHeaders(fetch?: ChaintracksFetchApi): Promise<WocGetHeadersHeader[]>
See also: ChaintracksFetchApi, WocGetHeadersHeader
Returns
returns the last 10 block headers including height, size, chainwork…
Links: API, Interfaces, Classes, Functions, Types, Variables
Links: API, Interfaces, Classes, Functions, Types, Variables
High speed WebSocket based based old block header listener
export async function WocHeadersBulkListener(fromHeight: number, toHeight: number, enqueue: (header: BlockHeader) => void, error: (code: number, message: string) => boolean, stop: StopListenerToken, chain: Chain = "main", idleWait = 5000): Promise<boolean>
See also: BlockHeader, Chain, StopListenerToken
Returns
true on normal completion, false if should restart if no error received.
Argument Details
‘test’ | ‘main’ |
Links: API, Interfaces, Classes, Functions, Types, Variables
v2 { “message”: { “data”: { “version”: 872415232, “previousblockhash”: “00000000000000000ea1f9ba0817a0f922ee227be306fd9097a4e76caf5ff411”, “merkleroot”: “dcd7efb3c39e8e2d597e4757b9a49c98f52f77a6df39d1d5936ac3abb2559944”, “time”: 1750182239, “bits”: 403926191, “nonce”: 1043732575, “hash”: “0000000000000000032d09ca772ca5b3bc5b90a79a5bbcc4a05c99fb6d3b23d8”, “height”: 901658 } } }
export async function WocHeadersBulkListener_test(): Promise<void>
Links: API, Interfaces, Classes, Functions, Types, Variables
High speed WebSocket based based new block header listener
export async function WocHeadersLiveListener(enqueue: (header: BlockHeader) => void, error: (code: number, message: string) => boolean, stop: StopListenerToken, chain: Chain = "main", idleWait = 100000): Promise<boolean>
See also: BlockHeader, Chain, StopListenerToken
Returns
true only if exit caused by stop
Argument Details
‘test’ | ‘main’ |
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function WocHeadersLiveListener_test(): Promise<void>
Links: API, Interfaces, Classes, Functions, Types, Variables
Add two Buffer encoded chainwork values
export function addWork(work1: string, work2: string): string
Returns
Sum of work1 + work2 as Buffer encoded chainWork value
Links: API, Interfaces, Classes, Functions, Types, Variables
export function arcDefaultUrl(chain: Chain): string
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
export function arcGorillaPoolUrl(chain: Chain): string | undefined
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
Computes double sha256 hash of bitcoin block header bytes are reversed to bigendian order
If header is a Buffer, it is required to 80 bytes long and in standard block header serialized encoding.
export function blockHash(header: BaseBlockHeader | number[] | Uint8Array): string {
const a = !Array.isArray(header) && !(header instanceof Uint8Array) ? serializeBaseBlockHeader(header) : header;
if (a.length !== 80)
throw new Error("Block header must be 80 bytes long.");
return asString(doubleSha256BE(a));
}
See also: BaseBlockHeader, asString, doubleSha256BE, serializeBaseBlockHeader
Returns
doule sha256 hash of header bytes reversed
Links: API, Interfaces, Classes, Functions, Types, Variables
Computes “target” value for 4 byte Bitcoin block header “bits” value.
export function convertBitsToTarget(bits: number | number[]): BigNumber
Returns
32 byte Buffer with “target” value
Argument Details
readUint32LE
Links: API, Interfaces, Classes, Functions, Types, Variables
Computes “chainWork” value for 4 byte Bitcoin block header “bits” value.
export function convertBitsToWork(bits: number | number[]): string
Returns
32 byte Buffer with “chainWork” value
Argument Details
readUint32LE
Links: API, Interfaces, Classes, Functions, Types, Variables
export function convertBufferToUint32(buffer: number[] | Uint8Array, littleEndian = true): number {
const a = littleEndian ? buffer : buffer.slice().reverse();
const n = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);
return n;
}
Returns
a number value in the Uint32 value range
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export function convertUint32ToBuffer(n: number, littleEndian = true): number[] {
const a = [
n & 255,
(n >> 8) & 255,
(n >> 16) & 255,
(n >> 24) & 255
];
return littleEndian ? a : a.reverse();
}
Returns
four byte buffer with Uint32 number encoded
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export function convertWocToBlockHeaderHex(woc: WocHeader): BlockHeader
See also: BlockHeader, WocHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export function createDefaultKnexChaintracksOptions(chain: Chain, rootFolder?: string, knexConfig?: Knex.Config): ChaintracksOptions
See also: Chain, ChaintracksOptions
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export function createDefaultWalletServicesOptions(chain: Chain, arcCallbackUrl?: string, arcCallbackToken?: string, arcApiKey?: string): WalletServicesOptions
See also: Chain, WalletServicesOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
export function createNoDbChaintracksOptions(chain: Chain): ChaintracksOptions
See also: Chain, ChaintracksOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
Deserialize a BaseBlockHeader from an 80 byte buffer
export function deserializeBaseBlockHeader(buffer: number[] | Uint8Array, offset = 0): BaseBlockHeader {
const reader = ReaderUint8Array.makeReader(buffer, offset);
const header: BaseBlockHeader = {
version: reader.readUInt32LE(),
previousHash: asString(reader.read(32).reverse()),
merkleRoot: asString(reader.read(32).reverse()),
time: reader.readUInt32LE(),
bits: reader.readUInt32LE(),
nonce: reader.readUInt32LE()
};
return header;
}
See also: BaseBlockHeader, ReaderUint8Array, asString, readUInt32LE
Links: API, Interfaces, Classes, Functions, Types, Variables
export function deserializeBaseBlockHeaders(buffer: number[] | Uint8Array, offset = 0, count?: number | undefined): BaseBlockHeader[]
See also: BaseBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export function deserializeBlockHeader(buffer: number[] | Uint8Array, offset = 0, height: number): BlockHeader
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export function deserializeBlockHeaders(firstHeight: number, buffer: number[] | Uint8Array, offset = 0, count?: number | undefined): BlockHeader[]
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Returns the genesis block for the specified chain.
export function genesisBuffer(chain: Chain): number[] {
return serializeBaseBlockHeader(genesisHeader(chain));
}
See also: Chain, genesisHeader, serializeBaseBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Returns the genesis block for the specified chain.
export function genesisHeader(chain: Chain): BlockHeader {
return chain === "main"
? {
version: 1,
previousHash: "0000000000000000000000000000000000000000000000000000000000000000",
merkleRoot: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
time: 1231006505,
bits: 486604799,
nonce: 2083236893,
height: 0,
hash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
}
: {
version: 1,
previousHash: "0000000000000000000000000000000000000000000000000000000000000000",
merkleRoot: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
time: 1296688602,
bits: 486604799,
nonce: 414098458,
height: 0,
hash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
};
}
See also: BlockHeader, Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function getBeefForTxid(services: Services, txid: string): Promise<Beef>
See also: Services
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function getExchangeRatesIo(key: string): Promise<ExchangeRatesIoApi>
See also: ExchangeRatesIoApi
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function getWhatsOnChainBlockHeaderByHash(hash: string, chain: Chain = "main", apiKey?: string): Promise<BlockHeader | undefined>
See also: BlockHeader, Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
Type guard function.
export function isBaseBlockHeader(header: BaseBlockHeader | BlockHeader | LiveBlockHeader): header is BaseBlockHeader {
return typeof header.previousHash === "string";
}
See also: BaseBlockHeader, BlockHeader, LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Type guard function.
export function isBlockHeader(header: BaseBlockHeader | BlockHeader | LiveBlockHeader): header is LiveBlockHeader {
return "height" in header && typeof header.previousHash === "string";
}
See also: BaseBlockHeader, BlockHeader, LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export function isKnownValidBulkHeaderFile(vbf: BulkHeaderFileInfo): boolean
See also: BulkHeaderFileInfo
Links: API, Interfaces, Classes, Functions, Types, Variables
Type guard function.
export function isLive(header: BlockHeader | LiveBlockHeader): header is LiveBlockHeader {
return (header as LiveBlockHeader).headerId !== undefined;
}
See also: BlockHeader, LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Type guard function.
export function isLiveBlockHeader(header: BaseBlockHeader | BlockHeader | LiveBlockHeader): header is LiveBlockHeader {
return "chainwork" in header && typeof header.previousHash === "string";
}
See also: BaseBlockHeader, BlockHeader, LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Returns true if work1 is more work (greater than) work2
export function isMoreWork(work1: string, work2: string): boolean
Links: API, Interfaces, Classes, Functions, Types, Variables
export function readUInt32BE(a: number[] | Uint8Array, offset: number): number
Links: API, Interfaces, Classes, Functions, Types, Variables
export function readUInt32LE(a: number[] | Uint8Array, offset: number): number
Links: API, Interfaces, Classes, Functions, Types, Variables
export function selectBulkHeaderFiles(files: BulkHeaderFileInfo[], chain: Chain, maxPerFile: number): BulkHeaderFileInfo[]
See also: BulkHeaderFileInfo, Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
Serializes a block header as an 80 byte Buffer. The exact serialized format is defined in the Bitcoin White Paper such that computing a double sha256 hash of the buffer computes the block hash for the header.
export function serializeBaseBlockHeader(header: BaseBlockHeader, buffer?: number[], offset?: number): number[] {
const writer = new Utils.Writer();
writer.writeUInt32LE(header.version);
writer.write(asArray(header.previousHash).reverse());
writer.write(asArray(header.merkleRoot).reverse());
writer.writeUInt32LE(header.time);
writer.writeUInt32LE(header.bits);
writer.writeUInt32LE(header.nonce);
const data = writer.toArray();
if (buffer) {
offset ||= 0;
for (let i = 0; i < data.length; i++) {
if (offset + i >= buffer.length) {
throw new Error(`Buffer overflow at offset ${offset + i} for data length ${data.length}`);
}
buffer[offset + i] = data[i];
}
}
return data;
}
See also: BaseBlockHeader, asArray, writeUInt32LE
Returns
80 byte Buffer
Links: API, Interfaces, Classes, Functions, Types, Variables
export function serializeBaseBlockHeaders(headers: BlockHeader[]): Uint8Array
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
Computes sha256 hash of file contents read as bytes with no encoding.
export async function sha256HashOfBinaryFile(fs: ChaintracksFsApi, filepath: string, bufferSize = 80000): Promise<{
hash: string;
length: number;
}>
See also: ChaintracksFsApi
Returns
{hash, length}
where hash
is base64 string form of file hash and length
is file length in bytes.
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Subtract Buffer encoded chainwork values
export function subWork(work1: string, work2: string): string
Returns
work1 - work2 as Buffer encoded chainWork value
Links: API, Interfaces, Classes, Functions, Types, Variables
Returns a copy of a Buffer with byte order reversed.
export function swapByteOrder(buffer: number[]): number[] {
return buffer.slice().reverse();
}
Returns
new buffer with byte order reversed.
Links: API, Interfaces, Classes, Functions, Types, Variables
Serializes a block header as an 80 byte array. The exact serialized format is defined in the Bitcoin White Paper such that computing a double sha256 hash of the array computes the block hash for the header.
export function toBinaryBaseBlockHeader(header: BaseBlockHeader): number[] {
const writer = new Utils.Writer();
writer.writeUInt32BE(header.version);
writer.writeReverse(asArray(header.previousHash));
writer.writeReverse(asArray(header.merkleRoot));
writer.writeUInt32BE(header.time);
writer.writeUInt32BE(header.bits);
writer.writeUInt32BE(header.nonce);
const r = writer.toArray();
return r;
}
See also: BaseBlockHeader, asArray, writeUInt32BE
Returns
80 byte array
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function updateChaintracksFiatExchangeRates(targetCurrencies: string[], options: WalletServicesOptions): Promise<FiatExchangeRates>
See also: FiatExchangeRates, WalletServicesOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
export async function updateExchangeratesapi(targetCurrencies: string[], options: WalletServicesOptions): Promise<FiatExchangeRates>
See also: FiatExchangeRates, WalletServicesOptions
Links: API, Interfaces, Classes, Functions, Types, Variables
export function validBulkHeaderFilesByFileHash(): Record<string, BulkHeaderFileInfo>
See also: BulkHeaderFileInfo
Links: API, Interfaces, Classes, Functions, Types, Variables
Throws Error if blockHash is in the dirtyHashes list.
export function validateAgainstDirtyHashes(blockHash: string): void
See also: blockHash
Links: API, Interfaces, Classes, Functions, Types, Variables
Validate headers contained in an array of bytes. The headers must be consecutive block headers, 80 bytes long, where the hash of each header equals the previousHash of the following header.
export function validateBufferOfHeaders(buffer: Uint8Array, previousHash: string, offset = 0, count = -1, previousChainWork?: string): {
lastHeaderHash: string;
lastChainWork: string | undefined;
}
Returns
Header hash of last header validated or previousHash if there where none.
Argument Details
buffer
.Links: API, Interfaces, Classes, Functions, Types, Variables
Validates the contents of a bulk header file.
export async function validateBulkFileData(bf: BulkHeaderFileInfo, prevHash: string, prevChainWork: string, fetch?: ChaintracksFetchApi): Promise<BulkHeaderFileInfo>
See also: BulkHeaderFileInfo, ChaintracksFetchApi
Returns
Validated BulkHeaderFileInfo with validated
set to true.
Argument Details
data
to validate.Links: API, Interfaces, Classes, Functions, Types, Variables
Verifies that buffer begins with valid genesis block header for the specified chain.
export function validateGenesisHeader(buffer: Uint8Array, chain: Chain): void
See also: Chain
Links: API, Interfaces, Classes, Functions, Types, Variables
Ensures that a header has a valid proof-of-work Requires chain is ‘main’
export function validateHeaderDifficulty(hash: Buffer, bits: number)
Returns
true if the header is valid
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
Given a block header, ensures that its format is correct. This does not check its difficulty or validity relative to the chain of headers.
Throws on format errors.
export function validateHeaderFormat(header: BlockHeader): void
See also: BlockHeader
Returns
true if the header is correctly formatted
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export function validateScriptHash(output: string, outputFormat?: GetUtxoStatusOutputFormat): string
See also: GetUtxoStatusOutputFormat
Links: API, Interfaces, Classes, Functions, Types, Variables
export function wocGetHeadersHeaderToBlockHeader(h: WocGetHeadersHeader): BlockHeader
See also: BlockHeader, WocGetHeadersHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export function workBNtoBuffer(work: BigNumber): string
Returns
Converted chainWork value from BN to hex string of 32 bytes.
Argument Details
Links: API, Interfaces, Classes, Functions, Types, Variables
export function writeUInt32BE(n: number, a: number[] | Uint8Array, offset: number): number
Links: API, Interfaces, Classes, Functions, Types, Variables
export function writeUInt32LE(n: number, a: number[] | Uint8Array, offset: number): number
Links: API, Interfaces, Classes, Functions, Types, Variables
EnqueueHandler |
ErrorHandler |
HeaderListener |
InsertHeaderResult |
ReorgListener |
StopListenerToken |
Links: API, Interfaces, Classes, Functions, Types, Variables
export type EnqueueHandler = (header: BlockHeader) => void
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
return true to ignore error, false to close service connection
export type ErrorHandler = (code: number, message: string) => boolean
Links: API, Interfaces, Classes, Functions, Types, Variables
export type HeaderListener = (header: BlockHeader) => void
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export type InsertHeaderResult = {
added: boolean;
dupe: boolean;
isActiveTip: boolean;
reorgDepth: number;
priorTip: LiveBlockHeader | undefined;
noPrev: boolean;
badPrev: boolean;
noActiveAncestor: boolean;
noTip: boolean;
}
See also: LiveBlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export type ReorgListener = (depth: number, oldTip: BlockHeader, newTip: BlockHeader) => void
See also: BlockHeader
Links: API, Interfaces, Classes, Functions, Types, Variables
export type StopListenerToken = {
stop: (() => void) | undefined;
}
Links: API, Interfaces, Classes, Functions, Types, Variables
ChaintracksFs |
dirtyHashes |
validBulkHeaderFiles |
Links: API, Interfaces, Classes, Functions, Types, Variables
ChaintracksFs: ChaintracksFsApi = ChaintracksFsStatics
See also: ChaintracksFsApi, ChaintracksFsStatics
Links: API, Interfaces, Classes, Functions, Types, Variables
dirtyHashes = {
"00000000000000000019f112ec0a9982926f1258cdcc558dd7c3b7e5dc7fa148": "This is the first header of the invalid SegWit chain.",
"0000000000000000004626ff6e3b936941d341c5932ece4357eeccac44e6d56c": "This is the first header of the invalid ABC chain."
}
Links: API, Interfaces, Classes, Functions, Types, Variables
validBulkHeaderFiles: BulkHeaderFileInfo[] = [
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_0.headers",
firstHeight: 0,
prevHash: "0000000000000000000000000000000000000000000000000000000000000000",
count: 100000,
lastHash: "000000004956cc2edd1a8caa05eacfa3c69f4c490bfc9ace820257834115ab35",
fileHash: "gAJPUfI2DfAabJTOBxT1rwy1cS4/QULaQHaQWa1RWNk=",
lastChainWork: "000000000000000000000000000000000000000000000000004143c00b3d47b8",
prevChainWork: "0000000000000000000000000000000000000000000000000000000000000000",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_1.headers",
firstHeight: 100000,
prevHash: "000000004956cc2edd1a8caa05eacfa3c69f4c490bfc9ace820257834115ab35",
count: 100000,
lastHash: "0000000000c470c4a573272aa4a680c93fc4c2f5df8ce9546441796f73277334",
fileHash: "OIJ010bnIbFobNppJzCNE9jFI1uANz0iNGvqpoG2xq4=",
lastChainWork: "00000000000000000000000000000000000000000000000004504f3a4e71aa13",
prevChainWork: "000000000000000000000000000000000000000000000000004143c00b3d47b8",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_2.headers",
firstHeight: 200000,
prevHash: "0000000000c470c4a573272aa4a680c93fc4c2f5df8ce9546441796f73277334",
count: 100000,
lastHash: "00000000dfe970844d1bf983d0745f709368b5c66224837a17ed633f0dabd300",
fileHash: "hZXE3im7V4tE0oROWM2mGB9xPXEcpVLRIYUPaYT3VV0=",
lastChainWork: "00000000000000000000000000000000000000000000000062378b066f9fba96",
prevChainWork: "00000000000000000000000000000000000000000000000004504f3a4e71aa13",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_3.headers",
firstHeight: 300000,
prevHash: "00000000dfe970844d1bf983d0745f709368b5c66224837a17ed633f0dabd300",
count: 100000,
lastHash: "0000000001127c76ac45f605f9300dfa96a8054533b96413883fdc4378aeb42d",
fileHash: "BGZxsk/Ooa4BOaoBEMOor+B8wL9ghW5A0We2G2fmyLE=",
lastChainWork: "0000000000000000000000000000000000000000000000040da9d61d8e129a53",
prevChainWork: "00000000000000000000000000000000000000000000000062378b066f9fba96",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_4.headers",
firstHeight: 400000,
prevHash: "0000000001127c76ac45f605f9300dfa96a8054533b96413883fdc4378aeb42d",
count: 100000,
lastHash: "0000000001965655a870175b510326e6393114d293896ddb237709eecb381ab8",
fileHash: "3DjOpFnatZ0OKrpACATfAtBITX2s8JjfYTAnDHVkGuw=",
lastChainWork: "00000000000000000000000000000000000000000000000461063a8389300d36",
prevChainWork: "0000000000000000000000000000000000000000000000040da9d61d8e129a53",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_5.headers",
firstHeight: 500000,
prevHash: "0000000001965655a870175b510326e6393114d293896ddb237709eecb381ab8",
count: 100000,
lastHash: "000000000000bb1644b4d9a643b165a52b3ffba077f2a12b8bd1f0a6b6cc0fbc",
fileHash: "wF008GqnZzAYsOwnmyFzIOmrJthHE3bq6oUg1FvHG1Y=",
lastChainWork: "0000000000000000000000000000000000000000000000067a8291cfec0aa549",
prevChainWork: "00000000000000000000000000000000000000000000000461063a8389300d36",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_6.headers",
firstHeight: 600000,
prevHash: "000000000000bb1644b4d9a643b165a52b3ffba077f2a12b8bd1f0a6b6cc0fbc",
count: 100000,
lastHash: "0000000000003e784511e93aca014ecaa6d4ba3637cf373f4b84dcac7c70cca0",
fileHash: "uc7IW6NRXXtX3oGWwOYjtetTaZ+1zhvijNEwPbK+rAs=",
lastChainWork: "0000000000000000000000000000000000000000000000078286c7f42f7ec693",
prevChainWork: "0000000000000000000000000000000000000000000000067a8291cfec0aa549",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_7.headers",
firstHeight: 700000,
prevHash: "0000000000003e784511e93aca014ecaa6d4ba3637cf373f4b84dcac7c70cca0",
count: 100000,
lastHash: "0000000000068f8658ff71cbf8f5b31c837cc6df5bf53e40f05459d4267b53e6",
fileHash: "yfomaIGZyoW/m7YdpZYNozeNrUmJBwaF0PpLdSADWJE=",
lastChainWork: "00000000000000000000000000000000000000000000000a551ea869597d2a74",
prevChainWork: "0000000000000000000000000000000000000000000000078286c7f42f7ec693",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_8.headers",
firstHeight: 800000,
prevHash: "0000000000068f8658ff71cbf8f5b31c837cc6df5bf53e40f05459d4267b53e6",
count: 100000,
lastHash: "0000000000214fbb71abe4695d935b8e089d306899c4a90124b1bc6806e6e299",
fileHash: "/AIS2PYHdMJBmRF9ECsZmCphoqhDyFWs+aO+3GIpPhg=",
lastChainWork: "00000000000000000000000000000000000000000000000eb93c12a85efec237",
prevChainWork: "00000000000000000000000000000000000000000000000a551ea869597d2a74",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_9.headers",
firstHeight: 900000,
prevHash: "0000000000214fbb71abe4695d935b8e089d306899c4a90124b1bc6806e6e299",
count: 100000,
lastHash: "00000000002208a5fee5b9baa4b5519d2cd8ab405754fca13704dc667448f21a",
fileHash: "lJtRGLYlMnHe6r0xuJJWauJA7DKL4ZYOqkYmUD2iwbM=",
lastChainWork: "000000000000000000000000000000000000000000000017e96a5ada9f4a8bfb",
prevChainWork: "00000000000000000000000000000000000000000000000eb93c12a85efec237",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_10.headers",
firstHeight: 1000000,
prevHash: "00000000002208a5fee5b9baa4b5519d2cd8ab405754fca13704dc667448f21a",
count: 100000,
lastHash: "000000000005bc8878ba47a47129c3e21f32f8c10b9658f9ee6db16a83870162",
fileHash: "tfWVFoIp4A6yXd2c0YietQ7hYlmLf7O884baego+D4E=",
lastChainWork: "000000000000000000000000000000000000000000000021bf46518c698a4bc8",
prevChainWork: "000000000000000000000000000000000000000000000017e96a5ada9f4a8bfb",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_11.headers",
firstHeight: 1100000,
prevHash: "000000000005bc8878ba47a47129c3e21f32f8c10b9658f9ee6db16a83870162",
count: 100000,
lastHash: "00000000f8bf61018ddd77d23c112e874682704a290252f635e7df06c8a317b8",
fileHash: "S0Y9WXGFFJLRsRkQRNvrtImOezjReEQ1eDdB2x5M6Mw=",
lastChainWork: "0000000000000000000000000000000000000000000000288b285ca9b1bb8065",
prevChainWork: "000000000000000000000000000000000000000000000021bf46518c698a4bc8",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_12.headers",
firstHeight: 1200000,
prevHash: "00000000f8bf61018ddd77d23c112e874682704a290252f635e7df06c8a317b8",
count: 100000,
lastHash: "0000000000000165e6678be46ec2b15c587611b86da7147f7069a0e7175d62da",
fileHash: "eFHQB8EaSfs4EKZxVsLhX8UA79kpOI4dR6j/z9P8frI=",
lastChainWork: "0000000000000000000000000000000000000000000000542144c6af6e9258ea",
prevChainWork: "0000000000000000000000000000000000000000000000288b285ca9b1bb8065",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_13.headers",
firstHeight: 1300000,
prevHash: "0000000000000165e6678be46ec2b15c587611b86da7147f7069a0e7175d62da",
count: 100000,
lastHash: "00000000000002ef0a47d0f242ab280bded8f4780bad506c71f2e1d2771becd4",
fileHash: "2MFJLBjHOBnuaDAICQFCL3y+6ejj0k92gbcmLWa1/Xc=",
lastChainWork: "0000000000000000000000000000000000000000000000dcc85f546d353f7b08",
prevChainWork: "0000000000000000000000000000000000000000000000542144c6af6e9258ea",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_14.headers",
firstHeight: 1400000,
prevHash: "00000000000002ef0a47d0f242ab280bded8f4780bad506c71f2e1d2771becd4",
count: 100000,
lastHash: "0000000000000168de8736c8a424fd5ebe1dcf0a030ed5fa0699b8c0fafc0b5e",
fileHash: "lWmP/pOR5ciEnu5tjIrf7OTEaiaMcfqFZQQYT7QH6qg=",
lastChainWork: "00000000000000000000000000000000000000000000011bed7ab81a56a65cbc",
prevChainWork: "0000000000000000000000000000000000000000000000dcc85f546d353f7b08",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_15.headers",
firstHeight: 1500000,
prevHash: "0000000000000168de8736c8a424fd5ebe1dcf0a030ed5fa0699b8c0fafc0b5e",
count: 100000,
lastHash: "00000000000005504bfd1a3ce4688c30c86740390102b6cd464a2fb5e0e3fed1",
fileHash: "1bCf0R0RsoadANX+6H4NH1b3jNuTPyTayoS1SpQXa2Q=",
lastChainWork: "000000000000000000000000000000000000000000000156c3b84396da4e60b9",
prevChainWork: "00000000000000000000000000000000000000000000011bed7ab81a56a65cbc",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "testNet_16.headers",
firstHeight: 1600000,
prevHash: "00000000000005504bfd1a3ce4688c30c86740390102b6cd464a2fb5e0e3fed1",
count: 77821,
lastHash: "0000000065ef364929e71688b29320c5835fabd8a1c0b6d42b6726cb4afcc798",
fileHash: "AK1FlgOaPVFOeG2x+Tp7htOt15UaSpHXZjgx3F263x8=",
lastChainWork: "00000000000000000000000000000000000000000000015814b641eb5d72e2ef",
prevChainWork: "000000000000000000000000000000000000000000000156c3b84396da4e60b9",
chain: "test",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_0.headers",
firstHeight: 0,
prevHash: "0000000000000000000000000000000000000000000000000000000000000000",
count: 100000,
lastHash: "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",
fileHash: "DMXYETHMphmYRh5y0+qsJhj67ML5Ui4LE1eEZDYbnZE=",
lastChainWork: "000000000000000000000000000000000000000000000000064492eaf00f2520",
prevChainWork: "0000000000000000000000000000000000000000000000000000000000000000",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_1.headers",
firstHeight: 100000,
prevHash: "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",
count: 100000,
lastHash: "00000000000003a20def7a05a77361b9657ff954b2f2080e135ea6f5970da215",
fileHash: "IID8O84Uny22i10fWHTQr6f9+9eFZ8dhVyegYPGSg+Q=",
lastChainWork: "00000000000000000000000000000000000000000000001ac0479f335782cb80",
prevChainWork: "000000000000000000000000000000000000000000000000064492eaf00f2520",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_2.headers",
firstHeight: 200000,
prevHash: "00000000000003a20def7a05a77361b9657ff954b2f2080e135ea6f5970da215",
count: 100000,
lastHash: "000000000000000067ecc744b5ae34eebbde14d21ca4db51652e4d67e155f07e",
fileHash: "wbfV/ZuPvLKHtRJN4QlHiKlpNncuqWA1dMJ6O9mhisc=",
lastChainWork: "000000000000000000000000000000000000000000005a795f5d6ede10bc6d60",
prevChainWork: "00000000000000000000000000000000000000000000001ac0479f335782cb80",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_3.headers",
firstHeight: 300000,
prevHash: "000000000000000067ecc744b5ae34eebbde14d21ca4db51652e4d67e155f07e",
count: 100000,
lastHash: "0000000000000000030034b661aed920a9bdf6bbfa6d2e7a021f78481882fa39",
fileHash: "5pklz64as2MG6y9lQiiClZaA82f6xoK1xdzkSqOZLsA=",
lastChainWork: "0000000000000000000000000000000000000000001229fea679a4cdc26e7460",
prevChainWork: "000000000000000000000000000000000000000000005a795f5d6ede10bc6d60",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_4.headers",
firstHeight: 400000,
prevHash: "0000000000000000030034b661aed920a9bdf6bbfa6d2e7a021f78481882fa39",
count: 100000,
lastHash: "0000000000000000043831d6ebb013716f0580287ee5e5687e27d0ed72e6e523",
fileHash: "2X78/S+Z/h5ELA63aC3xt6/o4G8JMcAOEiZ00ycKHsM=",
lastChainWork: "0000000000000000000000000000000000000000007ae4707601d47bc6695487",
prevChainWork: "0000000000000000000000000000000000000000001229fea679a4cdc26e7460",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_5.headers",
firstHeight: 500000,
prevHash: "0000000000000000043831d6ebb013716f0580287ee5e5687e27d0ed72e6e523",
count: 100000,
lastHash: "0000000000000000078f57b9a986b53b73f007c6b27b6f16409ca4eda83034e8",
fileHash: "Tzm60n66tIuq7wNdP6M1BH77iFzGCPbOMIl6smJ/LRg=",
lastChainWork: "000000000000000000000000000000000000000000e8f2ea21f069a214067ed7",
prevChainWork: "0000000000000000000000000000000000000000007ae4707601d47bc6695487",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_6.headers",
firstHeight: 600000,
prevHash: "0000000000000000078f57b9a986b53b73f007c6b27b6f16409ca4eda83034e8",
count: 100000,
lastHash: "000000000000000013abf3ab026610ed70e023476db8ce96f68637acdcbcf3cb",
fileHash: "O7SoyIDxhejB0Qs4rBO4OkfBK2yVZKhxra6YxZMhiIk=",
lastChainWork: "0000000000000000000000000000000000000000012f32fb33b26aa239be0fc3",
prevChainWork: "000000000000000000000000000000000000000000e8f2ea21f069a214067ed7",
chain: "main",
validated: true
},
{
sourceUrl: "https://cdn.projectbabbage.com/blockheaders",
fileName: "mainNet_7.headers",
firstHeight: 700000,
prevHash: "000000000000000013abf3ab026610ed70e023476db8ce96f68637acdcbcf3cb",
count: 100000,
lastHash: "00000000000000000b6ae23bbe9f549844c20943d8c20b8ceedbae8aa1dde8e0",
fileHash: "+0Wu2GrKgCv4o1yZfdWl60aAgvBj6Rt3xlWj8TQprUw=",
lastChainWork: "000000000000000000000000000000000000000001483b2995af390c20b58320",
prevChainWork: "0000000000000000000000000000000000000000012f32fb33b26aa239be0fc3",
chain: "main",
validated: true
},
{
chain: "main",
count: 100000,
fileHash: "xKYCsMzfbWdwq6RtEos4+4w7F3FroFMXb4tk4Z2gn5s=",
fileName: "mainNet_8.headers",
firstHeight: 800000,
lastChainWork: "000000000000000000000000000000000000000001664db1f2d50327928007e0",
lastHash: "00000000000000000e7dcc27c06ee353bd37260b2e7e664314c204f0324a5087",
prevChainWork: "000000000000000000000000000000000000000001483b2995af390c20b58320",
prevHash: "00000000000000000b6ae23bbe9f549844c20943d8c20b8ceedbae8aa1dde8e0",
sourceUrl: "https://cdn.projectbabbage.com/blockheaders"
},
{
chain: "main",
count: 7630,
fileHash: "R3JNRSzpFPvKXH2myRL+m420ycjrxRTcSI3aiMOJmfo=",
fileName: "mainNet_9.headers",
firstHeight: 900000,
lastChainWork: "00000000000000000000000000000000000000000167cca3f0721d58e023cf01",
lastHash: "00000000000000000c119d65afcc66b640e98b839414c7e66d22b428ecb24a43",
prevChainWork: "000000000000000000000000000000000000000001664db1f2d50327928007e0",
prevHash: "00000000000000000e7dcc27c06ee353bd37260b2e7e664314c204f0324a5087",
sourceUrl: "https://cdn.projectbabbage.com/blockheaders"
}
]
See also: BulkHeaderFileInfo
Links: API, Interfaces, Classes, Functions, Types, Variables