@bsv/overlay 0.3.1 → 0.4.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/dist/cjs/package.json +2 -2
- package/dist/cjs/src/Engine.js +15 -14
- package/dist/cjs/src/Engine.js.map +1 -1
- package/dist/cjs/src/GASP/OverlayGASPStorage.js +1 -1
- package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/Engine.js +15 -14
- package/dist/esm/src/Engine.js.map +1 -1
- package/dist/esm/src/GASP/OverlayGASPStorage.js +2 -2
- package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/Engine.d.ts +2 -1
- package/dist/types/src/Engine.d.ts.map +1 -1
- package/dist/types/src/LookupFormula.d.ts +4 -0
- package/dist/types/src/LookupFormula.d.ts.map +1 -1
- package/dist/types/src/LookupService.d.ts +6 -2
- package/dist/types/src/LookupService.d.ts.map +1 -1
- package/dist/types/src/TopicManager.d.ts +2 -2
- package/dist/types/src/TopicManager.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/Engine.ts +16 -17
- package/src/GASP/OverlayGASPStorage.ts +2 -2
- package/src/LookupFormula.ts +5 -0
- package/src/LookupService.ts +5 -1
- package/src/TopicManager.ts +2 -2
- package/src/__tests/Engine.test.ts +1 -1
package/src/Engine.ts
CHANGED
|
@@ -114,12 +114,13 @@ export class Engine {
|
|
|
114
114
|
* @param {TaggedBEEF} taggedBEEF - The transaction to process
|
|
115
115
|
* @param {function(STEAK): void} [onSTEAKReady] - Optional callback function invoked when the STEAK is ready.
|
|
116
116
|
* @param {string} mode — Indicates the submission behavior, whether historical or current. Historical transactions are not broadcast or propagated.
|
|
117
|
+
* @param {number[]} offChainValues — Values necessary to evaluate topical admittance that are not stored on-chain.
|
|
117
118
|
*
|
|
118
119
|
* The optional callback function should be used to get STEAK when ready, and avoid waiting for broadcast and transaction propagation to complete.
|
|
119
120
|
*
|
|
120
121
|
* @returns {Promise<STEAK>} The submitted transaction execution acknowledgement
|
|
121
122
|
*/
|
|
122
|
-
async submit (taggedBEEF: TaggedBEEF, onSteakReady?: (steak: STEAK) => void, mode: 'historical-tx' | 'current-tx' = 'current-tx'): Promise<STEAK> {
|
|
123
|
+
async submit (taggedBEEF: TaggedBEEF, onSteakReady?: (steak: STEAK) => void, mode: 'historical-tx' | 'current-tx' = 'current-tx', offChainValues?: number[]): Promise<STEAK> {
|
|
123
124
|
for (const t of taggedBEEF.topics) {
|
|
124
125
|
if (this.managers[t] === undefined || this.managers[t] === null) {
|
|
125
126
|
throw new Error(`This server does not support this topic: ${t}`)
|
|
@@ -209,7 +210,8 @@ export class Engine {
|
|
|
209
210
|
unlockingScript: tx.inputs[inputIndex].unlockingScript!,
|
|
210
211
|
txid: output.txid,
|
|
211
212
|
outputIndex: output.outputIndex,
|
|
212
|
-
topic
|
|
213
|
+
topic,
|
|
214
|
+
offChainValues
|
|
213
215
|
})
|
|
214
216
|
} else if (l.spendNotificationMode === 'whole-tx') {
|
|
215
217
|
await l.outputSpent({
|
|
@@ -217,7 +219,8 @@ export class Engine {
|
|
|
217
219
|
spendingAtomicBEEF: tx.toAtomicBEEF(),
|
|
218
220
|
txid: output.txid,
|
|
219
221
|
outputIndex: output.outputIndex,
|
|
220
|
-
topic
|
|
222
|
+
topic,
|
|
223
|
+
offChainValues
|
|
221
224
|
})
|
|
222
225
|
} else { // none
|
|
223
226
|
await l.outputSpent({
|
|
@@ -243,7 +246,7 @@ export class Engine {
|
|
|
243
246
|
const admissibleOutputsPromise = (async () => {
|
|
244
247
|
try {
|
|
245
248
|
this.startTime(`identifyAdmissibleOutputs_${txid.substring(0, 10)}`)
|
|
246
|
-
admissibleOutputs = await this.managers[topic].identifyAdmissibleOutputs(taggedBEEF.beef, previousCoins)
|
|
249
|
+
admissibleOutputs = await this.managers[topic].identifyAdmissibleOutputs(taggedBEEF.beef, previousCoins, offChainValues)
|
|
247
250
|
this.endTime(`identifyAdmissibleOutputs_${txid.substring(0, 10)}`)
|
|
248
251
|
} catch (_) {
|
|
249
252
|
steak[topic] = { outputsToAdmit: [], coinsToRetain: [] }
|
|
@@ -372,14 +375,16 @@ export class Engine {
|
|
|
372
375
|
outputIndex,
|
|
373
376
|
lockingScript: tx.outputs[outputIndex].lockingScript,
|
|
374
377
|
satoshis: tx.outputs[outputIndex].satoshis,
|
|
375
|
-
topic
|
|
378
|
+
topic,
|
|
379
|
+
offChainValues
|
|
376
380
|
})
|
|
377
381
|
} else {
|
|
378
382
|
await l.outputAdmittedByTopic({
|
|
379
383
|
mode: 'whole-tx',
|
|
380
384
|
atomicBEEF: tx.toAtomicBEEF(),
|
|
381
385
|
outputIndex,
|
|
382
|
-
topic
|
|
386
|
+
topic,
|
|
387
|
+
offChainValues
|
|
383
388
|
})
|
|
384
389
|
}
|
|
385
390
|
}))
|
|
@@ -453,16 +458,9 @@ export class Engine {
|
|
|
453
458
|
const lookupService = this.lookupServices[lookupQuestion.service]
|
|
454
459
|
if (lookupService === undefined || lookupService === null) throw new Error(`Lookup service not found for provider: ${lookupQuestion.service} `)
|
|
455
460
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return lookupResult as LookupAnswer
|
|
460
|
-
}
|
|
461
|
-
lookupResult = lookupResult as LookupFormula
|
|
462
|
-
|
|
463
|
-
const hydratedOutputs: Array<{ beef: number[], outputIndex: number }> = []
|
|
464
|
-
|
|
465
|
-
for (const { txid, outputIndex, history } of lookupResult) {
|
|
461
|
+
const lookupResult = await lookupService.lookup(lookupQuestion)
|
|
462
|
+
const hydratedOutputs: Array<{ beef: number[], outputIndex: number, context?: number[] }> = []
|
|
463
|
+
for (const { txid, outputIndex, history, context } of lookupResult) {
|
|
466
464
|
// Make sure this is an unspent output (UTXO)
|
|
467
465
|
const UTXO = await this.storage.findOutput(
|
|
468
466
|
txid,
|
|
@@ -478,7 +476,8 @@ export class Engine {
|
|
|
478
476
|
if (output?.beef !== undefined) {
|
|
479
477
|
hydratedOutputs.push({
|
|
480
478
|
beef: output.beef,
|
|
481
|
-
outputIndex: output.outputIndex
|
|
479
|
+
outputIndex: output.outputIndex,
|
|
480
|
+
context
|
|
482
481
|
})
|
|
483
482
|
}
|
|
484
483
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GASPNode, GASPNodeResponse, GASPStorage } from '@bsv/gasp'
|
|
2
|
-
import { MerklePath, Transaction } from '@bsv/sdk'
|
|
2
|
+
import { MerklePath, Transaction, Utils } from '@bsv/sdk'
|
|
3
3
|
import { Engine } from '../Engine.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -90,7 +90,7 @@ export class OverlayGASPStorage implements GASPStorage {
|
|
|
90
90
|
|
|
91
91
|
// Attempt to check if the current transaction is admissible
|
|
92
92
|
parsedTx.merklePath = MerklePath.fromHex(tx.proof)
|
|
93
|
-
const admittanceResult = await this.engine.managers[this.topic].identifyAdmissibleOutputs(parsedTx.toBEEF(), [])
|
|
93
|
+
const admittanceResult = await this.engine.managers[this.topic].identifyAdmissibleOutputs(parsedTx.toBEEF(), [], typeof tx.txMetadata === 'string' ? Utils.toArray(tx.txMetadata) : undefined)
|
|
94
94
|
|
|
95
95
|
if (admittanceResult.outputsToAdmit.includes(tx.outputIndex)) {
|
|
96
96
|
// The transaction is admissible, no further inputs are needed
|
package/src/LookupFormula.ts
CHANGED
|
@@ -23,4 +23,9 @@ export type LookupFormula = Array<{
|
|
|
23
23
|
* If not provided, no historical information will be included with the Lookup Answer, except that which may incidentally be required to fully anchor the Lookup Answer to the blockchain.
|
|
24
24
|
*/
|
|
25
25
|
history?: ((beef: number[], outputIndex: number, currentDepth: number) => Promise<boolean>) | number
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Context for the UTXO, derived from the off-chain values.
|
|
29
|
+
*/
|
|
30
|
+
context?: number[]
|
|
26
31
|
}>
|
package/src/LookupService.ts
CHANGED
|
@@ -18,12 +18,14 @@ export type OutputAdmittedByTopic =
|
|
|
18
18
|
topic: string // topic into which it was admitted
|
|
19
19
|
satoshis: number // value of the output
|
|
20
20
|
lockingScript: Script // script in this output
|
|
21
|
+
offChainValues?: number[] // off-chain values associated with the output
|
|
21
22
|
}
|
|
22
23
|
| { // «whole-tx» mode
|
|
23
24
|
mode: 'whole-tx'
|
|
24
25
|
atomicBEEF: number[] // whole transaction (Atomic BEEF)
|
|
25
26
|
outputIndex: number
|
|
26
27
|
topic: string
|
|
28
|
+
offChainValues?: number[]
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
/* ---------------------------------------------------------------------------
|
|
@@ -52,6 +54,7 @@ export type OutputSpent =
|
|
|
52
54
|
inputIndex: number
|
|
53
55
|
unlockingScript: Script
|
|
54
56
|
sequenceNumber: number
|
|
57
|
+
offChainValues?: number[]
|
|
55
58
|
}
|
|
56
59
|
| { // «whole-tx» – full spending TX
|
|
57
60
|
mode: 'whole-tx'
|
|
@@ -59,6 +62,7 @@ export type OutputSpent =
|
|
|
59
62
|
outputIndex: number
|
|
60
63
|
topic: string
|
|
61
64
|
spendingAtomicBEEF: number[]
|
|
65
|
+
offChainValues?: number[]
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
/* ---------------------------------------------------------------------------
|
|
@@ -121,7 +125,7 @@ export interface LookupService {
|
|
|
121
125
|
/* -------------------------------------------------------------------------
|
|
122
126
|
* Query API
|
|
123
127
|
* ----------------------------------------------------------------------- */
|
|
124
|
-
lookup: (question: LookupQuestion) => Promise<
|
|
128
|
+
lookup: (question: LookupQuestion) => Promise<LookupFormula>
|
|
125
129
|
|
|
126
130
|
/* -------------------------------------------------------------------------
|
|
127
131
|
* Documentation helpers
|
package/src/TopicManager.ts
CHANGED
|
@@ -9,13 +9,13 @@ export interface TopicManager {
|
|
|
9
9
|
* Accepts the transaction in BEEF format and an array of those input indices which spend previously-admitted outputs from the same topic.
|
|
10
10
|
* The transaction's BEEF structure will always contain the transactions associated with previous coins for reference (if any), regardless of whether the current transaction was directly proven.
|
|
11
11
|
*/
|
|
12
|
-
identifyAdmissibleOutputs: (beef: number[], previousCoins: number[]) => Promise<AdmittanceInstructions>
|
|
12
|
+
identifyAdmissibleOutputs: (beef: number[], previousCoins: number[], offChainValues?: number[]) => Promise<AdmittanceInstructions>
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Identifies and returns the inputs needed to anchor any topical outputs from this transaction to their associated previous history.
|
|
16
16
|
* @throws - if there are no potentially valid topical outputs in this transaction
|
|
17
17
|
*/
|
|
18
|
-
identifyNeededInputs?: (beef: number[]) => Promise<Array<{ txid: string, outputIndex: number }>>
|
|
18
|
+
identifyNeededInputs?: (beef: number[], offChainValues?: number[]) => Promise<Array<{ txid: string, outputIndex: number }>>
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Returns a Markdown-formatted documentation string for the topic manager.
|
|
@@ -534,7 +534,7 @@ describe('BSV Overlay Services Engine', () => {
|
|
|
534
534
|
beef: exampleBeef,
|
|
535
535
|
topics: ['Hello']
|
|
536
536
|
})
|
|
537
|
-
expect(engine.managers.Hello.identifyAdmissibleOutputs).toHaveBeenCalledWith(exampleBeef, [0])
|
|
537
|
+
expect(engine.managers.Hello.identifyAdmissibleOutputs).toHaveBeenCalledWith(exampleBeef, [0], undefined)
|
|
538
538
|
})
|
|
539
539
|
describe('When previous UTXOs were retained by the topic manager', () => {
|
|
540
540
|
it('Notifies all lookup services about the output being spent (not deleted, see the comment about this in deleteUTXODeep)', async () => {
|