@did-btcr2/api 0.4.0 → 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 -1
- package/dist/browser.js +65 -17
- package/dist/browser.mjs +65 -17
- package/dist/cjs/index.js +68 -12
- package/dist/esm/api.js +8 -9
- package/dist/esm/api.js.map +1 -1
- package/dist/esm/cas.js +61 -4
- package/dist/esm/cas.js.map +1 -1
- package/dist/types/api.d.ts +5 -2
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/cas.d.ts +34 -1
- package/dist/types/cas.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 +2 -2
- package/src/api.ts +8 -11
- package/src/cas.ts +84 -5
- package/src/types.ts +0 -7
package/dist/browser.js
CHANGED
|
@@ -12359,12 +12359,15 @@ var BTCR2 = (() => {
|
|
|
12359
12359
|
CasApi: () => CasApi,
|
|
12360
12360
|
CryptoApi: () => CryptoApi,
|
|
12361
12361
|
CryptosuiteApi: () => CryptosuiteApi,
|
|
12362
|
+
DEFAULT_CAS_GATEWAY: () => DEFAULT_CAS_GATEWAY,
|
|
12363
|
+
DEFAULT_CAS_TIMEOUT_MS: () => DEFAULT_CAS_TIMEOUT_MS,
|
|
12362
12364
|
DataIntegrityProofApi: () => DataIntegrityProofApi,
|
|
12363
12365
|
DidApi: () => DidApi,
|
|
12364
12366
|
DidBtcr2Api: () => DidBtcr2Api,
|
|
12365
12367
|
DidDocument: () => DidDocument,
|
|
12366
12368
|
DidDocumentBuilder: () => DidDocumentBuilder,
|
|
12367
12369
|
DidMethodApi: () => DidMethodApi,
|
|
12370
|
+
HttpGatewayCasExecutor: () => HttpGatewayCasExecutor,
|
|
12368
12371
|
Identifier: () => Identifier,
|
|
12369
12372
|
IdentifierTypes: () => IdentifierTypes2,
|
|
12370
12373
|
IpfsCasExecutor: () => IpfsCasExecutor,
|
|
@@ -146254,7 +146257,6 @@ a=end-of-candidates
|
|
|
146254
146257
|
...config.headers
|
|
146255
146258
|
};
|
|
146256
146259
|
}
|
|
146257
|
-
// ── validation ─────────────────────────────────────────────────────
|
|
146258
146260
|
static assertHex64(value4, label) {
|
|
146259
146261
|
if (!HEX64_RE.test(value4)) {
|
|
146260
146262
|
throw new Error(`Invalid ${label}: expected 64-char hex string`);
|
|
@@ -146265,7 +146267,6 @@ a=end-of-candidates
|
|
|
146265
146267
|
throw new Error("Invalid address: contains illegal characters");
|
|
146266
146268
|
}
|
|
146267
146269
|
}
|
|
146268
|
-
// ── helpers ──────────────────────────────────────────────────────────
|
|
146269
146270
|
get(path) {
|
|
146270
146271
|
return {
|
|
146271
146272
|
url: `${this.baseUrl}${path}`,
|
|
@@ -146281,7 +146282,6 @@ a=end-of-candidates
|
|
|
146281
146282
|
body
|
|
146282
146283
|
};
|
|
146283
146284
|
}
|
|
146284
|
-
// ── Transaction ──────────────────────────────────────────────────────
|
|
146285
146285
|
/** GET /tx/:txid */
|
|
146286
146286
|
getTx(txid) {
|
|
146287
146287
|
_EsploraProtocol.assertHex64(txid, "txid");
|
|
@@ -146301,7 +146301,6 @@ a=end-of-candidates
|
|
|
146301
146301
|
postTx(hex3) {
|
|
146302
146302
|
return this.post("/tx", hex3, { "Content-Type": "text/plain" });
|
|
146303
146303
|
}
|
|
146304
|
-
// ── Block ────────────────────────────────────────────────────────────
|
|
146305
146304
|
/** GET /blocks/tip/height */
|
|
146306
146305
|
getBlockTipHeight() {
|
|
146307
146306
|
return this.get("/blocks/tip/height");
|
|
@@ -146315,7 +146314,6 @@ a=end-of-candidates
|
|
|
146315
146314
|
getBlockHeight(height) {
|
|
146316
146315
|
return this.get(`/block-height/${height}`);
|
|
146317
146316
|
}
|
|
146318
|
-
// ── Address ──────────────────────────────────────────────────────────
|
|
146319
146317
|
/** GET /address/:address/txs */
|
|
146320
146318
|
getAddressTxs(address) {
|
|
146321
146319
|
_EsploraProtocol.assertAddress(address);
|
|
@@ -152636,6 +152634,7 @@ a=end-of-candidates
|
|
|
152636
152634
|
});
|
|
152637
152635
|
|
|
152638
152636
|
// src/cas.ts
|
|
152637
|
+
var DEFAULT_CAS_GATEWAY = "https://ipfs.io";
|
|
152639
152638
|
var IpfsCasExecutor = class {
|
|
152640
152639
|
#helia;
|
|
152641
152640
|
constructor(helia) {
|
|
@@ -152657,18 +152656,47 @@ a=end-of-candidates
|
|
|
152657
152656
|
return btoa(String.fromCharCode(...digest2.bytes.slice(2))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
152658
152657
|
}
|
|
152659
152658
|
};
|
|
152659
|
+
var HttpGatewayCasExecutor = class {
|
|
152660
|
+
#gatewayUrl;
|
|
152661
|
+
constructor(gatewayUrl) {
|
|
152662
|
+
this.#gatewayUrl = gatewayUrl.replace(/\/+$/, "");
|
|
152663
|
+
}
|
|
152664
|
+
async retrieve(hash4) {
|
|
152665
|
+
const hashBytes = decode25(hash4, "base64urlnopad");
|
|
152666
|
+
const cid = CID3.create(1, code8, create7(sha25611.code, hashBytes));
|
|
152667
|
+
try {
|
|
152668
|
+
const res = await fetch(`${this.#gatewayUrl}/ipfs/${cid.toString()}?format=raw`, {
|
|
152669
|
+
headers: { Accept: "application/vnd.ipld.raw" }
|
|
152670
|
+
});
|
|
152671
|
+
if (!res.ok) return null;
|
|
152672
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
152673
|
+
} catch {
|
|
152674
|
+
return null;
|
|
152675
|
+
}
|
|
152676
|
+
}
|
|
152677
|
+
async publish() {
|
|
152678
|
+
throw new Error(
|
|
152679
|
+
"HttpGatewayCasExecutor is read-only. Publishing requires a full IPFS node (use IpfsCasExecutor with Helia)."
|
|
152680
|
+
);
|
|
152681
|
+
}
|
|
152682
|
+
};
|
|
152683
|
+
var DEFAULT_CAS_TIMEOUT_MS = 3e4;
|
|
152660
152684
|
var CasApi = class {
|
|
152661
152685
|
#executor;
|
|
152686
|
+
#timeoutMs;
|
|
152662
152687
|
constructor(config) {
|
|
152663
152688
|
if (config.executor) {
|
|
152664
152689
|
this.#executor = config.executor;
|
|
152665
152690
|
} else if (config.helia) {
|
|
152666
152691
|
this.#executor = new IpfsCasExecutor(config.helia);
|
|
152692
|
+
} else if (config.gateway) {
|
|
152693
|
+
this.#executor = new HttpGatewayCasExecutor(config.gateway);
|
|
152667
152694
|
} else {
|
|
152668
152695
|
throw new Error(
|
|
152669
|
-
"CAS configuration requires
|
|
152696
|
+
"CAS configuration requires an executor, Helia instance, or gateway URL. Example: createApi({ cas: { gateway: 'https://ipfs.io' } })"
|
|
152670
152697
|
);
|
|
152671
152698
|
}
|
|
152699
|
+
this.#timeoutMs = config.timeoutMs ?? DEFAULT_CAS_TIMEOUT_MS;
|
|
152672
152700
|
}
|
|
152673
152701
|
/**
|
|
152674
152702
|
* Retrieve a JSON object from the CAS by its SHA-256 hash bytes.
|
|
@@ -152677,7 +152705,7 @@ a=end-of-candidates
|
|
|
152677
152705
|
*/
|
|
152678
152706
|
async retrieve(hashBytes) {
|
|
152679
152707
|
const hash4 = encode23(hashBytes, "base64urlnopad");
|
|
152680
|
-
const bytes5 = await this.#executor.retrieve(hash4);
|
|
152708
|
+
const bytes5 = await this.#withTimeout(this.#executor.retrieve(hash4));
|
|
152681
152709
|
if (!bytes5) return null;
|
|
152682
152710
|
return JSON.parse(new TextDecoder().decode(bytes5));
|
|
152683
152711
|
}
|
|
@@ -152690,7 +152718,29 @@ a=end-of-candidates
|
|
|
152690
152718
|
*/
|
|
152691
152719
|
async publish(object3) {
|
|
152692
152720
|
const bytes5 = new TextEncoder().encode(canonicalize6(object3));
|
|
152693
|
-
return await this.#executor.publish(bytes5);
|
|
152721
|
+
return await this.#withTimeout(this.#executor.publish(bytes5));
|
|
152722
|
+
}
|
|
152723
|
+
/**
|
|
152724
|
+
* Wraps a promise with a timeout. If `#timeoutMs` is 0, no timeout is applied.
|
|
152725
|
+
*/
|
|
152726
|
+
#withTimeout(promise) {
|
|
152727
|
+
if (!this.#timeoutMs) return promise;
|
|
152728
|
+
return new Promise((resolve, reject) => {
|
|
152729
|
+
const timer = setTimeout(
|
|
152730
|
+
() => reject(new Error(`CAS operation timed out after ${this.#timeoutMs}ms`)),
|
|
152731
|
+
this.#timeoutMs
|
|
152732
|
+
);
|
|
152733
|
+
promise.then(
|
|
152734
|
+
(val) => {
|
|
152735
|
+
clearTimeout(timer);
|
|
152736
|
+
resolve(val);
|
|
152737
|
+
},
|
|
152738
|
+
(err) => {
|
|
152739
|
+
clearTimeout(timer);
|
|
152740
|
+
reject(err);
|
|
152741
|
+
}
|
|
152742
|
+
);
|
|
152743
|
+
});
|
|
152694
152744
|
}
|
|
152695
152745
|
};
|
|
152696
152746
|
|
|
@@ -174085,18 +174135,16 @@ a=end-of-candidates
|
|
|
174085
174135
|
}
|
|
174086
174136
|
/**
|
|
174087
174137
|
* CAS API sub-facade (lazily initialized).
|
|
174088
|
-
*
|
|
174089
|
-
*
|
|
174138
|
+
*
|
|
174139
|
+
* When no `cas` config was provided to the constructor, defaults to a
|
|
174140
|
+
* read-only {@link HttpGatewayCasExecutor} backed by the public IPFS
|
|
174141
|
+
* gateway (`https://ipfs.io`). Override via `createApi({ cas: { ... } })`.
|
|
174142
|
+
* @throws {Error} If the instance has been disposed.
|
|
174090
174143
|
*/
|
|
174091
174144
|
get cas() {
|
|
174092
174145
|
this.#assertNotDisposed();
|
|
174093
174146
|
if (!this.#cas) {
|
|
174094
|
-
|
|
174095
|
-
throw new Error(
|
|
174096
|
-
"CAS not configured. Pass a cas config to createApi(), e.g.: createApi({ cas: { helia: await createHelia() } })"
|
|
174097
|
-
);
|
|
174098
|
-
}
|
|
174099
|
-
this.#cas = new CasApi(this.#casConfig);
|
|
174147
|
+
this.#cas = new CasApi(this.#casConfig ?? { gateway: DEFAULT_CAS_GATEWAY });
|
|
174100
174148
|
}
|
|
174101
174149
|
return this.#cas;
|
|
174102
174150
|
}
|
|
@@ -174109,7 +174157,7 @@ a=end-of-candidates
|
|
|
174109
174157
|
if (!this.#btcr2) {
|
|
174110
174158
|
this.#btcr2 = new DidMethodApi(
|
|
174111
174159
|
this.#btcConfig ? this.btc : void 0,
|
|
174112
|
-
this
|
|
174160
|
+
this.cas,
|
|
174113
174161
|
this.#log
|
|
174114
174162
|
);
|
|
174115
174163
|
}
|
package/dist/browser.mjs
CHANGED
|
@@ -146226,7 +146226,6 @@ var EsploraProtocol = class _EsploraProtocol {
|
|
|
146226
146226
|
...config.headers
|
|
146227
146227
|
};
|
|
146228
146228
|
}
|
|
146229
|
-
// ── validation ─────────────────────────────────────────────────────
|
|
146230
146229
|
static assertHex64(value4, label) {
|
|
146231
146230
|
if (!HEX64_RE.test(value4)) {
|
|
146232
146231
|
throw new Error(`Invalid ${label}: expected 64-char hex string`);
|
|
@@ -146237,7 +146236,6 @@ var EsploraProtocol = class _EsploraProtocol {
|
|
|
146237
146236
|
throw new Error("Invalid address: contains illegal characters");
|
|
146238
146237
|
}
|
|
146239
146238
|
}
|
|
146240
|
-
// ── helpers ──────────────────────────────────────────────────────────
|
|
146241
146239
|
get(path) {
|
|
146242
146240
|
return {
|
|
146243
146241
|
url: `${this.baseUrl}${path}`,
|
|
@@ -146253,7 +146251,6 @@ var EsploraProtocol = class _EsploraProtocol {
|
|
|
146253
146251
|
body
|
|
146254
146252
|
};
|
|
146255
146253
|
}
|
|
146256
|
-
// ── Transaction ──────────────────────────────────────────────────────
|
|
146257
146254
|
/** GET /tx/:txid */
|
|
146258
146255
|
getTx(txid) {
|
|
146259
146256
|
_EsploraProtocol.assertHex64(txid, "txid");
|
|
@@ -146273,7 +146270,6 @@ var EsploraProtocol = class _EsploraProtocol {
|
|
|
146273
146270
|
postTx(hex3) {
|
|
146274
146271
|
return this.post("/tx", hex3, { "Content-Type": "text/plain" });
|
|
146275
146272
|
}
|
|
146276
|
-
// ── Block ────────────────────────────────────────────────────────────
|
|
146277
146273
|
/** GET /blocks/tip/height */
|
|
146278
146274
|
getBlockTipHeight() {
|
|
146279
146275
|
return this.get("/blocks/tip/height");
|
|
@@ -146287,7 +146283,6 @@ var EsploraProtocol = class _EsploraProtocol {
|
|
|
146287
146283
|
getBlockHeight(height) {
|
|
146288
146284
|
return this.get(`/block-height/${height}`);
|
|
146289
146285
|
}
|
|
146290
|
-
// ── Address ──────────────────────────────────────────────────────────
|
|
146291
146286
|
/** GET /address/:address/txs */
|
|
146292
146287
|
getAddressTxs(address) {
|
|
146293
146288
|
_EsploraProtocol.assertAddress(address);
|
|
@@ -152608,6 +152603,7 @@ var sha5127 = from9({
|
|
|
152608
152603
|
});
|
|
152609
152604
|
|
|
152610
152605
|
// src/cas.ts
|
|
152606
|
+
var DEFAULT_CAS_GATEWAY = "https://ipfs.io";
|
|
152611
152607
|
var IpfsCasExecutor = class {
|
|
152612
152608
|
#helia;
|
|
152613
152609
|
constructor(helia) {
|
|
@@ -152629,18 +152625,47 @@ var IpfsCasExecutor = class {
|
|
|
152629
152625
|
return btoa(String.fromCharCode(...digest2.bytes.slice(2))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
152630
152626
|
}
|
|
152631
152627
|
};
|
|
152628
|
+
var HttpGatewayCasExecutor = class {
|
|
152629
|
+
#gatewayUrl;
|
|
152630
|
+
constructor(gatewayUrl) {
|
|
152631
|
+
this.#gatewayUrl = gatewayUrl.replace(/\/+$/, "");
|
|
152632
|
+
}
|
|
152633
|
+
async retrieve(hash4) {
|
|
152634
|
+
const hashBytes = decode25(hash4, "base64urlnopad");
|
|
152635
|
+
const cid = CID3.create(1, code8, create7(sha25611.code, hashBytes));
|
|
152636
|
+
try {
|
|
152637
|
+
const res = await fetch(`${this.#gatewayUrl}/ipfs/${cid.toString()}?format=raw`, {
|
|
152638
|
+
headers: { Accept: "application/vnd.ipld.raw" }
|
|
152639
|
+
});
|
|
152640
|
+
if (!res.ok) return null;
|
|
152641
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
152642
|
+
} catch {
|
|
152643
|
+
return null;
|
|
152644
|
+
}
|
|
152645
|
+
}
|
|
152646
|
+
async publish() {
|
|
152647
|
+
throw new Error(
|
|
152648
|
+
"HttpGatewayCasExecutor is read-only. Publishing requires a full IPFS node (use IpfsCasExecutor with Helia)."
|
|
152649
|
+
);
|
|
152650
|
+
}
|
|
152651
|
+
};
|
|
152652
|
+
var DEFAULT_CAS_TIMEOUT_MS = 3e4;
|
|
152632
152653
|
var CasApi = class {
|
|
152633
152654
|
#executor;
|
|
152655
|
+
#timeoutMs;
|
|
152634
152656
|
constructor(config) {
|
|
152635
152657
|
if (config.executor) {
|
|
152636
152658
|
this.#executor = config.executor;
|
|
152637
152659
|
} else if (config.helia) {
|
|
152638
152660
|
this.#executor = new IpfsCasExecutor(config.helia);
|
|
152661
|
+
} else if (config.gateway) {
|
|
152662
|
+
this.#executor = new HttpGatewayCasExecutor(config.gateway);
|
|
152639
152663
|
} else {
|
|
152640
152664
|
throw new Error(
|
|
152641
|
-
"CAS configuration requires
|
|
152665
|
+
"CAS configuration requires an executor, Helia instance, or gateway URL. Example: createApi({ cas: { gateway: 'https://ipfs.io' } })"
|
|
152642
152666
|
);
|
|
152643
152667
|
}
|
|
152668
|
+
this.#timeoutMs = config.timeoutMs ?? DEFAULT_CAS_TIMEOUT_MS;
|
|
152644
152669
|
}
|
|
152645
152670
|
/**
|
|
152646
152671
|
* Retrieve a JSON object from the CAS by its SHA-256 hash bytes.
|
|
@@ -152649,7 +152674,7 @@ var CasApi = class {
|
|
|
152649
152674
|
*/
|
|
152650
152675
|
async retrieve(hashBytes) {
|
|
152651
152676
|
const hash4 = encode23(hashBytes, "base64urlnopad");
|
|
152652
|
-
const bytes5 = await this.#executor.retrieve(hash4);
|
|
152677
|
+
const bytes5 = await this.#withTimeout(this.#executor.retrieve(hash4));
|
|
152653
152678
|
if (!bytes5) return null;
|
|
152654
152679
|
return JSON.parse(new TextDecoder().decode(bytes5));
|
|
152655
152680
|
}
|
|
@@ -152662,7 +152687,29 @@ var CasApi = class {
|
|
|
152662
152687
|
*/
|
|
152663
152688
|
async publish(object3) {
|
|
152664
152689
|
const bytes5 = new TextEncoder().encode(canonicalize6(object3));
|
|
152665
|
-
return await this.#executor.publish(bytes5);
|
|
152690
|
+
return await this.#withTimeout(this.#executor.publish(bytes5));
|
|
152691
|
+
}
|
|
152692
|
+
/**
|
|
152693
|
+
* Wraps a promise with a timeout. If `#timeoutMs` is 0, no timeout is applied.
|
|
152694
|
+
*/
|
|
152695
|
+
#withTimeout(promise) {
|
|
152696
|
+
if (!this.#timeoutMs) return promise;
|
|
152697
|
+
return new Promise((resolve, reject) => {
|
|
152698
|
+
const timer = setTimeout(
|
|
152699
|
+
() => reject(new Error(`CAS operation timed out after ${this.#timeoutMs}ms`)),
|
|
152700
|
+
this.#timeoutMs
|
|
152701
|
+
);
|
|
152702
|
+
promise.then(
|
|
152703
|
+
(val) => {
|
|
152704
|
+
clearTimeout(timer);
|
|
152705
|
+
resolve(val);
|
|
152706
|
+
},
|
|
152707
|
+
(err) => {
|
|
152708
|
+
clearTimeout(timer);
|
|
152709
|
+
reject(err);
|
|
152710
|
+
}
|
|
152711
|
+
);
|
|
152712
|
+
});
|
|
152666
152713
|
}
|
|
152667
152714
|
};
|
|
152668
152715
|
|
|
@@ -174057,18 +174104,16 @@ var DidBtcr2Api = class {
|
|
|
174057
174104
|
}
|
|
174058
174105
|
/**
|
|
174059
174106
|
* CAS API sub-facade (lazily initialized).
|
|
174060
|
-
*
|
|
174061
|
-
*
|
|
174107
|
+
*
|
|
174108
|
+
* When no `cas` config was provided to the constructor, defaults to a
|
|
174109
|
+
* read-only {@link HttpGatewayCasExecutor} backed by the public IPFS
|
|
174110
|
+
* gateway (`https://ipfs.io`). Override via `createApi({ cas: { ... } })`.
|
|
174111
|
+
* @throws {Error} If the instance has been disposed.
|
|
174062
174112
|
*/
|
|
174063
174113
|
get cas() {
|
|
174064
174114
|
this.#assertNotDisposed();
|
|
174065
174115
|
if (!this.#cas) {
|
|
174066
|
-
|
|
174067
|
-
throw new Error(
|
|
174068
|
-
"CAS not configured. Pass a cas config to createApi(), e.g.: createApi({ cas: { helia: await createHelia() } })"
|
|
174069
|
-
);
|
|
174070
|
-
}
|
|
174071
|
-
this.#cas = new CasApi(this.#casConfig);
|
|
174116
|
+
this.#cas = new CasApi(this.#casConfig ?? { gateway: DEFAULT_CAS_GATEWAY });
|
|
174072
174117
|
}
|
|
174073
174118
|
return this.#cas;
|
|
174074
174119
|
}
|
|
@@ -174081,7 +174126,7 @@ var DidBtcr2Api = class {
|
|
|
174081
174126
|
if (!this.#btcr2) {
|
|
174082
174127
|
this.#btcr2 = new DidMethodApi(
|
|
174083
174128
|
this.#btcConfig ? this.btc : void 0,
|
|
174084
|
-
this
|
|
174129
|
+
this.cas,
|
|
174085
174130
|
this.#log
|
|
174086
174131
|
);
|
|
174087
174132
|
}
|
|
@@ -174255,12 +174300,15 @@ export {
|
|
|
174255
174300
|
CasApi,
|
|
174256
174301
|
CryptoApi,
|
|
174257
174302
|
CryptosuiteApi,
|
|
174303
|
+
DEFAULT_CAS_GATEWAY,
|
|
174304
|
+
DEFAULT_CAS_TIMEOUT_MS,
|
|
174258
174305
|
DataIntegrityProofApi,
|
|
174259
174306
|
DidApi,
|
|
174260
174307
|
DidBtcr2Api,
|
|
174261
174308
|
DidDocument,
|
|
174262
174309
|
DidDocumentBuilder,
|
|
174263
174310
|
DidMethodApi,
|
|
174311
|
+
HttpGatewayCasExecutor,
|
|
174264
174312
|
Identifier,
|
|
174265
174313
|
IdentifierTypes2 as IdentifierTypes,
|
|
174266
174314
|
IpfsCasExecutor,
|
package/dist/cjs/index.js
CHANGED
|
@@ -34,12 +34,15 @@ __export(index_exports, {
|
|
|
34
34
|
CasApi: () => CasApi,
|
|
35
35
|
CryptoApi: () => CryptoApi,
|
|
36
36
|
CryptosuiteApi: () => CryptosuiteApi,
|
|
37
|
+
DEFAULT_CAS_GATEWAY: () => DEFAULT_CAS_GATEWAY,
|
|
38
|
+
DEFAULT_CAS_TIMEOUT_MS: () => DEFAULT_CAS_TIMEOUT_MS,
|
|
37
39
|
DataIntegrityProofApi: () => DataIntegrityProofApi,
|
|
38
40
|
DidApi: () => DidApi,
|
|
39
41
|
DidBtcr2Api: () => DidBtcr2Api,
|
|
40
42
|
DidDocument: () => import_method4.DidDocument,
|
|
41
43
|
DidDocumentBuilder: () => import_method4.DidDocumentBuilder,
|
|
42
44
|
DidMethodApi: () => DidMethodApi,
|
|
45
|
+
HttpGatewayCasExecutor: () => HttpGatewayCasExecutor,
|
|
43
46
|
Identifier: () => import_method4.Identifier,
|
|
44
47
|
IdentifierTypes: () => import_common4.IdentifierTypes,
|
|
45
48
|
IpfsCasExecutor: () => IpfsCasExecutor,
|
|
@@ -1129,6 +1132,7 @@ var sha512 = from2({
|
|
|
1129
1132
|
});
|
|
1130
1133
|
|
|
1131
1134
|
// src/cas.ts
|
|
1135
|
+
var DEFAULT_CAS_GATEWAY = "https://ipfs.io";
|
|
1132
1136
|
var IpfsCasExecutor = class {
|
|
1133
1137
|
#helia;
|
|
1134
1138
|
constructor(helia) {
|
|
@@ -1150,18 +1154,47 @@ var IpfsCasExecutor = class {
|
|
|
1150
1154
|
return btoa(String.fromCharCode(...digest.bytes.slice(2))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1151
1155
|
}
|
|
1152
1156
|
};
|
|
1157
|
+
var HttpGatewayCasExecutor = class {
|
|
1158
|
+
#gatewayUrl;
|
|
1159
|
+
constructor(gatewayUrl) {
|
|
1160
|
+
this.#gatewayUrl = gatewayUrl.replace(/\/+$/, "");
|
|
1161
|
+
}
|
|
1162
|
+
async retrieve(hash) {
|
|
1163
|
+
const hashBytes = (0, import_common.decode)(hash, "base64urlnopad");
|
|
1164
|
+
const cid = CID.create(1, code, create(sha256.code, hashBytes));
|
|
1165
|
+
try {
|
|
1166
|
+
const res = await fetch(`${this.#gatewayUrl}/ipfs/${cid.toString()}?format=raw`, {
|
|
1167
|
+
headers: { Accept: "application/vnd.ipld.raw" }
|
|
1168
|
+
});
|
|
1169
|
+
if (!res.ok) return null;
|
|
1170
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
1171
|
+
} catch {
|
|
1172
|
+
return null;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
async publish() {
|
|
1176
|
+
throw new Error(
|
|
1177
|
+
"HttpGatewayCasExecutor is read-only. Publishing requires a full IPFS node (use IpfsCasExecutor with Helia)."
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
var DEFAULT_CAS_TIMEOUT_MS = 3e4;
|
|
1153
1182
|
var CasApi = class {
|
|
1154
1183
|
#executor;
|
|
1184
|
+
#timeoutMs;
|
|
1155
1185
|
constructor(config) {
|
|
1156
1186
|
if (config.executor) {
|
|
1157
1187
|
this.#executor = config.executor;
|
|
1158
1188
|
} else if (config.helia) {
|
|
1159
1189
|
this.#executor = new IpfsCasExecutor(config.helia);
|
|
1190
|
+
} else if (config.gateway) {
|
|
1191
|
+
this.#executor = new HttpGatewayCasExecutor(config.gateway);
|
|
1160
1192
|
} else {
|
|
1161
1193
|
throw new Error(
|
|
1162
|
-
"CAS configuration requires
|
|
1194
|
+
"CAS configuration requires an executor, Helia instance, or gateway URL. Example: createApi({ cas: { gateway: 'https://ipfs.io' } })"
|
|
1163
1195
|
);
|
|
1164
1196
|
}
|
|
1197
|
+
this.#timeoutMs = config.timeoutMs ?? DEFAULT_CAS_TIMEOUT_MS;
|
|
1165
1198
|
}
|
|
1166
1199
|
/**
|
|
1167
1200
|
* Retrieve a JSON object from the CAS by its SHA-256 hash bytes.
|
|
@@ -1170,7 +1203,7 @@ var CasApi = class {
|
|
|
1170
1203
|
*/
|
|
1171
1204
|
async retrieve(hashBytes) {
|
|
1172
1205
|
const hash = (0, import_common.encode)(hashBytes, "base64urlnopad");
|
|
1173
|
-
const bytes = await this.#executor.retrieve(hash);
|
|
1206
|
+
const bytes = await this.#withTimeout(this.#executor.retrieve(hash));
|
|
1174
1207
|
if (!bytes) return null;
|
|
1175
1208
|
return JSON.parse(new TextDecoder().decode(bytes));
|
|
1176
1209
|
}
|
|
@@ -1183,7 +1216,29 @@ var CasApi = class {
|
|
|
1183
1216
|
*/
|
|
1184
1217
|
async publish(object) {
|
|
1185
1218
|
const bytes = new TextEncoder().encode((0, import_common.canonicalize)(object));
|
|
1186
|
-
return await this.#executor.publish(bytes);
|
|
1219
|
+
return await this.#withTimeout(this.#executor.publish(bytes));
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Wraps a promise with a timeout. If `#timeoutMs` is 0, no timeout is applied.
|
|
1223
|
+
*/
|
|
1224
|
+
#withTimeout(promise) {
|
|
1225
|
+
if (!this.#timeoutMs) return promise;
|
|
1226
|
+
return new Promise((resolve, reject) => {
|
|
1227
|
+
const timer = setTimeout(
|
|
1228
|
+
() => reject(new Error(`CAS operation timed out after ${this.#timeoutMs}ms`)),
|
|
1229
|
+
this.#timeoutMs
|
|
1230
|
+
);
|
|
1231
|
+
promise.then(
|
|
1232
|
+
(val) => {
|
|
1233
|
+
clearTimeout(timer);
|
|
1234
|
+
resolve(val);
|
|
1235
|
+
},
|
|
1236
|
+
(err) => {
|
|
1237
|
+
clearTimeout(timer);
|
|
1238
|
+
reject(err);
|
|
1239
|
+
}
|
|
1240
|
+
);
|
|
1241
|
+
});
|
|
1187
1242
|
}
|
|
1188
1243
|
};
|
|
1189
1244
|
|
|
@@ -2019,18 +2074,16 @@ var DidBtcr2Api = class {
|
|
|
2019
2074
|
}
|
|
2020
2075
|
/**
|
|
2021
2076
|
* CAS API sub-facade (lazily initialized).
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
2077
|
+
*
|
|
2078
|
+
* When no `cas` config was provided to the constructor, defaults to a
|
|
2079
|
+
* read-only {@link HttpGatewayCasExecutor} backed by the public IPFS
|
|
2080
|
+
* gateway (`https://ipfs.io`). Override via `createApi({ cas: { ... } })`.
|
|
2081
|
+
* @throws {Error} If the instance has been disposed.
|
|
2024
2082
|
*/
|
|
2025
2083
|
get cas() {
|
|
2026
2084
|
this.#assertNotDisposed();
|
|
2027
2085
|
if (!this.#cas) {
|
|
2028
|
-
|
|
2029
|
-
throw new Error(
|
|
2030
|
-
"CAS not configured. Pass a cas config to createApi(), e.g.: createApi({ cas: { helia: await createHelia() } })"
|
|
2031
|
-
);
|
|
2032
|
-
}
|
|
2033
|
-
this.#cas = new CasApi(this.#casConfig);
|
|
2086
|
+
this.#cas = new CasApi(this.#casConfig ?? { gateway: DEFAULT_CAS_GATEWAY });
|
|
2034
2087
|
}
|
|
2035
2088
|
return this.#cas;
|
|
2036
2089
|
}
|
|
@@ -2043,7 +2096,7 @@ var DidBtcr2Api = class {
|
|
|
2043
2096
|
if (!this.#btcr2) {
|
|
2044
2097
|
this.#btcr2 = new DidMethodApi(
|
|
2045
2098
|
this.#btcConfig ? this.btc : void 0,
|
|
2046
|
-
this
|
|
2099
|
+
this.cas,
|
|
2047
2100
|
this.#log
|
|
2048
2101
|
);
|
|
2049
2102
|
}
|
|
@@ -2218,12 +2271,15 @@ function createApi(config) {
|
|
|
2218
2271
|
CasApi,
|
|
2219
2272
|
CryptoApi,
|
|
2220
2273
|
CryptosuiteApi,
|
|
2274
|
+
DEFAULT_CAS_GATEWAY,
|
|
2275
|
+
DEFAULT_CAS_TIMEOUT_MS,
|
|
2221
2276
|
DataIntegrityProofApi,
|
|
2222
2277
|
DidApi,
|
|
2223
2278
|
DidBtcr2Api,
|
|
2224
2279
|
DidDocument,
|
|
2225
2280
|
DidDocumentBuilder,
|
|
2226
2281
|
DidMethodApi,
|
|
2282
|
+
HttpGatewayCasExecutor,
|
|
2227
2283
|
Identifier,
|
|
2228
2284
|
IdentifierTypes,
|
|
2229
2285
|
IpfsCasExecutor,
|
package/dist/esm/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
2
|
import { BitcoinApi } from './bitcoin.js';
|
|
3
|
-
import { CasApi } from './cas.js';
|
|
3
|
+
import { CasApi, DEFAULT_CAS_GATEWAY } from './cas.js';
|
|
4
4
|
import { CryptoApi } from './crypto.js';
|
|
5
5
|
import { DidApi } from './did.js';
|
|
6
6
|
import { assertString, NOOP_LOGGER } from './helpers.js';
|
|
@@ -53,17 +53,16 @@ export class DidBtcr2Api {
|
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* CAS API sub-facade (lazily initialized).
|
|
56
|
-
*
|
|
57
|
-
*
|
|
56
|
+
*
|
|
57
|
+
* When no `cas` config was provided to the constructor, defaults to a
|
|
58
|
+
* read-only {@link HttpGatewayCasExecutor} backed by the public IPFS
|
|
59
|
+
* gateway (`https://ipfs.io`). Override via `createApi({ cas: { ... } })`.
|
|
60
|
+
* @throws {Error} If the instance has been disposed.
|
|
58
61
|
*/
|
|
59
62
|
get cas() {
|
|
60
63
|
this.#assertNotDisposed();
|
|
61
64
|
if (!this.#cas) {
|
|
62
|
-
|
|
63
|
-
throw new Error('CAS not configured. Pass a cas config to createApi(), e.g.: '
|
|
64
|
-
+ 'createApi({ cas: { helia: await createHelia() } })');
|
|
65
|
-
}
|
|
66
|
-
this.#cas = new CasApi(this.#casConfig);
|
|
65
|
+
this.#cas = new CasApi(this.#casConfig ?? { gateway: DEFAULT_CAS_GATEWAY });
|
|
67
66
|
}
|
|
68
67
|
return this.#cas;
|
|
69
68
|
}
|
|
@@ -74,7 +73,7 @@ export class DidBtcr2Api {
|
|
|
74
73
|
get btcr2() {
|
|
75
74
|
this.#assertNotDisposed();
|
|
76
75
|
if (!this.#btcr2) {
|
|
77
|
-
this.#btcr2 = new DidMethodApi(this.#btcConfig ? this.btc : undefined, this
|
|
76
|
+
this.#btcr2 = new DidMethodApi(this.#btcConfig ? this.btc : undefined, this.cas, this.#log);
|
|
78
77
|
}
|
|
79
78
|
return this.#btcr2;
|
|
80
79
|
}
|
package/dist/esm/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAkB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAkB,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C;;;;;;GAMG;AACH,MAAM,OAAO,WAAW;IACtB,wEAAwE;IAC/D,MAAM,CAAY;IAC3B,mEAAmE;IAC1D,GAAG,CAAS;IACrB,iCAAiC;IACxB,GAAG,CAAgB;IAE5B,UAAU,CAAoB;IAC9B,IAAI,CAAc;IAClB,UAAU,CAAa;IACvB,IAAI,CAAU;IACd,MAAM,CAAgB;IACtB,IAAI,CAAS;IACb,SAAS,GAAG,KAAK,CAAC;IAElB,YAAY,MAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,GAAG,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,GAAG,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,MAAM,EAAE,MAAM,IAAI,WAAW,CAAC;QAC1C,IAAI,CAAC,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,IAAI,GAAG;QACL,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CACb,kEAAkE;sBAChE,8CAA8C,CACjD,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,GAAG;QACL,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,IAAI,KAAK;QACP,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAC5B,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EACtC,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,IAAI,CACV,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CACP,IAAkC,EAClC,YAAsC,EACtC,OAA0C;QAE1C,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,OAAO,IAAI,KAAK,eAAe;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,YAAwB,EAAE,OAAO,CAAC;YACnE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,YAA6B,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IAED;;;;;;OAMG;IACH,WAAW,CAAC,OAAwD;QAClE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7D,MAAM,EAAE,GAAG,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7E,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,OAA2B;QACvD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,OAA2B;QAC1D,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACnD,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpB,OAAO;oBACL,EAAE,EAAS,IAAI;oBACf,QAAQ,EAAG,GAAG,CAAC,WAA+B;oBAC9C,QAAQ,EAAG,GAAG,CAAC,mBAAmB;oBAClC,GAAG;iBACJ,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,EAAE,EAAa,KAAK;gBACpB,KAAK,EAAU,GAAG,CAAC,qBAAqB,EAAE,KAAK,IAAI,SAAS;gBAC5D,YAAY,EAAG,GAAG,CAAC,qBAAqB,EAAE,YAAkC;gBAC5E,GAAG;aACJ,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO;gBACL,EAAE,EAAa,KAAK;gBACpB,KAAK,EAAU,eAAe;gBAC9B,YAAY,EAAG,GAAG,CAAC,OAAO;gBAC1B,GAAG,EAAY;oBACb,WAAW,EAAc,IAAI;oBAC7B,mBAAmB,EAAM,EAAE;oBAC3B,qBAAqB,EAAI,EAAE,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE;iBAC7C;aACpC,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,SAAS,CAAC,EACd,GAAG,EACH,OAAO,EACP,oBAAoB,EACpB,QAAQ,EACR,cAAc,EACd,eAAe,GAQhB;QACC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEzB,IAAI,GAAG,GAAG,cAAc,CAAC;QACzB,IAAI,SAAS,GAAG,eAAe,CAAC;QAEhC,IAAI,CAAC,GAAG,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC9C,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,UAAU,CAAC,qBAAqB,CAAC;gBAC9C,MAAM,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;gBACrD,MAAM,KAAK,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,KAAK,CACb,yBAAyB,GAAG,cAAc,MAAM,GAAG,KAAK,EAAE,EAC1D,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB,CAAC;YACJ,CAAC;YACD,GAAG,GAAG,GAAG,IAAI,UAAU,CAAC,WAA+B,CAAC;YAExD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,UAAU,CAAC,mBAAmB,EAAE,SAAS,CAAC;gBAC/D,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBACxD,MAAM,IAAI,KAAK,CACb,qBAAqB,GAAG,oDAAoD;0BAC1E,qCAAqC,CACxC,CAAC;gBACJ,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7B,MAAM,IAAI,KAAK,CACb,qBAAqB,GAAG,sCAAsC,MAAM,CAAC,YAAY,CAAC,GAAG,CACtF,CAAC;gBACJ,CAAC;gBACD,SAAS,GAAG,MAAM,CAAC;YACrB,CAAC;QACH,CAAC;QAED,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YAC7B,cAAc,EAAM,GAAG;YACvB,OAAO;YACP,eAAe,EAAK,SAAS;YAC7B,oBAAoB;YACpB,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,OAAO;QACL,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,kBAAkB;QAChB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,MAAkB;IAC1C,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC"}
|