@bsv/sdk 1.1.25 → 1.1.26
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 +1 -1
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +154 -34
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/transaction/MerklePath.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +154 -34
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/transaction/MerklePath.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts +44 -4
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/docs/transaction.md +65 -5
- package/package.json +1 -1
- package/src/transaction/MerklePath.ts +11 -11
- package/src/transaction/Transaction.ts +195 -59
- package/src/transaction/__tests/Transaction.test.ts +222 -3
|
@@ -31,7 +31,7 @@ import { BEEF_MAGIC } from './Beef.js'
|
|
|
31
31
|
* earliest time or block height at which the transaction can be added to the block chain.
|
|
32
32
|
* @property {Record<string, any>} metadata - A key-value store for attaching additional data to
|
|
33
33
|
* the transaction object, not included in the transaction itself. Useful for adding descriptions, internal reference numbers, or other information.
|
|
34
|
-
* @property {MerkleProof} [
|
|
34
|
+
* @property {MerkleProof} [merklePath] - Optional. A merkle proof demonstrating the transaction's
|
|
35
35
|
* inclusion in a block. Useful for transaction verification using SPV.
|
|
36
36
|
*
|
|
37
37
|
* @example
|
|
@@ -60,44 +60,109 @@ export default class Transaction {
|
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* Creates a new transaction, linked to its inputs and their associated merkle paths, from a BEEF (BRC-62) structure.
|
|
63
|
-
*
|
|
63
|
+
* Optionally, you can provide a specific TXID to retrieve a particular transaction from the BEEF data.
|
|
64
|
+
* If the TXID is provided but not found in the BEEF data, an error will be thrown.
|
|
65
|
+
* If no TXID is provided, the last transaction in the BEEF data is returned.
|
|
66
|
+
* @param beef A binary representation of transactions in BEEF format.
|
|
67
|
+
* @param txid Optional TXID of the transaction to retrieve from the BEEF data.
|
|
64
68
|
* @returns An anchored transaction, linked to its associated inputs populated with merkle paths.
|
|
65
69
|
*/
|
|
66
|
-
static fromBEEF
|
|
70
|
+
static fromBEEF(beef: number[], txid?: string): Transaction {
|
|
67
71
|
const reader = new Reader(beef)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if
|
|
71
|
-
|
|
72
|
+
const { transactions, BUMPs } = Transaction.parseBEEFData(reader)
|
|
73
|
+
|
|
74
|
+
// The last transaction in the BEEF data can be used if txid is not provided
|
|
75
|
+
const txids = Object.keys(transactions)
|
|
76
|
+
const lastTXID = txids[txids.length - 1]
|
|
77
|
+
const targetTXID = txid || lastTXID
|
|
78
|
+
|
|
79
|
+
if (!transactions[targetTXID]) {
|
|
80
|
+
throw new Error(`Transaction with TXID ${targetTXID} not found in BEEF data.`)
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
//
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
// Recursive function for adding merkle proofs or input transactions
|
|
84
|
+
const addPathOrInputs = (obj: { pathIndex?: number, tx: Transaction }): void => {
|
|
85
|
+
if (typeof obj.pathIndex === 'number') {
|
|
86
|
+
const path = BUMPs[obj.pathIndex]
|
|
87
|
+
if (typeof path !== 'object') {
|
|
88
|
+
throw new Error('Invalid merkle path index found in BEEF!')
|
|
89
|
+
}
|
|
90
|
+
obj.tx.merklePath = path
|
|
91
|
+
} else {
|
|
92
|
+
for (let i = 0; i < obj.tx.inputs.length; i++) {
|
|
93
|
+
const input = obj.tx.inputs[i]
|
|
94
|
+
const sourceObj = transactions[input.sourceTXID]
|
|
95
|
+
if (typeof sourceObj !== 'object') {
|
|
96
|
+
throw new Error(`Reference to unknown TXID in BEEF: ${input.sourceTXID}`)
|
|
97
|
+
}
|
|
98
|
+
input.sourceTransaction = sourceObj.tx
|
|
99
|
+
addPathOrInputs(sourceObj)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
79
102
|
}
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
addPathOrInputs(transactions[targetTXID])
|
|
105
|
+
|
|
106
|
+
return transactions[targetTXID].tx
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates a new transaction from an Atomic BEEF (BRC-95) structure.
|
|
111
|
+
* Extracts the subject transaction and ensures that all transactions within the BEEF data
|
|
112
|
+
* are part of the dependency graph of the subject transaction.
|
|
113
|
+
* Throws errors if the Atomic BEEF data does not strictly adhere to the BRC-95 specification.
|
|
114
|
+
*
|
|
115
|
+
* @param beef A binary representation of an Atomic BEEF structure.
|
|
116
|
+
* @returns The subject transaction, linked to its associated inputs populated with merkle paths.
|
|
117
|
+
*/
|
|
118
|
+
static fromAtomicBEEF(beef: number[]): Transaction {
|
|
119
|
+
const reader = new Reader(beef)
|
|
120
|
+
// Read the Atomic BEEF prefix
|
|
121
|
+
const prefix = reader.readUInt32LE()
|
|
122
|
+
if (prefix !== 0x01010101) {
|
|
123
|
+
throw new Error(`Invalid Atomic BEEF prefix. Expected 0x01010101, received ${prefix.toString(16)}.`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Read the subject TXID
|
|
127
|
+
const subjectTXIDArray = reader.read(32)
|
|
128
|
+
const subjectTXID = toHex(subjectTXIDArray)
|
|
129
|
+
|
|
130
|
+
// The remaining data is the BEEF data
|
|
131
|
+
const beefReader = new Reader(reader.read())
|
|
132
|
+
const { transactions, BUMPs } = Transaction.parseBEEFData(beefReader)
|
|
133
|
+
|
|
134
|
+
// Ensure that the subject transaction exists
|
|
135
|
+
if (!transactions[subjectTXID]) {
|
|
136
|
+
throw new Error(`Subject transaction with TXID ${subjectTXID} not found in Atomic BEEF data.`)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Ensure that all transactions are part of the dependency graph of the subject transaction
|
|
140
|
+
const validTxids = new Set<string>()
|
|
141
|
+
const traverseDependencies = (txid: string) => {
|
|
142
|
+
if (validTxids.has(txid)) {
|
|
143
|
+
return
|
|
92
144
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
145
|
+
validTxids.add(txid)
|
|
146
|
+
const tx = transactions[txid].tx
|
|
147
|
+
for (const input of tx.inputs) {
|
|
148
|
+
const inputTxid = input.sourceTXID
|
|
149
|
+
if (!transactions[inputTxid]) {
|
|
150
|
+
throw new Error(`Input transaction with TXID ${inputTxid} is missing in Atomic BEEF data.`)
|
|
151
|
+
}
|
|
152
|
+
traverseDependencies(inputTxid)
|
|
96
153
|
}
|
|
97
|
-
transactions[txid] = obj
|
|
98
154
|
}
|
|
99
155
|
|
|
100
|
-
|
|
156
|
+
traverseDependencies(subjectTXID)
|
|
157
|
+
|
|
158
|
+
// Check for any unrelated transactions
|
|
159
|
+
for (const txid in transactions) {
|
|
160
|
+
if (!validTxids.has(txid)) {
|
|
161
|
+
throw new Error(`Unrelated transaction with TXID ${txid} found in Atomic BEEF data.`)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Build the transaction by linking inputs and merkle paths
|
|
101
166
|
const addPathOrInputs = (obj: { pathIndex?: number, tx: Transaction }): void => {
|
|
102
167
|
if (typeof obj.pathIndex === 'number') {
|
|
103
168
|
const path = BUMPs[obj.pathIndex]
|
|
@@ -110,7 +175,7 @@ export default class Transaction {
|
|
|
110
175
|
const input = obj.tx.inputs[i]
|
|
111
176
|
const sourceObj = transactions[input.sourceTXID]
|
|
112
177
|
if (typeof sourceObj !== 'object') {
|
|
113
|
-
throw new Error(`Reference to unknown TXID in
|
|
178
|
+
throw new Error(`Reference to unknown TXID in BEEF: ${input.sourceTXID}`)
|
|
114
179
|
}
|
|
115
180
|
input.sourceTransaction = sourceObj.tx
|
|
116
181
|
addPathOrInputs(sourceObj)
|
|
@@ -118,9 +183,47 @@ export default class Transaction {
|
|
|
118
183
|
}
|
|
119
184
|
}
|
|
120
185
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return transactions[
|
|
186
|
+
addPathOrInputs(transactions[subjectTXID])
|
|
187
|
+
|
|
188
|
+
return transactions[subjectTXID].tx
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Parses BEEF data from a Reader and returns the transactions and BUMPs.
|
|
193
|
+
*
|
|
194
|
+
* @param reader The Reader positioned at the start of BEEF data.
|
|
195
|
+
* @returns An object containing the transactions and BUMPs.
|
|
196
|
+
*/
|
|
197
|
+
private static parseBEEFData(reader: Reader): { transactions: Record<string, { pathIndex?: number, tx: Transaction }>, BUMPs: MerklePath[] } {
|
|
198
|
+
// Read the version
|
|
199
|
+
const version = reader.readUInt32LE()
|
|
200
|
+
if (version !== BEEF_MAGIC) {
|
|
201
|
+
throw new Error(`Invalid BEEF version. Expected ${BEEF_MAGIC}, received ${version}.`)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Read the BUMPs
|
|
205
|
+
const numberOfBUMPs = reader.readVarIntNum()
|
|
206
|
+
const BUMPs = []
|
|
207
|
+
for (let i = 0; i < numberOfBUMPs; i++) {
|
|
208
|
+
BUMPs.push(MerklePath.fromReader(reader))
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Read all transactions into an object
|
|
212
|
+
// The object has keys of TXIDs and values of objects with transactions and BUMP indexes
|
|
213
|
+
const numberOfTransactions = reader.readVarIntNum()
|
|
214
|
+
const transactions: Record<string, { pathIndex?: number, tx: Transaction }> = {}
|
|
215
|
+
for (let i = 0; i < numberOfTransactions; i++) {
|
|
216
|
+
const tx = Transaction.fromReader(reader)
|
|
217
|
+
const obj: { pathIndex?: number, tx: Transaction } = { tx }
|
|
218
|
+
const txid = tx.id('hex')
|
|
219
|
+
const hasBump = Boolean(reader.readUInt8())
|
|
220
|
+
if (hasBump) {
|
|
221
|
+
obj.pathIndex = reader.readVarIntNum()
|
|
222
|
+
}
|
|
223
|
+
transactions[txid] = obj
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return { transactions, BUMPs }
|
|
124
227
|
}
|
|
125
228
|
|
|
126
229
|
/**
|
|
@@ -128,7 +231,7 @@ export default class Transaction {
|
|
|
128
231
|
* @param ef A binary representation of a transaction in EF format.
|
|
129
232
|
* @returns An extended transaction, linked to its associated inputs by locking script and satoshis amounts only.
|
|
130
233
|
*/
|
|
131
|
-
static fromEF
|
|
234
|
+
static fromEF(ef: number[]): Transaction {
|
|
132
235
|
const br = new Reader(ef)
|
|
133
236
|
const version = br.readUInt32LE()
|
|
134
237
|
if (toHex(br.read(6)) !== '0000000000ef') throw new Error('Invalid EF marker')
|
|
@@ -190,7 +293,7 @@ export default class Transaction {
|
|
|
190
293
|
* outputs: { vout: number, offset: number, length: number }[]
|
|
191
294
|
* }
|
|
192
295
|
*/
|
|
193
|
-
static parseScriptOffsets
|
|
296
|
+
static parseScriptOffsets(bin: number[]): {
|
|
194
297
|
inputs: Array<{ vin: number, offset: number, length: number }>
|
|
195
298
|
outputs: Array<{ vout: number, offset: number, length: number }>
|
|
196
299
|
} {
|
|
@@ -216,7 +319,7 @@ export default class Transaction {
|
|
|
216
319
|
return { inputs, outputs }
|
|
217
320
|
}
|
|
218
321
|
|
|
219
|
-
static fromReader
|
|
322
|
+
static fromReader(br: Reader): Transaction {
|
|
220
323
|
const version = br.readUInt32LE()
|
|
221
324
|
const inputsLength = br.readVarIntNum()
|
|
222
325
|
const inputs: TransactionInput[] = []
|
|
@@ -257,7 +360,7 @@ export default class Transaction {
|
|
|
257
360
|
* @param {number[]} bin - The binary array representation of the transaction.
|
|
258
361
|
* @returns {Transaction} - A new Transaction instance.
|
|
259
362
|
*/
|
|
260
|
-
static fromBinary
|
|
363
|
+
static fromBinary(bin: number[]): Transaction {
|
|
261
364
|
const br = new Reader(bin)
|
|
262
365
|
return Transaction.fromReader(br)
|
|
263
366
|
}
|
|
@@ -269,7 +372,7 @@ export default class Transaction {
|
|
|
269
372
|
* @param {string} hex - The hexadecimal string representation of the transaction.
|
|
270
373
|
* @returns {Transaction} - A new Transaction instance.
|
|
271
374
|
*/
|
|
272
|
-
static fromHex
|
|
375
|
+
static fromHex(hex: string): Transaction {
|
|
273
376
|
return Transaction.fromBinary(toArray(hex, 'hex'))
|
|
274
377
|
}
|
|
275
378
|
|
|
@@ -280,22 +383,26 @@ export default class Transaction {
|
|
|
280
383
|
* @param {string} hex - The hexadecimal string representation of the transaction EF.
|
|
281
384
|
* @returns {Transaction} - A new Transaction instance.
|
|
282
385
|
*/
|
|
283
|
-
static fromHexEF
|
|
386
|
+
static fromHexEF(hex: string): Transaction {
|
|
284
387
|
return Transaction.fromEF(toArray(hex, 'hex'))
|
|
285
388
|
}
|
|
286
389
|
|
|
287
390
|
/**
|
|
288
391
|
* Creates a Transaction instance from a hexadecimal string encoded BEEF.
|
|
392
|
+
* Optionally, you can provide a specific TXID to retrieve a particular transaction from the BEEF data.
|
|
393
|
+
* If the TXID is provided but not found in the BEEF data, an error will be thrown.
|
|
394
|
+
* If no TXID is provided, the last transaction in the BEEF data is returned.
|
|
289
395
|
*
|
|
290
396
|
* @static
|
|
291
397
|
* @param {string} hex - The hexadecimal string representation of the transaction BEEF.
|
|
398
|
+
* @param {string} [txid] - Optional TXID of the transaction to retrieve from the BEEF data.
|
|
292
399
|
* @returns {Transaction} - A new Transaction instance.
|
|
293
400
|
*/
|
|
294
|
-
static fromHexBEEF
|
|
295
|
-
return Transaction.fromBEEF(toArray(hex, 'hex'))
|
|
401
|
+
static fromHexBEEF(hex: string, txid?: string): Transaction {
|
|
402
|
+
return Transaction.fromBEEF(toArray(hex, 'hex'), txid)
|
|
296
403
|
}
|
|
297
404
|
|
|
298
|
-
constructor
|
|
405
|
+
constructor(
|
|
299
406
|
version: number = 1,
|
|
300
407
|
inputs: TransactionInput[] = [],
|
|
301
408
|
outputs: TransactionOutput[] = [],
|
|
@@ -317,7 +424,7 @@ export default class Transaction {
|
|
|
317
424
|
* @param {TransactionInput} input - The TransactionInput object to add to the transaction.
|
|
318
425
|
* @throws {Error} - If the input does not have a sourceTXID or sourceTransaction defined.
|
|
319
426
|
*/
|
|
320
|
-
addInput
|
|
427
|
+
addInput(input: TransactionInput): void {
|
|
321
428
|
if (
|
|
322
429
|
typeof input.sourceTXID === 'undefined' &&
|
|
323
430
|
typeof input.sourceTransaction === 'undefined'
|
|
@@ -337,7 +444,7 @@ export default class Transaction {
|
|
|
337
444
|
*
|
|
338
445
|
* @param {TransactionOutput} output - The TransactionOutput object to add to the transaction.
|
|
339
446
|
*/
|
|
340
|
-
addOutput
|
|
447
|
+
addOutput(output: TransactionOutput): void {
|
|
341
448
|
this.cachedHash = undefined
|
|
342
449
|
this.outputs.push(output)
|
|
343
450
|
}
|
|
@@ -347,7 +454,7 @@ export default class Transaction {
|
|
|
347
454
|
*
|
|
348
455
|
* @param {Record<string, any>} metadata - The metadata object to merge into the existing metadata.
|
|
349
456
|
*/
|
|
350
|
-
updateMetadata
|
|
457
|
+
updateMetadata(metadata: Record<string, any>): void {
|
|
351
458
|
this.metadata = {
|
|
352
459
|
...this.metadata,
|
|
353
460
|
...metadata
|
|
@@ -365,7 +472,7 @@ export default class Transaction {
|
|
|
365
472
|
*
|
|
366
473
|
* TODO: Benford's law change distribution.
|
|
367
474
|
*/
|
|
368
|
-
async fee
|
|
475
|
+
async fee(modelOrFee?: FeeModel | number, changeDistribution: 'equal' | 'random' = 'equal'): Promise<void> {
|
|
369
476
|
this.cachedHash = undefined
|
|
370
477
|
if (typeof modelOrFee === 'undefined') {
|
|
371
478
|
modelOrFee = new SatoshisPerKilobyte(10)
|
|
@@ -426,7 +533,7 @@ export default class Transaction {
|
|
|
426
533
|
*
|
|
427
534
|
* @returns The current transaction fee
|
|
428
535
|
*/
|
|
429
|
-
getFee
|
|
536
|
+
getFee(): number {
|
|
430
537
|
let totalIn = 0
|
|
431
538
|
for (const input of this.inputs) {
|
|
432
539
|
if (typeof input.sourceTransaction !== 'object') {
|
|
@@ -444,7 +551,7 @@ export default class Transaction {
|
|
|
444
551
|
/**
|
|
445
552
|
* Signs a transaction, hydrating all its unlocking scripts based on the provided script templates where they are available.
|
|
446
553
|
*/
|
|
447
|
-
async sign
|
|
554
|
+
async sign(): Promise<void> {
|
|
448
555
|
this.cachedHash = undefined
|
|
449
556
|
for (const out of this.outputs) {
|
|
450
557
|
if (typeof out.satoshis === 'undefined') {
|
|
@@ -475,7 +582,7 @@ export default class Transaction {
|
|
|
475
582
|
* @param broadcaster The Broadcaster instance wwhere the transaction will be sent
|
|
476
583
|
* @returns A BroadcastResponse or BroadcastFailure from the Broadcaster
|
|
477
584
|
*/
|
|
478
|
-
async broadcast
|
|
585
|
+
async broadcast(broadcaster: Broadcaster = defaultBroadcaster()): Promise<BroadcastResponse | BroadcastFailure> {
|
|
479
586
|
return await broadcaster.broadcast(this)
|
|
480
587
|
}
|
|
481
588
|
|
|
@@ -484,7 +591,7 @@ export default class Transaction {
|
|
|
484
591
|
*
|
|
485
592
|
* @returns {number[]} - The binary array representation of the transaction.
|
|
486
593
|
*/
|
|
487
|
-
toBinary
|
|
594
|
+
toBinary(): number[] {
|
|
488
595
|
const writer = new Writer()
|
|
489
596
|
writer.writeUInt32LE(this.version)
|
|
490
597
|
writer.writeVarIntNum(this.inputs.length)
|
|
@@ -516,7 +623,7 @@ export default class Transaction {
|
|
|
516
623
|
*
|
|
517
624
|
* @returns {number[]} - The BRC-30 EF representation of the transaction.
|
|
518
625
|
*/
|
|
519
|
-
toEF
|
|
626
|
+
toEF(): number[] {
|
|
520
627
|
const writer = new Writer()
|
|
521
628
|
writer.writeUInt32LE(this.version)
|
|
522
629
|
writer.write([0, 0, 0, 0, 0, 0xef])
|
|
@@ -556,7 +663,7 @@ export default class Transaction {
|
|
|
556
663
|
*
|
|
557
664
|
* @returns {string} - The hexadecimal string representation of the transaction EF.
|
|
558
665
|
*/
|
|
559
|
-
toHexEF
|
|
666
|
+
toHexEF(): string {
|
|
560
667
|
return toHex(this.toEF())
|
|
561
668
|
}
|
|
562
669
|
|
|
@@ -565,7 +672,7 @@ export default class Transaction {
|
|
|
565
672
|
*
|
|
566
673
|
* @returns {string} - The hexadecimal string representation of the transaction.
|
|
567
674
|
*/
|
|
568
|
-
toHex
|
|
675
|
+
toHex(): string {
|
|
569
676
|
return toHex(this.toBinary())
|
|
570
677
|
}
|
|
571
678
|
|
|
@@ -574,17 +681,26 @@ export default class Transaction {
|
|
|
574
681
|
*
|
|
575
682
|
* @returns {string} - The hexadecimal string representation of the transaction BEEF.
|
|
576
683
|
*/
|
|
577
|
-
toHexBEEF
|
|
684
|
+
toHexBEEF(): string {
|
|
578
685
|
return toHex(this.toBEEF())
|
|
579
686
|
}
|
|
580
687
|
|
|
688
|
+
/**
|
|
689
|
+
* Converts the transaction to a hexadecimal string Atomic BEEF.
|
|
690
|
+
*
|
|
691
|
+
* @returns {string} - The hexadecimal string representation of the transaction Atomic BEEF.
|
|
692
|
+
*/
|
|
693
|
+
toHexAtomicBEEF(): string {
|
|
694
|
+
return toHex(this.toAtomicBEEF())
|
|
695
|
+
}
|
|
696
|
+
|
|
581
697
|
/**
|
|
582
698
|
* Calculates the transaction's hash.
|
|
583
699
|
*
|
|
584
700
|
* @param {'hex' | undefined} enc - The encoding to use for the hash. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
585
701
|
* @returns {string | number[]} - The hash of the transaction in the specified format.
|
|
586
702
|
*/
|
|
587
|
-
hash
|
|
703
|
+
hash(enc?: 'hex'): number[] | string {
|
|
588
704
|
let hash
|
|
589
705
|
if (this.cachedHash) {
|
|
590
706
|
hash = this.cachedHash
|
|
@@ -603,21 +719,21 @@ export default class Transaction {
|
|
|
603
719
|
*
|
|
604
720
|
* @returns {number[]} - The ID of the transaction in the binary array format.
|
|
605
721
|
*/
|
|
606
|
-
id
|
|
722
|
+
id(): number[]
|
|
607
723
|
/**
|
|
608
724
|
* Calculates the transaction's ID in hexadecimal format.
|
|
609
725
|
*
|
|
610
726
|
* @param {'hex'} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string.
|
|
611
727
|
* @returns {string} - The ID of the transaction in the hex format.
|
|
612
728
|
*/
|
|
613
|
-
id
|
|
729
|
+
id(enc: 'hex'): string
|
|
614
730
|
/**
|
|
615
731
|
* Calculates the transaction's ID.
|
|
616
732
|
*
|
|
617
733
|
* @param {'hex' | undefined} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
618
734
|
* @returns {string | number[]} - The ID of the transaction in the specified format.
|
|
619
735
|
*/
|
|
620
|
-
id
|
|
736
|
+
id(enc?: 'hex'): number[] | string {
|
|
621
737
|
const id = [...this.hash() as number[]]
|
|
622
738
|
id.reverse()
|
|
623
739
|
if (enc === 'hex') {
|
|
@@ -635,7 +751,7 @@ export default class Transaction {
|
|
|
635
751
|
*
|
|
636
752
|
* @example tx.verify(new WhatsOnChain(), new SatoshisPerKilobyte(1))
|
|
637
753
|
*/
|
|
638
|
-
async verify
|
|
754
|
+
async verify(
|
|
639
755
|
chainTracker: ChainTracker | 'scripts only' = defaultChainTracker(),
|
|
640
756
|
feeModel?: FeeModel
|
|
641
757
|
): Promise<boolean> {
|
|
@@ -746,7 +862,7 @@ export default class Transaction {
|
|
|
746
862
|
*
|
|
747
863
|
* @returns The serialized BEEF structure
|
|
748
864
|
*/
|
|
749
|
-
toBEEF
|
|
865
|
+
toBEEF(): number[] {
|
|
750
866
|
const writer = new Writer()
|
|
751
867
|
writer.writeUInt32LE(4022206465)
|
|
752
868
|
const BUMPs: MerklePath[] = []
|
|
@@ -817,4 +933,24 @@ export default class Transaction {
|
|
|
817
933
|
}
|
|
818
934
|
return writer.toArray()
|
|
819
935
|
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Serializes this transaction and its inputs into the Atomic BEEF (BRC-95) format.
|
|
939
|
+
* The Atomic BEEF format starts with a 4-byte prefix `0x01010101`, followed by the TXID of the subject transaction,
|
|
940
|
+
* and then the BEEF data containing only the subject transaction and its dependencies.
|
|
941
|
+
* This format ensures that the BEEF structure is atomic and contains no unrelated transactions.
|
|
942
|
+
*
|
|
943
|
+
* @returns {number[]} - The serialized Atomic BEEF structure.
|
|
944
|
+
*/
|
|
945
|
+
toAtomicBEEF(): number[] {
|
|
946
|
+
const writer = new Writer()
|
|
947
|
+
// Write the Atomic BEEF prefix
|
|
948
|
+
writer.writeUInt32LE(0x01010101)
|
|
949
|
+
// Write the subject TXID (big-endian)
|
|
950
|
+
writer.write(this.id() as number[])
|
|
951
|
+
// Append the BEEF data
|
|
952
|
+
const beefData = this.toBEEF()
|
|
953
|
+
writer.write(beefData)
|
|
954
|
+
return writer.toArray()
|
|
955
|
+
}
|
|
820
956
|
}
|