mainnet-js 1.1.19 → 1.1.21
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/index.html +1 -1
- package/dist/{mainnet-1.1.19.js → mainnet-1.1.21.js} +4 -4
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +1 -15
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/constant.d.ts +0 -1
- package/dist/module/network/constant.d.ts.map +1 -1
- package/dist/module/network/constant.js +0 -2
- package/dist/module/network/constant.js.map +1 -1
- package/dist/module/network/default.d.ts.map +1 -1
- package/dist/module/network/default.js +3 -7
- package/dist/module/network/default.js.map +1 -1
- package/dist/module/wallet/Bcmr.d.ts +2 -1
- package/dist/module/wallet/Bcmr.d.ts.map +1 -1
- package/dist/module/wallet/Bcmr.js +40 -35
- package/dist/module/wallet/Bcmr.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/network/ElectrumNetworkProvider.ts +1 -17
- package/src/network/constant.ts +0 -2
- package/src/network/default.ts +3 -8
- package/src/wallet/Bcmr.test.headless.js +90 -6
- package/src/wallet/Bcmr.test.ts +83 -32
- package/src/wallet/Bcmr.ts +44 -38
package/src/network/default.ts
CHANGED
|
@@ -12,8 +12,7 @@ import { Network } from "../interface.js";
|
|
|
12
12
|
import {
|
|
13
13
|
networkTickerMap,
|
|
14
14
|
clusterParams,
|
|
15
|
-
ELECTRUM_CASH_PROTOCOL_VERSION
|
|
16
|
-
ELECTRUM_CASH_PROTOCOL_VERSION_MAINNET,
|
|
15
|
+
ELECTRUM_CASH_PROTOCOL_VERSION
|
|
17
16
|
} from "./constant.js";
|
|
18
17
|
|
|
19
18
|
export function setGlobalProvider(
|
|
@@ -129,9 +128,7 @@ function getClient(servers: string[], network: Network) {
|
|
|
129
128
|
function getElectrumCluster(params: ElectrumClusterParams, network: Network) {
|
|
130
129
|
return new ElectrumCluster(
|
|
131
130
|
getUserAgent(),
|
|
132
|
-
|
|
133
|
-
? ELECTRUM_CASH_PROTOCOL_VERSION_MAINNET
|
|
134
|
-
: ELECTRUM_CASH_PROTOCOL_VERSION,
|
|
131
|
+
ELECTRUM_CASH_PROTOCOL_VERSION,
|
|
135
132
|
params.confidence,
|
|
136
133
|
params.distribution,
|
|
137
134
|
params.order,
|
|
@@ -146,9 +143,7 @@ function getElectrumClient(
|
|
|
146
143
|
) {
|
|
147
144
|
return new ElectrumClient(
|
|
148
145
|
getUserAgent(),
|
|
149
|
-
|
|
150
|
-
? ELECTRUM_CASH_PROTOCOL_VERSION_MAINNET
|
|
151
|
-
: ELECTRUM_CASH_PROTOCOL_VERSION,
|
|
146
|
+
ELECTRUM_CASH_PROTOCOL_VERSION,
|
|
152
147
|
params.host,
|
|
153
148
|
params.port,
|
|
154
149
|
params.scheme,
|
|
@@ -179,8 +179,8 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
179
179
|
});
|
|
180
180
|
expect(chain.length).toBe(1);
|
|
181
181
|
expect(chain[0].txHash).toBe(response.txId);
|
|
182
|
-
expect(chain[0].
|
|
183
|
-
"
|
|
182
|
+
expect(chain[0].uris[0]).toBe(
|
|
183
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
184
184
|
);
|
|
185
185
|
|
|
186
186
|
const tokenInfo = BCMR.getTokenInfo(
|
|
@@ -345,22 +345,34 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
345
345
|
expect(chain.length).toBe(4);
|
|
346
346
|
|
|
347
347
|
expect(chain[0].txHash).toBe(response.txId);
|
|
348
|
-
expect(chain[0].
|
|
348
|
+
expect(chain[0].uris[0]).toBe(
|
|
349
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v1.json"
|
|
350
|
+
);
|
|
351
|
+
expect(chain[0].httpsUrl).toBe(
|
|
349
352
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v1.json"
|
|
350
353
|
);
|
|
351
354
|
|
|
352
355
|
expect(chain[1].txHash).toBe(response2.txId);
|
|
353
|
-
expect(chain[1].
|
|
356
|
+
expect(chain[1].uris[0]).toBe(
|
|
357
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
358
|
+
);
|
|
359
|
+
expect(chain[1].httpsUrl).toBe(
|
|
354
360
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
355
361
|
);
|
|
356
362
|
|
|
357
363
|
expect(chain[2].txHash).toBe(response3.txId);
|
|
358
|
-
expect(chain[2].
|
|
364
|
+
expect(chain[2].uris[0]).toBe(
|
|
365
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
366
|
+
);
|
|
367
|
+
expect(chain[2].httpsUrl).toBe(
|
|
359
368
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
360
369
|
);
|
|
361
370
|
|
|
362
371
|
expect(chain[3].txHash).toBe(response4.txId);
|
|
363
|
-
expect(chain[3].
|
|
372
|
+
expect(chain[3].uris[0]).toBe(
|
|
373
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v4.json"
|
|
374
|
+
);
|
|
375
|
+
expect(chain[3].httpsUrl).toBe(
|
|
364
376
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v4.json"
|
|
365
377
|
);
|
|
366
378
|
|
|
@@ -380,4 +392,76 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
380
392
|
[process.env.ALICE_ID, registry]
|
|
381
393
|
);
|
|
382
394
|
});
|
|
395
|
+
|
|
396
|
+
test("Auth chain: BCMR, ipfs hash", async () => {
|
|
397
|
+
await page.evaluate(
|
|
398
|
+
async ([id, registry]) => {
|
|
399
|
+
const alice = await RegTestWallet.fromId(id);
|
|
400
|
+
const bob = await RegTestWallet.newRandom();
|
|
401
|
+
|
|
402
|
+
const chunks = [
|
|
403
|
+
"BCMR",
|
|
404
|
+
"QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv",
|
|
405
|
+
];
|
|
406
|
+
const opreturnData = OpReturnData.fromArray(chunks);
|
|
407
|
+
|
|
408
|
+
const response = await alice.send([
|
|
409
|
+
new SendRequest({ cashaddr: bob.cashaddr, value: 1000, unit: "sat" }),
|
|
410
|
+
opreturnData,
|
|
411
|
+
]);
|
|
412
|
+
const chain = await BCMR.buildAuthChain({
|
|
413
|
+
transactionHash: response.txId,
|
|
414
|
+
network: Network.REGTEST,
|
|
415
|
+
});
|
|
416
|
+
expect(chain.length).toBe(1);
|
|
417
|
+
expect(chain[0].contentHash).toBe(
|
|
418
|
+
"516d62577247354173703569476d557751486f67534a47525832367a75526e754c575079745a66694c3735735a76"
|
|
419
|
+
);
|
|
420
|
+
expect(chain[0].uris[0]).toBe(
|
|
421
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
422
|
+
);
|
|
423
|
+
expect(chain[0].httpsUrl).toBe(
|
|
424
|
+
"https://dweb.link/ipfs/QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
425
|
+
);
|
|
426
|
+
expect(chain[0].txHash).toBe(response.txId);
|
|
427
|
+
},
|
|
428
|
+
[process.env.ALICE_ID, registry]
|
|
429
|
+
);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
test("Auth chain: BCMR, sha256 content hash, 2 uris", async () => {
|
|
433
|
+
await page.evaluate(
|
|
434
|
+
async ([id, registry]) => {
|
|
435
|
+
const alice = await RegTestWallet.fromId(id);
|
|
436
|
+
const bob = await RegTestWallet.newRandom();
|
|
437
|
+
|
|
438
|
+
const chunks = [
|
|
439
|
+
"BCMR",
|
|
440
|
+
sha256.hash(utf8ToBin("registry_contents")),
|
|
441
|
+
"mainnet.cash",
|
|
442
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv",
|
|
443
|
+
];
|
|
444
|
+
const opreturnData = OpReturnData.fromArray(chunks);
|
|
445
|
+
const response = await alice.send([
|
|
446
|
+
new SendRequest({ cashaddr: bob.cashaddr, value: 1000, unit: "sat" }),
|
|
447
|
+
opreturnData,
|
|
448
|
+
]);
|
|
449
|
+
const chain = await BCMR.buildAuthChain({
|
|
450
|
+
transactionHash: response.txId,
|
|
451
|
+
network: Network.REGTEST,
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
expect(chain.length).toBe(1);
|
|
455
|
+
expect(chain[0].uris.length).toBe(2);
|
|
456
|
+
expect(chain[0].uris[0]).toBe("mainnet.cash");
|
|
457
|
+
expect(chain[0].uris[1]).toBe(
|
|
458
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
459
|
+
);
|
|
460
|
+
expect(chain[0].httpsUrl).toBe(
|
|
461
|
+
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
462
|
+
);
|
|
463
|
+
},
|
|
464
|
+
[process.env.ALICE_ID, registry]
|
|
465
|
+
);
|
|
466
|
+
});
|
|
383
467
|
});
|
package/src/wallet/Bcmr.test.ts
CHANGED
|
@@ -231,7 +231,10 @@ describe(`Test BCMR support`, () => {
|
|
|
231
231
|
expect(chain[0].contentHash).toBe(
|
|
232
232
|
"516d62577247354173703569476d557751486f67534a47525832367a75526e754c575079745a66694c3735735a76"
|
|
233
233
|
);
|
|
234
|
-
expect(chain[0].
|
|
234
|
+
expect(chain[0].uris[0]).toBe(
|
|
235
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
236
|
+
);
|
|
237
|
+
expect(chain[0].httpsUrl).toBe(
|
|
235
238
|
"https://dweb.link/ipfs/QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
236
239
|
);
|
|
237
240
|
expect(chain[0].txHash).toBe(response.txId);
|
|
@@ -244,11 +247,7 @@ describe(`Test BCMR support`, () => {
|
|
|
244
247
|
const bob = await RegTestWallet.newRandom();
|
|
245
248
|
|
|
246
249
|
const contentHashBin = sha256.hash(utf8ToBin("registry_contents"));
|
|
247
|
-
const chunks = [
|
|
248
|
-
"BCMR",
|
|
249
|
-
contentHashBin,
|
|
250
|
-
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json",
|
|
251
|
-
];
|
|
250
|
+
const chunks = ["BCMR", contentHashBin, "mainnet.cash"];
|
|
252
251
|
const opreturnData = OpReturnData.fromArray(chunks);
|
|
253
252
|
|
|
254
253
|
const response = await alice.send([
|
|
@@ -261,13 +260,14 @@ describe(`Test BCMR support`, () => {
|
|
|
261
260
|
});
|
|
262
261
|
expect(chain.length).toBe(1);
|
|
263
262
|
expect(chain[0].contentHash).toBe(binToHex(contentHashBin));
|
|
264
|
-
expect(chain[0].
|
|
263
|
+
expect(chain[0].uris[0]).toBe("mainnet.cash");
|
|
264
|
+
expect(chain[0].httpsUrl).toBe(
|
|
265
265
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
266
266
|
);
|
|
267
267
|
expect(chain[0].txHash).toBe(response.txId);
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
-
test("Auth chain: BCMR, sha256 content hash,
|
|
270
|
+
test("Auth chain: BCMR, sha256 content hash, 2 uris", async () => {
|
|
271
271
|
const alice = await RegTestWallet.fromId(
|
|
272
272
|
`wif:regtest:${process.env.PRIVATE_WIF!}`
|
|
273
273
|
);
|
|
@@ -276,20 +276,28 @@ describe(`Test BCMR support`, () => {
|
|
|
276
276
|
const chunks = [
|
|
277
277
|
"BCMR",
|
|
278
278
|
sha256.hash(utf8ToBin("registry_contents")),
|
|
279
|
-
"mainnet.cash
|
|
280
|
-
"
|
|
279
|
+
"mainnet.cash",
|
|
280
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv",
|
|
281
281
|
];
|
|
282
282
|
const opreturnData = OpReturnData.fromArray(chunks);
|
|
283
283
|
const response = await alice.send([
|
|
284
284
|
new SendRequest({ cashaddr: bob.cashaddr!, value: 1000, unit: "sat" }),
|
|
285
285
|
opreturnData,
|
|
286
286
|
]);
|
|
287
|
-
await
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
).
|
|
287
|
+
const chain = await BCMR.buildAuthChain({
|
|
288
|
+
transactionHash: response.txId!,
|
|
289
|
+
network: Network.REGTEST,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
expect(chain.length).toBe(1);
|
|
293
|
+
expect(chain[0].uris.length).toBe(2);
|
|
294
|
+
expect(chain[0].uris[0]).toBe("mainnet.cash");
|
|
295
|
+
expect(chain[0].uris[1]).toBe(
|
|
296
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
297
|
+
);
|
|
298
|
+
expect(chain[0].httpsUrl).toBe(
|
|
299
|
+
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
300
|
+
);
|
|
293
301
|
});
|
|
294
302
|
|
|
295
303
|
test("Auth chain: all OP_PUSDHDATA encodings", async () => {
|
|
@@ -346,7 +354,10 @@ describe(`Test BCMR support`, () => {
|
|
|
346
354
|
});
|
|
347
355
|
expect(chain.length).toBe(1);
|
|
348
356
|
expect(chain[0].txHash).toBe(response.txId!);
|
|
349
|
-
expect(chain[0].
|
|
357
|
+
expect(chain[0].uris[0]).toBe(
|
|
358
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
359
|
+
);
|
|
360
|
+
expect(chain[0].httpsUrl).toBe(
|
|
350
361
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
351
362
|
);
|
|
352
363
|
|
|
@@ -392,7 +403,7 @@ describe(`Test BCMR support`, () => {
|
|
|
392
403
|
let chunks = [
|
|
393
404
|
"BCMR",
|
|
394
405
|
registryContentHashBinBitcoinByteOrder,
|
|
395
|
-
"mainnet.cash
|
|
406
|
+
"mainnet.cash",
|
|
396
407
|
];
|
|
397
408
|
const opreturnData = OpReturnData.fromArray(chunks);
|
|
398
409
|
const response = await alice.send([
|
|
@@ -430,17 +441,24 @@ describe(`Test BCMR support`, () => {
|
|
|
430
441
|
|
|
431
442
|
expect(chain.length).toBe(3);
|
|
432
443
|
expect(chain[0].txHash).toBe(response.txId!);
|
|
433
|
-
expect(chain[0].
|
|
444
|
+
expect(chain[0].uris[0]).toBe("mainnet.cash");
|
|
445
|
+
expect(chain[0].httpsUrl).toBe(
|
|
434
446
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
435
447
|
);
|
|
436
448
|
|
|
437
449
|
expect(chain[1].txHash).toBe(response2.txId!);
|
|
438
|
-
expect(chain[1].
|
|
450
|
+
expect(chain[1].uris[0]).toBe(
|
|
451
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
452
|
+
);
|
|
453
|
+
expect(chain[1].httpsUrl).toBe(
|
|
439
454
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
440
455
|
);
|
|
441
456
|
|
|
442
457
|
expect(chain[2].txHash).toBe(response3.txId!);
|
|
443
|
-
expect(chain[2].
|
|
458
|
+
expect(chain[2].uris[0]).toBe(
|
|
459
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
460
|
+
);
|
|
461
|
+
expect(chain[2].httpsUrl).toBe(
|
|
444
462
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
445
463
|
);
|
|
446
464
|
|
|
@@ -453,7 +471,10 @@ describe(`Test BCMR support`, () => {
|
|
|
453
471
|
});
|
|
454
472
|
expect(noFollow.length).toBe(1);
|
|
455
473
|
expect(noFollow[0].txHash).toBe(response2.txId!);
|
|
456
|
-
expect(noFollow[0].
|
|
474
|
+
expect(noFollow[0].uris[0]).toBe(
|
|
475
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
476
|
+
);
|
|
477
|
+
expect(noFollow[0].httpsUrl).toBe(
|
|
457
478
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
458
479
|
);
|
|
459
480
|
|
|
@@ -465,12 +486,18 @@ describe(`Test BCMR support`, () => {
|
|
|
465
486
|
expect(follow.length).toBe(2);
|
|
466
487
|
|
|
467
488
|
expect(follow[0].txHash).toBe(response2.txId!);
|
|
468
|
-
expect(follow[0].
|
|
489
|
+
expect(follow[0].uris[0]).toBe(
|
|
490
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
491
|
+
);
|
|
492
|
+
expect(follow[0].httpsUrl).toBe(
|
|
469
493
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
470
494
|
);
|
|
471
495
|
|
|
472
496
|
expect(follow[1].txHash).toBe(response3.txId!);
|
|
473
|
-
expect(follow[1].
|
|
497
|
+
expect(follow[1].uris[0]).toBe(
|
|
498
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
499
|
+
);
|
|
500
|
+
expect(follow[1].httpsUrl).toBe(
|
|
474
501
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
475
502
|
);
|
|
476
503
|
}
|
|
@@ -610,22 +637,34 @@ describe(`Test BCMR support`, () => {
|
|
|
610
637
|
expect(chain.length).toBe(4);
|
|
611
638
|
|
|
612
639
|
expect(chain[0].txHash).toBe(response.txId!);
|
|
613
|
-
expect(chain[0].
|
|
640
|
+
expect(chain[0].uris[0]).toBe(
|
|
641
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v1.json"
|
|
642
|
+
);
|
|
643
|
+
expect(chain[0].httpsUrl).toBe(
|
|
614
644
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v1.json"
|
|
615
645
|
);
|
|
616
646
|
|
|
617
647
|
expect(chain[1].txHash).toBe(response2.txId!);
|
|
618
|
-
expect(chain[1].
|
|
648
|
+
expect(chain[1].uris[0]).toBe(
|
|
649
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
650
|
+
);
|
|
651
|
+
expect(chain[1].httpsUrl).toBe(
|
|
619
652
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v2.json"
|
|
620
653
|
);
|
|
621
654
|
|
|
622
655
|
expect(chain[2].txHash).toBe(response3.txId!);
|
|
623
|
-
expect(chain[2].
|
|
656
|
+
expect(chain[2].uris[0]).toBe(
|
|
657
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
658
|
+
);
|
|
659
|
+
expect(chain[2].httpsUrl).toBe(
|
|
624
660
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v3.json"
|
|
625
661
|
);
|
|
626
662
|
|
|
627
663
|
expect(chain[3].txHash).toBe(response4.txId!);
|
|
628
|
-
expect(chain[3].
|
|
664
|
+
expect(chain[3].uris[0]).toBe(
|
|
665
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v4.json"
|
|
666
|
+
);
|
|
667
|
+
expect(chain[3].httpsUrl).toBe(
|
|
629
668
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry_v4.json"
|
|
630
669
|
);
|
|
631
670
|
|
|
@@ -679,7 +718,10 @@ describe(`Test BCMR support`, () => {
|
|
|
679
718
|
expect(chain[0].contentHash).toBe(
|
|
680
719
|
"516d62577247354173703569476d557751486f67534a47525832367a75526e754c575079745a66694c3735735a76"
|
|
681
720
|
);
|
|
682
|
-
expect(chain[0].
|
|
721
|
+
expect(chain[0].uris[0]).toBe(
|
|
722
|
+
"ipfs://QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
723
|
+
);
|
|
724
|
+
expect(chain[0].httpsUrl).toBe(
|
|
683
725
|
"https://dweb.link/ipfs/QmbWrG5Asp5iGmUwQHogSJGRX26zuRnuLWPytZfiL75sZv"
|
|
684
726
|
);
|
|
685
727
|
expect(chain[0].txHash).toBe(genesisResponse.txId);
|
|
@@ -715,7 +757,10 @@ describe(`Test BCMR support`, () => {
|
|
|
715
757
|
});
|
|
716
758
|
expect(chain.length).toBe(1);
|
|
717
759
|
expect(chain[0].contentHash).toBe(binToHex(contentHashBin));
|
|
718
|
-
expect(chain[0].
|
|
760
|
+
expect(chain[0].uris[0]).toBe(
|
|
761
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
762
|
+
);
|
|
763
|
+
expect(chain[0].httpsUrl).toBe(
|
|
719
764
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
720
765
|
);
|
|
721
766
|
expect(chain[0].txHash).toBe(response.txId);
|
|
@@ -749,13 +794,19 @@ describe(`Test BCMR support`, () => {
|
|
|
749
794
|
});
|
|
750
795
|
expect(gappedChain.length).toBe(2);
|
|
751
796
|
expect(gappedChain[0].contentHash).toBe(binToHex(contentHashBin));
|
|
752
|
-
expect(gappedChain[0].
|
|
797
|
+
expect(gappedChain[0].uris[0]).toBe(
|
|
798
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
799
|
+
);
|
|
800
|
+
expect(gappedChain[0].httpsUrl).toBe(
|
|
753
801
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
754
802
|
);
|
|
755
803
|
expect(gappedChain[0].txHash).toBe(response.txId);
|
|
756
804
|
|
|
757
805
|
expect(gappedChain[1].contentHash).toBe(binToHex(contentHashBin));
|
|
758
|
-
expect(gappedChain[1].
|
|
806
|
+
expect(gappedChain[1].uris[0]).toBe(
|
|
807
|
+
"mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
808
|
+
);
|
|
809
|
+
expect(gappedChain[1].httpsUrl).toBe(
|
|
759
810
|
"https://mainnet.cash/.well-known/bitcoin-cash-metadata-registry.json"
|
|
760
811
|
);
|
|
761
812
|
expect(gappedChain[1].txHash).toBe(chainHeadResponse.txId);
|
package/src/wallet/Bcmr.ts
CHANGED
|
@@ -14,11 +14,13 @@ import ElectrumNetworkProvider from "../network/ElectrumNetworkProvider.js";
|
|
|
14
14
|
import { ElectrumRawTransaction } from "../network/interface.js";
|
|
15
15
|
import { IdentitySnapshot, Registry } from "./bcmr-v2.schema.js";
|
|
16
16
|
import { initProvider } from "../network/Connection.js";
|
|
17
|
+
import { OpReturnData } from "./model.js";
|
|
17
18
|
|
|
18
19
|
export interface AuthChainElement {
|
|
19
20
|
txHash: string;
|
|
20
21
|
contentHash: string;
|
|
21
|
-
|
|
22
|
+
uris: string[];
|
|
23
|
+
httpsUrl: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export type AuthChain = AuthChainElement[];
|
|
@@ -236,58 +238,62 @@ export class BCMR {
|
|
|
236
238
|
return {
|
|
237
239
|
txHash: hash,
|
|
238
240
|
contentHash: "",
|
|
239
|
-
|
|
241
|
+
uris: [],
|
|
242
|
+
httpsUrl: "",
|
|
240
243
|
};
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
const opReturnHex = opReturns[0];
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
let position = 1;
|
|
247
|
-
|
|
248
|
-
// handle direct push, OP_PUSHDATA1, OP_PUSHDATA2;
|
|
249
|
-
// OP_PUSHDATA4 is not supported in OP_RETURNs by consensus
|
|
250
|
-
while (opReturn[position]) {
|
|
251
|
-
let length = 0;
|
|
252
|
-
if (opReturn[position] === 0x4c) {
|
|
253
|
-
length = opReturn[position + 1];
|
|
254
|
-
position += 2;
|
|
255
|
-
} else if (opReturn[position] === 0x4d) {
|
|
256
|
-
length = binToNumberUint16LE(
|
|
257
|
-
opReturn.slice(position + 1, position + 3)
|
|
258
|
-
);
|
|
259
|
-
position += 3;
|
|
260
|
-
} else {
|
|
261
|
-
length = opReturn[position];
|
|
262
|
-
position += 1;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
chunks.push(opReturn.slice(position, position + length));
|
|
266
|
-
position += length;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (chunks.length < 2 || chunks.length > 3) {
|
|
247
|
+
const chunks = OpReturnData.parseBinary(hexToBin(opReturnHex));
|
|
248
|
+
if (chunks.length < 2) {
|
|
270
249
|
throw new Error(`Malformed BCMR output: ${opReturnHex}`);
|
|
271
250
|
}
|
|
272
251
|
|
|
273
252
|
const result: AuthChainElement = {
|
|
274
253
|
txHash: hash,
|
|
275
254
|
contentHash: "",
|
|
276
|
-
|
|
255
|
+
uris: [],
|
|
256
|
+
httpsUrl: "",
|
|
277
257
|
};
|
|
278
258
|
|
|
279
259
|
if (chunks.length === 2) {
|
|
280
260
|
// IPFS Publication Output
|
|
281
261
|
result.contentHash = binToHex(chunks[1]);
|
|
282
262
|
const ipfsCid = binToUtf8(chunks[1]);
|
|
283
|
-
result.
|
|
263
|
+
result.uris = [`ipfs://${ipfsCid}`];
|
|
264
|
+
result.httpsUrl = `https://dweb.link/ipfs/${ipfsCid}`;
|
|
284
265
|
} else {
|
|
285
|
-
//
|
|
266
|
+
// URI Publication Output
|
|
286
267
|
// content hash is in OP_SHA256 byte order per spec
|
|
287
268
|
result.contentHash = binToHex(chunks[1].slice());
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
269
|
+
|
|
270
|
+
const uris = chunks.slice(2);
|
|
271
|
+
|
|
272
|
+
for (const uri of uris) {
|
|
273
|
+
const uriString = binToUtf8(uri);
|
|
274
|
+
result.uris.push(uriString);
|
|
275
|
+
|
|
276
|
+
if (result.httpsUrl) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (uriString.indexOf("https://") === 0) {
|
|
281
|
+
result.httpsUrl = uriString;
|
|
282
|
+
} else if (uriString.indexOf("https://") === -1) {
|
|
283
|
+
result.httpsUrl = uriString;
|
|
284
|
+
|
|
285
|
+
// case for domain name specifier, like example.com
|
|
286
|
+
if (uriString.indexOf("/") === -1) {
|
|
287
|
+
result.httpsUrl = `${result.httpsUrl}/.well-known/bitcoin-cash-metadata-registry.json`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
result.httpsUrl = `https://${result.httpsUrl}`;
|
|
291
|
+
} else if (uriString.indexOf("ipfs://") === 0) {
|
|
292
|
+
const ipfsCid = uriString.replace("ipfs://", "");
|
|
293
|
+
result.httpsUrl = `https://dweb.link/ipfs/${ipfsCid}`;
|
|
294
|
+
} else {
|
|
295
|
+
throw new Error(`Unsupported uri type: ${uriString}`);
|
|
296
|
+
}
|
|
291
297
|
}
|
|
292
298
|
}
|
|
293
299
|
return result;
|
|
@@ -317,7 +323,7 @@ export class BCMR {
|
|
|
317
323
|
if (options.resolveBase) {
|
|
318
324
|
// check for accelerated path if "authchain" extension is in registry
|
|
319
325
|
const registry: Registry = await this.fetchMetadataRegistry(
|
|
320
|
-
element.
|
|
326
|
+
element.httpsUrl,
|
|
321
327
|
element.contentHash
|
|
322
328
|
);
|
|
323
329
|
if (
|
|
@@ -379,13 +385,13 @@ export class BCMR {
|
|
|
379
385
|
|
|
380
386
|
// combine the authchain element with the rest obtained
|
|
381
387
|
return [...chainBase, element, ...chainHead].filter(
|
|
382
|
-
(val) => val.
|
|
388
|
+
(val) => val.httpsUrl.length
|
|
383
389
|
);
|
|
384
390
|
}
|
|
385
391
|
}
|
|
386
392
|
|
|
387
393
|
// return the last chain element (or the only found in an edge case)
|
|
388
|
-
return [...chainBase, element].filter((val) => val.
|
|
394
|
+
return [...chainBase, element].filter((val) => val.httpsUrl.length);
|
|
389
395
|
}
|
|
390
396
|
|
|
391
397
|
/**
|
|
@@ -420,7 +426,7 @@ export class BCMR {
|
|
|
420
426
|
}
|
|
421
427
|
|
|
422
428
|
const registry = await this.fetchMetadataRegistry(
|
|
423
|
-
authChain.reverse()[0].
|
|
429
|
+
authChain.reverse()[0].httpsUrl
|
|
424
430
|
);
|
|
425
431
|
|
|
426
432
|
this.addMetadataRegistry(registry);
|