@bsv/sdk 1.1.32 → 1.1.33

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.
@@ -926,7 +926,9 @@ export class Beef {
926
926
  mergeBeef(beef: number[] | Beef)
927
927
  isValid(allowTxidOnly?: boolean): boolean
928
928
  async verify(chainTracker: ChainTracker, allowTxidOnly?: boolean): Promise<boolean>
929
+ toWriter(writer: Writer)
929
930
  toBinary(): number[]
931
+ toBinaryAtomic(txid: string)
930
932
  toHex(): string
931
933
  static fromReader(br: Reader): Beef
932
934
  static fromBinary(bin: number[]): Beef
@@ -1187,6 +1189,21 @@ Returns
1187
1189
 
1188
1190
  A binary array representing the BEEF
1189
1191
 
1192
+ #### Method toBinaryAtomic
1193
+
1194
+ Serialize this Beef as AtomicBEEF.
1195
+
1196
+ `txid` must exist and be the last transaction
1197
+ in sorted (dependency) order.
1198
+
1199
+ ```ts
1200
+ toBinaryAtomic(txid: string)
1201
+ ```
1202
+
1203
+ Returns
1204
+
1205
+ serialized contents of this Beef with AtomicBEEF prefix.
1206
+
1190
1207
  #### Method toHex
1191
1208
 
1192
1209
  Returns a hex string representing the serialized BEEF
@@ -1209,6 +1226,14 @@ Returns
1209
1226
 
1210
1227
  Summary of `Beef` contents as multi-line string.
1211
1228
 
1229
+ #### Method toWriter
1230
+
1231
+ Serializes this data to `writer`
1232
+
1233
+ ```ts
1234
+ toWriter(writer: Writer)
1235
+ ```
1236
+
1212
1237
  #### Method trimKnownTxids
1213
1238
 
1214
1239
  Ensure that all the txids in `knownTxids` are txidOnly
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.1.32",
3
+ "version": "1.1.33",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -396,11 +396,10 @@ export class Beef {
396
396
  }
397
397
 
398
398
  /**
399
- * Returns a binary array representing the serialized BEEF
400
- * @returns A binary array representing the BEEF
401
- */
402
- toBinary (): number[] {
403
- const writer = new Writer()
399
+ * Serializes this data to `writer`
400
+ * @param writer
401
+ */
402
+ toWriter (writer: Writer) {
404
403
  writer.writeUInt32LE(this.magic)
405
404
 
406
405
  writer.writeVarIntNum(this.bumps.length)
@@ -412,7 +411,38 @@ export class Beef {
412
411
  for (const tx of this.txs) {
413
412
  tx.toWriter(writer, this.magic)
414
413
  }
414
+ }
415
+
416
+ /**
417
+ * Returns a binary array representing the serialized BEEF
418
+ * @returns A binary array representing the BEEF
419
+ */
420
+ toBinary (): number[] {
421
+ const writer = new Writer()
422
+ this.toWriter(writer)
423
+ return writer.toArray()
424
+ }
415
425
 
426
+ /**
427
+ * Serialize this Beef as AtomicBEEF.
428
+ *
429
+ * `txid` must exist and be the last transaction
430
+ * in sorted (dependency) order.
431
+ *
432
+ * @param txid
433
+ * @returns serialized contents of this Beef with AtomicBEEF prefix.
434
+ */
435
+ toBinaryAtomic(txid: string) {
436
+ this.sortTxs()
437
+ const tx = this.findTxid(txid)
438
+ if (!tx)
439
+ throw new Error(`${txid} does not exist in this Beef`)
440
+ if (this.txs[this.txs.length - 1] !== tx)
441
+ throw new Error(`${txid} is not the last transaction in this Beef`)
442
+ const writer = new Writer()
443
+ writer.writeUInt32LE(ATOMIC_BEEF)
444
+ writer.write(toArray(txid, 'hex'))
445
+ this.toWriter(writer)
416
446
  return writer.toArray()
417
447
  }
418
448
 
@@ -429,7 +459,7 @@ export class Beef {
429
459
  let atomicTxid: string | undefined = undefined
430
460
  if (version === ATOMIC_BEEF) {
431
461
  // Skip the txid and re-read the BEEF version
432
- atomicTxid = toHex(br.readReverse(32))
462
+ atomicTxid = toHex(br.read(32))
433
463
  version = br.readUInt32LE()
434
464
  }
435
465
  if (version !== BEEF_MAGIC && version !== BEEF_MAGIC_V2) { throw new Error(`Serialized BEEF must start with ${BEEF_MAGIC} or ${BEEF_MAGIC_V2} but starts with ${version}`) }
@@ -138,7 +138,18 @@ export default class Transaction {
138
138
 
139
139
  // Ensure that all transactions are part of the dependency graph of the subject transaction
140
140
  const validTxids = new Set<string>()
141
+ // All BUMP level 0 hashes are valid.
142
+ for (const bump of BUMPs) {
143
+ for (const n of bump.path[0])
144
+ if (n.hash)
145
+ validTxids.add(n.hash)
146
+ }
147
+ // To keep track of which transactions were used.
148
+ const unusedTxTxids = new Set<string>()
149
+ for (const txid of Object.keys(transactions)) unusedTxTxids.add(txid)
150
+
141
151
  const traverseDependencies = (txid: string) => {
152
+ unusedTxTxids.delete(txid)
142
153
  if (validTxids.has(txid)) {
143
154
  return
144
155
  }
@@ -156,10 +167,8 @@ export default class Transaction {
156
167
  traverseDependencies(subjectTXID)
157
168
 
158
169
  // 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
- }
170
+ for (const txid of unusedTxTxids) {
171
+ throw new Error(`Unrelated transaction with TXID ${txid} found in Atomic BEEF data.`)
163
172
  }
164
173
 
165
174
  // Build the transaction by linking inputs and merkle paths
@@ -101,7 +101,7 @@ describe('Beef tests', () => {
101
101
  }
102
102
  })
103
103
 
104
- test('4_all merkleRoots equal', async () => {
104
+ test('1_all merkleRoots equal', async () => {
105
105
  {
106
106
  const beef = Beef.fromString(beefs[0])
107
107
  expect(beef.isValid(undefined)).toBe(true)
@@ -115,7 +115,7 @@ describe('Beef tests', () => {
115
115
  }
116
116
  })
117
117
 
118
- test('4_allowTxidOnly', async () => {
118
+ test('2_allowTxidOnly', async () => {
119
119
  {
120
120
  const beef = Beef.fromString(beefs[0])
121
121
  expect(beef.isValid(undefined)).toBe(true)
@@ -125,7 +125,7 @@ describe('Beef tests', () => {
125
125
  }
126
126
  })
127
127
 
128
- test('4_removeExistingTxid', async () => {
128
+ test('3_removeExistingTxid', async () => {
129
129
  {
130
130
  const beef = Beef.fromString(beefs[0])
131
131
  expect(beef.isValid(undefined)).toBe(true)
@@ -165,7 +165,7 @@ describe('Beef tests', () => {
165
165
  }
166
166
  })
167
167
 
168
- test('4_mergeBeef', async () => {
168
+ test('5_mergeBeef', async () => {
169
169
  {
170
170
  const beef = Beef.fromString(beefs[0])
171
171
  const beefB = Beef.fromString(beefs[0])
@@ -201,7 +201,7 @@ describe('Beef tests', () => {
201
201
  }
202
202
  })
203
203
 
204
- test('4_BeefParty', async () => {
204
+ test('6_BeefParty', async () => {
205
205
 
206
206
  const bp = new BeefParty(['b', 'c'])
207
207
  expect(bp.isParty('a')).toBe(false)
@@ -254,7 +254,7 @@ describe('Beef tests', () => {
254
254
  }
255
255
  })
256
256
 
257
- test('5_AtomicBeef', async () => {
257
+ test('7_AtomicBeef', async () => {
258
258
  {
259
259
  const beef = Beef.fromString(beefs[0])
260
260
  expect(beef.toHex()).toBe(beefs[0])
@@ -291,6 +291,20 @@ describe('Beef tests', () => {
291
291
  expect(beef2.toHex()).toBe(beefHex)
292
292
  }
293
293
  })
294
+
295
+ test('8_toBinaryAtomic', async () => {
296
+ {
297
+ const beef = Beef.fromString(beefs[0])
298
+ const tx = Transaction.fromHex(txs[0])
299
+ beef.mergeTransaction(tx)
300
+ const sr = beef.sortTxs()
301
+ const log = beef.toLogString()
302
+ const atomic = beef.toBinaryAtomic(tx.id('hex'))
303
+ const t2 = Transaction.fromAtomicBEEF(atomic)
304
+ const beef2 = t2.toAtomicBEEF()
305
+ expect(atomic).toEqual(beef2)
306
+ }
307
+ })
294
308
  })
295
309
 
296
310
  const txs: string[] = [