@bsv/overlay 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +57 -27
- package/README.md +102 -269
- package/dist/cjs/mod.d.ts +15 -0
- package/dist/cjs/mod.d.ts.map +1 -0
- package/dist/cjs/mod.js +4 -1
- package/dist/cjs/mod.js.map +1 -1
- package/dist/cjs/package.json +41 -13
- package/dist/cjs/src/Advertisement.d.ts +9 -0
- package/dist/cjs/src/Advertisement.d.ts.map +1 -0
- package/dist/cjs/src/Advertiser.d.ts +36 -0
- package/dist/cjs/src/Advertiser.d.ts.map +1 -0
- package/dist/cjs/src/BASM.d.ts +110 -0
- package/dist/cjs/src/BASM.d.ts.map +1 -0
- package/dist/cjs/src/BASM.js.map +1 -1
- package/dist/cjs/src/BASMRemote.d.ts +14 -0
- package/dist/cjs/src/BASMRemote.d.ts.map +1 -0
- package/dist/cjs/src/BASMRemote.js.map +1 -1
- package/dist/cjs/src/Engine.d.ts +379 -0
- package/dist/cjs/src/Engine.d.ts.map +1 -0
- package/dist/cjs/src/Engine.js +425 -418
- package/dist/cjs/src/Engine.js.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts +24 -0
- package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts.map +1 -0
- package/dist/cjs/src/GASP/OverlayGASPRemote.js +7 -10
- package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts +103 -0
- package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts.map +1 -0
- package/dist/cjs/src/GASP/OverlayGASPStorage.js +32 -30
- package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/cjs/src/LookupFormula.d.ts +29 -0
- package/dist/cjs/src/LookupFormula.d.ts.map +1 -0
- package/dist/cjs/src/LookupService.d.ts +85 -0
- package/dist/cjs/src/LookupService.d.ts.map +1 -0
- package/dist/cjs/src/Output.d.ts +32 -0
- package/dist/cjs/src/Output.d.ts.map +1 -0
- package/dist/cjs/src/SafeLog.d.ts +14 -0
- package/dist/cjs/src/SafeLog.d.ts.map +1 -0
- package/dist/cjs/src/SafeLog.js +44 -0
- package/dist/cjs/src/SafeLog.js.map +1 -0
- package/{src/SyncConfiguration.ts → dist/cjs/src/SyncConfiguration.d.ts} +2 -1
- package/dist/cjs/src/SyncConfiguration.d.ts.map +1 -0
- package/dist/cjs/src/TopicManager.d.ts +35 -0
- package/dist/cjs/src/TopicManager.d.ts.map +1 -0
- package/dist/cjs/src/storage/Storage.d.ts +237 -0
- package/dist/cjs/src/storage/Storage.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/KnexStorage.d.ts +69 -0
- package/dist/cjs/src/storage/knex/KnexStorage.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/KnexStorage.js +7 -10
- package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
- package/dist/cjs/src/storage/knex/all-migrations.d.ts +11 -0
- package/dist/cjs/src/storage/knex/all-migrations.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/all-migrations.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.d.ts +9 -0
- package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.js.map +1 -1
- package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.d.ts +4 -0
- package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.d.ts.map +1 -0
- package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.js.map +1 -1
- package/dist/esm/mod.js +2 -1
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/src/BASMRemote.js.map +1 -1
- package/dist/esm/src/Engine.js +404 -396
- package/dist/esm/src/Engine.js.map +1 -1
- package/dist/esm/src/GASP/OverlayGASPRemote.js +2 -2
- package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
- package/dist/esm/src/GASP/OverlayGASPStorage.js +21 -18
- package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/esm/src/SafeLog.js +40 -0
- package/dist/esm/src/SafeLog.js.map +1 -0
- package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
- package/dist/types/mod.d.ts +5 -4
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/src/BASMRemote.d.ts.map +1 -1
- package/dist/types/src/Engine.d.ts +18 -1
- package/dist/types/src/Engine.d.ts.map +1 -1
- package/dist/types/src/GASP/OverlayGASPRemote.d.ts +2 -2
- package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
- package/dist/types/src/GASP/OverlayGASPStorage.d.ts +3 -1
- package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
- package/dist/types/src/SafeLog.d.ts +14 -0
- package/dist/types/src/SafeLog.d.ts.map +1 -0
- package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
- package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
- package/package.json +85 -28
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +0 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +0 -1
- package/dist/types/tsconfig.types.tsbuildinfo +0 -1
- package/docs/API.md +0 -944
- package/docs/BRC-136-BASM.md +0 -327
- package/docs/README.md +0 -16
- package/docs/Synchronization.md +0 -212
- package/docs/concepts/00-overview.md +0 -85
- package/docs/concepts/01-best-practices.md +0 -202
- package/docs/concepts/02-query-performance.md +0 -345
- package/docs/concepts/03-database-monitoring.md +0 -211
- package/docs/concepts/04-pagination-example.md +0 -186
- package/docs/concepts/05-recommendations-summary.md +0 -158
- package/docs/concepts/README.md +0 -20
- package/docs/examples/README.md +0 -15
- package/docs/examples/gs-wip.md +0 -111
- package/docs/internal/README.md +0 -11
- package/mod.ts +0 -40
- package/src/Advertisement.ts +0 -8
- package/src/Advertiser.ts +0 -41
- package/src/BASM.ts +0 -208
- package/src/BASMRemote.ts +0 -54
- package/src/Engine.ts +0 -2194
- package/src/GASP/OverlayGASPRemote.ts +0 -108
- package/src/GASP/OverlayGASPStorage.ts +0 -384
- package/src/LookupFormula.ts +0 -31
- package/src/LookupService.ts +0 -136
- package/src/Output.ts +0 -31
- package/src/TopicManager.ts +0 -40
- package/src/__tests/BASM.test.ts +0 -44
- package/src/__tests/BASMChain.test.ts +0 -295
- package/src/__tests/Engine.test.ts +0 -1381
- package/src/__tests/OverlayGASPRemote.test.ts +0 -135
- package/src/__tests/OverlayGASPStorage.test.ts +0 -205
- package/src/storage/Storage.ts +0 -260
- package/src/storage/knex/KnexStorage.ts +0 -651
- package/src/storage/knex/all-migrations.ts +0 -32
- package/src/storage/knex/migrations/2024-05-18-001-initial.ts +0 -30
- package/src/storage/knex/migrations/2024-07-10-001-block-height.ts +0 -15
- package/src/storage/knex/migrations/2024-07-17-001-transactions.ts +0 -64
- package/src/storage/knex/migrations/2024-07-18-001-indexes.ts +0 -30
- package/src/storage/knex/migrations/2025-05-28-001-enlarge.ts +0 -42
- package/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.ts +0 -46
- package/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.ts +0 -24
- package/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.ts +0 -18
- package/src/storage/knex/migrations/2026-05-29-001-brc136-basm.ts +0 -123
package/docs/examples/gs-wip.md
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Getting Started with BSV Overlay Services Engine
|
|
2
|
-
|
|
3
|
-
[🏠 Home](../README.md) | [📚 API](../API.md) | [💡 Concepts](../concepts/README.md) | [📖 Examples](./README.md) | [⚙️ Internal](../internal/README.md)
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Introduction to BSV Overlay Services Engine
|
|
8
|
-
|
|
9
|
-
The BSV Overlay Services Engine is designed to process transactions and manage data within a blockchain-based system, specifically targeting the Bitcoin SV (BSV) blockchain. It integrates various components such as Topic Managers, Lookup Services, Storage, and Chain Tracker to provide a robust environment for managing transaction data and overlay services.
|
|
10
|
-
|
|
11
|
-
### Components of the System
|
|
12
|
-
|
|
13
|
-
1. **Topic Managers**: Responsible for managing the admittance of transactions related to specific topics.
|
|
14
|
-
2. **Lookup Services**: Handle the lookup of UTXO (Unspent Transaction Output) data for transactions.
|
|
15
|
-
3. **Storage**: Manages persistent data storage, tracking UTXOs and their states within the system.
|
|
16
|
-
4. **Chain Tracker**: Verifies SPV (Simplified Payment Verification) data associated with transactions to ensure their validity.
|
|
17
|
-
|
|
18
|
-
### Setting Up the Engine
|
|
19
|
-
|
|
20
|
-
Before you can use the engine, you must initialize it with the required components:
|
|
21
|
-
|
|
22
|
-
```ts
|
|
23
|
-
import { Engine, KnexStorage } from "@bsv/overlay";
|
|
24
|
-
import { HelloTopicManager, HelloLookupService } from 'hello-services';
|
|
25
|
-
import { WoChain } from "@bsv/sdk";
|
|
26
|
-
|
|
27
|
-
// Initialize components
|
|
28
|
-
const managers = {
|
|
29
|
-
"exampleTopic": new HelloTopicManager()
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const lookupServices = {
|
|
33
|
-
"exampleLookup": new HelloLookupService()
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const storage = new KnexStorage();
|
|
37
|
-
const chainTracker = new WoChain();
|
|
38
|
-
|
|
39
|
-
// Create the engine instance
|
|
40
|
-
const engine = new Engine(managers, lookupServices, storage, chainTracker);
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Submitting a Transaction
|
|
44
|
-
|
|
45
|
-
To submit a transaction for processing by the Overlay Services:
|
|
46
|
-
|
|
47
|
-
```ts
|
|
48
|
-
import { Transaction } from '@bsv/sdk'
|
|
49
|
-
|
|
50
|
-
const tx = new Transaction(/* ... */);
|
|
51
|
-
|
|
52
|
-
const transaction = {
|
|
53
|
-
beef: tx.toBEEF(),
|
|
54
|
-
topics: ['exampleTopic']
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Submit transaction
|
|
58
|
-
engine.submit(transaction).then(steak => {
|
|
59
|
-
console.log("Transaction processed:", steak);
|
|
60
|
-
}).catch(error => {
|
|
61
|
-
console.error("Error processing transaction:", error);
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Lookup Queries
|
|
66
|
-
|
|
67
|
-
To perform a lookup query using the engine:
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
const question = {
|
|
71
|
-
service: 'exampleLookup',
|
|
72
|
-
query: {
|
|
73
|
-
name: 'Bob'
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Perform a lookup
|
|
78
|
-
engine.lookup(question).then(answer => {
|
|
79
|
-
console.log("Lookup result:", answer);
|
|
80
|
-
}).catch(error => {
|
|
81
|
-
console.error("Error performing lookup:", error);
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Managing UTXOs
|
|
86
|
-
|
|
87
|
-
The system's core functionality involves managing UTXOs:
|
|
88
|
-
|
|
89
|
-
1. **Inserting a New UTXO**: Store new UTXO data when transactions are processed.
|
|
90
|
-
2. **Deleting a UTXO**: Remove UTXOs that are no longer needed or have been consumed by newer transactions.
|
|
91
|
-
3. **Tracking UTXO Consumption**: Monitor which transactions consume which UTXOs.
|
|
92
|
-
|
|
93
|
-
### Retrieving Documentation
|
|
94
|
-
|
|
95
|
-
To retrieve documentation for specific managers or services:
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
// For a topic manager
|
|
99
|
-
engine.getDocumentationForTopicManger("exampleTopic").then(doc => {
|
|
100
|
-
console.log("Documentation for Topic Manager:", doc);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// For a lookup service
|
|
104
|
-
engine.getDocumentationForLookupServiceProvider("exampleLookup").then(doc => {
|
|
105
|
-
console.log("Documentation for Lookup Service:", doc);
|
|
106
|
-
});
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Conclusion
|
|
110
|
-
|
|
111
|
-
The BSV Overlay Services Engine provides a powerful toolset for managing transactions and data on the Bitcoin SV blockchain. It's designed to handle complex data structures and ensure the integrity and security of transactions through rigorous validation and management processes. By following this tutorial, developers can effectively integrate and utilize these capabilities within their blockchain applications.
|
package/docs/internal/README.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Internals
|
|
2
|
-
|
|
3
|
-
[🏠 Home](../README.md) | [📚 API](../API.md) | [💡 Concepts](../concepts/README.md) | [📖 Examples](../examples/README.md) | [⚙️ Internal](./README.md)
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
These documents cover the internal components of the Overlay Services engine. Generally, these are only useful for creating customized deployments.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
[🏠 Home](../README.md) | [📚 API](../API.md) | [💡 Concepts](../concepts/README.md) | [📖 Examples](../examples/README.md) | [⚙️ Internal](./README.md)
|
package/mod.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// Fundamentals
|
|
2
|
-
export { Engine } from "./src/Engine.js"
|
|
3
|
-
export type * from "./src/LookupService.js"
|
|
4
|
-
export type { TopicManager } from "./src/TopicManager.js"
|
|
5
|
-
|
|
6
|
-
// Interfaces and structures
|
|
7
|
-
export type { Storage, AppliedTransaction } from "./src/storage/Storage.js"
|
|
8
|
-
export type { Output } from './src/Output.js'
|
|
9
|
-
export type { TaggedBEEF, STEAK, LookupQuestion, LookupAnswer, AdmittanceInstructions } from '@bsv/sdk'
|
|
10
|
-
export type { LookupFormula } from './src/LookupFormula.js'
|
|
11
|
-
export type { Advertisement } from './src/Advertisement.js'
|
|
12
|
-
export type { AdvertisementData, Advertiser } from './src/Advertiser.js'
|
|
13
|
-
export {
|
|
14
|
-
BASM_ZERO_HASH,
|
|
15
|
-
computeBasmRoot,
|
|
16
|
-
computeTac,
|
|
17
|
-
extractMerkleProofMetadata
|
|
18
|
-
} from './src/BASM.js'
|
|
19
|
-
export type {
|
|
20
|
-
AdmittedListRequest,
|
|
21
|
-
AdmittedListResponse,
|
|
22
|
-
AdmittedTxRef,
|
|
23
|
-
BASMPeerSyncReport,
|
|
24
|
-
CompoundMerklePathRequest,
|
|
25
|
-
CompoundMerklePathResponse,
|
|
26
|
-
MerkleProofMetadata,
|
|
27
|
-
RawTransactionRecord,
|
|
28
|
-
RawTransactionRequest,
|
|
29
|
-
RawTransactionResponse,
|
|
30
|
-
TopicAnchorHeader,
|
|
31
|
-
TopicAnchorHeaderResolver,
|
|
32
|
-
TopicAnchorRangeRequest,
|
|
33
|
-
TopicAnchorRangeResponse,
|
|
34
|
-
TopicAnchorTip,
|
|
35
|
-
TopicBlockAnchor
|
|
36
|
-
} from './src/BASM.js'
|
|
37
|
-
|
|
38
|
-
// The Knex storage system
|
|
39
|
-
export { KnexStorage } from './src/storage/knex/KnexStorage.js'
|
|
40
|
-
export * as KnexStorageMigrations from './src/storage/knex/all-migrations.js'
|
package/src/Advertisement.ts
DELETED
package/src/Advertiser.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Script, TaggedBEEF } from '@bsv/sdk'
|
|
2
|
-
import { Advertisement } from './Advertisement.js'
|
|
3
|
-
|
|
4
|
-
export interface AdvertisementData {
|
|
5
|
-
protocol: 'SHIP' | 'SLAP'
|
|
6
|
-
topicOrServiceName: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Interface for managing SHIP and SLAP advertisements.
|
|
11
|
-
* Provides methods for creating, finding, and revoking advertisements.
|
|
12
|
-
*/
|
|
13
|
-
export interface Advertiser {
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Creates a new SHIP/SLAP advertisement for a given topic.
|
|
17
|
-
* @param adsData - The data indicating the type of advertisement.
|
|
18
|
-
* @returns A promise that resolves to the created advertisement as TaggedBEEF.
|
|
19
|
-
*/
|
|
20
|
-
createAdvertisements: (adsData: AdvertisementData[]) => Promise<TaggedBEEF>
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Finds all SHIP/SLAP advertisements.
|
|
24
|
-
* @returns A promise that resolves to an array of SHIP/SLAP advertisements.
|
|
25
|
-
*/
|
|
26
|
-
findAllAdvertisements: (protocol: 'SHIP' | 'SLAP') => Promise<Advertisement[]>
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Revokes an existing advertisement, either SHIP or SLAP.
|
|
30
|
-
* @param advertisements - The advertisements to revoke, either SHIP or SLAP.
|
|
31
|
-
* @returns A promise that resolves to the revocation transaction as TaggedBEEF.
|
|
32
|
-
*/
|
|
33
|
-
revokeAdvertisements: (advertisements: Advertisement[]) => Promise<TaggedBEEF>
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Parses an output script to extract an advertisement.
|
|
37
|
-
* @param outputScript - The script of the output to be parsed.
|
|
38
|
-
* @returns The parsed advertisement
|
|
39
|
-
*/
|
|
40
|
-
parseAdvertisement: (outputScript: Script) => Advertisement
|
|
41
|
-
}
|
package/src/BASM.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
import { MerklePath } from '@bsv/sdk'
|
|
3
|
-
|
|
4
|
-
export const BASM_ZERO_HASH = '0000000000000000000000000000000000000000000000000000000000000000'
|
|
5
|
-
|
|
6
|
-
export interface TopicBlockAnchor {
|
|
7
|
-
topic: string
|
|
8
|
-
blockHeight: number
|
|
9
|
-
blockHash: string
|
|
10
|
-
basmRoot: string
|
|
11
|
-
admittedCount: number
|
|
12
|
-
tac: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface TopicAnchorTip {
|
|
16
|
-
topic: string
|
|
17
|
-
blockHeight: number
|
|
18
|
-
blockHash?: string
|
|
19
|
-
basmRoot?: string
|
|
20
|
-
admittedCount?: number
|
|
21
|
-
tac: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface AdmittedTxRef {
|
|
25
|
-
txid: string
|
|
26
|
-
blockIndex: number
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface RawTransactionRecord {
|
|
30
|
-
txid: string
|
|
31
|
-
rawTx: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface RawTransactionRequest {
|
|
35
|
-
txids: string[]
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface RawTransactionResponse {
|
|
39
|
-
transactions: RawTransactionRecord[]
|
|
40
|
-
missing: string[]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface TopicAnchorHeader {
|
|
44
|
-
blockHeight: number
|
|
45
|
-
blockHash: string
|
|
46
|
-
merkleRoot?: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type TopicAnchorHeaderResolver = (blockHeight: number) => Promise<TopicAnchorHeader | undefined>
|
|
50
|
-
|
|
51
|
-
export interface TopicAnchorRangeRequest {
|
|
52
|
-
fromHeight: number
|
|
53
|
-
toHeight: number
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface TopicAnchorRangeResponse {
|
|
57
|
-
topic: string
|
|
58
|
-
anchors: TopicBlockAnchor[]
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface AdmittedListRequest {
|
|
62
|
-
blockHeight: number
|
|
63
|
-
blockHash?: string
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface AdmittedListResponse {
|
|
67
|
-
topic: string
|
|
68
|
-
blockHeight: number
|
|
69
|
-
blockHash?: string
|
|
70
|
-
admitted: AdmittedTxRef[]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface CompoundMerklePathRequest {
|
|
74
|
-
blockHeight: number
|
|
75
|
-
txids: string[]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface CompoundMerklePathResponse {
|
|
79
|
-
topic: string
|
|
80
|
-
blockHeight: number
|
|
81
|
-
txids: string[]
|
|
82
|
-
merklePath: string
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface MerkleProofMetadata {
|
|
86
|
-
blockHeight: number
|
|
87
|
-
blockIndex: number
|
|
88
|
-
merkleRoot: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface ReorgReport {
|
|
92
|
-
perTopic: Array<{
|
|
93
|
-
topic: string
|
|
94
|
-
demotedTxids: string[]
|
|
95
|
-
rebuiltFrom: number
|
|
96
|
-
rebuiltTo: number
|
|
97
|
-
}>
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface BASMPeerSyncReport {
|
|
101
|
-
topic: string
|
|
102
|
-
endpoint: string
|
|
103
|
-
status: 'matched' | 'advanced' | 'diverged' | 'skipped' | 'error'
|
|
104
|
-
localTip?: TopicAnchorTip
|
|
105
|
-
remoteTip?: TopicAnchorTip
|
|
106
|
-
checkedHeights: number[]
|
|
107
|
-
missingTxids: string[]
|
|
108
|
-
fetchedTxCount: number
|
|
109
|
-
message?: string
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
type AdmittedTxLike = string | AdmittedTxRef
|
|
113
|
-
|
|
114
|
-
function sha256d(buffer: Buffer): Buffer {
|
|
115
|
-
const first = createHash('sha256').update(buffer).digest()
|
|
116
|
-
return createHash('sha256').update(first).digest()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function assertHashHex(hash: string, label: string): void {
|
|
120
|
-
if (!/^[0-9a-fA-F]{64}$/.test(hash)) {
|
|
121
|
-
throw new Error(`${label} must be 32 bytes of hex`)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function displayHexToInternal(hash: string): Buffer {
|
|
126
|
-
assertHashHex(hash, 'hash')
|
|
127
|
-
return Buffer.from(hash, 'hex').reverse()
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function internalToDisplayHex(hash: Buffer): string {
|
|
131
|
-
return Buffer.from(hash).reverse().toString('hex')
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function normalizeAdmittedTxids(admitted: AdmittedTxLike[]): string[] {
|
|
135
|
-
return admitted
|
|
136
|
-
.map((item, originalIndex) => {
|
|
137
|
-
if (typeof item === 'string') {
|
|
138
|
-
return { txid: item, blockIndex: originalIndex }
|
|
139
|
-
}
|
|
140
|
-
return item
|
|
141
|
-
})
|
|
142
|
-
.sort((a, b) => a.blockIndex - b.blockIndex)
|
|
143
|
-
.map(item => item.txid.toLowerCase())
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Computes a BRC-136 BASM root from admitted topic txids.
|
|
148
|
-
*
|
|
149
|
-
* The API accepts normal display-order txid hex because that is what the BSV
|
|
150
|
-
* TypeScript stack exposes at its public boundaries. Hashing is performed on
|
|
151
|
-
* internal byte order as required by the BRC, and the returned root is display
|
|
152
|
-
* order for JSON/wire compatibility.
|
|
153
|
-
*/
|
|
154
|
-
export function computeBasmRoot(admitted: AdmittedTxLike[]): string {
|
|
155
|
-
const txids = normalizeAdmittedTxids(admitted)
|
|
156
|
-
|
|
157
|
-
if (txids.length === 0) {
|
|
158
|
-
return BASM_ZERO_HASH
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
let layer = txids.map(txid => displayHexToInternal(txid))
|
|
162
|
-
if (layer.length === 1) {
|
|
163
|
-
return internalToDisplayHex(layer[0])
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
while (layer.length > 1) {
|
|
167
|
-
const next: Buffer[] = []
|
|
168
|
-
for (let i = 0; i < layer.length; i += 2) {
|
|
169
|
-
const left = layer[i]
|
|
170
|
-
const right = i + 1 < layer.length ? layer[i + 1] : left
|
|
171
|
-
next.push(sha256d(Buffer.concat([left, right])))
|
|
172
|
-
}
|
|
173
|
-
layer = next
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return internalToDisplayHex(layer[0])
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Computes the BRC-136 cumulative Topic Anchor Chain hash:
|
|
181
|
-
* SHA256d(prevTac || blockHash || basmRoot), with all inputs reversed to
|
|
182
|
-
* internal byte order before hashing and the output returned as display hex.
|
|
183
|
-
*/
|
|
184
|
-
export function computeTac(prevTac: string, blockHash: string, basmRoot: string): string {
|
|
185
|
-
const input = Buffer.concat([
|
|
186
|
-
displayHexToInternal(prevTac.toLowerCase()),
|
|
187
|
-
displayHexToInternal(blockHash.toLowerCase()),
|
|
188
|
-
displayHexToInternal(basmRoot.toLowerCase())
|
|
189
|
-
])
|
|
190
|
-
return internalToDisplayHex(sha256d(input))
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function extractMerkleProofMetadata(txid: string, proof?: MerklePath): MerkleProofMetadata | undefined {
|
|
194
|
-
if (proof === undefined) {
|
|
195
|
-
return undefined
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const leaf = proof.path[0]?.find(candidate => candidate.hash === txid)
|
|
199
|
-
if (leaf === undefined) {
|
|
200
|
-
return undefined
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return {
|
|
204
|
-
blockHeight: proof.blockHeight,
|
|
205
|
-
blockIndex: leaf.offset,
|
|
206
|
-
merkleRoot: proof.computeRoot(txid)
|
|
207
|
-
}
|
|
208
|
-
}
|
package/src/BASMRemote.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AdmittedListResponse,
|
|
3
|
-
CompoundMerklePathResponse,
|
|
4
|
-
RawTransactionResponse,
|
|
5
|
-
TopicAnchorRangeResponse,
|
|
6
|
-
TopicAnchorTip
|
|
7
|
-
} from './BASM.js'
|
|
8
|
-
|
|
9
|
-
export class BASMRemote {
|
|
10
|
-
constructor(
|
|
11
|
-
private readonly endpoint: string,
|
|
12
|
-
private readonly topic: string,
|
|
13
|
-
private readonly fetchImpl: typeof fetch = fetch.bind(globalThis)
|
|
14
|
-
) { }
|
|
15
|
-
|
|
16
|
-
async requestTopicAnchorTip(): Promise<TopicAnchorTip> {
|
|
17
|
-
return await this.post<TopicAnchorTip>('/requestTopicAnchorTip', {})
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async requestTopicAnchorRange(fromHeight: number, toHeight: number): Promise<TopicAnchorRangeResponse> {
|
|
21
|
-
return await this.post<TopicAnchorRangeResponse>('/requestTopicAnchorRange', { fromHeight, toHeight })
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async requestAdmittedList(blockHeight: number, blockHash?: string): Promise<AdmittedListResponse> {
|
|
25
|
-
return await this.post<AdmittedListResponse>('/requestAdmittedList', { blockHeight, blockHash })
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async requestCompoundMerklePath(blockHeight: number, txids: string[]): Promise<CompoundMerklePathResponse> {
|
|
29
|
-
return await this.post<CompoundMerklePathResponse>('/requestCompoundMerklePath', { blockHeight, txids })
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async requestRawTransactions(txids: string[]): Promise<RawTransactionResponse> {
|
|
33
|
-
return await this.post<RawTransactionResponse>('/requestRawTransactions', { txids })
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private async post<T>(path: string, body: unknown): Promise<T> {
|
|
37
|
-
const response = await this.fetchImpl(new URL(path, this.endpoint).toString(), {
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: {
|
|
40
|
-
Accept: 'application/json',
|
|
41
|
-
'Content-Type': 'application/json',
|
|
42
|
-
'x-bsv-topic': this.topic
|
|
43
|
-
},
|
|
44
|
-
body: JSON.stringify(body)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const text = await response.text()
|
|
48
|
-
if (!response.ok) {
|
|
49
|
-
throw new Error(`BASM peer ${this.endpoint} returned ${response.status}: ${text}`)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return (text.length === 0 ? {} : JSON.parse(text)) as T
|
|
53
|
-
}
|
|
54
|
-
}
|