@bsv/sdk 1.1.4 → 1.1.6
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/compat/Utxo.js.map +1 -1
- package/dist/cjs/src/primitives/Hash.js +0 -1
- package/dist/cjs/src/primitives/Hash.js.map +1 -1
- package/dist/cjs/src/transaction/MerklePath.js +8 -4
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +12 -2
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/compat/Utxo.js.map +1 -1
- package/dist/esm/src/primitives/Hash.js +0 -1
- package/dist/esm/src/primitives/Hash.js.map +1 -1
- package/dist/esm/src/transaction/MerklePath.js +8 -4
- package/dist/esm/src/transaction/MerklePath.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +12 -2
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/compat/Utxo.d.ts +2 -2
- package/dist/types/src/compat/Utxo.d.ts.map +1 -1
- package/dist/types/src/primitives/Hash.d.ts.map +1 -1
- package/dist/types/src/transaction/MerklePath.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts +3 -1
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/docs/transaction.md +8 -2
- package/package.json +1 -1
- package/src/compat/Utxo.ts +31 -31
- package/src/primitives/Hash.ts +0 -1
- package/src/transaction/MerklePath.ts +25 -31
- package/src/transaction/Transaction.ts +38 -29
|
@@ -62,7 +62,7 @@ export default class Transaction {
|
|
|
62
62
|
* @param beef A binary representation of a transaction in BEEF format.
|
|
63
63
|
* @returns An anchored transaction, linked to its associated inputs populated with merkle paths.
|
|
64
64
|
*/
|
|
65
|
-
static fromBEEF(beef: number[]): Transaction {
|
|
65
|
+
static fromBEEF (beef: number[]): Transaction {
|
|
66
66
|
const reader = new Reader(beef)
|
|
67
67
|
// Read the version
|
|
68
68
|
const version = reader.readUInt32LE()
|
|
@@ -122,13 +122,12 @@ export default class Transaction {
|
|
|
122
122
|
return transactions[lastTXID].tx
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
126
125
|
/**
|
|
127
126
|
* Creates a new transaction, linked to its inputs and their associated merkle paths, from a EF (BRC-30) structure.
|
|
128
127
|
* @param ef A binary representation of a transaction in EF format.
|
|
129
128
|
* @returns An extended transaction, linked to its associated inputs by locking script and satoshis amounts only.
|
|
130
129
|
*/
|
|
131
|
-
static fromEF(ef: number[]): Transaction {
|
|
130
|
+
static fromEF (ef: number[]): Transaction {
|
|
132
131
|
const br = new Reader(ef)
|
|
133
132
|
const version = br.readUInt32LE()
|
|
134
133
|
if (toHex(br.read(6)) !== '0000000000ef') throw new Error('Invalid EF marker')
|
|
@@ -190,7 +189,7 @@ export default class Transaction {
|
|
|
190
189
|
* outputs: { vout: number, offset: number, length: number }[]
|
|
191
190
|
* }
|
|
192
191
|
*/
|
|
193
|
-
static parseScriptOffsets(bin: number[]): {
|
|
192
|
+
static parseScriptOffsets (bin: number[]): {
|
|
194
193
|
inputs: Array<{ vin: number, offset: number, length: number }>
|
|
195
194
|
outputs: Array<{ vout: number, offset: number, length: number }>
|
|
196
195
|
} {
|
|
@@ -216,7 +215,7 @@ export default class Transaction {
|
|
|
216
215
|
return { inputs, outputs }
|
|
217
216
|
}
|
|
218
217
|
|
|
219
|
-
private static fromReader(br: Reader): Transaction {
|
|
218
|
+
private static fromReader (br: Reader): Transaction {
|
|
220
219
|
const version = br.readUInt32LE()
|
|
221
220
|
const inputsLength = br.readVarIntNum()
|
|
222
221
|
const inputs: TransactionInput[] = []
|
|
@@ -257,7 +256,7 @@ export default class Transaction {
|
|
|
257
256
|
* @param {number[]} bin - The binary array representation of the transaction.
|
|
258
257
|
* @returns {Transaction} - A new Transaction instance.
|
|
259
258
|
*/
|
|
260
|
-
static fromBinary(bin: number[]): Transaction {
|
|
259
|
+
static fromBinary (bin: number[]): Transaction {
|
|
261
260
|
const br = new Reader(bin)
|
|
262
261
|
return Transaction.fromReader(br)
|
|
263
262
|
}
|
|
@@ -269,7 +268,7 @@ export default class Transaction {
|
|
|
269
268
|
* @param {string} hex - The hexadecimal string representation of the transaction.
|
|
270
269
|
* @returns {Transaction} - A new Transaction instance.
|
|
271
270
|
*/
|
|
272
|
-
static fromHex(hex: string): Transaction {
|
|
271
|
+
static fromHex (hex: string): Transaction {
|
|
273
272
|
return Transaction.fromBinary(toArray(hex, 'hex'))
|
|
274
273
|
}
|
|
275
274
|
|
|
@@ -280,7 +279,7 @@ export default class Transaction {
|
|
|
280
279
|
* @param {string} hex - The hexadecimal string representation of the transaction EF.
|
|
281
280
|
* @returns {Transaction} - A new Transaction instance.
|
|
282
281
|
*/
|
|
283
|
-
static fromHexEF(hex: string): Transaction {
|
|
282
|
+
static fromHexEF (hex: string): Transaction {
|
|
284
283
|
return Transaction.fromEF(toArray(hex, 'hex'))
|
|
285
284
|
}
|
|
286
285
|
|
|
@@ -291,11 +290,11 @@ export default class Transaction {
|
|
|
291
290
|
* @param {string} hex - The hexadecimal string representation of the transaction BEEF.
|
|
292
291
|
* @returns {Transaction} - A new Transaction instance.
|
|
293
292
|
*/
|
|
294
|
-
static fromHexBEEF(hex: string): Transaction {
|
|
293
|
+
static fromHexBEEF (hex: string): Transaction {
|
|
295
294
|
return Transaction.fromBEEF(toArray(hex, 'hex'))
|
|
296
295
|
}
|
|
297
296
|
|
|
298
|
-
constructor(
|
|
297
|
+
constructor (
|
|
299
298
|
version: number = 1,
|
|
300
299
|
inputs: TransactionInput[] = [],
|
|
301
300
|
outputs: TransactionOutput[] = [],
|
|
@@ -317,7 +316,7 @@ export default class Transaction {
|
|
|
317
316
|
* @param {TransactionInput} input - The TransactionInput object to add to the transaction.
|
|
318
317
|
* @throws {Error} - If the input does not have a sourceTXID or sourceTransaction defined.
|
|
319
318
|
*/
|
|
320
|
-
addInput(input: TransactionInput): void {
|
|
319
|
+
addInput (input: TransactionInput): void {
|
|
321
320
|
if (
|
|
322
321
|
typeof input.sourceTXID === 'undefined' &&
|
|
323
322
|
typeof input.sourceTransaction === 'undefined'
|
|
@@ -337,7 +336,7 @@ export default class Transaction {
|
|
|
337
336
|
*
|
|
338
337
|
* @param {TransactionOutput} output - The TransactionOutput object to add to the transaction.
|
|
339
338
|
*/
|
|
340
|
-
addOutput(output: TransactionOutput): void {
|
|
339
|
+
addOutput (output: TransactionOutput): void {
|
|
341
340
|
this.cachedHash = undefined
|
|
342
341
|
this.outputs.push(output)
|
|
343
342
|
}
|
|
@@ -347,7 +346,7 @@ export default class Transaction {
|
|
|
347
346
|
*
|
|
348
347
|
* @param {Record<string, any>} metadata - The metadata object to merge into the existing metadata.
|
|
349
348
|
*/
|
|
350
|
-
updateMetadata(metadata: Record<string, any>): void {
|
|
349
|
+
updateMetadata (metadata: Record<string, any>): void {
|
|
351
350
|
this.metadata = {
|
|
352
351
|
...this.metadata,
|
|
353
352
|
...metadata
|
|
@@ -365,7 +364,7 @@ export default class Transaction {
|
|
|
365
364
|
*
|
|
366
365
|
* TODO: Benford's law change distribution.
|
|
367
366
|
*/
|
|
368
|
-
async fee(modelOrFee?: FeeModel | number, changeDistribution: 'equal' | 'random' = 'equal'): Promise<void> {
|
|
367
|
+
async fee (modelOrFee?: FeeModel | number, changeDistribution: 'equal' | 'random' = 'equal'): Promise<void> {
|
|
369
368
|
this.cachedHash = undefined
|
|
370
369
|
if (typeof modelOrFee === 'undefined') {
|
|
371
370
|
modelOrFee = new SatoshisPerKilobyte(10)
|
|
@@ -426,7 +425,7 @@ export default class Transaction {
|
|
|
426
425
|
*
|
|
427
426
|
* @returns The current transaction fee
|
|
428
427
|
*/
|
|
429
|
-
getFee(): number {
|
|
428
|
+
getFee (): number {
|
|
430
429
|
let totalIn = 0
|
|
431
430
|
for (const input of this.inputs) {
|
|
432
431
|
if (typeof input.sourceTransaction !== 'object') {
|
|
@@ -444,7 +443,7 @@ export default class Transaction {
|
|
|
444
443
|
/**
|
|
445
444
|
* Signs a transaction, hydrating all its unlocking scripts based on the provided script templates where they are available.
|
|
446
445
|
*/
|
|
447
|
-
async sign(): Promise<void> {
|
|
446
|
+
async sign (): Promise<void> {
|
|
448
447
|
this.cachedHash = undefined
|
|
449
448
|
for (const out of this.outputs) {
|
|
450
449
|
if (typeof out.satoshis === 'undefined') {
|
|
@@ -475,7 +474,7 @@ export default class Transaction {
|
|
|
475
474
|
* @param broadcaster The Broadcaster instance wwhere the transaction will be sent
|
|
476
475
|
* @returns A BroadcastResponse or BroadcastFailure from the Broadcaster
|
|
477
476
|
*/
|
|
478
|
-
async broadcast(broadcaster: Broadcaster = defaultBroadcaster()): Promise<BroadcastResponse | BroadcastFailure> {
|
|
477
|
+
async broadcast (broadcaster: Broadcaster = defaultBroadcaster()): Promise<BroadcastResponse | BroadcastFailure> {
|
|
479
478
|
return await broadcaster.broadcast(this)
|
|
480
479
|
}
|
|
481
480
|
|
|
@@ -484,7 +483,7 @@ export default class Transaction {
|
|
|
484
483
|
*
|
|
485
484
|
* @returns {number[]} - The binary array representation of the transaction.
|
|
486
485
|
*/
|
|
487
|
-
toBinary(): number[] {
|
|
486
|
+
toBinary (): number[] {
|
|
488
487
|
const writer = new Writer()
|
|
489
488
|
writer.writeUInt32LE(this.version)
|
|
490
489
|
writer.writeVarIntNum(this.inputs.length)
|
|
@@ -516,7 +515,7 @@ export default class Transaction {
|
|
|
516
515
|
*
|
|
517
516
|
* @returns {number[]} - The BRC-30 EF representation of the transaction.
|
|
518
517
|
*/
|
|
519
|
-
toEF(): number[] {
|
|
518
|
+
toEF (): number[] {
|
|
520
519
|
const writer = new Writer()
|
|
521
520
|
writer.writeUInt32LE(this.version)
|
|
522
521
|
writer.write([0, 0, 0, 0, 0, 0xef])
|
|
@@ -556,7 +555,7 @@ export default class Transaction {
|
|
|
556
555
|
*
|
|
557
556
|
* @returns {string} - The hexadecimal string representation of the transaction EF.
|
|
558
557
|
*/
|
|
559
|
-
toHexEF(): string {
|
|
558
|
+
toHexEF (): string {
|
|
560
559
|
return toHex(this.toEF())
|
|
561
560
|
}
|
|
562
561
|
|
|
@@ -565,7 +564,7 @@ export default class Transaction {
|
|
|
565
564
|
*
|
|
566
565
|
* @returns {string} - The hexadecimal string representation of the transaction.
|
|
567
566
|
*/
|
|
568
|
-
toHex(): string {
|
|
567
|
+
toHex (): string {
|
|
569
568
|
return toHex(this.toBinary())
|
|
570
569
|
}
|
|
571
570
|
|
|
@@ -574,7 +573,7 @@ export default class Transaction {
|
|
|
574
573
|
*
|
|
575
574
|
* @returns {string} - The hexadecimal string representation of the transaction BEEF.
|
|
576
575
|
*/
|
|
577
|
-
toHexBEEF(): string {
|
|
576
|
+
toHexBEEF (): string {
|
|
578
577
|
return toHex(this.toBEEF())
|
|
579
578
|
}
|
|
580
579
|
|
|
@@ -584,7 +583,7 @@ export default class Transaction {
|
|
|
584
583
|
* @param {'hex' | undefined} enc - The encoding to use for the hash. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
585
584
|
* @returns {string | number[]} - The hash of the transaction in the specified format.
|
|
586
585
|
*/
|
|
587
|
-
hash(enc?: 'hex'): number[] | string {
|
|
586
|
+
hash (enc?: 'hex'): number[] | string {
|
|
588
587
|
let hash
|
|
589
588
|
if (this.cachedHash) {
|
|
590
589
|
hash = this.cachedHash
|
|
@@ -604,21 +603,21 @@ export default class Transaction {
|
|
|
604
603
|
*
|
|
605
604
|
* @returns {number[]} - The ID of the transaction in the binary array format.
|
|
606
605
|
*/
|
|
607
|
-
id(): number[]
|
|
606
|
+
id (): number[]
|
|
608
607
|
/**
|
|
609
608
|
* Calculates the transaction's ID in hexadecimal format.
|
|
610
609
|
*
|
|
611
610
|
* @param {'hex'} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string.
|
|
612
611
|
* @returns {string} - The ID of the transaction in the hex format.
|
|
613
612
|
*/
|
|
614
|
-
id(enc: 'hex'): string
|
|
613
|
+
id (enc: 'hex'): string
|
|
615
614
|
/**
|
|
616
615
|
* Calculates the transaction's ID.
|
|
617
616
|
*
|
|
618
617
|
* @param {'hex' | undefined} enc - The encoding to use for the ID. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
|
|
619
618
|
* @returns {string | number[]} - The ID of the transaction in the specified format.
|
|
620
619
|
*/
|
|
621
|
-
id(enc?: 'hex'): number[] | string {
|
|
620
|
+
id (enc?: 'hex'): number[] | string {
|
|
622
621
|
const id = [...this.hash() as number[]]
|
|
623
622
|
id.reverse()
|
|
624
623
|
if (enc === 'hex') {
|
|
@@ -633,8 +632,10 @@ export default class Transaction {
|
|
|
633
632
|
* @param chainTracker - An instance of ChainTracker, a Bitcoin block header tracker. If the value is set to 'scripts only', headers will not be verified. If not provided then the default chain tracker will be used.
|
|
634
633
|
*
|
|
635
634
|
* @returns Whether the transaction is valid according to the rules of SPV.
|
|
635
|
+
*
|
|
636
|
+
* @example tx.verify(new WhatsOnChain(), new SatoshisPerKilobyte(1))
|
|
636
637
|
*/
|
|
637
|
-
async verify(chainTracker: ChainTracker | 'scripts only' = defaultChainTracker()): Promise<boolean> {
|
|
638
|
+
async verify (chainTracker: ChainTracker | 'scripts only' = defaultChainTracker(), feeModel?: FeeModel): Promise<boolean> {
|
|
638
639
|
// If the transaction has a valid merkle path, verification is complete.
|
|
639
640
|
if (typeof this.merklePath === 'object' && chainTracker !== 'scripts only') {
|
|
640
641
|
const proofValid = await this.merklePath.verify(
|
|
@@ -647,6 +648,14 @@ export default class Transaction {
|
|
|
647
648
|
}
|
|
648
649
|
}
|
|
649
650
|
|
|
651
|
+
if (typeof feeModel !== 'undefined') {
|
|
652
|
+
const cpTx = Transaction.fromHexEF(this.toHexEF())
|
|
653
|
+
delete cpTx.outputs[0].satoshis
|
|
654
|
+
cpTx.outputs[0].change = true
|
|
655
|
+
await cpTx.fee(feeModel)
|
|
656
|
+
if (this.getFee() < cpTx.getFee()) throw new Error(`Verification failed because the transaction ${this.id('hex')} has an insufficient fee and has not been mined.`)
|
|
657
|
+
}
|
|
658
|
+
|
|
650
659
|
// Verify each input transaction and evaluate the spend events.
|
|
651
660
|
// Also, keep a total of the input amounts for later.
|
|
652
661
|
let inputTotal = 0
|
|
@@ -660,7 +669,7 @@ export default class Transaction {
|
|
|
660
669
|
}
|
|
661
670
|
const sourceOutput = input.sourceTransaction.outputs[input.sourceOutputIndex]
|
|
662
671
|
inputTotal += sourceOutput.satoshis
|
|
663
|
-
const inputVerified = await input.sourceTransaction.verify(chainTracker)
|
|
672
|
+
const inputVerified = await input.sourceTransaction.verify(chainTracker, feeModel)
|
|
664
673
|
if (!inputVerified) {
|
|
665
674
|
return false
|
|
666
675
|
}
|
|
@@ -702,7 +711,7 @@ export default class Transaction {
|
|
|
702
711
|
*
|
|
703
712
|
* @returns The serialized BEEF structure
|
|
704
713
|
*/
|
|
705
|
-
toBEEF(): number[] {
|
|
714
|
+
toBEEF (): number[] {
|
|
706
715
|
const writer = new Writer()
|
|
707
716
|
writer.writeUInt32LE(4022206465)
|
|
708
717
|
const BUMPs: MerklePath[] = []
|