@did-btcr2/method 0.22.0 → 0.23.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.
Files changed (105) hide show
  1. package/dist/browser.js +274 -1239
  2. package/dist/browser.mjs +274 -1239
  3. package/dist/cjs/core/beacon/aggregation/cohort/index.js +13 -2
  4. package/dist/cjs/core/beacon/aggregation/cohort/index.js.map +1 -1
  5. package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js +7 -2
  6. package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
  7. package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js +5 -10
  8. package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js.map +1 -1
  9. package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js +4 -7
  10. package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
  11. package/dist/cjs/core/beacon/aggregation/session/index.js +15 -3
  12. package/dist/cjs/core/beacon/aggregation/session/index.js.map +1 -1
  13. package/dist/cjs/core/beacon/cas-beacon.js +1 -1
  14. package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
  15. package/dist/cjs/core/beacon/signal-discovery.js +6 -6
  16. package/dist/cjs/core/beacon/signal-discovery.js.map +1 -1
  17. package/dist/cjs/core/beacon/singleton.js +13 -12
  18. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  19. package/dist/cjs/core/beacon/smt-beacon.js +1 -1
  20. package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
  21. package/dist/cjs/core/identifier.js +11 -13
  22. package/dist/cjs/core/identifier.js.map +1 -1
  23. package/dist/cjs/core/resolve.js +14 -15
  24. package/dist/cjs/core/resolve.js.map +1 -1
  25. package/dist/cjs/core/update.js +2 -2
  26. package/dist/cjs/core/update.js.map +1 -1
  27. package/dist/cjs/did-btcr2.js +11 -14
  28. package/dist/cjs/did-btcr2.js.map +1 -1
  29. package/dist/cjs/utils/did-document.js +13 -2
  30. package/dist/cjs/utils/did-document.js.map +1 -1
  31. package/dist/esm/core/beacon/aggregation/cohort/index.js +13 -2
  32. package/dist/esm/core/beacon/aggregation/cohort/index.js.map +1 -1
  33. package/dist/esm/core/beacon/aggregation/cohort/messages/base.js +7 -2
  34. package/dist/esm/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
  35. package/dist/esm/core/beacon/aggregation/communication/adapter/did-comm.js +5 -10
  36. package/dist/esm/core/beacon/aggregation/communication/adapter/did-comm.js.map +1 -1
  37. package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js +4 -7
  38. package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
  39. package/dist/esm/core/beacon/aggregation/session/index.js +15 -3
  40. package/dist/esm/core/beacon/aggregation/session/index.js.map +1 -1
  41. package/dist/esm/core/beacon/cas-beacon.js +1 -1
  42. package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
  43. package/dist/esm/core/beacon/signal-discovery.js +6 -6
  44. package/dist/esm/core/beacon/signal-discovery.js.map +1 -1
  45. package/dist/esm/core/beacon/singleton.js +13 -12
  46. package/dist/esm/core/beacon/singleton.js.map +1 -1
  47. package/dist/esm/core/beacon/smt-beacon.js +1 -1
  48. package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
  49. package/dist/esm/core/identifier.js +11 -13
  50. package/dist/esm/core/identifier.js.map +1 -1
  51. package/dist/esm/core/resolve.js +14 -15
  52. package/dist/esm/core/resolve.js.map +1 -1
  53. package/dist/esm/core/update.js +2 -2
  54. package/dist/esm/core/update.js.map +1 -1
  55. package/dist/esm/did-btcr2.js +11 -14
  56. package/dist/esm/did-btcr2.js.map +1 -1
  57. package/dist/esm/utils/did-document.js +13 -2
  58. package/dist/esm/utils/did-document.js.map +1 -1
  59. package/dist/types/core/beacon/aggregation/cohort/index.d.ts +1 -1
  60. package/dist/types/core/beacon/aggregation/cohort/index.d.ts.map +1 -1
  61. package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts +1 -1
  62. package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts.map +1 -1
  63. package/dist/types/core/beacon/aggregation/communication/adapter/did-comm.d.ts.map +1 -1
  64. package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts.map +1 -1
  65. package/dist/types/core/beacon/aggregation/session/index.d.ts +1 -1
  66. package/dist/types/core/beacon/aggregation/session/index.d.ts.map +1 -1
  67. package/dist/types/core/beacon/beacon.d.ts +3 -3
  68. package/dist/types/core/beacon/beacon.d.ts.map +1 -1
  69. package/dist/types/core/beacon/cas-beacon.d.ts +3 -3
  70. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
  71. package/dist/types/core/beacon/signal-discovery.d.ts +5 -5
  72. package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -1
  73. package/dist/types/core/beacon/singleton.d.ts +3 -3
  74. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  75. package/dist/types/core/beacon/smt-beacon.d.ts +3 -3
  76. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
  77. package/dist/types/core/identifier.d.ts +17 -21
  78. package/dist/types/core/identifier.d.ts.map +1 -1
  79. package/dist/types/core/interfaces.d.ts +2 -2
  80. package/dist/types/core/interfaces.d.ts.map +1 -1
  81. package/dist/types/core/resolve.d.ts +3 -3
  82. package/dist/types/core/resolve.d.ts.map +1 -1
  83. package/dist/types/core/update.d.ts +2 -2
  84. package/dist/types/core/update.d.ts.map +1 -1
  85. package/dist/types/did-btcr2.d.ts +4 -4
  86. package/dist/types/did-btcr2.d.ts.map +1 -1
  87. package/dist/types/utils/did-document.d.ts +3 -1
  88. package/dist/types/utils/did-document.d.ts.map +1 -1
  89. package/package.json +5 -6
  90. package/src/core/beacon/aggregation/cohort/index.ts +13 -2
  91. package/src/core/beacon/aggregation/cohort/messages/base.ts +7 -2
  92. package/src/core/beacon/aggregation/communication/adapter/did-comm.ts +5 -12
  93. package/src/core/beacon/aggregation/communication/adapter/nostr.ts +5 -8
  94. package/src/core/beacon/aggregation/session/index.ts +15 -3
  95. package/src/core/beacon/beacon.ts +3 -3
  96. package/src/core/beacon/cas-beacon.ts +3 -3
  97. package/src/core/beacon/signal-discovery.ts +9 -9
  98. package/src/core/beacon/singleton.ts +15 -15
  99. package/src/core/beacon/smt-beacon.ts +3 -3
  100. package/src/core/identifier.ts +31 -28
  101. package/src/core/interfaces.ts +2 -2
  102. package/src/core/resolve.ts +17 -18
  103. package/src/core/update.ts +4 -4
  104. package/src/did-btcr2.ts +21 -19
  105. package/src/utils/did-document.ts +14 -2
@@ -40,7 +40,12 @@ export class BaseMessage {
40
40
  * Converts a BaseMessage to a JSON object.
41
41
  * @returns {Base} The JSON representation of the BaseMessage.
42
42
  */
43
- public json(): Base {
44
- return Object.fromEntries(Object.entries(this)) as Base;
43
+ public toJSON(): Base {
44
+ return {
45
+ type : this.type,
46
+ to : this.to,
47
+ from : this.from,
48
+ body : this.body
49
+ };
45
50
  }
46
51
  }
@@ -34,12 +34,7 @@ export class DidCommAdapterConfig implements ServiceAdapterConfig {
34
34
  idType : 'KEY',
35
35
  network : 'mutinynet'
36
36
  };
37
- this.did = config?.did || Identifier.encode(
38
- {
39
- ...this.components,
40
- genesisBytes : this.keys.public
41
- }
42
- );
37
+ this.did = config?.did || Identifier.encode(this.keys.public, this.components);
43
38
  this.coordinatorDids = config?.coordinatorDids || [];
44
39
  }
45
40
  }
@@ -128,24 +123,22 @@ export class DidCommAdapter implements CommunicationService {
128
123
  if(!keys) {
129
124
  this.config.keys.secret = Secp256k1SecretKey.random();
130
125
  this.config.keys.public = Secp256k1SecretKey.getPublicKey(this.config.keys.secret).compressed;
131
- this.config.did = Identifier.encode(
126
+ this.config.did = Identifier.encode(this.config.keys.public,
132
127
  {
133
128
  idType : this.config.components.idType || 'KEY',
134
129
  version : this.config.components.version || 1,
135
- network : this.config.components.network || 'signet',
136
- genesisBytes : this.config.keys.public
130
+ network : this.config.components.network || 'regtest',
137
131
  }
138
132
  );
139
133
  return this.config as ServiceAdapterConfig;
140
134
  }
141
135
 
142
136
  this.config.keys = keys;
143
- this.config.did = Identifier.encode(
137
+ this.config.did = Identifier.encode(this.config.keys.public,
144
138
  {
145
139
  idType : this.config.components.idType || 'KEY',
146
140
  version : this.config.components.version || 1,
147
- network : this.config.components.network || 'signet',
148
- genesisBytes : this.config.keys.public
141
+ network : this.config.components.network || 'regtest',
149
142
  }
150
143
  );
151
144
  return this.config as ServiceAdapterConfig;
@@ -93,11 +93,10 @@ export class NostrAdapter implements CommunicationService {
93
93
  constructor(config: NostrAdapterConfig = { keys: {} as RawSchnorrKeyPair, components: {}, relays: DEFAULT_NOSTR_RELAYS }) {
94
94
  this.config = config;
95
95
  this.config.keys = this.config.keys || SchnorrKeyPair.generate().raw;
96
- this.config.did = config.did || Identifier.encode({
97
- idType : config.components.idType || 'KEY',
96
+ this.config.did = config.did || Identifier.encode(this.config.keys.public!, {
97
+ idType : config.components.idType || 'KEY',
98
98
  version : config.components.version || 1,
99
- network : config.components.network || 'signet',
100
- genesisBytes : this.config.keys.public!
99
+ network : config.components.network || 'signet'
101
100
  });
102
101
  }
103
102
 
@@ -297,24 +296,22 @@ export class NostrAdapter implements CommunicationService {
297
296
  if(!keys) {
298
297
  this.config.keys.secret = Secp256k1SecretKey.random();
299
298
  this.config.keys.public = Secp256k1SecretKey.getPublicKey(this.config.keys.secret).compressed;
300
- this.config.did = Identifier.encode(
299
+ this.config.did = Identifier.encode(this.config.keys.public,
301
300
  {
302
301
  idType : this.config.components.idType || 'KEY',
303
302
  version : this.config.components.version || 1,
304
303
  network : this.config.components.network || 'signet',
305
- genesisBytes : this.config.keys.public
306
304
  }
307
305
  );
308
306
  return this.config as ServiceAdapterConfig;
309
307
  }
310
308
 
311
309
  this.config.keys = keys;
312
- this.config.did = Identifier.encode(
310
+ this.config.did = Identifier.encode(this.config.keys.public,
313
311
  {
314
312
  idType : this.config.components.idType || 'KEY',
315
313
  version : this.config.components.version || 1,
316
314
  network : this.config.components.network || 'signet',
317
- genesisBytes : this.config.keys.public
318
315
  }
319
316
  );
320
317
  return this.config as ServiceAdapterConfig;
@@ -188,7 +188,7 @@ export class BeaconCohortSigningSession implements SigningSession {
188
188
  `Missing ${missing} nonce contributions. ` +
189
189
  `Received ${this.cohort?.participants.length} of ${this.nonceContributions.size} nonce contributions. ` +
190
190
  `Current status: ${this.status}`,
191
- 'NONCE_CONTRIBUTION_ERROR', this.json()
191
+ 'NONCE_CONTRIBUTION_ERROR', this.toJSON()
192
192
  );
193
193
  }
194
194
  const sortedPubkeys = musig2.sortKeys(this.cohort.cohortKeys);
@@ -267,8 +267,20 @@ export class BeaconCohortSigningSession implements SigningSession {
267
267
  * Converts the signing session instance to a JSON object representation.
268
268
  * @returns {BeaconCohortSigningSession} The JSON object representation of the signing session.
269
269
  */
270
- public json(): BeaconCohortSigningSession {
271
- return Object.fromEntries(Object.entries(this)) as BeaconCohortSigningSession;
270
+ public toJSON(): Partial<BeaconCohortSigningSession> {
271
+ return {
272
+ id : this.id,
273
+ cohort : this.cohort,
274
+ pendingTx : this.pendingTx,
275
+ nonceContributions : this.nonceContributions,
276
+ aggregatedNonce : this.aggregatedNonce,
277
+ partialSignatures : this.partialSignatures,
278
+ signature : this.signature,
279
+ status : this.status,
280
+ processedRequests : this.processedRequests,
281
+ nonceSecrets : this.nonceSecrets,
282
+ musig2Session : this.musig2Session
283
+ };
272
284
  }
273
285
 
274
286
  /**
@@ -1,5 +1,5 @@
1
1
  import { KeyBytes } from '@did-btcr2/common';
2
- import { BitcoinNetworkConnection } from '../../../../bitcoin/dist/types/bitcoin.js';
2
+ import { BitcoinConnection } from '@did-btcr2/bitcoin';
3
3
  import { SignedBTCR2Update } from '../../../../cryptosuite/dist/types/data-integrity-proof/interface.js';
4
4
  import { SidecarData } from '../types.js';
5
5
  import { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
@@ -47,12 +47,12 @@ export abstract class Beacon {
47
47
  * Used during the update path.
48
48
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
49
49
  * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
50
- * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
50
+ * @param {BitcoinConnection} bitcoin The Bitcoin network connection.
51
51
  * @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
52
52
  */
53
53
  abstract broadcastSignal(
54
54
  signedUpdate: SignedBTCR2Update,
55
55
  secretKey: KeyBytes,
56
- bitcoin: BitcoinNetworkConnection
56
+ bitcoin: BitcoinConnection
57
57
  ): Promise<SignedBTCR2Update>;
58
58
  }
@@ -1,4 +1,4 @@
1
- import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
1
+ import { BitcoinConnection } from '@did-btcr2/bitcoin';
2
2
  import { KeyBytes } from '@did-btcr2/common';
3
3
  import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
4
  import { SidecarData } from '../types.js';
@@ -39,14 +39,14 @@ export class CASBeacon extends Beacon {
39
39
  * Broadcast CAS Beacon signal to the Bitcoin network.
40
40
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
41
41
  * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
42
- * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
42
+ * @param {BitcoinConnection} bitcoin The Bitcoin network connection.
43
43
  * @return {Promise<SignedBTCR2Update>} The signed update that was broadcasted.
44
44
  * @throws {CASBeaconError} if broadcasting fails.
45
45
  */
46
46
  async broadcastSignal(
47
47
  signedUpdate: SignedBTCR2Update,
48
48
  secretKey: KeyBytes,
49
- bitcoin: BitcoinNetworkConnection
49
+ bitcoin: BitcoinConnection
50
50
  ): Promise<SignedBTCR2Update> {
51
51
  throw new CASBeaconError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signedUpdate, secretKey, bitcoin});
52
52
  }
@@ -1,5 +1,5 @@
1
1
  import {
2
- BitcoinNetworkConnection,
2
+ BitcoinConnection,
3
3
  BlockV3,
4
4
  GENESIS_TX_ID,
5
5
  RawTransactionV2,
@@ -21,23 +21,23 @@ export class BeaconSignalDiscovery {
21
21
  * Retrieves the beacon signals for the given array of BeaconService objects
22
22
  * using an esplora/electrs REST API connection via a bitcoin I/O driver.
23
23
  * @param {Array<BeaconService>} beaconServices Array of BeaconService objects to retrieve signals for
24
- * @param {BitcoinNetworkConnection} bitcoin Bitcoin network connection to use for REST calls
24
+ * @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls
25
25
  * @returns {Promise<Map<BeaconService, Array<BeaconSignal>>>} Map of beacon service to its discovered signals
26
26
  */
27
27
  static async indexer(
28
28
  beaconServices: Array<BeaconService>,
29
- bitcoin: BitcoinNetworkConnection
29
+ bitcoin: BitcoinConnection
30
30
  ): Promise<Map<BeaconService, Array<BeaconSignal>>> {
31
31
  const beaconServiceSignals = new Map<BeaconService, Array<BeaconSignal>>();
32
32
 
33
33
  // Fetch the current block count once before the loop
34
- const currentBlockCount = await bitcoin.network.rest.block.count();
34
+ const currentBlockCount = await bitcoin.rest.block.count();
35
35
 
36
36
  // Iterate over each beacon
37
37
  for (const beaconService of beaconServices) {
38
38
  beaconServiceSignals.set(beaconService, []);
39
39
  // Get the transactions for the beacon address via REST
40
- const beaconSignals = await bitcoin.network.rest.address.getTxs(
40
+ const beaconSignals = await bitcoin.rest.address.getTxs(
41
41
  beaconService.serviceEndpoint as string
42
42
  );
43
43
 
@@ -104,12 +104,12 @@ export class BeaconSignalDiscovery {
104
104
  /**
105
105
  * Traverse the full blockchain from genesis to chain top looking for beacon signals.
106
106
  * @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
107
- * @param {BitcoinNetworkConnection} bitcoin Bitcoin network connection to use for RPC calls.
107
+ * @param {BitcoinConnection} bitcoin Bitcoin network connection to use for RPC calls.
108
108
  * @returns {Promise<Map<BeaconService, Array<BeaconSignal>>>} Map of beacon service to its discovered signals.
109
109
  */
110
110
  static async fullnode(
111
111
  beaconServices: Array<BeaconService>,
112
- bitcoin: BitcoinNetworkConnection
112
+ bitcoin: BitcoinConnection
113
113
  ): Promise<Map<BeaconService, Array<BeaconSignal>>> {
114
114
  const beaconServiceSignals = new Map<BeaconService, Array<BeaconSignal>>();
115
115
 
@@ -118,7 +118,7 @@ export class BeaconSignalDiscovery {
118
118
  }
119
119
 
120
120
  // Get the RPC connection from the bitcoin network
121
- const rpc = bitcoin.network.rpc;
121
+ const rpc = bitcoin.rpc;
122
122
 
123
123
  // Ensure that the RPC connection is available
124
124
  if(!rpc) {
@@ -135,7 +135,7 @@ export class BeaconSignalDiscovery {
135
135
  let height = 0;
136
136
 
137
137
  // Opt into rpc connection to get the block data at the blockhash
138
- let block = await bitcoin.network.rpc!.getBlock({ height }) as BlockV3;
138
+ let block = await bitcoin.rpc!.getBlock({ height }) as BlockV3;
139
139
 
140
140
  console.info(`Searching for beacon signals, please wait ...`);
141
141
  while (block.height <= targetHeight) {
@@ -1,8 +1,7 @@
1
- import { AddressUtxo, BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
1
+ import { AddressUtxo, BitcoinConnection } from '@did-btcr2/bitcoin';
2
2
  import { Canonicalization, INVALID_SIDECAR_DATA, KeyBytes, MISSING_UPDATE_DATA } from '@did-btcr2/common';
3
3
  import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
4
  import { SchnorrKeyPair } from '@did-btcr2/keypair';
5
- import { Signer } from '@did-btcr2/kms';
6
5
  import { opcodes, Psbt, script } from 'bitcoinjs-lib';
7
6
  import { base58btc } from 'multiformats/bases/base58';
8
7
  import { SidecarData } from '../types.js';
@@ -55,10 +54,10 @@ export class SingletonBeacon extends Beacon {
55
54
  );
56
55
  }
57
56
 
58
- // Canonicalize, hash and encode to base58 the signed update object found in sidecar or CAS
59
- const encodedUpdate = Canonicalization.process(signedUpdate, { encoding: 'base58' });
57
+ // Canonicalize, hash and encode to base58btc the signed update object found in sidecar or CAS
58
+ const encodedUpdate = Canonicalization.process(signedUpdate, { encoding: 'base58btc' });
60
59
 
61
- // Encode the signal bytes hex string to base58
60
+ // Encode the signal bytes hex string to base58btc
62
61
  const signalBytes = base58btc.encode(Buffer.from(updateHash, 'hex'));
63
62
 
64
63
  // Check for mismatch between found sidecar/cas update hash and onchain beacon signal hash
@@ -81,20 +80,20 @@ export class SingletonBeacon extends Beacon {
81
80
  * Broadcasts a SingletonBeacon signal to the Bitcoin network.
82
81
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
83
82
  * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
84
- * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
83
+ * @param {BitcoinConnection} bitcoin The Bitcoin network connection.
85
84
  * @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
86
85
  * @throws {SingletonBeaconError} if the bitcoin address is invalid or unfunded.
87
86
  */
88
87
  async broadcastSignal(
89
88
  signedUpdate: SignedBTCR2Update,
90
89
  secretKey: KeyBytes,
91
- bitcoin: BitcoinNetworkConnection
90
+ bitcoin: BitcoinConnection
92
91
  ): Promise<SignedBTCR2Update> {
93
92
  // Convert the serviceEndpoint to a bitcoin address by removing the 'bitcoin:' prefix
94
93
  const bitcoinAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
95
94
 
96
95
  // Query the Bitcoin network for UTXOs associated with the bitcoinAddress
97
- const utxos = await bitcoin.network.rest.address.getUtxos(bitcoinAddress);
96
+ const utxos = await bitcoin.rest.address.getUtxos(bitcoinAddress);
98
97
 
99
98
  // If no utxos are found, throw an error indicating the address is unfunded.
100
99
  if(!utxos.length) {
@@ -118,13 +117,13 @@ export class SingletonBeacon extends Beacon {
118
117
  }
119
118
 
120
119
  // Get the previous tx to the utxo being spent
121
- const prevTx = await bitcoin.network.rest.transaction.getHex(utxo.txid);
120
+ const prevTx = await bitcoin.rest.transaction.getHex(utxo.txid);
122
121
 
123
122
  // Canonicalize and hash the signed update for OP_RETURN output
124
123
  const updateHash = Canonicalization.andHash(signedUpdate);
125
124
 
126
125
  // Construct a spend transaction
127
- const spendTx = new Psbt({ network: bitcoin.network.data })
126
+ const spendTx = new Psbt({ network: bitcoin.data })
128
127
  // Spend tx contains the utxo as its input
129
128
  .addInput({
130
129
  hash : utxo.txid,
@@ -137,11 +136,12 @@ export class SingletonBeacon extends Beacon {
137
136
  // Add an OP_RETURN output containing the update hash
138
137
  .addOutput({ script: script.compile([opcodes.OP_RETURN, updateHash]), value: 0n });
139
138
 
140
- // Construct a Schnorr key pair from the secret key
139
+ // Construct a key pair and PSBT signer from the secret key
141
140
  const keyPair = SchnorrKeyPair.fromSecret(secretKey);
142
-
143
- // Construct a signer object from the key pair and bitcoin network
144
- const signer = new Signer({ keyPair, network: bitcoin.network.name });
141
+ const signer = {
142
+ publicKey : keyPair.publicKey.compressed,
143
+ sign : (hash: Uint8Array) => keyPair.secretKey.sign(hash, { scheme: 'ecdsa' }),
144
+ };
145
145
 
146
146
  // Sign 0th input, finalize extract to hex in prep for broadcast
147
147
  const signedTx = spendTx.signInput(0, signer)
@@ -150,7 +150,7 @@ export class SingletonBeacon extends Beacon {
150
150
  .toHex();
151
151
 
152
152
  // Broadcast spendTx to the Bitcoin network.
153
- const txid = await bitcoin.network.rest.transaction.send(signedTx);
153
+ const txid = await bitcoin.rest.transaction.send(signedTx);
154
154
 
155
155
  // Log the txid of the broadcasted transaction
156
156
  console.info(`Singleton Beacon Signal Broadcasted with txid: ${txid}`);
@@ -1,4 +1,4 @@
1
- import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
1
+ import { BitcoinConnection } from '@did-btcr2/bitcoin';
2
2
  import { KeyBytes } from '@did-btcr2/common';
3
3
  import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
4
  import { SidecarData } from '../types.js';
@@ -39,14 +39,14 @@ export class SMTBeacon extends Beacon {
39
39
  * Broadcast CAS Beacon signal to the Bitcoin network.
40
40
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
41
41
  * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
42
- * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
42
+ * @param {BitcoinConnection} bitcoin The Bitcoin network connection.
43
43
  * @return {Promise<SignedBTCR2Update>} The signed update that was broadcasted.
44
44
  * @throws {SMTBeaconError} if broadcasting fails.
45
45
  */
46
46
  async broadcastSignal(
47
47
  signedUpdate: SignedBTCR2Update,
48
48
  secretKey: KeyBytes,
49
- bitcoin: BitcoinNetworkConnection
49
+ bitcoin: BitcoinConnection
50
50
  ): Promise<SignedBTCR2Update> {
51
51
  throw new SMTBeaconError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signedUpdate, secretKey, bitcoin});
52
52
  }
@@ -1,24 +1,32 @@
1
- import { BitcoinNetworkNames, Bytes, IdentifierError, IdentifierTypes, INVALID_DID, METHOD_NOT_SUPPORTED } from '@did-btcr2/common';
1
+ import { BitcoinNetworkNames, Bytes, DocumentBytes, IdentifierError, IdentifierTypes, INVALID_DID, KeyBytes, METHOD_NOT_SUPPORTED, SchnorrKeyPairObject } from '@did-btcr2/common';
2
2
  import { CompressedSecp256k1PublicKey, SchnorrKeyPair } from '@did-btcr2/keypair';
3
3
  import { bech32m } from '@scure/base';
4
+ import { DidCreateOptions } from '../did-btcr2.js';
4
5
 
5
6
  /**
6
7
  * Components of a did:btcr2 identifier.
7
8
  * @interface DidComponents
9
+ * @extends {IdentifierComponents}
8
10
  * @property {string} hrp The human-readable part of the Bech32m encoding.
11
+ */
12
+ export interface DidComponents extends IdentifierComponents {
13
+ hrp: string;
14
+ };
15
+
16
+ /**
17
+ * Components of a did:btcr2 identifier.
18
+ * @interface IdentifierComponents
9
19
  * @property {string} idType Identifier type (key or external).
10
20
  * @property {number} version Identifier version.
11
- * @property {string | number} network Bitcoin network name or number.
21
+ * @property {string} network Bitcoin network name or number.
12
22
  * @property {Bytes} genesisBytes Public key or an intermediate document bytes.
13
23
  */
14
- export interface DidComponents {
15
- hrp: string;
24
+ export interface IdentifierComponents {
16
25
  idType: string;
17
26
  version: number;
18
27
  network: string;
19
28
  genesisBytes: Bytes;
20
- };
21
-
29
+ }
22
30
  /**
23
31
  * Implements {@link https://dcdpr.github.io/did-btcr2/#syntax | 3 Syntax}.
24
32
  * A did:btcr2 DID consists of a did:btcr2 prefix, followed by an id-bech32 value, which is a Bech32m encoding of:
@@ -41,20 +49,15 @@ export class Identifier {
41
49
  * - a key-value representing a secp256k1 public key; or
42
50
  * - a hash-value representing the hash of an initiating external DID document.
43
51
  *
44
- * @param {DidComponents} params See {@link DidComponents} for details.
45
- * @param {IdentifierTypes} params.idType Identifier type (key or external).
46
- * @param {string} params.network Bitcoin network name.
47
- * @param {number} params.version Identifier version.
48
- * @param {KeyBytes | DocumentBytes} params.genesisBytes Public key or an intermediate document bytes.
52
+ * @param {KeyBytes | DocumentBytes} genesisBytes The genesis bytes (public key or document bytes).
53
+ * @param {DidCreateOptions} options The DID creation options.
49
54
  * @returns {string} The new did:btcr2 identifier.
50
55
  */
51
- static encode({ idType, version, network, genesisBytes }: {
52
- idType: string;
53
- version: number;
54
- network: string;
55
- genesisBytes: Bytes;
56
- }): string {
57
- // 1. If idType is not a valid value per above, raise invalidDid error.
56
+ static encode(genesisBytes: KeyBytes | DocumentBytes, options: DidCreateOptions): string {
57
+ // Deconstruct the options
58
+ const { idType, version = 1, network } = options;
59
+
60
+ // If idType is not a valid value per above, raise invalidDid error.
58
61
  if (!(idType in IdentifierTypes)) {
59
62
  throw new IdentifierError('Expected "idType" to be "KEY" or "EXTERNAL"', INVALID_DID, {idType});
60
63
  }
@@ -275,16 +278,16 @@ export class Identifier {
275
278
  * Generates a new did:btcr2 identifier based on a newly generated key pair.
276
279
  * @returns {string} The new did:btcr2 identifier.
277
280
  */
278
- static generate(): { keys: SchnorrKeyPair; identifier: { controller: string; id: string } } {
279
- const keys = SchnorrKeyPair.generate();
280
- const did = this.encode({
281
- idType : IdentifierTypes.KEY,
282
- version : 1,
283
- network : 'bitcoin',
284
- genesisBytes : keys.publicKey.compressed
285
- });
286
-
287
- return { keys, identifier: { controller: did, id: '#initialKey'} };
281
+ static generate(): { keyPair: SchnorrKeyPairObject; did: string } {
282
+ const keyPair = SchnorrKeyPair.generate();
283
+ const did = this.encode(keyPair.publicKey.compressed,
284
+ {
285
+ idType : 'KEY',
286
+ version : 1,
287
+ network : 'regtest'
288
+ }
289
+ );
290
+ return { keyPair: keyPair.toJSON(), did };
288
291
  }
289
292
 
290
293
  /**
@@ -1,4 +1,4 @@
1
- import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
1
+ import { BitcoinConnection } from '@did-btcr2/bitcoin';
2
2
  import { DidResolutionOptions } from '@web5/dids';
3
3
  import { Sidecar } from './types.js';
4
4
 
@@ -44,7 +44,7 @@ export interface ResolutionOptions extends ResolutionOptionsCore {
44
44
  * Drivers for interacting with external systems, such as the Bitcoin network.
45
45
  */
46
46
  drivers?: {
47
- bitcoin?: BitcoinNetworkConnection;
47
+ bitcoin?: BitcoinConnection;
48
48
  };
49
49
  }
50
50
 
@@ -1,5 +1,5 @@
1
1
  import {
2
- BitcoinNetworkConnection,
2
+ BitcoinConnection,
3
3
  getNetwork
4
4
  } from '@did-btcr2/bitcoin';
5
5
  import {
@@ -64,12 +64,12 @@ export class Resolve {
64
64
  * @returns {DidDocument} The resolved DID Document object.
65
65
  */
66
66
  static deterministic(didComponents: DidComponents): DidDocument {
67
- // Encode the did from the didComponents
68
- const did = Identifier.encode(didComponents);
69
-
70
67
  // Deconstruct the bytes from the given components
71
68
  const { genesisBytes } = didComponents;
72
69
 
70
+ // Encode the did from the didComponents
71
+ const did = Identifier.encode(genesisBytes, didComponents);
72
+
73
73
  // Construct a new CompressedSecp256k1PublicKey and deconstruct the publicKey and publicKeyMultibase
74
74
  const { multibase: publicKeyMultibase } = new CompressedSecp256k1PublicKey(genesisBytes);
75
75
 
@@ -107,19 +107,18 @@ export class Resolve {
107
107
  // Canonicalize and sha256 hash the currentDocument
108
108
  const hashBytes = Canonicalization.process(genesisDocument, { encoding: 'hex' });
109
109
 
110
- // Compare the genesisBytes to the hashBytes
111
- const genesisBytes = bytesToHex(didComponents.genesisBytes);
110
+ const { genesisBytes } = didComponents;
112
111
 
113
112
  // If the genesisBytes do not match the hashBytes, throw an error
114
- if (genesisBytes !== hashBytes) {
113
+ if (bytesToHex(genesisBytes) !== hashBytes) {
115
114
  throw new ResolveError(
116
- `Initial document mismatch: genesisBytes ${genesisBytes} !== hashBytes ${hashBytes}`,
115
+ `Initial document mismatch: genesisBytes ${bytesToHex(genesisBytes)} !== hashBytes ${hashBytes}`,
117
116
  INVALID_DID_DOCUMENT, { genesisBytes, hashBytes }
118
117
  );
119
118
  }
120
119
 
121
120
  // Encode the did from the didComponents
122
- const did = Identifier.encode(didComponents);
121
+ const did = Identifier.encode(genesisBytes, didComponents);
123
122
 
124
123
  // Replace the placeholder did with the did throughout the currentDocument.
125
124
  const currentDocument = JSON.parse(
@@ -209,16 +208,16 @@ export class Resolve {
209
208
  * Signal Bytes (last output in OP_RETURN transaction).
210
209
  * @param {Array<BeaconService>} beaconServices The array of BeaconService objects to search for signals.
211
210
  * @param {SidecarData} sidecarData The sidecar data containing maps of updates, CAS announcements, and SMT proofs.
212
- * @param {BitcoinNetworkConnection} bitcoin The bitcoin network connection used to fetch beacon signals
211
+ * @param {BitcoinConnection} bitcoin The bitcoin network connection used to fetch beacon signals
213
212
  * @returns {Promise<Array<[SignedBTCR2Update, BlockMetadata]>>} The array of BTCR2 Signed Updates announced by the Beacon Signals.
214
213
  */
215
214
  static async beaconSignals(
216
215
  beaconServices: Array<BeaconService>,
217
216
  sidecarData: SidecarData,
218
- bitcoin: BitcoinNetworkConnection
217
+ bitcoin: BitcoinConnection
219
218
  ): Promise<Array<[SignedBTCR2Update, BlockMetadata]>> {
220
219
  // Discover Beacon Signals via indexer server (esplora/electrs) or full node
221
- const beaconServicesSignals = bitcoin.network.rest
220
+ const beaconServicesSignals = bitcoin.rest
222
221
  ? await BeaconSignalDiscovery.indexer(beaconServices, bitcoin)
223
222
  : await BeaconSignalDiscovery.fullnode(beaconServices, bitcoin);
224
223
 
@@ -276,7 +275,7 @@ export class Resolve {
276
275
  // Iterate over each (update block) pair
277
276
  for(const [update, block] of updates) {
278
277
  // Get the hash of the current document
279
- const currentDocumentHash = Canonicalization.process(response.didDocument, { encoding: 'base58' });
278
+ const currentDocumentHash = Canonicalization.process(response.didDocument, { encoding: 'base58btc' });
280
279
 
281
280
  // Safely convert block.time to timestamp
282
281
  const blocktime = DateUtils.blocktimeToTimestamp(block.time);
@@ -318,7 +317,7 @@ export class Resolve {
318
317
  // Create unsigned_update by removing the proof property from update.
319
318
  const unsignedUpdate = JSONUtils.deleteKeys(update, ['proof']) as UnsignedBTCR2Update;
320
319
  // Push the canonicalized unsigned update hash to the updateHashHistory
321
- updateHashHistory.push(Canonicalization.process(unsignedUpdate, { encoding: 'base58' }));
320
+ updateHashHistory.push(Canonicalization.process(unsignedUpdate, { encoding: 'base58btc' }));
322
321
  }
323
322
 
324
323
  // If update.targetVersionId > currentVersionId + 1, throw LATE_PUBLISHING error
@@ -455,16 +454,16 @@ export class Resolve {
455
454
  DidDocument.validate(updatedDocument);
456
455
 
457
456
  // Canonicalize and hash the updatedDocument to get the currentDocumentHash.
458
- const currentDocumentHash = Canonicalization.process(updatedDocument, { encoding: 'base58' });
457
+ const currentDocumentHash = Canonicalization.process(updatedDocument, { encoding: 'base58btc' });
459
458
 
460
459
  // Prepare the update targetHash for comparison with currentDocumentHash.
461
- const updateTargetHash = update.targetHash.startsWith('z') ? update.targetHash : `z${update.targetHash}`;
460
+ const updateTargetHash = update.targetHash;
462
461
 
463
462
  // Make sure the update.targetHash equals currentDocumentHash.
464
- if (updateTargetHash !== currentDocumentHash) {
463
+ if (update.targetHash !== currentDocumentHash) {
465
464
  // If they do not match, throw INVALID_DID_UPDATE error.
466
465
  throw new ResolveError(
467
- `Invalid update: updateTargetHash !== currentDocumentHash`,
466
+ `Invalid update: update.targetHash !== currentDocumentHash`,
468
467
  INVALID_DID_UPDATE, { updateTargetHash, currentDocumentHash }
469
468
  );
470
469
  }
@@ -15,7 +15,7 @@ import {
15
15
  import { Btcr2DidDocument, DidDocument, DidVerificationMethod } from '../utils/did-document.js';
16
16
  import { BeaconFactory } from './beacon/factory.js';
17
17
  import { BeaconService } from './beacon/interfaces.js';
18
- import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
18
+ import { BitcoinConnection } from '@did-btcr2/bitcoin';
19
19
 
20
20
  /**
21
21
  * Implements {@link https://dcdpr.github.io/did-btcr2/operations/update.html | 7.3 Update}.
@@ -56,7 +56,7 @@ export class Update {
56
56
  patch : patches,
57
57
  targetHash : '',
58
58
  targetVersionId : sourceVersionId + 1,
59
- sourceHash : Canonicalization.process(sourceDocument, { encoding: 'base58' }),
59
+ sourceHash : Canonicalization.process(sourceDocument, { encoding: 'base58btc' }),
60
60
  };
61
61
 
62
62
  // Apply all JSON patches to sourceDocument.
@@ -74,7 +74,7 @@ export class Update {
74
74
  }
75
75
 
76
76
  // Set the targetHash by canonicalizing the targetDocument and encoding it in base58.
77
- unsignedUpdate.targetHash = Canonicalization.process(targetDocument, { encoding: 'base58' });
77
+ unsignedUpdate.targetHash = Canonicalization.process(targetDocument, { encoding: 'base58btc' });
78
78
 
79
79
  // Return unsignedUpdate.
80
80
  return unsignedUpdate;
@@ -140,7 +140,7 @@ export class Update {
140
140
  beaconService: BeaconService,
141
141
  update: SignedBTCR2Update,
142
142
  secretKey: KeyBytes,
143
- bitcoin: BitcoinNetworkConnection
143
+ bitcoin: BitcoinConnection
144
144
  ): Promise<SignedBTCR2Update> {
145
145
  // Establish a beacon object
146
146
  const beacon = BeaconFactory.establish(beaconService);