@did-btcr2/api 0.1.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.
package/src/api.ts ADDED
@@ -0,0 +1,302 @@
1
+ import {
2
+ BitcoinCoreRpcClient,
3
+ BitcoinRestClient,
4
+ BlockV3,
5
+ RawTransactionV2,
6
+ RestClientConfigParams,
7
+ RpcClientConfig
8
+ } from '@did-btcr2/bitcoin';
9
+ import type {
10
+ Bytes,
11
+ CryptosuiteName,
12
+ DocumentBytes,
13
+ Entropy,
14
+ HashBytes,
15
+ Hex,
16
+ JSONObject,
17
+ KeyBytes,
18
+ PatchOperation,
19
+ ProofBytes,
20
+ SchnorrKeyPairObject,
21
+ SignatureBytes
22
+ } from '@did-btcr2/common';
23
+ import { DEFAULT_BLOCK_CONFIRMATIONS, DEFAULT_REST_CONFIG, DEFAULT_RPC_CONFIG, IdentifierTypes, NotImplementedError } from '@did-btcr2/common';
24
+ import type { MultikeyObject } from '@did-btcr2/cryptosuite';
25
+ import { SchnorrMultikey } from '@did-btcr2/cryptosuite';
26
+ import { SchnorrKeyPair, Secp256k1SecretKey } from '@did-btcr2/keypair';
27
+ import type { DidCreateOptions, DidResolutionOptions, SignalsMetadata, UpdateParams } from '@did-btcr2/method';
28
+ import { DidBtcr2, DidDocument, DidDocumentBuilder, Identifier } from '@did-btcr2/method';
29
+ import type { DidResolutionResult, DidService, DidVerificationMethod } from '@web5/dids';
30
+
31
+ export { DidDocument, DidDocumentBuilder, Identifier, IdentifierTypes };
32
+ export type {
33
+ BlockV3,
34
+ Bytes,
35
+ CryptosuiteName,
36
+ DidResolutionResult,
37
+ DidService,
38
+ DidVerificationMethod,
39
+ DocumentBytes,
40
+ HashBytes,
41
+ Hex,
42
+ JSONObject,
43
+ KeyBytes,
44
+ MultikeyObject,
45
+ PatchOperation,
46
+ ProofBytes,
47
+ RawTransactionV2,
48
+ RestClientConfigParams,
49
+ RpcClientConfig,
50
+ SchnorrKeyPairObject,
51
+ SignatureBytes
52
+ };
53
+
54
+ /* =========================
55
+ * Configuration Interfaces
56
+ * ========================= */
57
+
58
+ export type NetworkName = 'mainnet' | 'testnet4' | 'signet' | 'regtest';
59
+
60
+ export type BitcoinApiConfig = {
61
+ /** Shortcut to compute base URLs and params via @did-btcr2/bitcoin getNetwork */
62
+ network?: NetworkName;
63
+ /** Override REST client settings */
64
+ rest?: RestClientConfigParams;
65
+ /** Override RPC client settings */
66
+ rpc?: RpcClientConfig;
67
+ /** Default number of confirmations to consider "final" */
68
+ defaultConfirmations?: number;
69
+ };
70
+
71
+ export type ApiConfig = {
72
+ bitcoin?: BitcoinApiConfig;
73
+ };
74
+
75
+ /* =========================
76
+ * Sub-facade: KeyPair
77
+ * ========================= */
78
+
79
+ export class KeyPairApi {
80
+ /** Generate a new Schnorr keypair (secp256k1). */
81
+ static generate(): SchnorrKeyPair {
82
+ return new SchnorrKeyPair();
83
+ }
84
+
85
+ /** Import from secret key bytes or bigint. */
86
+ static fromSecret(ent: Entropy): SchnorrKeyPair {
87
+ const sk = new Secp256k1SecretKey(ent);
88
+ return new SchnorrKeyPair({ secretKey: sk });
89
+ }
90
+ }
91
+
92
+ export class MultikeyApi {
93
+ /**
94
+ * Create a Schnorr Multikey wrapper (includes verificationMethod, sign/verify).
95
+ * If secret is present, the multikey can sign.
96
+ */
97
+ static create(params: {
98
+ id: string;
99
+ controller: string;
100
+ keys: SchnorrKeyPair
101
+ }): SchnorrMultikey {
102
+ return new SchnorrMultikey(params);
103
+ }
104
+
105
+ /** Produce a DID Verification Method JSON from a multikey. */
106
+ static toVerificationMethod(mk: SchnorrMultikey): DidVerificationMethod {
107
+ return mk.toVerificationMethod();
108
+ }
109
+
110
+ /** Sign bytes via the multikey (requires secret). */
111
+ static async sign(mk: SchnorrMultikey, data: Bytes): Promise<SignatureBytes> {
112
+ return mk.sign(data);
113
+ }
114
+
115
+ /** Verify signature via multikey. */
116
+ static async verify(mk: SchnorrMultikey, data: Bytes, signature: SignatureBytes): Promise<boolean> {
117
+ return mk.verify(data, signature);
118
+ }
119
+ }
120
+
121
+ /* =========================
122
+ * Sub-facade: Crypto
123
+ * ========================= */
124
+
125
+ export class CryptoApi {
126
+ public static keyPairApi = new KeyPairApi();
127
+ public static multikeyApi = new MultikeyApi();
128
+ }
129
+
130
+ /* =========================
131
+ * Sub-facade: Bitcoin
132
+ * ========================= */
133
+
134
+ export class BitcoinApi {
135
+ readonly rest: BitcoinRestClient;
136
+ readonly rpc: BitcoinCoreRpcClient;
137
+ readonly defaultConfirmations: number;
138
+
139
+ constructor(cfg?: BitcoinApiConfig) {
140
+ const restCfg = {
141
+ host : cfg?.rest?.host ?? DEFAULT_REST_CONFIG.host,
142
+ ...cfg?.rest
143
+ };
144
+
145
+ const rpcCfg = {
146
+ ...DEFAULT_RPC_CONFIG,
147
+ ...cfg?.rpc
148
+ };
149
+
150
+ this.rest = new BitcoinRestClient(restCfg);
151
+ this.rpc = new BitcoinCoreRpcClient(rpcCfg);
152
+ this.defaultConfirmations = cfg?.defaultConfirmations ?? DEFAULT_BLOCK_CONFIRMATIONS;
153
+ }
154
+
155
+ /** Fetch a transaction by txid via REST. */
156
+ async getTransaction(txid: string) {
157
+ return await this.rest.transaction.get(txid);
158
+ }
159
+
160
+ /** Broadcast a raw tx (hex) via REST. */
161
+ async send(rawTxHex: string) {
162
+ return await this.rest.transaction.send(rawTxHex);
163
+ }
164
+
165
+ /** Get UTXOs for an address via REST. */
166
+ async getUtxos(address: string) {
167
+ return await this.rest.address.getUtxos(address);
168
+ }
169
+
170
+ /** Get a block by hash or height via REST. */
171
+ async getBlock(params: { hash?: string; height?: number }) {
172
+ return await this.rest.block.get({ blockhash: params.hash, height: params.height });
173
+ }
174
+ }
175
+
176
+ /* =========================
177
+ * Sub-facade: KeyManager
178
+ * ========================= */
179
+
180
+ // export class KeyManagerApi {
181
+ // readonly impl: IMethodKeyManager;
182
+
183
+ // constructor(params?: ApiKeyManagerConfig) {
184
+ // this.impl = new MethodKeyManager(params);
185
+ // }
186
+
187
+ // setActive(keyUri: string) {
188
+ // this.impl.activeKeyUri = keyUri;
189
+ // }
190
+
191
+ // export(keyUri: string) {
192
+ // return this.impl.export(keyUri);
193
+ // }
194
+
195
+ // import(mk: SchnorrMultikey, opts?: { importKey?: boolean; active?: boolean }) {
196
+ // return this.impl.import(mk, opts);
197
+ // }
198
+
199
+ // sign(keyUri: string, hash: HashBytes): Promise<SignatureBytes> {
200
+ // return this.impl.sign(keyUri, hash);
201
+ // }
202
+ // }
203
+
204
+ /* =========================
205
+ * Sub-facade: DID / CRUD
206
+ * ========================= */
207
+
208
+ export class DidApi {
209
+ /**
210
+ * Create a deterministic DID from a public key (bytes).
211
+ */
212
+ async createDeterministic({ genesisBytes, options }: {
213
+ genesisBytes: KeyBytes;
214
+ options: DidCreateOptions;
215
+ }) {
216
+ return await DidBtcr2.create({ idType: 'KEY', genesisBytes, options });
217
+ }
218
+
219
+ /**
220
+ * Create from an intermediate DID document (external genesis).
221
+ */
222
+ async createExternal({ genesisBytes, options }: {
223
+ genesisBytes: DocumentBytes;
224
+ options: DidCreateOptions;
225
+ }) {
226
+ return await DidBtcr2.create({ idType: 'KEY', genesisBytes, options });
227
+ }
228
+
229
+ /**
230
+ * Resolve DID document from DID (did:btcr2:...).
231
+ */
232
+ async resolve(did: string, options: DidResolutionOptions): Promise<DidResolutionResult> {
233
+ return await DidBtcr2.resolve(did, options);
234
+ }
235
+
236
+ /**
237
+ * Update a DID Document using a JSON Patch, signed as capabilityInvocation.
238
+ * You provide the prior DID Document (to pick VM), a JSON Patch, and a signer multikey.
239
+ * This delegates to MethodUpdate (which follows the cryptosuite rules internally).
240
+ */
241
+ async update({
242
+ identifier,
243
+ sourceDocument,
244
+ sourceVersionId,
245
+ patch,
246
+ verificationMethodId,
247
+ beaconIds
248
+ }: UpdateParams): Promise<SignalsMetadata> {
249
+ // The Update class exposes the algorithm that creates a DID Update Payload and proof;
250
+ // keep this wrapper narrow so testing can mock MethodUpdate directly.
251
+ const result = await DidBtcr2.update({
252
+ identifier,
253
+ sourceDocument,
254
+ sourceVersionId,
255
+ patch,
256
+ verificationMethodId,
257
+ beaconIds,
258
+ });
259
+ return result;
260
+ }
261
+
262
+ /** Deactivate convenience: applies the standard `deactivated: true` patch. */
263
+ async deactivate(): Promise<SignalsMetadata> {
264
+ // This class is a stub in method right now; expose a narrow wrapper for future expansion.
265
+ // return DidBtcr2.deactivate({ identifier, patch }); // No-op holder; implement when core adds behavior.
266
+ throw new NotImplementedError(
267
+ 'DidApi.deactivate is not implemented yet.',
268
+ {
269
+ type : 'DID_API_METHOD_NOT_IMPLEMENTED',
270
+ name : 'NOT_IMPLEMENTED_ERROR'
271
+ }
272
+ );
273
+ }
274
+ }
275
+
276
+ /* =========================
277
+ * Root facade
278
+ * ========================= */
279
+
280
+ export class DidBtcr2Api {
281
+ readonly bitcoin: BitcoinApi;
282
+ readonly did: DidApi;
283
+ readonly keys: KeyPairApi;
284
+ readonly crypto: CryptoApi;
285
+ // readonly keyManager: KeyManagerApi;
286
+
287
+ constructor(config?: ApiConfig) {
288
+ this.bitcoin = new BitcoinApi(config?.bitcoin);
289
+ this.did = new DidApi();
290
+ this.keys = new KeyPairApi();
291
+ this.crypto = new CryptoApi();
292
+ // this.keyManager = new KeyManagerApi(config?.keyManager);
293
+ }
294
+ }
295
+
296
+ /* =========================
297
+ * Factory
298
+ * ========================= */
299
+
300
+ export function createApi(config?: ApiConfig) {
301
+ return new DidBtcr2Api(config);
302
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './api.js';