@bsv/sdk 1.1.24 → 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/totp/totp.js +1 -1
- package/dist/cjs/src/totp/totp.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +492 -0
- package/dist/cjs/src/transaction/Beef.js.map +1 -0
- package/dist/cjs/src/transaction/BeefParty.js +97 -0
- package/dist/cjs/src/transaction/BeefParty.js.map +1 -0
- package/dist/cjs/src/transaction/BeefTx.js +123 -0
- package/dist/cjs/src/transaction/BeefTx.js.map +1 -0
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +156 -35
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/src/transaction/index.js +7 -1
- package/dist/cjs/src/transaction/index.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/totp/totp.js +1 -1
- package/dist/esm/src/totp/totp.js.map +1 -1
- package/dist/esm/src/transaction/Beef.js +485 -0
- package/dist/esm/src/transaction/Beef.js.map +1 -0
- package/dist/esm/src/transaction/BeefParty.js +93 -0
- package/dist/esm/src/transaction/BeefParty.js.map +1 -0
- package/dist/esm/src/transaction/BeefTx.js +121 -0
- package/dist/esm/src/transaction/BeefTx.js.map +1 -0
- package/dist/esm/src/transaction/MerklePath.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +156 -35
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/src/transaction/index.js +3 -0
- package/dist/esm/src/transaction/index.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/transaction/Beef.d.ts +143 -0
- package/dist/types/src/transaction/Beef.d.ts.map +1 -0
- package/dist/types/src/transaction/BeefParty.d.ts +62 -0
- package/dist/types/src/transaction/BeefParty.d.ts.map +1 -0
- package/dist/types/src/transaction/BeefTx.d.ts +35 -0
- package/dist/types/src/transaction/BeefTx.d.ts.map +1 -0
- 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/src/transaction/index.d.ts +3 -0
- package/dist/types/src/transaction/index.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/docs/primitives.md +372 -55
- package/docs/transaction.md +531 -5
- package/package.json +1 -1
- package/src/totp/totp.ts +1 -1
- package/src/transaction/Beef.ts +533 -0
- package/src/transaction/BeefParty.ts +100 -0
- package/src/transaction/BeefTx.ts +121 -0
- package/src/transaction/MerklePath.ts +11 -11
- package/src/transaction/Transaction.ts +196 -59
- package/src/transaction/__tests/Beef.test.ts +290 -0
- package/src/transaction/__tests/Transaction.test.ts +222 -3
- package/src/transaction/index.ts +3 -0
|
@@ -12,6 +12,7 @@ import Spend from '../script/Spend.js'
|
|
|
12
12
|
import ChainTracker from './ChainTracker.js'
|
|
13
13
|
import { defaultBroadcaster } from './broadcasters/DefaultBroadcaster.js'
|
|
14
14
|
import { defaultChainTracker } from './chaintrackers/DefaultChainTracker.js'
|
|
15
|
+
import { BEEF_MAGIC } from './Beef.js'
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Represents a complete Bitcoin transaction. This class encapsulates all the details
|
|
@@ -30,7 +31,7 @@ import { defaultChainTracker } from './chaintrackers/DefaultChainTracker.js'
|
|
|
30
31
|
* earliest time or block height at which the transaction can be added to the block chain.
|
|
31
32
|
* @property {Record<string, any>} metadata - A key-value store for attaching additional data to
|
|
32
33
|
* the transaction object, not included in the transaction itself. Useful for adding descriptions, internal reference numbers, or other information.
|
|
33
|
-
* @property {MerkleProof} [
|
|
34
|
+
* @property {MerkleProof} [merklePath] - Optional. A merkle proof demonstrating the transaction's
|
|
34
35
|
* inclusion in a block. Useful for transaction verification using SPV.
|
|
35
36
|
*
|
|
36
37
|
* @example
|
|
@@ -59,44 +60,109 @@ export default class Transaction {
|
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* Creates a new transaction, linked to its inputs and their associated merkle paths, from a BEEF (BRC-62) structure.
|
|
62
|
-
*
|
|
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.
|
|
63
68
|
* @returns An anchored transaction, linked to its associated inputs populated with merkle paths.
|
|
64
69
|
*/
|
|
65
|
-
static fromBEEF
|
|
70
|
+
static fromBEEF(beef: number[], txid?: string): Transaction {
|
|
66
71
|
const reader = new Reader(beef)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if
|
|
70
|
-
|
|
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.`)
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
//
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
+
}
|
|
78
102
|
}
|
|
79
103
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
91
144
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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)
|
|
95
153
|
}
|
|
96
|
-
transactions[txid] = obj
|
|
97
154
|
}
|
|
98
155
|
|
|
99
|
-
|
|
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
|
|
100
166
|
const addPathOrInputs = (obj: { pathIndex?: number, tx: Transaction }): void => {
|
|
101
167
|
if (typeof obj.pathIndex === 'number') {
|
|
102
168
|
const path = BUMPs[obj.pathIndex]
|
|
@@ -109,7 +175,7 @@ export default class Transaction {
|
|
|
109
175
|
const input = obj.tx.inputs[i]
|
|
110
176
|
const sourceObj = transactions[input.sourceTXID]
|
|
111
177
|
if (typeof sourceObj !== 'object') {
|
|
112
|
-
throw new Error(`Reference to unknown TXID in
|
|
178
|
+
throw new Error(`Reference to unknown TXID in BEEF: ${input.sourceTXID}`)
|
|
113
179
|
}
|
|
114
180
|
input.sourceTransaction = sourceObj.tx
|
|
115
181
|
addPathOrInputs(sourceObj)
|
|
@@ -117,9 +183,47 @@ export default class Transaction {
|
|
|
117
183
|
}
|
|
118
184
|
}
|
|
119
185
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
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 }
|
|
123
227
|
}
|
|
124
228
|
|
|
125
229
|
/**
|
|
@@ -127,7 +231,7 @@ export default class Transaction {
|
|
|
127
231
|
* @param ef A binary representation of a transaction in EF format.
|
|
128
232
|
* @returns An extended transaction, linked to its associated inputs by locking script and satoshis amounts only.
|
|
129
233
|
*/
|
|
130
|
-
static fromEF
|
|
234
|
+
static fromEF(ef: number[]): Transaction {
|
|
131
235
|
const br = new Reader(ef)
|
|
132
236
|
const version = br.readUInt32LE()
|
|
133
237
|
if (toHex(br.read(6)) !== '0000000000ef') throw new Error('Invalid EF marker')
|
|
@@ -189,7 +293,7 @@ export default class Transaction {
|
|
|
189
293
|
* outputs: { vout: number, offset: number, length: number }[]
|
|
190
294
|
* }
|
|
191
295
|
*/
|
|
192
|
-
static parseScriptOffsets
|
|
296
|
+
static parseScriptOffsets(bin: number[]): {
|
|
193
297
|
inputs: Array<{ vin: number, offset: number, length: number }>
|
|
194
298
|
outputs: Array<{ vout: number, offset: number, length: number }>
|
|
195
299
|
} {
|
|
@@ -215,7 +319,7 @@ export default class Transaction {
|
|
|
215
319
|
return { inputs, outputs }
|
|
216
320
|
}
|
|
217
321
|
|
|
218
|
-
static fromReader
|
|
322
|
+
static fromReader(br: Reader): Transaction {
|
|
219
323
|
const version = br.readUInt32LE()
|
|
220
324
|
const inputsLength = br.readVarIntNum()
|
|
221
325
|
const inputs: TransactionInput[] = []
|
|
@@ -256,7 +360,7 @@ export default class Transaction {
|
|
|
256
360
|
* @param {number[]} bin - The binary array representation of the transaction.
|
|
257
361
|
* @returns {Transaction} - A new Transaction instance.
|
|
258
362
|
*/
|
|
259
|
-
static fromBinary
|
|
363
|
+
static fromBinary(bin: number[]): Transaction {
|
|
260
364
|
const br = new Reader(bin)
|
|
261
365
|
return Transaction.fromReader(br)
|
|
262
366
|
}
|
|
@@ -268,7 +372,7 @@ export default class Transaction {
|
|
|
268
372
|
* @param {string} hex - The hexadecimal string representation of the transaction.
|
|
269
373
|
* @returns {Transaction} - A new Transaction instance.
|
|
270
374
|
*/
|
|
271
|
-
static fromHex
|
|
375
|
+
static fromHex(hex: string): Transaction {
|
|
272
376
|
return Transaction.fromBinary(toArray(hex, 'hex'))
|
|
273
377
|
}
|
|
274
378
|
|
|
@@ -279,22 +383,26 @@ export default class Transaction {
|
|
|
279
383
|
* @param {string} hex - The hexadecimal string representation of the transaction EF.
|
|
280
384
|
* @returns {Transaction} - A new Transaction instance.
|
|
281
385
|
*/
|
|
282
|
-
static fromHexEF
|
|
386
|
+
static fromHexEF(hex: string): Transaction {
|
|
283
387
|
return Transaction.fromEF(toArray(hex, 'hex'))
|
|
284
388
|
}
|
|
285
389
|
|
|
286
390
|
/**
|
|
287
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.
|
|
288
395
|
*
|
|
289
396
|
* @static
|
|
290
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.
|
|
291
399
|
* @returns {Transaction} - A new Transaction instance.
|
|
292
400
|
*/
|
|
293
|
-
static fromHexBEEF
|
|
294
|
-
return Transaction.fromBEEF(toArray(hex, 'hex'))
|
|
401
|
+
static fromHexBEEF(hex: string, txid?: string): Transaction {
|
|
402
|
+
return Transaction.fromBEEF(toArray(hex, 'hex'), txid)
|
|
295
403
|
}
|
|
296
404
|
|
|
297
|
-
constructor
|
|
405
|
+
constructor(
|
|
298
406
|
version: number = 1,
|
|
299
407
|
inputs: TransactionInput[] = [],
|
|
300
408
|
outputs: TransactionOutput[] = [],
|
|
@@ -316,7 +424,7 @@ export default class Transaction {
|
|
|
316
424
|
* @param {TransactionInput} input - The TransactionInput object to add to the transaction.
|
|
317
425
|
* @throws {Error} - If the input does not have a sourceTXID or sourceTransaction defined.
|
|
318
426
|
*/
|
|
319
|
-
addInput
|
|
427
|
+
addInput(input: TransactionInput): void {
|
|
320
428
|
if (
|
|
321
429
|
typeof input.sourceTXID === 'undefined' &&
|
|
322
430
|
typeof input.sourceTransaction === 'undefined'
|
|
@@ -336,7 +444,7 @@ export default class Transaction {
|
|
|
336
444
|
*
|
|
337
445
|
* @param {TransactionOutput} output - The TransactionOutput object to add to the transaction.
|
|
338
446
|
*/
|
|
339
|
-
addOutput
|
|
447
|
+
addOutput(output: TransactionOutput): void {
|
|
340
448
|
this.cachedHash = undefined
|
|
341
449
|
this.outputs.push(output)
|
|
342
450
|
}
|
|
@@ -346,7 +454,7 @@ export default class Transaction {
|
|
|
346
454
|
*
|
|
347
455
|
* @param {Record<string, any>} metadata - The metadata object to merge into the existing metadata.
|
|
348
456
|
*/
|
|
349
|
-
updateMetadata
|
|
457
|
+
updateMetadata(metadata: Record<string, any>): void {
|
|
350
458
|
this.metadata = {
|
|
351
459
|
...this.metadata,
|
|
352
460
|
...metadata
|
|
@@ -364,7 +472,7 @@ export default class Transaction {
|
|
|
364
472
|
*
|
|
365
473
|
* TODO: Benford's law change distribution.
|
|
366
474
|
*/
|
|
367
|
-
async fee
|
|
475
|
+
async fee(modelOrFee?: FeeModel | number, changeDistribution: 'equal' | 'random' = 'equal'): Promise<void> {
|
|
368
476
|
this.cachedHash = undefined
|
|
369
477
|
if (typeof modelOrFee === 'undefined') {
|
|
370
478
|
modelOrFee = new SatoshisPerKilobyte(10)
|
|
@@ -425,7 +533,7 @@ export default class Transaction {
|
|
|
425
533
|
*
|
|
426
534
|
* @returns The current transaction fee
|
|
427
535
|
*/
|
|
428
|
-
getFee
|
|
536
|
+
getFee(): number {
|
|
429
537
|
let totalIn = 0
|
|
430
538
|
for (const input of this.inputs) {
|
|
431
539
|
if (typeof input.sourceTransaction !== 'object') {
|
|
@@ -443,7 +551,7 @@ export default class Transaction {
|
|
|
443
551
|
/**
|
|
444
552
|
* Signs a transaction, hydrating all its unlocking scripts based on the provided script templates where they are available.
|
|
445
553
|
*/
|
|
446
|
-
async sign
|
|
554
|
+
async sign(): Promise<void> {
|
|
447
555
|
this.cachedHash = undefined
|
|
448
556
|
for (const out of this.outputs) {
|
|
449
557
|
if (typeof out.satoshis === 'undefined') {
|
|
@@ -474,7 +582,7 @@ export default class Transaction {
|
|
|
474
582
|
* @param broadcaster The Broadcaster instance wwhere the transaction will be sent
|
|
475
583
|
* @returns A BroadcastResponse or BroadcastFailure from the Broadcaster
|
|
476
584
|
*/
|
|
477
|
-
async broadcast
|
|
585
|
+
async broadcast(broadcaster: Broadcaster = defaultBroadcaster()): Promise<BroadcastResponse | BroadcastFailure> {
|
|
478
586
|
return await broadcaster.broadcast(this)
|
|
479
587
|
}
|
|
480
588
|
|
|
@@ -483,7 +591,7 @@ export default class Transaction {
|
|
|
483
591
|
*
|
|
484
592
|
* @returns {number[]} - The binary array representation of the transaction.
|
|
485
593
|
*/
|
|
486
|
-
toBinary
|
|
594
|
+
toBinary(): number[] {
|
|
487
595
|
const writer = new Writer()
|
|
488
596
|
writer.writeUInt32LE(this.version)
|
|
489
597
|
writer.writeVarIntNum(this.inputs.length)
|
|
@@ -515,7 +623,7 @@ export default class Transaction {
|
|
|
515
623
|
*
|
|
516
624
|
* @returns {number[]} - The BRC-30 EF representation of the transaction.
|
|
517
625
|
*/
|
|
518
|
-
toEF
|
|
626
|
+
toEF(): number[] {
|
|
519
627
|
const writer = new Writer()
|
|
520
628
|
writer.writeUInt32LE(this.version)
|
|
521
629
|
writer.write([0, 0, 0, 0, 0, 0xef])
|
|
@@ -555,7 +663,7 @@ export default class Transaction {
|
|
|
555
663
|
*
|
|
556
664
|
* @returns {string} - The hexadecimal string representation of the transaction EF.
|
|
557
665
|
*/
|
|
558
|
-
toHexEF
|
|
666
|
+
toHexEF(): string {
|
|
559
667
|
return toHex(this.toEF())
|
|
560
668
|
}
|
|
561
669
|
|
|
@@ -564,7 +672,7 @@ export default class Transaction {
|
|
|
564
672
|
*
|
|
565
673
|
* @returns {string} - The hexadecimal string representation of the transaction.
|
|
566
674
|
*/
|
|
567
|
-
toHex
|
|
675
|
+
toHex(): string {
|
|
568
676
|
return toHex(this.toBinary())
|
|
569
677
|
}
|
|
570
678
|
|
|
@@ -573,17 +681,26 @@ export default class Transaction {
|
|
|
573
681
|
*
|
|
574
682
|
* @returns {string} - The hexadecimal string representation of the transaction BEEF.
|
|
575
683
|
*/
|
|
576
|
-
toHexBEEF
|
|
684
|
+
toHexBEEF(): string {
|
|
577
685
|
return toHex(this.toBEEF())
|
|
578
686
|
}
|
|
579
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
|
+
|
|
580
697
|
/**
|
|
581
698
|
* Calculates the transaction's hash.
|
|
582
699
|
*
|
|
583
700
|
* @param {'hex' | undefined} enc - The encoding to use for the hash. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
584
701
|
* @returns {string | number[]} - The hash of the transaction in the specified format.
|
|
585
702
|
*/
|
|
586
|
-
hash
|
|
703
|
+
hash(enc?: 'hex'): number[] | string {
|
|
587
704
|
let hash
|
|
588
705
|
if (this.cachedHash) {
|
|
589
706
|
hash = this.cachedHash
|
|
@@ -602,21 +719,21 @@ export default class Transaction {
|
|
|
602
719
|
*
|
|
603
720
|
* @returns {number[]} - The ID of the transaction in the binary array format.
|
|
604
721
|
*/
|
|
605
|
-
id
|
|
722
|
+
id(): number[]
|
|
606
723
|
/**
|
|
607
724
|
* Calculates the transaction's ID in hexadecimal format.
|
|
608
725
|
*
|
|
609
726
|
* @param {'hex'} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string.
|
|
610
727
|
* @returns {string} - The ID of the transaction in the hex format.
|
|
611
728
|
*/
|
|
612
|
-
id
|
|
729
|
+
id(enc: 'hex'): string
|
|
613
730
|
/**
|
|
614
731
|
* Calculates the transaction's ID.
|
|
615
732
|
*
|
|
616
733
|
* @param {'hex' | undefined} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
617
734
|
* @returns {string | number[]} - The ID of the transaction in the specified format.
|
|
618
735
|
*/
|
|
619
|
-
id
|
|
736
|
+
id(enc?: 'hex'): number[] | string {
|
|
620
737
|
const id = [...this.hash() as number[]]
|
|
621
738
|
id.reverse()
|
|
622
739
|
if (enc === 'hex') {
|
|
@@ -634,7 +751,7 @@ export default class Transaction {
|
|
|
634
751
|
*
|
|
635
752
|
* @example tx.verify(new WhatsOnChain(), new SatoshisPerKilobyte(1))
|
|
636
753
|
*/
|
|
637
|
-
async verify
|
|
754
|
+
async verify(
|
|
638
755
|
chainTracker: ChainTracker | 'scripts only' = defaultChainTracker(),
|
|
639
756
|
feeModel?: FeeModel
|
|
640
757
|
): Promise<boolean> {
|
|
@@ -745,7 +862,7 @@ export default class Transaction {
|
|
|
745
862
|
*
|
|
746
863
|
* @returns The serialized BEEF structure
|
|
747
864
|
*/
|
|
748
|
-
toBEEF
|
|
865
|
+
toBEEF(): number[] {
|
|
749
866
|
const writer = new Writer()
|
|
750
867
|
writer.writeUInt32LE(4022206465)
|
|
751
868
|
const BUMPs: MerklePath[] = []
|
|
@@ -816,4 +933,24 @@ export default class Transaction {
|
|
|
816
933
|
}
|
|
817
934
|
return writer.toArray()
|
|
818
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
|
+
}
|
|
819
956
|
}
|