@helia/block-brokers 2.0.3 → 2.1.0-338885f
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.min.js +6 -1
- package/dist/src/bitswap.d.ts +5 -3
- package/dist/src/bitswap.d.ts.map +1 -1
- package/dist/src/bitswap.js +17 -6
- package/dist/src/bitswap.js.map +1 -1
- package/dist/src/trustless-gateway/broker.d.ts +24 -4
- package/dist/src/trustless-gateway/broker.d.ts.map +1 -1
- package/dist/src/trustless-gateway/broker.js +25 -4
- package/dist/src/trustless-gateway/broker.js.map +1 -1
- package/dist/src/trustless-gateway/index.d.ts +3 -2
- package/dist/src/trustless-gateway/index.d.ts.map +1 -1
- package/dist/src/trustless-gateway/index.js.map +1 -1
- package/dist/src/trustless-gateway/session.d.ts +25 -0
- package/dist/src/trustless-gateway/session.d.ts.map +1 -0
- package/dist/src/trustless-gateway/session.js +68 -0
- package/dist/src/trustless-gateway/session.js.map +1 -0
- package/dist/src/trustless-gateway/trustless-gateway.d.ts +11 -1
- package/dist/src/trustless-gateway/trustless-gateway.d.ts.map +1 -1
- package/dist/src/trustless-gateway/trustless-gateway.js +57 -17
- package/dist/src/trustless-gateway/trustless-gateway.js.map +1 -1
- package/package.json +14 -3
- package/src/bitswap.ts +26 -13
- package/src/trustless-gateway/broker.ts +48 -11
- package/src/trustless-gateway/index.ts +3 -2
- package/src/trustless-gateway/session.ts +98 -0
- package/src/trustless-gateway/trustless-gateway.ts +69 -17
- package/dist/typedoc-urls.json +0 -4
package/dist/src/bitswap.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { BitswapOptions } from '@helia/bitswap';
|
|
2
|
+
import type { BlockBroker, Routing } from '@helia/interface';
|
|
3
|
+
import type { Libp2p, ComponentLogger } from '@libp2p/interface';
|
|
3
4
|
import type { Blockstore } from 'interface-blockstore';
|
|
4
|
-
import type { BitswapOptions } from 'ipfs-bitswap';
|
|
5
5
|
import type { MultihashHasher } from 'multiformats/hashes/interface';
|
|
6
6
|
interface BitswapComponents {
|
|
7
7
|
libp2p: Libp2p;
|
|
8
8
|
blockstore: Blockstore;
|
|
9
9
|
hashers: Record<string, MultihashHasher>;
|
|
10
|
+
routing: Routing;
|
|
11
|
+
logger: ComponentLogger;
|
|
10
12
|
}
|
|
11
13
|
export interface BitswapInit extends BitswapOptions {
|
|
12
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitswap.d.ts","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"bitswap.d.ts","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAwE,MAAM,gBAAgB,CAAA;AAC1H,OAAO,KAAK,EAAwB,WAAW,EAA+C,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/H,OAAO,KAAK,EAAE,MAAM,EAAa,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAEpE,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc;CAElD;AAuED;;;GAGG;AACH,wBAAgB,OAAO,CAAE,IAAI,GAAE,WAAgB,GAAG,CAAC,UAAU,EAAE,iBAAiB,KAAK,WAAW,CAE/F"}
|
package/dist/src/bitswap.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { createBitswap } from '
|
|
1
|
+
import { createBitswap } from '@helia/bitswap';
|
|
2
2
|
class BitswapBlockBroker {
|
|
3
3
|
bitswap;
|
|
4
4
|
started;
|
|
5
5
|
constructor(components, init = {}) {
|
|
6
|
-
const {
|
|
7
|
-
this.bitswap = createBitswap(
|
|
6
|
+
const { hashers } = components;
|
|
7
|
+
this.bitswap = createBitswap(components, {
|
|
8
8
|
hashLoader: {
|
|
9
9
|
getHasher: async (codecOrName) => {
|
|
10
10
|
let hasher;
|
|
@@ -37,12 +37,23 @@ class BitswapBlockBroker {
|
|
|
37
37
|
await this.bitswap.stop();
|
|
38
38
|
this.started = false;
|
|
39
39
|
}
|
|
40
|
-
announce(cid, block, options) {
|
|
41
|
-
this.bitswap.notify(cid, block, options);
|
|
40
|
+
async announce(cid, block, options) {
|
|
41
|
+
await this.bitswap.notify(cid, block, options);
|
|
42
42
|
}
|
|
43
|
-
async retrieve(cid,
|
|
43
|
+
async retrieve(cid, options = {}) {
|
|
44
44
|
return this.bitswap.want(cid, options);
|
|
45
45
|
}
|
|
46
|
+
createSession(options) {
|
|
47
|
+
const session = this.bitswap.createSession(options);
|
|
48
|
+
return {
|
|
49
|
+
announce: async (cid, block, options) => {
|
|
50
|
+
await this.bitswap.notify(cid, block, options);
|
|
51
|
+
},
|
|
52
|
+
retrieve: async (cid, options) => {
|
|
53
|
+
return session.retrieve(cid, options);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
46
57
|
}
|
|
47
58
|
/**
|
|
48
59
|
* A helper factory for users who want to override Helia `blockBrokers` but
|
package/dist/src/bitswap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitswap.js","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"bitswap.js","sourceRoot":"","sources":["../../src/bitswap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAoB9C,MAAM,kBAAkB;IACL,OAAO,CAAS;IACzB,OAAO,CAAS;IAExB,YAAa,UAA6B,EAAE,OAAoB,EAAE;QAChE,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAA;QAE9B,IAAI,CAAC,OAAO,GAAG,aAAa,CAAC,UAAU,EAAE;YACvC,UAAU,EAAE;gBACV,SAAS,EAAE,KAAK,EAAE,WAA4B,EAAoC,EAAE;oBAClF,IAAI,MAAmC,CAAA;oBAEvC,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;wBACpC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;4BAC5C,OAAO,MAAM,CAAC,IAAI,KAAK,WAAW,CAAA;wBACpC,CAAC,CAAC,CAAA;oBACJ,CAAC;yBAAM,CAAC;wBACN,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;oBAC/B,CAAC;oBAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;wBACnB,OAAO,MAAM,CAAA;oBACf,CAAC;oBAED,MAAM,IAAI,KAAK,CAAC,wCAAwC,WAAW,GAAG,CAAC,CAAA;gBACzE,CAAC;aACF;YACD,GAAG,IAAI;SACR,CAAC,CAAA;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,KAAiB,EAAE,OAA2D;QACtG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAE,GAAQ,EAAE,UAAiE,EAAE;QAC3F,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC;IAED,aAAa,CAAE,OAA8D;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QAEnD,OAAO;YACL,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBACtC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;YAChD,CAAC;YAED,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;gBAC/B,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YACvC,CAAC;SACF,CAAA;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAE,OAAoB,EAAE;IAC7C,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AACjE,CAAC"}
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
import type { TrustlessGatewayBlockBrokerInit, TrustlessGatewayComponents, TrustlessGatewayGetBlockProgressEvents } from './index.js';
|
|
2
|
-
import type { BlockRetrievalOptions,
|
|
2
|
+
import type { BlockRetrievalOptions, BlockBroker, CreateSessionOptions } from '@helia/interface';
|
|
3
3
|
import type { CID } from 'multiformats/cid';
|
|
4
|
-
|
|
4
|
+
export interface CreateTrustlessGatewaySessionOptions extends CreateSessionOptions<TrustlessGatewayGetBlockProgressEvents> {
|
|
5
|
+
/**
|
|
6
|
+
* By default we will only connect to peers with HTTPS addresses, pass true
|
|
7
|
+
* to also connect to HTTP addresses.
|
|
8
|
+
*
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
allowInsecure?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* By default we will only connect to peers with public or DNS addresses, pass
|
|
14
|
+
* true to also connect to private addresses.
|
|
15
|
+
*
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
allowLocal?: boolean;
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* A class that accepts a list of trustless gateways that are queried
|
|
7
22
|
* for blocks.
|
|
8
23
|
*/
|
|
9
|
-
export declare class TrustlessGatewayBlockBroker implements
|
|
24
|
+
export declare class TrustlessGatewayBlockBroker implements BlockBroker<TrustlessGatewayGetBlockProgressEvents> {
|
|
25
|
+
private readonly components;
|
|
10
26
|
private readonly gateways;
|
|
27
|
+
private readonly routing;
|
|
11
28
|
private readonly log;
|
|
29
|
+
private readonly logger;
|
|
12
30
|
constructor(components: TrustlessGatewayComponents, init?: TrustlessGatewayBlockBrokerInit);
|
|
13
|
-
|
|
31
|
+
addGateway(gatewayOrUrl: string): void;
|
|
32
|
+
retrieve(cid: CID, options?: BlockRetrievalOptions<TrustlessGatewayGetBlockProgressEvents>): Promise<Uint8Array>;
|
|
33
|
+
createSession(options?: CreateTrustlessGatewaySessionOptions): BlockBroker<TrustlessGatewayGetBlockProgressEvents>;
|
|
14
34
|
}
|
|
15
35
|
//# sourceMappingURL=broker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"broker.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,+BAA+B,EAAE,0BAA0B,EAAE,sCAAsC,EAAE,MAAM,YAAY,CAAA;AACrI,OAAO,KAAK,EAAW,qBAAqB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAEzG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,WAAW,oCAAqC,SAAQ,oBAAoB,CAAC,sCAAsC,CAAC;IACxH;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED;;;GAGG;AACH,qBAAa,2BAA4B,YAAW,WAAW,CAAC,sCAAsC,CAAC;IACrG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE3B,UAAU,EAAE,0BAA0B,EAAE,IAAI,GAAE,+BAAoC;IAW/F,UAAU,CAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAIjC,QAAQ,CAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,qBAAqB,CAAC,sCAAsC,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA2C3H,aAAa,CAAE,OAAO,GAAE,oCAAyC,GAAG,WAAW,CAAC,sCAAsC,CAAC;CAMxH"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createTrustlessGatewaySession } from './session.js';
|
|
1
2
|
import { TrustlessGateway } from './trustless-gateway.js';
|
|
2
3
|
import { DEFAULT_TRUSTLESS_GATEWAYS } from './index.js';
|
|
3
4
|
/**
|
|
@@ -5,15 +6,24 @@ import { DEFAULT_TRUSTLESS_GATEWAYS } from './index.js';
|
|
|
5
6
|
* for blocks.
|
|
6
7
|
*/
|
|
7
8
|
export class TrustlessGatewayBlockBroker {
|
|
9
|
+
components;
|
|
8
10
|
gateways;
|
|
11
|
+
routing;
|
|
9
12
|
log;
|
|
13
|
+
logger;
|
|
10
14
|
constructor(components, init = {}) {
|
|
15
|
+
this.components = components;
|
|
11
16
|
this.log = components.logger.forComponent('helia:trustless-gateway-block-broker');
|
|
17
|
+
this.logger = components.logger;
|
|
18
|
+
this.routing = components.routing;
|
|
12
19
|
this.gateways = (init.gateways ?? DEFAULT_TRUSTLESS_GATEWAYS)
|
|
13
20
|
.map((gatewayOrUrl) => {
|
|
14
|
-
return new TrustlessGateway(gatewayOrUrl);
|
|
21
|
+
return new TrustlessGateway(gatewayOrUrl, components.logger);
|
|
15
22
|
});
|
|
16
23
|
}
|
|
24
|
+
addGateway(gatewayOrUrl) {
|
|
25
|
+
this.gateways.push(new TrustlessGateway(gatewayOrUrl, this.components.logger));
|
|
26
|
+
}
|
|
17
27
|
async retrieve(cid, options = {}) {
|
|
18
28
|
// Loop through the gateways until we get a block or run out of gateways
|
|
19
29
|
// TODO: switch to toSorted when support is better
|
|
@@ -30,7 +40,7 @@ export class TrustlessGatewayBlockBroker {
|
|
|
30
40
|
catch (err) {
|
|
31
41
|
this.log.error('failed to validate block for %c from %s', cid, gateway.url, err);
|
|
32
42
|
gateway.incrementInvalidBlocks();
|
|
33
|
-
throw new Error(`
|
|
43
|
+
throw new Error(`Block for CID ${cid} from gateway ${gateway.url} failed validation`);
|
|
34
44
|
}
|
|
35
45
|
return block;
|
|
36
46
|
}
|
|
@@ -40,7 +50,7 @@ export class TrustlessGatewayBlockBroker {
|
|
|
40
50
|
aggregateErrors.push(err);
|
|
41
51
|
}
|
|
42
52
|
else {
|
|
43
|
-
aggregateErrors.push(new Error(`
|
|
53
|
+
aggregateErrors.push(new Error(`Unable to fetch raw block for CID ${cid} from gateway ${gateway.url}`));
|
|
44
54
|
}
|
|
45
55
|
// if signal was aborted, exit the loop
|
|
46
56
|
if (options.signal?.aborted === true) {
|
|
@@ -49,7 +59,18 @@ export class TrustlessGatewayBlockBroker {
|
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
61
|
}
|
|
52
|
-
|
|
62
|
+
if (aggregateErrors.length > 0) {
|
|
63
|
+
throw new AggregateError(aggregateErrors, `Unable to fetch raw block for CID ${cid} from any gateway`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw new Error(`Unable to fetch raw block for CID ${cid} from any gateway`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
createSession(options = {}) {
|
|
70
|
+
return createTrustlessGatewaySession({
|
|
71
|
+
logger: this.logger,
|
|
72
|
+
routing: this.routing
|
|
73
|
+
}, options);
|
|
53
74
|
}
|
|
54
75
|
}
|
|
55
76
|
//# sourceMappingURL=broker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../../src/trustless-gateway/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Routing, BlockBroker } from '@helia/interface';
|
|
2
2
|
import type { ComponentLogger } from '@libp2p/interface';
|
|
3
3
|
import type { ProgressEvent } from 'progress-events';
|
|
4
4
|
export declare const DEFAULT_TRUSTLESS_GATEWAYS: string[];
|
|
@@ -7,7 +7,8 @@ export interface TrustlessGatewayBlockBrokerInit {
|
|
|
7
7
|
gateways?: Array<string | URL>;
|
|
8
8
|
}
|
|
9
9
|
export interface TrustlessGatewayComponents {
|
|
10
|
+
routing: Routing;
|
|
10
11
|
logger: ComponentLogger;
|
|
11
12
|
}
|
|
12
|
-
export declare function trustlessGateway(init?: TrustlessGatewayBlockBrokerInit): (components: TrustlessGatewayComponents) =>
|
|
13
|
+
export declare function trustlessGateway(init?: TrustlessGatewayBlockBrokerInit): (components: TrustlessGatewayComponents) => BlockBroker<TrustlessGatewayGetBlockProgressEvents>;
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,eAAO,MAAM,0BAA0B,UAStC,CAAA;AAED,MAAM,MAAM,sCAAsC,GAChD,aAAa,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;AAEzD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,wBAAgB,gBAAgB,CAAE,IAAI,GAAE,+BAAoC,GAAG,CAAC,UAAU,EAAE,0BAA0B,KAAK,WAAW,CAAC,sCAAsC,CAAC,CAE7K"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/trustless-gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAKzD,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,wGAAwG;IACxG,gCAAgC;IAEhC,wGAAwG;IACxG,6BAA6B;IAE7B,wGAAwG;IACxG,sBAAsB;CACvB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/trustless-gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAKzD,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,wGAAwG;IACxG,gCAAgC;IAEhC,wGAAwG;IACxG,6BAA6B;IAE7B,wGAAwG;IACxG,sBAAsB;CACvB,CAAA;AAcD,MAAM,UAAU,gBAAgB,CAAE,OAAwC,EAAE;IAC1E,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,2BAA2B,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;AAC1E,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AbstractSession } from '@helia/utils';
|
|
2
|
+
import { TrustlessGateway } from './trustless-gateway.js';
|
|
3
|
+
import type { CreateTrustlessGatewaySessionOptions } from './broker.js';
|
|
4
|
+
import type { TrustlessGatewayGetBlockProgressEvents } from './index.js';
|
|
5
|
+
import type { BlockRetrievalOptions, Routing } from '@helia/interface';
|
|
6
|
+
import type { ComponentLogger } from '@libp2p/interface';
|
|
7
|
+
import type { AbortOptions } from 'interface-store';
|
|
8
|
+
import type { CID } from 'multiformats/cid';
|
|
9
|
+
export interface TrustlessGatewaySessionComponents {
|
|
10
|
+
logger: ComponentLogger;
|
|
11
|
+
routing: Routing;
|
|
12
|
+
}
|
|
13
|
+
declare class TrustlessGatewaySession extends AbstractSession<TrustlessGateway, TrustlessGatewayGetBlockProgressEvents> {
|
|
14
|
+
private readonly routing;
|
|
15
|
+
private readonly allowInsecure;
|
|
16
|
+
private readonly allowLocal;
|
|
17
|
+
constructor(components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions);
|
|
18
|
+
queryProvider(cid: CID, provider: TrustlessGateway, options: BlockRetrievalOptions): Promise<Uint8Array>;
|
|
19
|
+
findNewProviders(cid: CID, options?: AbortOptions): AsyncGenerator<TrustlessGateway>;
|
|
20
|
+
toEvictionKey(provider: TrustlessGateway): Uint8Array | string;
|
|
21
|
+
equals(providerA: TrustlessGateway, providerB: TrustlessGateway): boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function createTrustlessGatewaySession(components: TrustlessGatewaySessionComponents, init: CreateTrustlessGatewaySessionOptions): TrustlessGatewaySession;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAI9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,YAAY,CAAA;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAK3C,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,cAAM,uBAAwB,SAAQ,eAAe,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;IAC7G,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAEvB,UAAU,EAAE,iCAAiC,EAAE,IAAI,EAAE,oCAAoC;IAWhG,aAAa,CAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;IAWvG,gBAAgB,CAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,YAAiB,GAAG,cAAc,CAAC,gBAAgB,CAAC;IAoBjG,aAAa,CAAE,QAAQ,EAAE,gBAAgB,GAAG,UAAU,GAAG,MAAM;IAI/D,MAAM,CAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,GAAG,OAAO;CAG3E;AAoBD,wBAAgB,6BAA6B,CAAE,UAAU,EAAE,iCAAiC,EAAE,IAAI,EAAE,oCAAoC,GAAG,uBAAuB,CAEjK"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { AbstractSession } from '@helia/utils';
|
|
2
|
+
import { isPrivateIp } from '@libp2p/utils/private-ip';
|
|
3
|
+
import { DNS, HTTP, HTTPS } from '@multiformats/multiaddr-matcher';
|
|
4
|
+
import { multiaddrToUri } from '@multiformats/multiaddr-to-uri';
|
|
5
|
+
import { TrustlessGateway } from './trustless-gateway.js';
|
|
6
|
+
const DEFAULT_ALLOW_INSECURE = false;
|
|
7
|
+
const DEFAULT_ALLOW_LOCAL = false;
|
|
8
|
+
class TrustlessGatewaySession extends AbstractSession {
|
|
9
|
+
routing;
|
|
10
|
+
allowInsecure;
|
|
11
|
+
allowLocal;
|
|
12
|
+
constructor(components, init) {
|
|
13
|
+
super(components, {
|
|
14
|
+
...init,
|
|
15
|
+
name: 'helia:trustless-gateway:session'
|
|
16
|
+
});
|
|
17
|
+
this.routing = components.routing;
|
|
18
|
+
this.allowInsecure = init.allowInsecure ?? DEFAULT_ALLOW_INSECURE;
|
|
19
|
+
this.allowLocal = init.allowLocal ?? DEFAULT_ALLOW_LOCAL;
|
|
20
|
+
}
|
|
21
|
+
async queryProvider(cid, provider, options) {
|
|
22
|
+
this.log('fetching BLOCK for %c from %s', cid, provider.url);
|
|
23
|
+
const block = await provider.getRawBlock(cid, options.signal);
|
|
24
|
+
this.log.trace('got block for %c from %s', cid, provider.url);
|
|
25
|
+
await options.validateFn?.(block);
|
|
26
|
+
return block;
|
|
27
|
+
}
|
|
28
|
+
async *findNewProviders(cid, options = {}) {
|
|
29
|
+
for await (const provider of this.routing.findProviders(cid, options)) {
|
|
30
|
+
// require http(s) addresses
|
|
31
|
+
const httpAddresses = filterMultiaddrs(provider.multiaddrs, this.allowInsecure, this.allowLocal);
|
|
32
|
+
if (httpAddresses.length === 0) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// take first address?
|
|
36
|
+
// /ip4/x.x.x.x/tcp/31337/http
|
|
37
|
+
// /ip4/x.x.x.x/tcp/31337/https
|
|
38
|
+
// etc
|
|
39
|
+
const uri = multiaddrToUri(httpAddresses[0]);
|
|
40
|
+
this.log('found http-gateway provider %p %s for cid %c', provider.id, uri, cid);
|
|
41
|
+
yield new TrustlessGateway(uri, this.logger);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
toEvictionKey(provider) {
|
|
45
|
+
return provider.url.toString();
|
|
46
|
+
}
|
|
47
|
+
equals(providerA, providerB) {
|
|
48
|
+
return providerA.url.toString() === providerB.url.toString();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function filterMultiaddrs(multiaddrs, allowInsecure, allowLocal) {
|
|
52
|
+
return multiaddrs.filter(ma => {
|
|
53
|
+
if (HTTPS.matches(ma) || (allowInsecure && HTTP.matches(ma))) {
|
|
54
|
+
if (allowLocal) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (DNS.matches(ma)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return isPrivateIp(ma.toOptions().host) === false;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function createTrustlessGatewaySession(components, init) {
|
|
66
|
+
return new TrustlessGatewaySession(components, init);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/trustless-gateway/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import type { ComponentLogger } from '@libp2p/interface';
|
|
1
2
|
import type { CID } from 'multiformats/cid';
|
|
3
|
+
export interface TrustlessGatewayStats {
|
|
4
|
+
attempts: number;
|
|
5
|
+
errors: number;
|
|
6
|
+
invalidBlocks: number;
|
|
7
|
+
successes: number;
|
|
8
|
+
pendingResponses?: number;
|
|
9
|
+
}
|
|
2
10
|
/**
|
|
3
11
|
* A `TrustlessGateway` keeps track of the number of attempts, errors, and
|
|
4
12
|
* successes for a given gateway url so that we can prioritize gateways that
|
|
@@ -8,7 +16,8 @@ import type { CID } from 'multiformats/cid';
|
|
|
8
16
|
export declare class TrustlessGateway {
|
|
9
17
|
#private;
|
|
10
18
|
readonly url: URL;
|
|
11
|
-
|
|
19
|
+
private readonly log;
|
|
20
|
+
constructor(url: URL | string, logger: ComponentLogger);
|
|
12
21
|
/**
|
|
13
22
|
* Fetch a raw block from `this.url` following the specification defined at
|
|
14
23
|
* https://specs.ipfs.tech/http-gateways/trustless-gateway/
|
|
@@ -27,5 +36,6 @@ export declare class TrustlessGateway {
|
|
|
27
36
|
* Increment the number of invalid blocks returned by this gateway.
|
|
28
37
|
*/
|
|
29
38
|
incrementInvalidBlocks(): void;
|
|
39
|
+
getStats(): TrustlessGatewayStats;
|
|
30
40
|
}
|
|
31
41
|
//# sourceMappingURL=trustless-gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trustless-gateway.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trustless-gateway.d.ts","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,mBAAmB,CAAA;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;;IAC3B,SAAgB,GAAG,EAAE,GAAG,CAAA;IAoCxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEf,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,MAAM,EAAE,eAAe;IAmBvD;;;OAGG;IACG,WAAW,CAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAgDvE;;;;;;;OAOG;IACH,WAAW,IAAK,MAAM;IAyBtB;;OAEG;IACH,sBAAsB,IAAK,IAAI;IAI/B,QAAQ,IAAK,qBAAqB;CASnC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { base64 } from 'multiformats/bases/base64';
|
|
1
2
|
/**
|
|
2
3
|
* A `TrustlessGateway` keeps track of the number of attempts, errors, and
|
|
3
4
|
* successes for a given gateway url so that we can prioritize gateways that
|
|
@@ -30,15 +31,36 @@ export class TrustlessGateway {
|
|
|
30
31
|
* The number of times this gateway has successfully fetched a block.
|
|
31
32
|
*/
|
|
32
33
|
#successes = 0;
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* A map of pending responses for this gateway. This is used to ensure that
|
|
36
|
+
* only one request per CID is made to a given gateway at a time, and that we
|
|
37
|
+
* don't make multiple in-flight requests for the same CID to the same gateway.
|
|
38
|
+
*/
|
|
39
|
+
#pendingResponses = new Map();
|
|
40
|
+
log;
|
|
41
|
+
constructor(url, logger) {
|
|
34
42
|
this.url = url instanceof URL ? url : new URL(url);
|
|
43
|
+
this.log = logger.forComponent(`helia:trustless-gateway-block-broker:${this.url.hostname}`);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* This function returns a unique string for the multihash.bytes of the CID.
|
|
47
|
+
*
|
|
48
|
+
* Some useful resources for why this is needed can be found using the links below:
|
|
49
|
+
*
|
|
50
|
+
* - https://github.com/ipfs/helia/pull/503#discussion_r1572451331
|
|
51
|
+
* - https://github.com/ipfs/kubo/issues/6815
|
|
52
|
+
* - https://www.notion.so/pl-strflt/Handling-ambiguity-around-CIDs-9d5e14f6516f438980b01ef188efe15d#d9d45cd1ed8b4d349b96285de4aed5ab
|
|
53
|
+
*/
|
|
54
|
+
#uniqueBlockId(cid) {
|
|
55
|
+
const multihashBytes = cid.multihash.bytes;
|
|
56
|
+
return base64.encode(multihashBytes);
|
|
35
57
|
}
|
|
36
58
|
/**
|
|
37
59
|
* Fetch a raw block from `this.url` following the specification defined at
|
|
38
60
|
* https://specs.ipfs.tech/http-gateways/trustless-gateway/
|
|
39
61
|
*/
|
|
40
62
|
async getRawBlock(cid, signal) {
|
|
41
|
-
const gwUrl = this.url;
|
|
63
|
+
const gwUrl = new URL(this.url.toString());
|
|
42
64
|
gwUrl.pathname = `/ipfs/${cid.toString()}`;
|
|
43
65
|
// necessary as not every gateway supports dag-cbor, but every should support
|
|
44
66
|
// sending raw block as-is
|
|
@@ -46,23 +68,29 @@ export class TrustlessGateway {
|
|
|
46
68
|
if (signal?.aborted === true) {
|
|
47
69
|
throw new Error(`Signal to fetch raw block for CID ${cid} from gateway ${this.url} was aborted prior to fetch`);
|
|
48
70
|
}
|
|
71
|
+
const blockId = this.#uniqueBlockId(cid);
|
|
49
72
|
try {
|
|
50
|
-
this.#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
let pendingResponse = this.#pendingResponses.get(blockId);
|
|
74
|
+
if (pendingResponse == null) {
|
|
75
|
+
this.#attempts++;
|
|
76
|
+
pendingResponse = fetch(gwUrl.toString(), {
|
|
77
|
+
signal,
|
|
78
|
+
headers: {
|
|
79
|
+
Accept: 'application/vnd.ipld.raw'
|
|
80
|
+
},
|
|
81
|
+
cache: 'force-cache'
|
|
82
|
+
}).then(async (res) => {
|
|
83
|
+
this.log('GET %s %d', gwUrl, res.status);
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
this.#errors++;
|
|
86
|
+
throw new Error(`unable to fetch raw block for CID ${cid} from gateway ${this.url}`);
|
|
87
|
+
}
|
|
88
|
+
this.#successes++;
|
|
89
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
90
|
+
});
|
|
91
|
+
this.#pendingResponses.set(blockId, pendingResponse);
|
|
63
92
|
}
|
|
64
|
-
|
|
65
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
93
|
+
return await pendingResponse;
|
|
66
94
|
}
|
|
67
95
|
catch (cause) {
|
|
68
96
|
// @ts-expect-error - TS thinks signal?.aborted can only be false now
|
|
@@ -73,6 +101,9 @@ export class TrustlessGateway {
|
|
|
73
101
|
this.#errors++;
|
|
74
102
|
throw new Error(`unable to fetch raw block for CID ${cid}`);
|
|
75
103
|
}
|
|
104
|
+
finally {
|
|
105
|
+
this.#pendingResponses.delete(blockId);
|
|
106
|
+
}
|
|
76
107
|
}
|
|
77
108
|
/**
|
|
78
109
|
* Encapsulate the logic for determining whether a gateway is considered
|
|
@@ -110,5 +141,14 @@ export class TrustlessGateway {
|
|
|
110
141
|
incrementInvalidBlocks() {
|
|
111
142
|
this.#invalidBlocks++;
|
|
112
143
|
}
|
|
144
|
+
getStats() {
|
|
145
|
+
return {
|
|
146
|
+
attempts: this.#attempts,
|
|
147
|
+
errors: this.#errors,
|
|
148
|
+
invalidBlocks: this.#invalidBlocks,
|
|
149
|
+
successes: this.#successes,
|
|
150
|
+
pendingResponses: this.#pendingResponses.size
|
|
151
|
+
};
|
|
152
|
+
}
|
|
113
153
|
}
|
|
114
154
|
//# sourceMappingURL=trustless-gateway.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trustless-gateway.js","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"trustless-gateway.js","sourceRoot":"","sources":["../../../src/trustless-gateway/trustless-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAYlD;;;;;GAKG;AACH,MAAM,OAAO,gBAAgB;IACX,GAAG,CAAK;IACxB;;;;;OAKG;IACH,SAAS,GAAG,CAAC,CAAA;IAEb;;;;;OAKG;IACH,OAAO,GAAG,CAAC,CAAA;IAEX;;;;OAIG;IACH,cAAc,GAAG,CAAC,CAAA;IAElB;;OAEG;IACH,UAAU,GAAG,CAAC,CAAA;IAEd;;;;OAIG;IACH,iBAAiB,GAAG,IAAI,GAAG,EAA+B,CAAA;IAEzC,GAAG,CAAQ;IAE5B,YAAa,GAAiB,EAAE,MAAuB;QACrD,IAAI,CAAC,GAAG,GAAG,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAClD,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,wCAAwC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED;;;;;;;;OAQG;IACH,cAAc,CAAE,GAAQ;QACtB,MAAM,cAAc,GAAG,GAAG,CAAC,SAAS,CAAC,KAAK,CAAA;QAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IACtC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAE,GAAQ,EAAE,MAAoB;QAC/C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC1C,KAAK,CAAC,QAAQ,GAAG,SAAS,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAA;QAE1C,6EAA6E;QAC7E,0BAA0B;QAC1B,KAAK,CAAC,MAAM,GAAG,aAAa,CAAA;QAE5B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,iBAAiB,IAAI,CAAC,GAAG,6BAA6B,CAAC,CAAA;QACjH,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;QACxC,IAAI,CAAC;YACH,IAAI,eAAe,GAAoC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC1F,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,SAAS,EAAE,CAAA;gBAChB,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE;oBACxC,MAAM;oBACN,OAAO,EAAE;wBACP,MAAM,EAAE,0BAA0B;qBACnC;oBACD,KAAK,EAAE,aAAa;iBACrB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACpB,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;oBACxC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;wBACZ,IAAI,CAAC,OAAO,EAAE,CAAA;wBACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;oBACtF,CAAC;oBACD,IAAI,CAAC,UAAU,EAAE,CAAA;oBACjB,OAAO,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;gBAChD,CAAC,CAAC,CAAA;gBACF,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;YACtD,CAAC;YACD,OAAO,MAAM,eAAe,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qEAAqE;YACrE,yCAAyC;YACzC,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,iBAAiB,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;YAC3F,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,EAAE,CAAC,CAAA;QAC7D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,WAAW;QACT;;;WAGG;QACH,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,CAAA;QACV,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;YAC5B,wCAAwC;YACxC,OAAO,CAAC,QAAQ,CAAA;QAClB,CAAC;QAED;;;;;;;WAOG;QACH,OAAO,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;IAChE,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,IAAI,CAAC,cAAc,EAAE,CAAA;IACvB,CAAC;IAED,QAAQ;QACN,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,aAAa,EAAE,IAAI,CAAC,cAAc;YAClC,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI;SAC9C,CAAA;IACH,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helia/block-brokers",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0-338885f",
|
|
4
4
|
"description": "Block brokers for Helia",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/ipfs/helia/tree/main/packages/block-brokers#readme",
|
|
@@ -53,17 +53,28 @@
|
|
|
53
53
|
"test:electron-main": "aegir test -t electron-main"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@helia/
|
|
56
|
+
"@helia/bitswap": "1.0.0-338885f",
|
|
57
|
+
"@helia/interface": "4.2.0-338885f",
|
|
58
|
+
"@helia/utils": "0.2.0-338885f",
|
|
57
59
|
"@libp2p/interface": "^1.1.4",
|
|
60
|
+
"@libp2p/utils": "^5.2.6",
|
|
61
|
+
"@multiformats/multiaddr": "^12.2.1",
|
|
62
|
+
"@multiformats/multiaddr-matcher": "^1.2.0",
|
|
63
|
+
"@multiformats/multiaddr-to-uri": "^10.0.1",
|
|
58
64
|
"interface-blockstore": "^5.2.10",
|
|
59
|
-
"
|
|
65
|
+
"interface-store": "^5.1.8",
|
|
60
66
|
"multiformats": "^13.1.0",
|
|
61
67
|
"progress-events": "^1.0.0"
|
|
62
68
|
},
|
|
63
69
|
"devDependencies": {
|
|
64
70
|
"@libp2p/logger": "^4.0.7",
|
|
71
|
+
"@libp2p/peer-id-factory": "^4.0.7",
|
|
72
|
+
"@multiformats/uri-to-multiaddr": "^8.0.0",
|
|
73
|
+
"@types/polka": "^0.5.7",
|
|
65
74
|
"@types/sinon": "^17.0.3",
|
|
66
75
|
"aegir": "^42.2.5",
|
|
76
|
+
"cors": "^2.8.5",
|
|
77
|
+
"polka": "^0.5.2",
|
|
67
78
|
"sinon": "^17.0.1",
|
|
68
79
|
"sinon-ts": "^2.0.0"
|
|
69
80
|
}
|
package/src/bitswap.ts
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import { createBitswap } from '
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import { createBitswap } from '@helia/bitswap'
|
|
2
|
+
import type { BitswapOptions, Bitswap, BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents } from '@helia/bitswap'
|
|
3
|
+
import type { BlockAnnounceOptions, BlockBroker, BlockRetrievalOptions, CreateSessionOptions, Routing } from '@helia/interface'
|
|
4
|
+
import type { Libp2p, Startable, ComponentLogger } from '@libp2p/interface'
|
|
4
5
|
import type { Blockstore } from 'interface-blockstore'
|
|
5
|
-
import type { Bitswap, BitswapNotifyProgressEvents, BitswapOptions, BitswapWantBlockProgressEvents } from 'ipfs-bitswap'
|
|
6
6
|
import type { CID } from 'multiformats/cid'
|
|
7
7
|
import type { MultihashHasher } from 'multiformats/hashes/interface'
|
|
8
|
-
import type { ProgressOptions } from 'progress-events'
|
|
9
8
|
|
|
10
9
|
interface BitswapComponents {
|
|
11
10
|
libp2p: Libp2p
|
|
12
11
|
blockstore: Blockstore
|
|
13
12
|
hashers: Record<string, MultihashHasher>
|
|
13
|
+
routing: Routing
|
|
14
|
+
logger: ComponentLogger
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export interface BitswapInit extends BitswapOptions {
|
|
17
18
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
class BitswapBlockBroker implements
|
|
21
|
-
ProgressOptions<BitswapWantBlockProgressEvents>
|
|
22
|
-
>, Startable {
|
|
21
|
+
class BitswapBlockBroker implements BlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents>, Startable {
|
|
23
22
|
private readonly bitswap: Bitswap
|
|
24
23
|
private started: boolean
|
|
25
24
|
|
|
26
25
|
constructor (components: BitswapComponents, init: BitswapInit = {}) {
|
|
27
|
-
const {
|
|
26
|
+
const { hashers } = components
|
|
28
27
|
|
|
29
|
-
this.bitswap = createBitswap(
|
|
28
|
+
this.bitswap = createBitswap(components, {
|
|
30
29
|
hashLoader: {
|
|
31
30
|
getHasher: async (codecOrName: string | number): Promise<MultihashHasher<number>> => {
|
|
32
31
|
let hasher: MultihashHasher | undefined
|
|
@@ -65,13 +64,27 @@ ProgressOptions<BitswapWantBlockProgressEvents>
|
|
|
65
64
|
this.started = false
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
announce (cid: CID, block: Uint8Array, options?:
|
|
69
|
-
this.bitswap.notify(cid, block, options)
|
|
67
|
+
async announce (cid: CID, block: Uint8Array, options?: BlockAnnounceOptions<BitswapNotifyProgressEvents>): Promise<void> {
|
|
68
|
+
await this.bitswap.notify(cid, block, options)
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
async retrieve (cid: CID,
|
|
71
|
+
async retrieve (cid: CID, options: BlockRetrievalOptions<BitswapWantBlockProgressEvents> = {}): Promise<Uint8Array> {
|
|
73
72
|
return this.bitswap.want(cid, options)
|
|
74
73
|
}
|
|
74
|
+
|
|
75
|
+
createSession (options?: CreateSessionOptions<BitswapWantBlockProgressEvents>): BlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents> {
|
|
76
|
+
const session = this.bitswap.createSession(options)
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
announce: async (cid, block, options) => {
|
|
80
|
+
await this.bitswap.notify(cid, block, options)
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
retrieve: async (cid, options) => {
|
|
84
|
+
return session.retrieve(cid, options)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
/**
|