@did-btcr2/method 0.19.0 → 0.22.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 (120) hide show
  1. package/README.md +223 -1
  2. package/dist/browser.js +3496 -4202
  3. package/dist/browser.mjs +3496 -4202
  4. package/dist/cjs/core/beacon/beacon.js +25 -0
  5. package/dist/cjs/core/beacon/beacon.js.map +1 -0
  6. package/dist/cjs/core/beacon/cas-beacon.js +20 -36
  7. package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
  8. package/dist/cjs/core/beacon/error.js +4 -4
  9. package/dist/cjs/core/beacon/error.js.map +1 -1
  10. package/dist/cjs/core/beacon/factory.js +5 -7
  11. package/dist/cjs/core/beacon/factory.js.map +1 -1
  12. package/dist/cjs/core/beacon/interfaces.js +1 -31
  13. package/dist/cjs/core/beacon/interfaces.js.map +1 -1
  14. package/dist/cjs/core/beacon/signal-discovery.js +183 -0
  15. package/dist/cjs/core/beacon/signal-discovery.js.map +1 -0
  16. package/dist/cjs/core/beacon/singleton.js +56 -86
  17. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  18. package/dist/cjs/core/beacon/smt-beacon.js +22 -39
  19. package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
  20. package/dist/cjs/core/beacon/utils.js +4 -9
  21. package/dist/cjs/core/beacon/utils.js.map +1 -1
  22. package/dist/cjs/core/resolve.js +121 -307
  23. package/dist/cjs/core/resolve.js.map +1 -1
  24. package/dist/cjs/core/update.js +62 -154
  25. package/dist/cjs/core/update.js.map +1 -1
  26. package/dist/cjs/did-btcr2.js +100 -91
  27. package/dist/cjs/did-btcr2.js.map +1 -1
  28. package/dist/cjs/index.js +3 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/utils/appendix.js +6 -15
  31. package/dist/cjs/utils/appendix.js.map +1 -1
  32. package/dist/cjs/utils/did-document-builder.js +5 -6
  33. package/dist/cjs/utils/did-document-builder.js.map +1 -1
  34. package/dist/cjs/utils/did-document.js +42 -38
  35. package/dist/cjs/utils/did-document.js.map +1 -1
  36. package/dist/esm/core/beacon/beacon.js +25 -0
  37. package/dist/esm/core/beacon/beacon.js.map +1 -0
  38. package/dist/esm/core/beacon/cas-beacon.js +20 -36
  39. package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
  40. package/dist/esm/core/beacon/error.js +4 -4
  41. package/dist/esm/core/beacon/error.js.map +1 -1
  42. package/dist/esm/core/beacon/factory.js +5 -7
  43. package/dist/esm/core/beacon/factory.js.map +1 -1
  44. package/dist/esm/core/beacon/interfaces.js +1 -31
  45. package/dist/esm/core/beacon/interfaces.js.map +1 -1
  46. package/dist/esm/core/beacon/signal-discovery.js +183 -0
  47. package/dist/esm/core/beacon/signal-discovery.js.map +1 -0
  48. package/dist/esm/core/beacon/singleton.js +56 -86
  49. package/dist/esm/core/beacon/singleton.js.map +1 -1
  50. package/dist/esm/core/beacon/smt-beacon.js +22 -39
  51. package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
  52. package/dist/esm/core/beacon/utils.js +4 -9
  53. package/dist/esm/core/beacon/utils.js.map +1 -1
  54. package/dist/esm/core/resolve.js +121 -307
  55. package/dist/esm/core/resolve.js.map +1 -1
  56. package/dist/esm/core/update.js +62 -154
  57. package/dist/esm/core/update.js.map +1 -1
  58. package/dist/esm/did-btcr2.js +100 -91
  59. package/dist/esm/did-btcr2.js.map +1 -1
  60. package/dist/esm/index.js +3 -1
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/utils/appendix.js +6 -15
  63. package/dist/esm/utils/appendix.js.map +1 -1
  64. package/dist/esm/utils/did-document-builder.js +5 -6
  65. package/dist/esm/utils/did-document-builder.js.map +1 -1
  66. package/dist/esm/utils/did-document.js +42 -38
  67. package/dist/esm/utils/did-document.js.map +1 -1
  68. package/dist/types/core/beacon/beacon.d.ts +44 -0
  69. package/dist/types/core/beacon/beacon.d.ts.map +1 -0
  70. package/dist/types/core/beacon/cas-beacon.d.ts +19 -30
  71. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
  72. package/dist/types/core/beacon/error.d.ts +2 -2
  73. package/dist/types/core/beacon/error.d.ts.map +1 -1
  74. package/dist/types/core/beacon/factory.d.ts +4 -6
  75. package/dist/types/core/beacon/factory.d.ts.map +1 -1
  76. package/dist/types/core/beacon/interfaces.d.ts +7 -46
  77. package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
  78. package/dist/types/core/beacon/signal-discovery.d.ts +25 -0
  79. package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -0
  80. package/dist/types/core/beacon/singleton.d.ts +17 -30
  81. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  82. package/dist/types/core/beacon/smt-beacon.d.ts +21 -33
  83. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
  84. package/dist/types/core/beacon/utils.d.ts.map +1 -1
  85. package/dist/types/core/interfaces.d.ts +1 -8
  86. package/dist/types/core/interfaces.d.ts.map +1 -1
  87. package/dist/types/core/resolve.d.ts +34 -47
  88. package/dist/types/core/resolve.d.ts.map +1 -1
  89. package/dist/types/core/types.d.ts +21 -8
  90. package/dist/types/core/types.d.ts.map +1 -1
  91. package/dist/types/core/update.d.ts +30 -73
  92. package/dist/types/core/update.d.ts.map +1 -1
  93. package/dist/types/did-btcr2.d.ts +44 -47
  94. package/dist/types/did-btcr2.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +3 -1
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/utils/appendix.d.ts.map +1 -1
  98. package/dist/types/utils/did-document-builder.d.ts +5 -1
  99. package/dist/types/utils/did-document-builder.d.ts.map +1 -1
  100. package/dist/types/utils/did-document.d.ts +26 -21
  101. package/dist/types/utils/did-document.d.ts.map +1 -1
  102. package/package.json +8 -7
  103. package/src/core/beacon/beacon.ts +58 -0
  104. package/src/core/beacon/cas-beacon.ts +30 -44
  105. package/src/core/beacon/error.ts +5 -6
  106. package/src/core/beacon/factory.ts +7 -9
  107. package/src/core/beacon/interfaces.ts +7 -64
  108. package/src/core/beacon/signal-discovery.ts +237 -0
  109. package/src/core/beacon/singleton.ts +78 -100
  110. package/src/core/beacon/smt-beacon.ts +32 -49
  111. package/src/core/beacon/utils.ts +16 -13
  112. package/src/core/interfaces.ts +1 -9
  113. package/src/core/resolve.ts +163 -395
  114. package/src/core/types.ts +25 -8
  115. package/src/core/update.ts +91 -236
  116. package/src/did-btcr2.ts +154 -116
  117. package/src/index.ts +8 -1
  118. package/src/utils/appendix.ts +8 -22
  119. package/src/utils/did-document-builder.ts +5 -7
  120. package/src/utils/did-document.ts +80 -73
@@ -1,74 +1,51 @@
1
1
  import { AddressUtxo, BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
2
- import { HexString, INVALID_SIDECAR_DATA, MethodError, MISSING_UPDATE_DATA, SingletonBeaconError } from '@did-btcr2/common';
3
- import { BTCR2SignedUpdate } from '@did-btcr2/cryptosuite';
4
- import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
5
- import { Kms, Signer } from '@did-btcr2/kms';
2
+ import { Canonicalization, INVALID_SIDECAR_DATA, KeyBytes, MISSING_UPDATE_DATA } from '@did-btcr2/common';
3
+ import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
+ import { SchnorrKeyPair } from '@did-btcr2/keypair';
5
+ import { Signer } from '@did-btcr2/kms';
6
6
  import { opcodes, Psbt, script } from 'bitcoinjs-lib';
7
7
  import { base58btc } from 'multiformats/bases/base58';
8
- import { canonicalization } from '../../did-btcr2.js';
9
- import { Identifier } from '../identifier.js';
10
8
  import { SidecarData } from '../types.js';
11
- import { AggregateBeacon, BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
9
+ import { Beacon } from './beacon.js';
10
+ import { SingletonBeaconError } from './error.js';
11
+ import { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
12
12
 
13
13
  /**
14
14
  * Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#singleton-beacon | Singleton Beacon}.
15
- *
16
15
  * @class SingletonBeacon
17
16
  * @type {SingletonBeacon}
18
- * @extends {AggregateBeacon}
17
+ * @extends {Beacon}
19
18
  */
20
- export class SingletonBeacon extends AggregateBeacon {
19
+ export class SingletonBeacon extends Beacon {
21
20
 
22
21
  /**
23
22
  * Creates an instance of SingletonBeacon.
24
- * @param {BeaconService} service The Beacon service.
25
- * @param {?BeaconSidecarData} sidecar The SingletonBeacon sidecar data.
26
- */
27
- constructor(
28
- service: BeaconService,
29
- signals: Array<BeaconSignal>,
30
- sidecar: SidecarData,
31
- bitcoin?: BitcoinNetworkConnection
32
- ) {
33
- super({ ...service, type: 'SingletonBeacon' }, signals, sidecar, bitcoin);
34
- }
35
-
36
- /**
37
- * Static, convenience method for establishing a CASBeacon object.
38
- * @param {string} service The Beacon service.
39
- * @param {SidecarData} sidecar The sidecar data.
40
- * @returns {SingletonBeacon} The Singleton Beacon.
41
- */
42
- static establish(service: BeaconService, signals: Array<BeaconSignal>, sidecar: SidecarData): SingletonBeacon {
43
- return new SingletonBeacon(service, signals, sidecar);
44
- }
45
-
46
- /**
47
- * Generates a Beacon Signal for a Singleton Beacon Service.
48
- * @param {HexString} updateHash The update hash to be included in the Beacon Signal.
49
- * @returns {BeaconSignal} The generated signal.
50
- * @throws {MethodError} if the signal is invalid.
23
+ * @param {BeaconService} service The BeaconService object representing the funded beacon to announce the update to.
24
+ *
51
25
  */
52
- generateSignal(updateHash: HexString): BeaconSignal {
53
- throw new MethodError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {updateHash});
26
+ constructor(service: BeaconService) {
27
+ super({ ...service, type: 'SingletonBeacon' });
54
28
  }
55
29
 
56
30
  /**
57
31
  * Processes an array of Beacon Signals associated with a Singleton Beacon Service.
58
- * @returns {Promise<BTCR2SignedUpdate | undefined>} The DID Update payload announced by the Beacon Signal.
32
+ * @returns {Promise<SignedBTCR2Update | undefined>} The DID Update payload announced by the Beacon Signal.
59
33
  * @throws {SingletonBeaconError} if the signalTx is invalid or the signalSidecarData is invalid.
60
34
  */
61
- async processSignals(): Promise<Array<[BTCR2SignedUpdate, BlockMetadata]>> {
35
+ async processSignals(
36
+ signals: Array<BeaconSignal>,
37
+ sidecar: SidecarData
38
+ ): Promise<Array<[SignedBTCR2Update, BlockMetadata]>> {
62
39
  // Initialize an empty array to hold the BTCR2 signed updates
63
- const updates = new Array<[BTCR2SignedUpdate, BlockMetadata]>();
40
+ const updates = new Array<[SignedBTCR2Update, BlockMetadata]>();
64
41
 
65
- // Loop through each signal in this.signals
66
- for(const signal of this.signals || []) {
42
+ // Loop through each signal in signals
43
+ for(const signal of signals) {
67
44
  // Grab the beacon signal bytes hash from the signal
68
45
  const updateHash = signal.signalBytes;
69
46
 
70
47
  // Use the updateHash as the sidecar data lookup key to retrieve the btcr2 update
71
- const signedUpdate = this.sidecar.updateMap.get(updateHash);
48
+ const signedUpdate = sidecar.updateMap.get(updateHash);
72
49
 
73
50
  // If no btcr2 update is found in sidecar data maps, throw missingUpdateData error.
74
51
  if(!signedUpdate) {
@@ -79,7 +56,7 @@ export class SingletonBeacon extends AggregateBeacon {
79
56
  }
80
57
 
81
58
  // Canonicalize, hash and encode to base58 the signed update object found in sidecar or CAS
82
- const encodedUpdate = canonicalization.process(signedUpdate, { encoding: 'base58' });
59
+ const encodedUpdate = Canonicalization.process(signedUpdate, { encoding: 'base58' });
83
60
 
84
61
  // Encode the signal bytes hex string to base58
85
62
  const signalBytes = base58btc.encode(Buffer.from(updateHash, 'hex'));
@@ -100,28 +77,39 @@ export class SingletonBeacon extends AggregateBeacon {
100
77
  // Return the array of signed updates
101
78
  return updates;
102
79
  }
103
-
104
80
  /**
105
- * Broadcasts a SingletonBeacon signal.
106
- * TODO: Design and implement a way to construct, sign and send via RPC
107
- *
108
- * @returns {SignedRawTx} Successful output of a bitcoin transaction.
81
+ * Broadcasts a SingletonBeacon signal to the Bitcoin network.
82
+ * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
83
+ * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
84
+ * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
85
+ * @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
109
86
  * @throws {SingletonBeaconError} if the bitcoin address is invalid or unfunded.
110
87
  */
111
- async broadcastSignal(updateHash: HexString): Promise<HexString> {
112
- // 1. Initialize an addressURI variable to beacon.serviceEndpoint.
113
- // 2. Set bitcoinAddress to the decoding of addressURI following BIP21.
88
+ async broadcastSignal(
89
+ signedUpdate: SignedBTCR2Update,
90
+ secretKey: KeyBytes,
91
+ bitcoin: BitcoinNetworkConnection
92
+ ): Promise<SignedBTCR2Update> {
93
+ // Convert the serviceEndpoint to a bitcoin address by removing the 'bitcoin:' prefix
114
94
  const bitcoinAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
115
95
 
116
- // 3. Ensure bitcoinAddress is funded, if not, fund this address.
117
- // let inputs: Array<CreateRawTxInputs> = [];
96
+ // Query the Bitcoin network for UTXOs associated with the bitcoinAddress
97
+ const utxos = await bitcoin.network.rest.address.getUtxos(bitcoinAddress);
118
98
 
119
- const utxos = await this.bitcoin.network.rest.address.getUtxos(bitcoinAddress);
99
+ // If no utxos are found, throw an error indicating the address is unfunded.
120
100
  if(!utxos.length) {
121
- throw new SingletonBeaconError('No UTXOs found, please fund address!', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
101
+ throw new SingletonBeaconError(
102
+ 'No UTXOs found, please fund address!',
103
+ 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress }
104
+ );
122
105
  }
123
106
 
124
- const utxo: AddressUtxo = utxos.sort((a, b) => b.status.block_height - a.status.block_height)[0];
107
+ // Sort utxos by block height and take the most recent one
108
+ const utxo: AddressUtxo | undefined = utxos.sort(
109
+ (a, b) => b.status.block_height - a.status.block_height
110
+ ).shift();
111
+
112
+ // If no utxos are found, throw an error.
125
113
  if(!utxo) {
126
114
  throw new SingletonBeaconError(
127
115
  'Beacon bitcoin address unfunded or utxos unconfirmed.',
@@ -129,55 +117,45 @@ export class SingletonBeacon extends AggregateBeacon {
129
117
  );
130
118
  }
131
119
 
132
- // 4. Set hashBytes to the result of passing signedUpdate to the JSON Canonicalization and Hash algorithm.
133
- const udpateHashBytes = Buffer.from(updateHash, 'hex');
134
- if (udpateHashBytes.length !== 32) {
135
- throw new SingletonBeaconError('Hash must be 32 bytes');
136
- }
137
-
138
- // 5. Initialize spendTx to a Bitcoin transaction that spends a transaction controlled by the bitcoinAddress and
139
- // contains at least one transaction output. This output MUST have the following format
140
- // [OP_RETURN, OP_PUSH32, hashBytes]
141
- const {txid, vout} = utxo;
142
- const prevTx = await this.bitcoin.network.rest.transaction.getHex(txid);
143
- const input = {
144
- hash : txid,
145
- index : vout,
146
- nonWitnessUtxo : Buffer.from(prevTx, 'hex')
147
- };
148
- // TODO: Figure out a good way to estimate fees
149
- const spendTx = new Psbt({ network: this.bitcoin.network.data })
150
- .addInput(input)
120
+ // Get the previous tx to the utxo being spent
121
+ const prevTx = await bitcoin.network.rest.transaction.getHex(utxo.txid);
122
+
123
+ // Canonicalize and hash the signed update for OP_RETURN output
124
+ const updateHash = Canonicalization.andHash(signedUpdate);
125
+
126
+ // Construct a spend transaction
127
+ const spendTx = new Psbt({ network: bitcoin.network.data })
128
+ // Spend tx contains the utxo as its input
129
+ .addInput({
130
+ hash : utxo.txid,
131
+ index : utxo.vout,
132
+ nonWitnessUtxo : Buffer.from(prevTx, 'hex')
133
+ })
134
+ // Add a change output minus a fee of 500 sats
135
+ // TODO: calculate fee based on transaction vsize and current fee rates
151
136
  .addOutput({ address: bitcoinAddress, value: BigInt(utxo.value) - BigInt(500) })
152
- .addOutput({ script: script.compile([opcodes.OP_RETURN, udpateHashBytes]), value: 0n });
153
-
154
- // 6. Retrieve the cryptographic material, e.g private key or signing capability, associated with the bitcoinAddress
155
- // or service. How this is done is left to the implementer.
156
- const components = Identifier.decode(this.service.id);
157
- const keyUri = new CompressedSecp256k1PublicKey(components.genesisBytes).hex;
158
- const keyPair = Kms.getKey(keyUri as string);
159
- if (!keyPair) {
160
- throw new Error('Key pair not found.');
161
- }
137
+ // Add an OP_RETURN output containing the update hash
138
+ .addOutput({ script: script.compile([opcodes.OP_RETURN, updateHash]), value: 0n });
139
+
140
+ // Construct a Schnorr key pair from the secret key
141
+ const keyPair = SchnorrKeyPair.fromSecret(secretKey);
162
142
 
163
- const signer = new Signer({ keyPair, network: this.bitcoin.network.name });
143
+ // Construct a signer object from the key pair and bitcoin network
144
+ const signer = new Signer({ keyPair, network: bitcoin.network.name });
164
145
 
165
- // 7. Sign the spendTx.
146
+ // Sign 0th input, finalize extract to hex in prep for broadcast
166
147
  const signedTx = spendTx.signInput(0, signer)
167
148
  .finalizeAllInputs()
168
149
  .extractTransaction()
169
150
  .toHex();
170
- if(!spendTx) {
171
- throw new SingletonBeaconError('Failed to sign raw transaction.', 'RAW_TX_SIGN_FAILED', { spendTx });
172
- }
173
151
 
174
- // 8. Broadcast spendTx to the Bitcoin network.
175
- const spentTx = await this.bitcoin.network.rest.transaction.send(signedTx);
176
- if(!spentTx) {
177
- throw new SingletonBeaconError('Failed to send raw transaction.', 'SEND_FAILED', { spentTx });
178
- }
152
+ // Broadcast spendTx to the Bitcoin network.
153
+ const txid = await bitcoin.network.rest.transaction.send(signedTx);
154
+
155
+ // Log the txid of the broadcasted transaction
156
+ console.info(`Singleton Beacon Signal Broadcasted with txid: ${txid}`);
179
157
 
180
- // Return the signed update and the spend tx id.
181
- return spentTx;
158
+ // Return the signed update
159
+ return signedUpdate;
182
160
  }
183
161
  }
@@ -1,70 +1,53 @@
1
1
  import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
2
- import { HexString, MethodError } from '@did-btcr2/common';
3
- import { BTCR2SignedUpdate } from '@did-btcr2/cryptosuite';
2
+ import { KeyBytes } from '@did-btcr2/common';
3
+ import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
4
4
  import { SidecarData } from '../types.js';
5
- import { AggregateBeacon, BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
5
+ import { Beacon } from './beacon.js';
6
+ import { SMTBeaconError } from './error.js';
7
+ import { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
6
8
 
7
9
  /**
8
- * TODO: Finish implementation
9
10
  * Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#smt-beacon | SMTBeacon}.
10
11
  * @class SMTBeacon
11
12
  * @type {SMTBeacon}
12
- * @extends {AggregateBeacon}
13
+ * @extends {Beacon}
13
14
  */
14
- export class SMTBeacon extends AggregateBeacon {
15
+ export class SMTBeacon extends Beacon {
15
16
  /**
16
- * Creates an instance of SingletonBeacon.
17
+ * Creates an instance of SMTBeacon.
17
18
  * @param {BeaconService} service The Beacon service.
18
- * @param {Array<BeaconSignal>} signals The SingletonBeacon sidecar data.
19
- * @param {SidecarData} sidecar The sidecar data.
20
19
  */
21
- constructor(
22
- service: BeaconService,
23
- signals: Array<BeaconSignal>,
24
- sidecar: SidecarData,
25
- bitcoin?: BitcoinNetworkConnection
26
- ) {
27
- super({ ...service, type: 'SMTBeacon' }, signals, sidecar, bitcoin);
28
- }
29
-
30
- /**
31
- * Static, convenience method for establishing a SMTBeacon object.
32
- * @param {string} service The Beacon service.
33
- * @param {SidecarData} sidecar The sidecar data.
34
- * @returns {SingletonBeacon} The Singleton Beacon.
35
- */
36
- static establish(service: BeaconService, signals: Array<BeaconSignal>, sidecar: SidecarData): SMTBeacon {
37
- return new SMTBeacon(service, signals, sidecar);
38
- }
39
-
40
- /**
41
- * TODO: Figure out if this is necessary or not.
42
- * @param {HexString} updateHash The hash of the BTCR2 update to generate the signal for.
43
- * @returns {BeaconSignal} The generated signal.
44
- * @throws {MethodError} if the signal is invalid.
45
- */
46
- generateSignal(updateHash: HexString): BeaconSignal {
47
- throw new MethodError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {updateHash});
20
+ constructor(service: BeaconService) {
21
+ super({ ...service, type: 'SMTBeacon' });
48
22
  }
49
23
 
50
24
  /**
51
- * Process SMTBeacon signals.
52
- * @returns {Promise<Array<BTCR2SignedUpdate>>} The processed signed update or undefined.
53
- * @throws {MethodError} if the signal processing fails.
25
+ * Implements {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process-smt-beacon | 7.2.e.1 Process SMT Beacon}.
26
+ * @param {Array<BeaconSignal>} signals The array of Beacon Signals to process.
27
+ * @param {SidecarData} sidecar The sidecar data associated with the SMT Beacon.
28
+ * @returns {Promise<Array<[SignedBTCR2Update, BlockMetadata]>>} The processed signals.
29
+ * @throws {SMTBeaconError} if processing fails.
54
30
  */
55
- async processSignals(): Promise<Array<[BTCR2SignedUpdate, BlockMetadata]>> {
56
- throw new MethodError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`);
31
+ processSignals(
32
+ signals: Array<BeaconSignal>,
33
+ sidecar: SidecarData
34
+ ): Promise<Array<[SignedBTCR2Update, BlockMetadata]>> {
35
+ throw new SMTBeaconError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signals, sidecar});
57
36
  }
58
37
 
59
-
60
38
  /**
61
- * Broadcast a SMTBeacon signal.
62
- * @param {HexString} updateHash The hash of the BTCR2 update to broadcast.
63
- * @returns {Promise<SignalsMetadata>} The result of the broadcast.
64
- * @throws {MethodError} if the broadcast fails.
39
+ * Broadcast CAS Beacon signal to the Bitcoin network.
40
+ * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
41
+ * @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
42
+ * @param {BitcoinNetworkConnection} bitcoin The Bitcoin network connection.
43
+ * @return {Promise<SignedBTCR2Update>} The signed update that was broadcasted.
44
+ * @throws {SMTBeaconError} if broadcasting fails.
65
45
  */
66
- async broadcastSignal(updateHash: HexString): Promise<HexString> {
67
- throw new MethodError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {updateHash});
46
+ async broadcastSignal(
47
+ signedUpdate: SignedBTCR2Update,
48
+ secretKey: KeyBytes,
49
+ bitcoin: BitcoinNetworkConnection
50
+ ): Promise<SignedBTCR2Update> {
51
+ throw new SMTBeaconError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signedUpdate, secretKey, bitcoin});
68
52
  }
69
-
70
53
  }
@@ -5,6 +5,7 @@ import { Appendix } from '../../utils/appendix.js';
5
5
  import { DidDocument } from '../../utils/did-document.js';
6
6
  import { Identifier } from '../identifier.js';
7
7
  import { BeaconService } from './interfaces.js';
8
+ import { BeaconError } from './error.js';
8
9
 
9
10
  /**
10
11
  * Static class of utility functions for the Beacon Service
@@ -40,9 +41,6 @@ export class BeaconUtils {
40
41
  // Return false if the serviceEndpoint is not a valid BIP21 bitcoin address.
41
42
  if ([obj.serviceEndpoint].flat().some(ep => typeof ep === 'string' && !ep.startsWith('bitcoin:'))) return false;
42
43
 
43
- // Return false if the casType exists and is not a string.
44
- if(obj.casType && typeof obj.casType !== 'string') return false;
45
-
46
44
  // Else return true
47
45
  return true;
48
46
  }
@@ -73,9 +71,11 @@ export class BeaconUtils {
73
71
  return addrTypes.map(
74
72
  (addrType) => this.createBeaconService(did, addrType, beaconType)
75
73
  );
76
- } catch (error) {
77
- console.error(error);
78
- process.exit(1);
74
+ } catch (error: any) {
75
+ throw new BeaconError(
76
+ 'Failed to create beacon services: ' + error.message,
77
+ 'BEACON_SERVICE_ERROR', { did, beaconType }
78
+ );
79
79
  }
80
80
  }
81
81
 
@@ -101,13 +101,14 @@ export class BeaconUtils {
101
101
  const serviceEndpoint = `bitcoin:${payments[addressType]({ pubkey, network }).address}`;
102
102
  // Return the beacon serviceD
103
103
  return { id, type: beaconType, serviceEndpoint, };
104
- } catch (error) {
105
- console.error(error);
106
- process.exit(1);
104
+ } catch (error: any) {
105
+ throw new BeaconError(
106
+ 'Failed to create beacon service: ' + error.message,
107
+ 'BEACON_SERVICE_ERROR', { did, beaconType }
108
+ );
107
109
  }
108
110
  }
109
111
 
110
-
111
112
  /**
112
113
  * Generate three default Beacon Service Endpoints for a given `k` (public-key-based) identifier.
113
114
  * @param {string} did The DID for which to create the beacon services.
@@ -147,9 +148,11 @@ export class BeaconUtils {
147
148
  serviceEndpoint : `bitcoin:${p2tr}`
148
149
  },
149
150
  ];
150
- } catch (error) {
151
- console.error(error);
152
- process.exit(1);
151
+ } catch (error: any) {
152
+ throw new BeaconError(
153
+ 'Failed to create beacon services: ' + error.message,
154
+ 'BEACON_SERVICE_ERROR', { id, publicKey, network, beaconType }
155
+ );
153
156
  }
154
157
  }
155
158
 
@@ -43,17 +43,9 @@ export interface ResolutionOptions extends ResolutionOptionsCore {
43
43
  /**
44
44
  * Drivers for interacting with external systems, such as the Bitcoin network.
45
45
  */
46
- drivers: {
46
+ drivers?: {
47
47
  bitcoin?: BitcoinNetworkConnection;
48
48
  };
49
-
50
- /**
51
- * Flag to signal a full blockchain search for beacon signals from genesis
52
- * block to chain tip during resolution, instead of using an indexer.
53
- * @type {boolean}
54
- * @default false
55
- */
56
- fullBlockchainTraversal?: boolean;
57
49
  }
58
50
 
59
51
  /**