@did-btcr2/api 0.2.1 → 0.3.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/README.md +1 -1
- package/dist/browser.js +149910 -127351
- package/dist/browser.mjs +149186 -126627
- package/dist/cjs/api.js +210 -150
- package/dist/cjs/api.js.map +1 -1
- package/dist/cjs/bitcoin.js +110 -0
- package/dist/cjs/bitcoin.js.map +1 -0
- package/dist/cjs/cas.js +90 -0
- package/dist/cjs/cas.js.map +1 -0
- package/dist/cjs/crypto.js +425 -0
- package/dist/cjs/crypto.js.map +1 -0
- package/dist/cjs/did.js +70 -0
- package/dist/cjs/did.js.map +1 -0
- package/dist/cjs/helpers.js +28 -0
- package/dist/cjs/helpers.js.map +1 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/kms.js +73 -0
- package/dist/cjs/kms.js.map +1 -0
- package/dist/cjs/method.js +262 -0
- package/dist/cjs/method.js.map +1 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/api.js +210 -150
- package/dist/esm/api.js.map +1 -1
- package/dist/esm/bitcoin.js +110 -0
- package/dist/esm/bitcoin.js.map +1 -0
- package/dist/esm/cas.js +90 -0
- package/dist/esm/cas.js.map +1 -0
- package/dist/esm/crypto.js +425 -0
- package/dist/esm/crypto.js.map +1 -0
- package/dist/esm/did.js +70 -0
- package/dist/esm/did.js.map +1 -0
- package/dist/esm/helpers.js +28 -0
- package/dist/esm/helpers.js.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/kms.js +73 -0
- package/dist/esm/kms.js.map +1 -0
- package/dist/esm/method.js +262 -0
- package/dist/esm/method.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/types/api.d.ts +107 -97
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/bitcoin.d.ts +64 -0
- package/dist/types/bitcoin.d.ts.map +1 -0
- package/dist/types/cas.d.ts +70 -0
- package/dist/types/cas.d.ts.map +1 -0
- package/dist/types/crypto.d.ts +310 -0
- package/dist/types/crypto.d.ts.map +1 -0
- package/dist/types/did.d.ts +51 -0
- package/dist/types/did.d.ts.map +1 -0
- package/dist/types/helpers.d.ts +10 -0
- package/dist/types/helpers.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/kms.d.ts +49 -0
- package/dist/types/kms.d.ts.map +1 -0
- package/dist/types/method.d.ts +117 -0
- package/dist/types/method.d.ts.map +1 -0
- package/dist/types/types.d.ts +128 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +7 -6
- package/src/api.ts +246 -262
- package/src/bitcoin.ts +129 -0
- package/src/cas.ts +121 -0
- package/src/crypto.ts +525 -0
- package/src/did.ts +75 -0
- package/src/helpers.ts +35 -0
- package/src/index.ts +37 -1
- package/src/kms.ts +95 -0
- package/src/method.ts +331 -0
- package/src/types.ts +122 -0
package/src/api.ts
CHANGED
|
@@ -1,313 +1,297 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from '
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import type { DidResolutionResult, DidService, DidVerificationMethod } from '@web5/dids';
|
|
32
|
-
|
|
33
|
-
export { DidDocument, DidDocumentBuilder, Identifier, IdentifierTypes };
|
|
34
|
-
export type {
|
|
35
|
-
BlockV3,
|
|
36
|
-
Bytes,
|
|
37
|
-
CryptosuiteName,
|
|
38
|
-
DidResolutionResult,
|
|
39
|
-
DidService,
|
|
40
|
-
DidVerificationMethod,
|
|
41
|
-
DocumentBytes,
|
|
42
|
-
HashBytes,
|
|
43
|
-
Hex,
|
|
44
|
-
JSONObject,
|
|
45
|
-
KeyBytes,
|
|
46
|
-
MultikeyObject,
|
|
47
|
-
PatchOperation,
|
|
48
|
-
ProofBytes,
|
|
49
|
-
RawTransactionV2,
|
|
50
|
-
RestClientConfigParams,
|
|
51
|
-
RpcClientConfig,
|
|
52
|
-
SchnorrKeyPairObject,
|
|
53
|
-
SignatureBytes
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/* =========================
|
|
57
|
-
* Configuration Interfaces
|
|
58
|
-
* ========================= */
|
|
59
|
-
|
|
60
|
-
export type NetworkName = 'mainnet' | 'testnet4' | 'signet' | 'regtest';
|
|
61
|
-
|
|
62
|
-
export type BitcoinApiConfig = {
|
|
63
|
-
/** Shortcut to compute base URLs and params via @did-btcr2/bitcoin getNetwork */
|
|
64
|
-
network?: NetworkName;
|
|
65
|
-
/** Override REST client settings */
|
|
66
|
-
rest?: RestClientConfigParams;
|
|
67
|
-
/** Override RPC client settings */
|
|
68
|
-
rpc?: RpcClientConfig;
|
|
69
|
-
/** Default number of confirmations to consider "final" */
|
|
70
|
-
defaultConfirmations?: number;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export type ApiConfig = {
|
|
74
|
-
bitcoin?: BitcoinApiConfig;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/* =========================
|
|
78
|
-
* Sub-facade: KeyPair
|
|
79
|
-
* ========================= */
|
|
1
|
+
import type { NetworkName } from '@did-btcr2/bitcoin';
|
|
2
|
+
import type { DocumentBytes, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
+
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
|
+
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
5
|
+
import { KeyIdentifier } from '@did-btcr2/kms';
|
|
6
|
+
import type { Btcr2DidDocument, DidCreateOptions, ResolutionOptions } from '@did-btcr2/method';
|
|
7
|
+
import type { DidResolutionResult } from '@web5/dids';
|
|
8
|
+
import { BitcoinApi } from './bitcoin.js';
|
|
9
|
+
import { CasApi, type CasConfig } from './cas.js';
|
|
10
|
+
import { CryptoApi } from './crypto.js';
|
|
11
|
+
import { DidApi } from './did.js';
|
|
12
|
+
import { assertString, NOOP_LOGGER } from './helpers.js';
|
|
13
|
+
import { KeyManagerApi } from './kms.js';
|
|
14
|
+
import { DidMethodApi } from './method.js';
|
|
15
|
+
import type { ApiConfig, BitcoinApiConfig, Logger, ResolutionResult } from './types.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Main DidBtcr2Api facade — the primary entry point for the SDK.
|
|
19
|
+
*
|
|
20
|
+
* Exposes sub-facades for Bitcoin, DID Method, KeyPair, Crypto, and
|
|
21
|
+
* KeyManager operations. Created via the {@link createApi} factory.
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export class DidBtcr2Api {
|
|
25
|
+
/** Cryptographic operations (keypair, multikey, cryptosuite, proof). */
|
|
26
|
+
readonly crypto: CryptoApi;
|
|
27
|
+
/** DID identifier operations (encode, decode, generate, parse). */
|
|
28
|
+
readonly did: DidApi;
|
|
29
|
+
/** Key management operations. */
|
|
30
|
+
readonly kms: KeyManagerApi;
|
|
80
31
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
32
|
+
#btcConfig?: BitcoinApiConfig;
|
|
33
|
+
#btc?: BitcoinApi;
|
|
34
|
+
#casConfig?: CasConfig;
|
|
35
|
+
#cas?: CasApi;
|
|
36
|
+
#btcr2?: DidMethodApi;
|
|
37
|
+
#log: Logger;
|
|
38
|
+
#disposed = false;
|
|
86
39
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
40
|
+
constructor(config?: ApiConfig) {
|
|
41
|
+
this.#btcConfig = config?.btc;
|
|
42
|
+
this.#casConfig = config?.cas;
|
|
43
|
+
this.#log = config?.logger ?? NOOP_LOGGER;
|
|
44
|
+
this.kms = new KeyManagerApi(config?.kms);
|
|
45
|
+
this.did = new DidApi();
|
|
46
|
+
this.crypto = new CryptoApi();
|
|
91
47
|
}
|
|
92
|
-
}
|
|
93
48
|
|
|
94
|
-
export class MultikeyApi {
|
|
95
49
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
50
|
+
* Bitcoin API sub-facade (lazily initialized).
|
|
51
|
+
* Only available when `btc` config was provided to the constructor.
|
|
52
|
+
* @throws {Error} If the instance has been disposed or no Bitcoin config was provided.
|
|
98
53
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/** Sign bytes via the multikey (requires secret). */
|
|
113
|
-
static async sign(mk: SchnorrMultikey, data: Bytes): Promise<SignatureBytes> {
|
|
114
|
-
return mk.sign(data);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Verify signature via multikey. */
|
|
118
|
-
static async verify(mk: SchnorrMultikey, data: Bytes, signature: SignatureBytes): Promise<boolean> {
|
|
119
|
-
return mk.verify(data, signature);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/* =========================
|
|
124
|
-
* Sub-facade: Crypto
|
|
125
|
-
* ========================= */
|
|
126
|
-
|
|
127
|
-
export class CryptoApi {
|
|
128
|
-
public static keyPairApi = new KeyPairApi();
|
|
129
|
-
public static multikeyApi = new MultikeyApi();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/* =========================
|
|
133
|
-
* Sub-facade: Bitcoin
|
|
134
|
-
* ========================= */
|
|
135
|
-
|
|
136
|
-
export class BitcoinApi {
|
|
137
|
-
readonly rest: BitcoinRestClient;
|
|
138
|
-
readonly rpc: BitcoinCoreRpcClient;
|
|
139
|
-
readonly defaultConfirmations: number;
|
|
140
|
-
|
|
141
|
-
constructor(cfg?: BitcoinApiConfig) {
|
|
142
|
-
const restCfg = {
|
|
143
|
-
host : cfg?.rest?.host ?? DEFAULT_REST_CONFIG.host,
|
|
144
|
-
...cfg?.rest
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const rpcCfg = {
|
|
148
|
-
...DEFAULT_RPC_CONFIG,
|
|
149
|
-
...cfg?.rpc
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
this.rest = new BitcoinRestClient(restCfg);
|
|
153
|
-
this.rpc = new BitcoinCoreRpcClient(rpcCfg);
|
|
154
|
-
this.defaultConfirmations = cfg?.defaultConfirmations ?? DEFAULT_BLOCK_CONFIRMATIONS;
|
|
54
|
+
get btc(): BitcoinApi {
|
|
55
|
+
this.#assertNotDisposed();
|
|
56
|
+
if (!this.#btc) {
|
|
57
|
+
if (!this.#btcConfig) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
'Bitcoin not configured. Pass a btc config to createApi(), e.g.: '
|
|
60
|
+
+ 'createApi({ btc: { network: \'regtest\' } })'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
this.#btc = new BitcoinApi(this.#btcConfig);
|
|
64
|
+
}
|
|
65
|
+
return this.#btc;
|
|
155
66
|
}
|
|
156
67
|
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
|
|
68
|
+
/**
|
|
69
|
+
* CAS API sub-facade (lazily initialized).
|
|
70
|
+
* Only available when `cas` config was provided to the constructor.
|
|
71
|
+
* @throws {Error} If the instance has been disposed or no CAS config was provided.
|
|
72
|
+
*/
|
|
73
|
+
get cas(): CasApi {
|
|
74
|
+
this.#assertNotDisposed();
|
|
75
|
+
if (!this.#cas) {
|
|
76
|
+
if (!this.#casConfig) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
'CAS not configured. Pass a cas config to createApi(), e.g.: '
|
|
79
|
+
+ 'createApi({ cas: { helia: await createHelia() } })'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
this.#cas = new CasApi(this.#casConfig);
|
|
83
|
+
}
|
|
84
|
+
return this.#cas;
|
|
160
85
|
}
|
|
161
86
|
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
87
|
+
/**
|
|
88
|
+
* DID Method API sub-facade (lazily initialized with bitcoin + CAS wiring).
|
|
89
|
+
* @throws {Error} If the instance has been disposed.
|
|
90
|
+
*/
|
|
91
|
+
get btcr2(): DidMethodApi {
|
|
92
|
+
this.#assertNotDisposed();
|
|
93
|
+
if (!this.#btcr2) {
|
|
94
|
+
this.#btcr2 = new DidMethodApi(
|
|
95
|
+
this.#btcConfig ? this.btc : undefined,
|
|
96
|
+
this.#casConfig ? this.cas : undefined,
|
|
97
|
+
this.#log
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return this.#btcr2;
|
|
165
101
|
}
|
|
166
102
|
|
|
167
|
-
/**
|
|
168
|
-
|
|
169
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Whether this API instance has been disposed.
|
|
105
|
+
*/
|
|
106
|
+
get disposed(): boolean {
|
|
107
|
+
return this.#disposed;
|
|
170
108
|
}
|
|
171
109
|
|
|
172
|
-
/**
|
|
173
|
-
|
|
174
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Create a DID using either deterministic (KEY) or external (EXTERNAL) mode.
|
|
112
|
+
* @param type The creation mode.
|
|
113
|
+
* @param genesisBytes Public key bytes (deterministic) or document bytes (external).
|
|
114
|
+
* @param options Creation options (idType is set for you).
|
|
115
|
+
* @returns The created DID identifier string.
|
|
116
|
+
*/
|
|
117
|
+
createDid(
|
|
118
|
+
type: 'deterministic' | 'external',
|
|
119
|
+
genesisBytes: KeyBytes | DocumentBytes,
|
|
120
|
+
options?: Omit<DidCreateOptions, 'idType'>
|
|
121
|
+
): string {
|
|
122
|
+
this.#assertNotDisposed();
|
|
123
|
+
return type === 'deterministic'
|
|
124
|
+
? this.btcr2.createDeterministic(genesisBytes as KeyBytes, options)
|
|
125
|
+
: this.btcr2.createExternal(genesisBytes as DocumentBytes, options);
|
|
175
126
|
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/* =========================
|
|
179
|
-
* Sub-facade: KeyManager
|
|
180
|
-
* ========================= */
|
|
181
|
-
|
|
182
|
-
// export class KeyManagerApi {
|
|
183
|
-
// readonly impl: IMethodKeyManager;
|
|
184
|
-
|
|
185
|
-
// constructor(params?: ApiKeyManagerConfig) {
|
|
186
|
-
// this.impl = new MethodKeyManager(params);
|
|
187
|
-
// }
|
|
188
127
|
|
|
189
|
-
// setActive(keyUri: string) {
|
|
190
|
-
// this.impl.activeKeyUri = keyUri;
|
|
191
|
-
// }
|
|
192
|
-
|
|
193
|
-
// export(keyUri: string) {
|
|
194
|
-
// return this.impl.export(keyUri);
|
|
195
|
-
// }
|
|
196
|
-
|
|
197
|
-
// import(mk: SchnorrMultikey, opts?: { importKey?: boolean; active?: boolean }) {
|
|
198
|
-
// return this.impl.import(mk, opts);
|
|
199
|
-
// }
|
|
200
|
-
|
|
201
|
-
// sign(keyUri: string, hash: HashBytes): Promise<SignatureBytes> {
|
|
202
|
-
// return this.impl.sign(keyUri, hash);
|
|
203
|
-
// }
|
|
204
|
-
// }
|
|
205
|
-
|
|
206
|
-
/* =========================
|
|
207
|
-
* Sub-facade: DID / CRUD
|
|
208
|
-
* ========================= */
|
|
209
|
-
|
|
210
|
-
export class DidApi {
|
|
211
128
|
/**
|
|
212
|
-
*
|
|
129
|
+
* Generate a new DID, create the keypair, and import it into the KMS.
|
|
130
|
+
* @param options Optional settings.
|
|
131
|
+
* @param options.setActive Whether to set the imported key as active in the KMS (default `true`).
|
|
132
|
+
* @param options.network Network for the generated DID (default `'regtest'`).
|
|
133
|
+
* @returns The generated DID string and KMS key identifier.
|
|
213
134
|
*/
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
options
|
|
217
|
-
|
|
218
|
-
|
|
135
|
+
generateDid(options?: { setActive?: boolean; network?: NetworkName }): { did: string; keyId: KeyIdentifier } {
|
|
136
|
+
this.#assertNotDisposed();
|
|
137
|
+
const { keyPair, did } = this.did.generate(options?.network);
|
|
138
|
+
const kp = SchnorrKeyPair.fromJSON(keyPair);
|
|
139
|
+
const keyId = this.kms.import(kp, { setActive: options?.setActive ?? true });
|
|
140
|
+
return { did, keyId };
|
|
219
141
|
}
|
|
220
142
|
|
|
221
143
|
/**
|
|
222
|
-
*
|
|
144
|
+
* Resolve a DID, automatically injecting the configured Bitcoin connection.
|
|
145
|
+
* @param did The DID to resolve.
|
|
146
|
+
* @param options Optional resolution options.
|
|
147
|
+
* @returns The resolution result.
|
|
223
148
|
*/
|
|
224
|
-
async
|
|
225
|
-
|
|
226
|
-
options
|
|
227
|
-
}) {
|
|
228
|
-
return DidBtcr2.create(genesisBytes, options);
|
|
149
|
+
async resolveDid(did: string, options?: ResolutionOptions): Promise<DidResolutionResult> {
|
|
150
|
+
this.#assertNotDisposed();
|
|
151
|
+
return await this.btcr2.resolve(did, options);
|
|
229
152
|
}
|
|
230
153
|
|
|
231
154
|
/**
|
|
232
|
-
* Resolve DID
|
|
155
|
+
* Resolve a DID and return a discriminated result instead of throwing.
|
|
156
|
+
* Useful when resolution failure is an expected outcome (e.g. checking
|
|
157
|
+
* whether a DID exists before creating it).
|
|
158
|
+
* @param did The DID to resolve.
|
|
159
|
+
* @param options Optional resolution options.
|
|
160
|
+
* @returns A {@link ResolutionResult} with `ok: true` on success or
|
|
161
|
+
* `ok: false` with error details on failure.
|
|
233
162
|
*/
|
|
234
|
-
async
|
|
235
|
-
|
|
163
|
+
async tryResolveDid(did: string, options?: ResolutionOptions): Promise<ResolutionResult> {
|
|
164
|
+
this.#assertNotDisposed();
|
|
165
|
+
assertString(did, 'did');
|
|
166
|
+
try {
|
|
167
|
+
const raw = await this.btcr2.resolve(did, options);
|
|
168
|
+
if (raw.didDocument) {
|
|
169
|
+
return {
|
|
170
|
+
ok : true,
|
|
171
|
+
document : raw.didDocument as Btcr2DidDocument,
|
|
172
|
+
metadata : raw.didDocumentMetadata,
|
|
173
|
+
raw,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
ok : false,
|
|
178
|
+
error : raw.didResolutionMetadata?.error ?? 'unknown',
|
|
179
|
+
errorMessage : raw.didResolutionMetadata?.errorMessage as string | undefined,
|
|
180
|
+
raw,
|
|
181
|
+
};
|
|
182
|
+
} catch (err: any) {
|
|
183
|
+
return {
|
|
184
|
+
ok : false,
|
|
185
|
+
error : 'internalError',
|
|
186
|
+
errorMessage : err.message,
|
|
187
|
+
raw : {
|
|
188
|
+
didDocument : null,
|
|
189
|
+
didDocumentMetadata : {},
|
|
190
|
+
didResolutionMetadata : { error: 'internalError', errorMessage: err.message },
|
|
191
|
+
} as unknown as DidResolutionResult,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
236
194
|
}
|
|
237
195
|
|
|
238
196
|
/**
|
|
239
|
-
* Update a DID
|
|
240
|
-
*
|
|
241
|
-
*
|
|
197
|
+
* Update a DID document: resolve the current state, apply patches, sign, and announce.
|
|
198
|
+
* Automatically injects the configured Bitcoin connection.
|
|
199
|
+
*
|
|
200
|
+
* If `sourceDocument` and `sourceVersionId` are both provided, resolution
|
|
201
|
+
* is skipped. Otherwise the DID is resolved first to obtain them.
|
|
202
|
+
* @param params The update parameters.
|
|
203
|
+
* @returns The signed update.
|
|
242
204
|
*/
|
|
243
|
-
async
|
|
244
|
-
|
|
205
|
+
async updateDid({
|
|
206
|
+
did,
|
|
245
207
|
patches,
|
|
246
|
-
sourceVersionId,
|
|
247
208
|
verificationMethodId,
|
|
248
209
|
beaconId,
|
|
249
|
-
|
|
250
|
-
|
|
210
|
+
sourceDocument,
|
|
211
|
+
sourceVersionId,
|
|
251
212
|
}: {
|
|
252
|
-
|
|
213
|
+
did: string;
|
|
253
214
|
patches: PatchOperation[];
|
|
254
|
-
sourceVersionId: number;
|
|
255
215
|
verificationMethodId: string;
|
|
256
216
|
beaconId: string;
|
|
257
|
-
|
|
258
|
-
|
|
217
|
+
sourceDocument?: Btcr2DidDocument;
|
|
218
|
+
sourceVersionId?: number;
|
|
259
219
|
}): Promise<SignedBTCR2Update> {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
220
|
+
this.#assertNotDisposed();
|
|
221
|
+
assertString(did, 'did');
|
|
222
|
+
|
|
223
|
+
let doc = sourceDocument;
|
|
224
|
+
let versionId = sourceVersionId;
|
|
225
|
+
|
|
226
|
+
if (!doc || versionId === undefined) {
|
|
227
|
+
const resolution = await this.resolveDid(did);
|
|
228
|
+
if (!resolution.didDocument) {
|
|
229
|
+
const meta = resolution.didResolutionMetadata;
|
|
230
|
+
const detail = meta?.error ? `: ${meta.error}` : '.';
|
|
231
|
+
const extra = meta?.errorMessage ? ` ${meta.errorMessage}` : '';
|
|
232
|
+
throw new Error(
|
|
233
|
+
`Failed to resolve DID ${did} for update${detail}${extra}`,
|
|
234
|
+
{ cause: meta }
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
doc = doc ?? resolution.didDocument as Btcr2DidDocument;
|
|
238
|
+
|
|
239
|
+
if (versionId === undefined) {
|
|
240
|
+
const rawVersionId = resolution.didDocumentMetadata?.versionId;
|
|
241
|
+
if (rawVersionId === undefined || rawVersionId === null) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`Resolution of DID ${did} succeeded but returned no versionId in metadata. `
|
|
244
|
+
+ 'Provide sourceVersionId explicitly.'
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
const parsed = Number(rawVersionId);
|
|
248
|
+
if (!Number.isFinite(parsed)) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`Resolution of DID ${did} returned a non-numeric versionId: ${String(rawVersionId)}.`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
versionId = parsed;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return await this.btcr2.update({
|
|
258
|
+
sourceDocument : doc,
|
|
264
259
|
patches,
|
|
265
|
-
sourceVersionId,
|
|
260
|
+
sourceVersionId : versionId,
|
|
266
261
|
verificationMethodId,
|
|
267
262
|
beaconId,
|
|
268
|
-
signingMaterial,
|
|
269
|
-
bitcoin,
|
|
270
263
|
});
|
|
271
264
|
}
|
|
272
265
|
|
|
273
|
-
/**
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Release internal references. After disposal, accessing `btc`, `btcr2`,
|
|
268
|
+
* or calling top-level methods will throw.
|
|
269
|
+
*
|
|
270
|
+
* Note: the underlying {@link BitcoinConnection} does not hold persistent
|
|
271
|
+
* connections, so this is primarily a guard against accidental reuse.
|
|
272
|
+
*/
|
|
273
|
+
dispose(): void {
|
|
274
|
+
this.#btc = undefined;
|
|
275
|
+
this.#cas = undefined;
|
|
276
|
+
this.#btcr2 = undefined;
|
|
277
|
+
this.#btcConfig = undefined;
|
|
278
|
+
this.#casConfig = undefined;
|
|
279
|
+
this.#disposed = true;
|
|
284
280
|
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/* =========================
|
|
288
|
-
* Root facade
|
|
289
|
-
* ========================= */
|
|
290
281
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
readonly crypto: CryptoApi;
|
|
296
|
-
// readonly keyManager: KeyManagerApi;
|
|
297
|
-
|
|
298
|
-
constructor(config?: ApiConfig) {
|
|
299
|
-
this.bitcoin = new BitcoinApi(config?.bitcoin);
|
|
300
|
-
this.did = new DidApi();
|
|
301
|
-
this.keys = new KeyPairApi();
|
|
302
|
-
this.crypto = new CryptoApi();
|
|
303
|
-
// this.keyManager = new KeyManagerApi(config?.keyManager);
|
|
282
|
+
#assertNotDisposed(): void {
|
|
283
|
+
if (this.#disposed) {
|
|
284
|
+
throw new Error('This DidBtcr2Api instance has been disposed and can no longer be used.');
|
|
285
|
+
}
|
|
304
286
|
}
|
|
305
287
|
}
|
|
306
288
|
|
|
307
|
-
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
|
|
311
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Create a new {@link DidBtcr2Api} instance with the given configuration.
|
|
291
|
+
* @param config Optional configuration for the API.
|
|
292
|
+
* @returns The created DidBtcr2Api instance.
|
|
293
|
+
* @public
|
|
294
|
+
*/
|
|
295
|
+
export function createApi(config?: ApiConfig): DidBtcr2Api {
|
|
312
296
|
return new DidBtcr2Api(config);
|
|
313
297
|
}
|