@did-btcr2/api 0.3.1 → 0.5.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/dist/.tsbuildinfo +1 -0
- package/dist/browser.js +125576 -120390
- package/dist/browser.mjs +125637 -120451
- package/dist/cjs/index.js +2295 -14
- package/dist/esm/api.js +9 -10
- package/dist/esm/api.js.map +1 -1
- package/dist/esm/bitcoin.js.map +1 -1
- package/dist/esm/cas.js +68 -12
- package/dist/esm/cas.js.map +1 -1
- package/dist/esm/crypto.js.map +1 -1
- package/dist/esm/did.js.map +1 -1
- package/dist/esm/kms.js.map +1 -1
- package/dist/esm/method.js +5 -5
- package/dist/esm/method.js.map +1 -1
- package/dist/types/api.d.ts +8 -5
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/bitcoin.d.ts +2 -1
- package/dist/types/bitcoin.d.ts.map +1 -1
- package/dist/types/cas.d.ts +39 -5
- package/dist/types/cas.d.ts.map +1 -1
- package/dist/types/crypto.d.ts +4 -3
- package/dist/types/crypto.d.ts.map +1 -1
- package/dist/types/did.d.ts +1 -2
- package/dist/types/did.d.ts.map +1 -1
- package/dist/types/kms.d.ts +3 -2
- package/dist/types/kms.d.ts.map +1 -1
- package/dist/types/method.d.ts +5 -5
- package/dist/types/method.d.ts.map +1 -1
- package/dist/types/types.d.ts +0 -7
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/api.ts +11 -14
- package/src/bitcoin.ts +3 -2
- package/src/cas.ts +92 -13
- package/src/crypto.ts +10 -8
- package/src/did.ts +2 -2
- package/src/kms.ts +4 -3
- package/src/method.ts +9 -9
- package/src/types.ts +0 -7
- package/dist/cjs/api.js +0 -240
- package/dist/cjs/api.js.map +0 -1
- package/dist/cjs/bitcoin.js +0 -110
- package/dist/cjs/bitcoin.js.map +0 -1
- package/dist/cjs/cas.js +0 -90
- package/dist/cjs/cas.js.map +0 -1
- package/dist/cjs/crypto.js +0 -425
- package/dist/cjs/crypto.js.map +0 -1
- package/dist/cjs/did.js +0 -70
- package/dist/cjs/did.js.map +0 -1
- package/dist/cjs/helpers.js +0 -28
- package/dist/cjs/helpers.js.map +0 -1
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/kms.js +0 -73
- package/dist/cjs/kms.js.map +0 -1
- package/dist/cjs/method.js +0 -262
- package/dist/cjs/method.js.map +0 -1
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/types.js.map +0 -1
package/dist/types/method.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
1
|
+
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { DocumentBytes, HexString, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
-
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
4
|
import type { Btcr2DidDocument, DidCreateOptions, ResolutionOptions } from '@did-btcr2/method';
|
|
5
5
|
import type { DidResolutionResult, DidVerificationMethod } from '@web5/dids';
|
|
6
|
-
import { BitcoinApi } from './bitcoin.js';
|
|
7
|
-
import { CasApi } from './cas.js';
|
|
6
|
+
import type { BitcoinApi } from './bitcoin.js';
|
|
7
|
+
import type { CasApi } from './cas.js';
|
|
8
8
|
import type { Logger } from './types.js';
|
|
9
9
|
/**
|
|
10
10
|
* DID method operations sub-facade: create, resolve, update, deactivate.
|
|
@@ -33,7 +33,7 @@ export declare class DidMethodApi {
|
|
|
33
33
|
*/
|
|
34
34
|
createExternal(genesisBytes: DocumentBytes, options?: Omit<DidCreateOptions, 'idType'>): string;
|
|
35
35
|
/**
|
|
36
|
-
* Resolve a DID by driving the sans-I/O
|
|
36
|
+
* Resolve a DID by driving the sans-I/O `Resolver` state machine (from @did-btcr2/method).
|
|
37
37
|
* If a Bitcoin connection is configured on the API, it is used automatically
|
|
38
38
|
* to fetch beacon signals. Sidecar data flows through `options.sidecar`.
|
|
39
39
|
* @param did The DID to resolve.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"method.d.ts","sourceRoot":"","sources":["../../src/method.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"method.d.ts","sourceRoot":"","sources":["../../src/method.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAmB,gBAAgB,EAA8D,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE5K,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;GAMG;AACH,qBAAa,YAAY;;gBAKX,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAM3D;;;;;;OAMG;IACH,mBAAmB,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAAG,MAAM;IAKnG;;;;;;OAMG;IACH,cAAc,CAAC,YAAY,EAAE,aAAa,EAAE,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAAG,MAAM;IAKnG;;;;;;;OAOG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAqGrF;;;;;OAKG;IACG,MAAM,CAAC,EACX,cAAc,EACd,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,QAAQ,EACR,eAAe,EACf,OAAO,GACR,EAAE;QACD,cAAc,EAAE,gBAAgB,CAAC;QACjC,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;QACvC,OAAO,CAAC,EAAE,iBAAiB,CAAC;KAC7B,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAa9B;;;;;OAKG;IACH,gBAAgB,CAAC,WAAW,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,qBAAqB;IAIzF;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,cAAc,EAAE,gBAAgB,GAAG,aAAa;IAI5D,iEAAiE;IAC3D,UAAU,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAS/C;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;;IAUxB,gBAAgB;gBACJ,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB;IAKrE,uEAAuE;IACvE,KAAK,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAK/B,+DAA+D;IAC/D,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,IAAI;IAKpC,iCAAiC;IACjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKzB,uDAAuD;IACvD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK9B,qDAAqD;IACrD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK9B,0DAA0D;IAC1D,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI;IAKrD,uDAAuD;IACvD,WAAW,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI;IAKhD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAqB5C"}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type { CasConfig } from './cas.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* Pluggable logger interface. All methods are optional-call; the default
|
|
8
8
|
* implementation is a silent no-op.
|
|
9
|
-
* @public
|
|
10
9
|
*/
|
|
11
10
|
export type Logger = {
|
|
12
11
|
debug(message: string, ...args: unknown[]): void;
|
|
@@ -21,7 +20,6 @@ export type Logger = {
|
|
|
21
20
|
* than a union. This local alias provides compile-time safety at the API
|
|
22
21
|
* facade level. Upstream runtime validation in `Identifier.encode()` still
|
|
23
22
|
* catches invalid values.
|
|
24
|
-
* @public
|
|
25
23
|
*/
|
|
26
24
|
export type IdType = 'KEY' | 'EXTERNAL';
|
|
27
25
|
/**
|
|
@@ -35,14 +33,12 @@ export type IdType = 'KEY' | 'EXTERNAL';
|
|
|
35
33
|
* api.resolveDid(did); // OK
|
|
36
34
|
* api.btc.getTransaction(did); // Type error — DidString is not TxId
|
|
37
35
|
* ```
|
|
38
|
-
* @public
|
|
39
36
|
*/
|
|
40
37
|
export type DidString = string & {
|
|
41
38
|
readonly __brand: 'DidString';
|
|
42
39
|
};
|
|
43
40
|
/**
|
|
44
41
|
* A branded string representing a Bitcoin transaction ID (64-char hex).
|
|
45
|
-
* @public
|
|
46
42
|
*/
|
|
47
43
|
export type TxId = string & {
|
|
48
44
|
readonly __brand: 'TxId';
|
|
@@ -61,7 +57,6 @@ export type TxId = string & {
|
|
|
61
57
|
* console.log(result.error, result.errorMessage);
|
|
62
58
|
* }
|
|
63
59
|
* ```
|
|
64
|
-
* @public
|
|
65
60
|
*/
|
|
66
61
|
export type ResolutionResult = {
|
|
67
62
|
ok: true;
|
|
@@ -91,7 +86,6 @@ export type ResolutionResult = {
|
|
|
91
86
|
* // Use regtest with custom RPC credentials, default REST
|
|
92
87
|
* { network: 'regtest', rpc: { host: 'http://mynode:18443', username: 'u', password: 'p' } }
|
|
93
88
|
* ```
|
|
94
|
-
* @public
|
|
95
89
|
*/
|
|
96
90
|
export type BitcoinApiConfig = {
|
|
97
91
|
/** Bitcoin network name (e.g., 'regtest', 'testnet4', 'bitcoin'). */
|
|
@@ -116,7 +110,6 @@ export type BitcoinApiConfig = {
|
|
|
116
110
|
};
|
|
117
111
|
/**
|
|
118
112
|
* Top-level API configuration options.
|
|
119
|
-
* @public
|
|
120
113
|
*/
|
|
121
114
|
export type ApiConfig = {
|
|
122
115
|
btc?: BitcoinApiConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAExC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;IAAC,GAAG,EAAE,mBAAmB,CAAA;CAAE,GACzH;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAElF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qEAAqE;IACrE,OAAO,EAAE,WAAW,CAAC;IACrB,gEAAgE;IAChE,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3B,+DAA+D;IAC/D,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-btcr2/api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SDK for accessing the did:btcr2 method functionality.",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
"multiformats": "^13.3.1",
|
|
85
85
|
"nostr-tools": "^2.15.0",
|
|
86
86
|
"tiny-secp256k1": "^2.2.3",
|
|
87
|
-
"@did-btcr2/
|
|
88
|
-
"@did-btcr2/cryptosuite": "^6.0.
|
|
89
|
-
"@did-btcr2/
|
|
90
|
-
"@did-btcr2/
|
|
91
|
-
"@did-btcr2/kms": "^0.4.
|
|
92
|
-
"@did-btcr2/method": "^0.
|
|
87
|
+
"@did-btcr2/bitcoin": "^0.5.3",
|
|
88
|
+
"@did-btcr2/cryptosuite": "^6.0.6",
|
|
89
|
+
"@did-btcr2/common": "^9.0.0",
|
|
90
|
+
"@did-btcr2/keypair": "^0.11.4",
|
|
91
|
+
"@did-btcr2/kms": "^0.4.2",
|
|
92
|
+
"@did-btcr2/method": "^0.26.0"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@eslint/js": "^9.22.0",
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
"mocha-junit-reporter": "^2.2.1",
|
|
112
112
|
"node-stdlib-browser": "^1.3.1",
|
|
113
113
|
"rimraf": "^6.0.1",
|
|
114
|
+
"tsup": "^8.5.1",
|
|
114
115
|
"typedoc-plugin-markdown": "^4.7.0",
|
|
115
116
|
"typescript": "^5.6.2",
|
|
116
117
|
"typescript-eslint": "^8.19.1"
|
|
@@ -124,7 +125,7 @@
|
|
|
124
125
|
"reinstall": "pnpm install --force",
|
|
125
126
|
"build": "pnpm clean:build && pnpm build:esm && pnpm build:cjs && pnpm build:browser",
|
|
126
127
|
"build:esm": "rimraf dist/esm dist/types && pnpm tsc -p tsconfig.json",
|
|
127
|
-
"build:cjs": "
|
|
128
|
+
"build:cjs": "tsup && echo '{\"type\": \"commonjs\"}' > ./dist/cjs/package.json",
|
|
128
129
|
"build:browser": "rimraf dist/browser.mjs dist/browser.js && node build/bundles.js",
|
|
129
130
|
"build:tests": "pnpm clean:tests && pnpm tsc -p tests/tsconfig.json",
|
|
130
131
|
"build:all": "pnpm build && pnpm build:tests",
|
package/src/api.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { NetworkName } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { DocumentBytes, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
-
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
4
|
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
5
|
-
import { KeyIdentifier } from '@did-btcr2/kms';
|
|
5
|
+
import type { KeyIdentifier } from '@did-btcr2/kms';
|
|
6
6
|
import type { Btcr2DidDocument, DidCreateOptions, ResolutionOptions } from '@did-btcr2/method';
|
|
7
7
|
import type { DidResolutionResult } from '@web5/dids';
|
|
8
8
|
import { BitcoinApi } from './bitcoin.js';
|
|
9
|
-
import { CasApi, type CasConfig } from './cas.js';
|
|
9
|
+
import { CasApi, DEFAULT_CAS_GATEWAY, type CasConfig } from './cas.js';
|
|
10
10
|
import { CryptoApi } from './crypto.js';
|
|
11
11
|
import { DidApi } from './did.js';
|
|
12
12
|
import { assertString, NOOP_LOGGER } from './helpers.js';
|
|
@@ -67,19 +67,16 @@ export class DidBtcr2Api {
|
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* CAS API sub-facade (lazily initialized).
|
|
70
|
-
*
|
|
71
|
-
*
|
|
70
|
+
*
|
|
71
|
+
* When no `cas` config was provided to the constructor, defaults to a
|
|
72
|
+
* read-only {@link HttpGatewayCasExecutor} backed by the public IPFS
|
|
73
|
+
* gateway (`https://ipfs.io`). Override via `createApi({ cas: { ... } })`.
|
|
74
|
+
* @throws {Error} If the instance has been disposed.
|
|
72
75
|
*/
|
|
73
76
|
get cas(): CasApi {
|
|
74
77
|
this.#assertNotDisposed();
|
|
75
78
|
if (!this.#cas) {
|
|
76
|
-
|
|
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);
|
|
79
|
+
this.#cas = new CasApi(this.#casConfig ?? { gateway: DEFAULT_CAS_GATEWAY });
|
|
83
80
|
}
|
|
84
81
|
return this.#cas;
|
|
85
82
|
}
|
|
@@ -93,7 +90,7 @@ export class DidBtcr2Api {
|
|
|
93
90
|
if (!this.#btcr2) {
|
|
94
91
|
this.#btcr2 = new DidMethodApi(
|
|
95
92
|
this.#btcConfig ? this.btc : undefined,
|
|
96
|
-
this
|
|
93
|
+
this.cas,
|
|
97
94
|
this.#log
|
|
98
95
|
);
|
|
99
96
|
}
|
|
@@ -267,7 +264,7 @@ export class DidBtcr2Api {
|
|
|
267
264
|
* Release internal references. After disposal, accessing `btc`, `btcr2`,
|
|
268
265
|
* or calling top-level methods will throw.
|
|
269
266
|
*
|
|
270
|
-
* Note: the underlying
|
|
267
|
+
* Note: the underlying `BitcoinConnection` does not hold persistent
|
|
271
268
|
* connections, so this is primarily a guard against accidental reuse.
|
|
272
269
|
*/
|
|
273
270
|
dispose(): void {
|
package/src/bitcoin.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BitcoinCoreRpcClient,
|
|
3
|
+
BitcoinRestClient} from '@did-btcr2/bitcoin';
|
|
1
4
|
import {
|
|
2
5
|
BitcoinConnection,
|
|
3
|
-
BitcoinCoreRpcClient,
|
|
4
|
-
BitcoinRestClient,
|
|
5
6
|
type RawTransactionRest
|
|
6
7
|
} from '@did-btcr2/bitcoin';
|
|
7
8
|
import { assertString } from './helpers.js';
|
package/src/cas.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { HashBytes } from '@did-btcr2/common';
|
|
2
|
+
import { canonicalize, decode as decodeHash, encode as encodeHash } from '@did-btcr2/common';
|
|
2
3
|
import type { Helia } from 'helia';
|
|
3
4
|
import { CID } from 'multiformats/cid';
|
|
4
5
|
import * as raw from 'multiformats/codecs/raw';
|
|
5
6
|
import { create as createDigest } from 'multiformats/hashes/digest';
|
|
6
7
|
import { sha256 } from 'multiformats/hashes/sha2';
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
/** Default IPFS HTTP gateway used for CAS reads when no CAS config is provided. */
|
|
10
|
+
export const DEFAULT_CAS_GATEWAY = 'https://ipfs.io';
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Executor interface for content-addressed storage.
|
|
@@ -36,7 +39,7 @@ export class IpfsCasExecutor implements CasExecutor {
|
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
async retrieve(hash: string): Promise<Uint8Array | null> {
|
|
39
|
-
const hashBytes = decodeHash(hash, '
|
|
42
|
+
const hashBytes = decodeHash(hash, 'base64urlnopad');
|
|
40
43
|
const cid = CID.create(1, raw.code, createDigest(sha256.code, hashBytes));
|
|
41
44
|
try {
|
|
42
45
|
return await this.#helia.blockstore.get(cid);
|
|
@@ -55,15 +58,70 @@ export class IpfsCasExecutor implements CasExecutor {
|
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Read-only {@link CasExecutor} backed by an IPFS HTTP gateway.
|
|
63
|
+
*
|
|
64
|
+
* Converts the base64url SHA-256 hash to a CIDv1 (raw codec) and fetches
|
|
65
|
+
* the raw block via the
|
|
66
|
+
* {@link https://specs.ipfs.tech/http-gateways/trustless-gateway/ | Trustless Gateway}
|
|
67
|
+
* protocol.
|
|
68
|
+
*
|
|
69
|
+
* Publishing is not supported — use {@link IpfsCasExecutor} with a Helia
|
|
70
|
+
* instance for writes.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
export class HttpGatewayCasExecutor implements CasExecutor {
|
|
74
|
+
readonly #gatewayUrl: string;
|
|
75
|
+
|
|
76
|
+
constructor(gatewayUrl: string) {
|
|
77
|
+
this.#gatewayUrl = gatewayUrl.replace(/\/+$/, '');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async retrieve(hash: string): Promise<Uint8Array | null> {
|
|
81
|
+
const hashBytes = decodeHash(hash, 'base64urlnopad');
|
|
82
|
+
const cid = CID.create(1, raw.code, createDigest(sha256.code, hashBytes));
|
|
83
|
+
try {
|
|
84
|
+
const res = await fetch(`${this.#gatewayUrl}/ipfs/${cid.toString()}?format=raw`, {
|
|
85
|
+
headers : { Accept: 'application/vnd.ipld.raw' },
|
|
86
|
+
});
|
|
87
|
+
if (!res.ok) return null;
|
|
88
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async publish(): Promise<string> {
|
|
95
|
+
throw new Error(
|
|
96
|
+
'HttpGatewayCasExecutor is read-only. '
|
|
97
|
+
+ 'Publishing requires a full IPFS node (use IpfsCasExecutor with Helia).'
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Default timeout (ms) for CAS operations. */
|
|
103
|
+
export const DEFAULT_CAS_TIMEOUT_MS = 30_000;
|
|
104
|
+
|
|
58
105
|
/**
|
|
59
106
|
* Configuration for the CAS (Content-Addressed Storage) driver.
|
|
107
|
+
*
|
|
108
|
+
* Provide exactly one of `executor`, `helia`, or `gateway`.
|
|
109
|
+
* Priority if multiple are set: `executor` > `helia` > `gateway`.
|
|
60
110
|
* @public
|
|
61
111
|
*/
|
|
62
112
|
export type CasConfig = {
|
|
63
|
-
/** Custom executor implementation (overrides
|
|
113
|
+
/** Custom executor implementation (overrides all other options). */
|
|
64
114
|
executor?: CasExecutor;
|
|
65
115
|
/** Pre-existing Helia instance for the default IPFS executor. */
|
|
66
116
|
helia?: Helia;
|
|
117
|
+
/** IPFS HTTP gateway URL for read-only CAS access (e.g. `'https://ipfs.io'`). */
|
|
118
|
+
gateway?: string;
|
|
119
|
+
/**
|
|
120
|
+
* Timeout in milliseconds for CAS operations. Prevents indefinite hangs
|
|
121
|
+
* when a Helia DHT lookup or gateway request stalls. Default: 30 000 ms.
|
|
122
|
+
* Set to `0` to disable.
|
|
123
|
+
*/
|
|
124
|
+
timeoutMs?: number;
|
|
67
125
|
};
|
|
68
126
|
|
|
69
127
|
/**
|
|
@@ -81,28 +139,32 @@ export type CasConfig = {
|
|
|
81
139
|
*/
|
|
82
140
|
export class CasApi {
|
|
83
141
|
readonly #executor: CasExecutor;
|
|
142
|
+
readonly #timeoutMs: number;
|
|
84
143
|
|
|
85
144
|
constructor(config: CasConfig) {
|
|
86
145
|
if (config.executor) {
|
|
87
146
|
this.#executor = config.executor;
|
|
88
147
|
} else if (config.helia) {
|
|
89
148
|
this.#executor = new IpfsCasExecutor(config.helia);
|
|
149
|
+
} else if (config.gateway) {
|
|
150
|
+
this.#executor = new HttpGatewayCasExecutor(config.gateway);
|
|
90
151
|
} else {
|
|
91
152
|
throw new Error(
|
|
92
|
-
'CAS configuration requires
|
|
93
|
-
+ 'Example: createApi({ cas: {
|
|
153
|
+
'CAS configuration requires an executor, Helia instance, or gateway URL. '
|
|
154
|
+
+ 'Example: createApi({ cas: { gateway: \'https://ipfs.io\' } })'
|
|
94
155
|
);
|
|
95
156
|
}
|
|
157
|
+
this.#timeoutMs = config.timeoutMs ?? DEFAULT_CAS_TIMEOUT_MS;
|
|
96
158
|
}
|
|
97
159
|
|
|
98
160
|
/**
|
|
99
|
-
* Retrieve a JSON object from the CAS by its
|
|
100
|
-
* @param
|
|
161
|
+
* Retrieve a JSON object from the CAS by its SHA-256 hash bytes.
|
|
162
|
+
* @param hashBytes Raw SHA-256 hash bytes of the JCS-canonicalized object.
|
|
101
163
|
* @returns The parsed JSON object, or `null` if not found.
|
|
102
164
|
*/
|
|
103
|
-
async retrieve(
|
|
104
|
-
|
|
105
|
-
const bytes = await this.#executor.retrieve(hash);
|
|
165
|
+
async retrieve(hashBytes: HashBytes): Promise<object | null> {
|
|
166
|
+
const hash = encodeHash(hashBytes, 'base64urlnopad');
|
|
167
|
+
const bytes = await this.#withTimeout(this.#executor.retrieve(hash));
|
|
106
168
|
if (!bytes) return null;
|
|
107
169
|
return JSON.parse(new TextDecoder().decode(bytes)) as object;
|
|
108
170
|
}
|
|
@@ -110,12 +172,29 @@ export class CasApi {
|
|
|
110
172
|
/**
|
|
111
173
|
* Publish a JSON object to the CAS.
|
|
112
174
|
* The object is JCS-canonicalized before storage; the returned hash
|
|
113
|
-
* matches what
|
|
175
|
+
* matches what `canonicalHash` (from @did-btcr2/common) would produce.
|
|
114
176
|
* @param object The JSON object to publish.
|
|
115
177
|
* @returns The base64url-encoded SHA-256 hash (content address).
|
|
116
178
|
*/
|
|
117
179
|
async publish(object: object): Promise<string> {
|
|
118
180
|
const bytes = new TextEncoder().encode(canonicalize(object as Record<string, any>));
|
|
119
|
-
return await this.#executor.publish(bytes);
|
|
181
|
+
return await this.#withTimeout(this.#executor.publish(bytes));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Wraps a promise with a timeout. If `#timeoutMs` is 0, no timeout is applied.
|
|
186
|
+
*/
|
|
187
|
+
#withTimeout<T>(promise: Promise<T>): Promise<T> {
|
|
188
|
+
if (!this.#timeoutMs) return promise;
|
|
189
|
+
return new Promise<T>((resolve, reject) => {
|
|
190
|
+
const timer = setTimeout(
|
|
191
|
+
() => reject(new Error(`CAS operation timed out after ${this.#timeoutMs}ms`)),
|
|
192
|
+
this.#timeoutMs
|
|
193
|
+
);
|
|
194
|
+
promise.then(
|
|
195
|
+
(val) => { clearTimeout(timer); resolve(val); },
|
|
196
|
+
(err) => { clearTimeout(timer); reject(err); },
|
|
197
|
+
);
|
|
198
|
+
});
|
|
120
199
|
}
|
|
121
200
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import type { Bytes, Entropy, HexString, KeyBytes, SchnorrKeyPairObject, SignatureBytes } from '@did-btcr2/common';
|
|
2
|
-
import {
|
|
3
|
-
BIP340Cryptosuite,
|
|
4
|
-
BIP340DataIntegrityProof,
|
|
2
|
+
import type {
|
|
5
3
|
BTCR2Update,
|
|
6
4
|
DataIntegrityConfig,
|
|
7
5
|
DataIntegrityProofObject,
|
|
8
|
-
type FromPublicKey,
|
|
9
|
-
type Multikey,
|
|
10
|
-
SchnorrMultikey,
|
|
11
6
|
SignedBTCR2Update,
|
|
12
7
|
UnsignedBTCR2Update,
|
|
13
8
|
VerificationResult
|
|
14
9
|
} from '@did-btcr2/cryptosuite';
|
|
10
|
+
import {
|
|
11
|
+
BIP340Cryptosuite,
|
|
12
|
+
BIP340DataIntegrityProof,
|
|
13
|
+
type FromPublicKey,
|
|
14
|
+
type Multikey,
|
|
15
|
+
SchnorrMultikey
|
|
16
|
+
} from '@did-btcr2/cryptosuite';
|
|
15
17
|
import { CompressedSecp256k1PublicKey, SchnorrKeyPair, Secp256k1SecretKey } from '@did-btcr2/keypair';
|
|
16
|
-
import { KeyIdentifier } from '@did-btcr2/kms';
|
|
18
|
+
import type { KeyIdentifier } from '@did-btcr2/kms';
|
|
17
19
|
import type { DidVerificationMethod } from '@web5/dids';
|
|
18
|
-
import { KeyManagerApi } from './kms.js';
|
|
20
|
+
import type { KeyManagerApi } from './kms.js';
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Schnorr keypair operations.
|
package/src/did.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { DocumentBytes } from '@did-btcr2/common';
|
|
|
3
3
|
import { IdentifierTypes } from '@did-btcr2/common';
|
|
4
4
|
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
5
5
|
import type { SchnorrKeyPairObject } from '@did-btcr2/common';
|
|
6
|
-
import type { DidCreateOptions } from '@did-btcr2/method';
|
|
7
|
-
import { Identifier
|
|
6
|
+
import type { DidCreateOptions , IdentifierComponents } from '@did-btcr2/method';
|
|
7
|
+
import { Identifier } from '@did-btcr2/method';
|
|
8
8
|
import { Did } from '@web5/dids';
|
|
9
9
|
import { assertBytes, assertString } from './helpers.js';
|
|
10
10
|
|
package/src/kms.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Bytes, HashBytes, SignatureBytes } from '@did-btcr2/common';
|
|
2
|
-
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
|
+
import type { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
|
+
import type {
|
|
4
|
+
KeyIdentifier,
|
|
5
|
+
KeyManager} from '@did-btcr2/kms';
|
|
3
6
|
import {
|
|
4
7
|
type GenerateKeyOptions,
|
|
5
8
|
type ImportKeyOptions,
|
|
6
|
-
KeyIdentifier,
|
|
7
|
-
KeyManager,
|
|
8
9
|
Kms,
|
|
9
10
|
type SignOptions,
|
|
10
11
|
} from '@did-btcr2/kms';
|
package/src/method.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
1
|
+
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { DocumentBytes, HexString, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
-
import { IdentifierTypes, NotImplementedError } from '@did-btcr2/common';
|
|
4
|
-
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import { decode as decodeHash, IdentifierTypes, NotImplementedError } from '@did-btcr2/common';
|
|
4
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
5
5
|
import type { Btcr2DidDocument, CASAnnouncement, DidCreateOptions, NeedCASAnnouncement, NeedGenesisDocument, NeedSignedUpdate, ResolutionOptions } from '@did-btcr2/method';
|
|
6
6
|
import { BeaconSignalDiscovery, DidBtcr2 } from '@did-btcr2/method';
|
|
7
7
|
import type { DidResolutionResult, DidVerificationMethod } from '@web5/dids';
|
|
8
|
-
import { BitcoinApi } from './bitcoin.js';
|
|
9
|
-
import { CasApi } from './cas.js';
|
|
8
|
+
import type { BitcoinApi } from './bitcoin.js';
|
|
9
|
+
import type { CasApi } from './cas.js';
|
|
10
10
|
import { assertBytes, assertCompressedPubkey, assertString, NOOP_LOGGER } from './helpers.js';
|
|
11
11
|
import type { Logger } from './types.js';
|
|
12
12
|
|
|
@@ -53,7 +53,7 @@ export class DidMethodApi {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Resolve a DID by driving the sans-I/O
|
|
56
|
+
* Resolve a DID by driving the sans-I/O `Resolver` state machine (from @did-btcr2/method).
|
|
57
57
|
* If a Bitcoin connection is configured on the API, it is used automatically
|
|
58
58
|
* to fetch beacon signals. Sidecar data flows through `options.sidecar`.
|
|
59
59
|
* @param did The DID to resolve.
|
|
@@ -96,7 +96,7 @@ export class DidMethodApi {
|
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
98
|
this.#log.debug('Fetching genesis document from CAS: %s', need.genesisHash);
|
|
99
|
-
const doc = await this.#cas.retrieve(need.genesisHash);
|
|
99
|
+
const doc = await this.#cas.retrieve(decodeHash(need.genesisHash, 'hex'));
|
|
100
100
|
if(!doc) {
|
|
101
101
|
throw new Error(
|
|
102
102
|
`Genesis document not found in CAS (hash: ${need.genesisHash}).`
|
|
@@ -114,7 +114,7 @@ export class DidMethodApi {
|
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
this.#log.debug('Fetching CAS announcement from CAS: %s', need.announcementHash);
|
|
117
|
-
const announcement = await this.#cas.retrieve(need.announcementHash);
|
|
117
|
+
const announcement = await this.#cas.retrieve(decodeHash(need.announcementHash, 'hex'));
|
|
118
118
|
if(!announcement) {
|
|
119
119
|
throw new Error(
|
|
120
120
|
`CAS announcement not found in CAS (hash: ${need.announcementHash}).`
|
|
@@ -132,7 +132,7 @@ export class DidMethodApi {
|
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
this.#log.debug('Fetching signed update from CAS: %s', need.updateHash);
|
|
135
|
-
const update = await this.#cas.retrieve(need.updateHash);
|
|
135
|
+
const update = await this.#cas.retrieve(decodeHash(need.updateHash, 'hex'));
|
|
136
136
|
if(!update) {
|
|
137
137
|
throw new Error(
|
|
138
138
|
`Signed update not found in CAS (hash: ${need.updateHash}).`
|
package/src/types.ts
CHANGED
|
@@ -7,7 +7,6 @@ import type { CasConfig } from './cas.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* Pluggable logger interface. All methods are optional-call; the default
|
|
9
9
|
* implementation is a silent no-op.
|
|
10
|
-
* @public
|
|
11
10
|
*/
|
|
12
11
|
export type Logger = {
|
|
13
12
|
debug(message: string, ...args: unknown[]): void;
|
|
@@ -23,7 +22,6 @@ export type Logger = {
|
|
|
23
22
|
* than a union. This local alias provides compile-time safety at the API
|
|
24
23
|
* facade level. Upstream runtime validation in `Identifier.encode()` still
|
|
25
24
|
* catches invalid values.
|
|
26
|
-
* @public
|
|
27
25
|
*/
|
|
28
26
|
export type IdType = 'KEY' | 'EXTERNAL';
|
|
29
27
|
|
|
@@ -38,13 +36,11 @@ export type IdType = 'KEY' | 'EXTERNAL';
|
|
|
38
36
|
* api.resolveDid(did); // OK
|
|
39
37
|
* api.btc.getTransaction(did); // Type error — DidString is not TxId
|
|
40
38
|
* ```
|
|
41
|
-
* @public
|
|
42
39
|
*/
|
|
43
40
|
export type DidString = string & { readonly __brand: 'DidString' };
|
|
44
41
|
|
|
45
42
|
/**
|
|
46
43
|
* A branded string representing a Bitcoin transaction ID (64-char hex).
|
|
47
|
-
* @public
|
|
48
44
|
*/
|
|
49
45
|
export type TxId = string & { readonly __brand: 'TxId' };
|
|
50
46
|
|
|
@@ -62,7 +58,6 @@ export type TxId = string & { readonly __brand: 'TxId' };
|
|
|
62
58
|
* console.log(result.error, result.errorMessage);
|
|
63
59
|
* }
|
|
64
60
|
* ```
|
|
65
|
-
* @public
|
|
66
61
|
*/
|
|
67
62
|
export type ResolutionResult =
|
|
68
63
|
| { ok: true; document: Btcr2DidDocument; metadata: DidResolutionResult['didDocumentMetadata']; raw: DidResolutionResult }
|
|
@@ -85,7 +80,6 @@ export type ResolutionResult =
|
|
|
85
80
|
* // Use regtest with custom RPC credentials, default REST
|
|
86
81
|
* { network: 'regtest', rpc: { host: 'http://mynode:18443', username: 'u', password: 'p' } }
|
|
87
82
|
* ```
|
|
88
|
-
* @public
|
|
89
83
|
*/
|
|
90
84
|
export type BitcoinApiConfig = {
|
|
91
85
|
/** Bitcoin network name (e.g., 'regtest', 'testnet4', 'bitcoin'). */
|
|
@@ -111,7 +105,6 @@ export type BitcoinApiConfig = {
|
|
|
111
105
|
|
|
112
106
|
/**
|
|
113
107
|
* Top-level API configuration options.
|
|
114
|
-
* @public
|
|
115
108
|
*/
|
|
116
109
|
export type ApiConfig = {
|
|
117
110
|
btc?: BitcoinApiConfig;
|