Skip to content

fix!: remove @libp2p/components #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# @libp2p/delegated-content-routing <!-- omit in toc -->

[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
[![IRC](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p)
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-delegated-content-routing.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-delegated-content-routing)
[![CI](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-interfaces/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/libp2p/js-libp2p-delegated-content-routing/actions/workflows/js-test-and-release.yml)
[![CI](https://img.shields.io/github/workflow/status/libp2p/js-libp2p-delegated-content-routing/test%20&%20maybe%20release/master?style=flat-square)](https://github.com/libp2p/js-libp2p-delegated-content-routing/actions/workflows/js-test-and-release.yml)

> Leverage other peers in the libp2p network to perform Content Routing calls.

Expand Down Expand Up @@ -37,24 +36,29 @@ npm install ipfs-http-client @libp2p/delegated-content-routing
## Example

```js
import { DelegatedContentRouting } from '@libp2p/delegated-content-routing'
import ipfsHttpClient from 'ipfs-http-client'
import { createLibp2p } from 'libp2p'
import { delegatedContentRouting } from '@libp2p/delegated-content-routing'
import { create as createIpfsHttpClient } from 'ipfs-http-client')

// default is to use ipfs.io
const routing = new DelegatedContentRouting(peerId, ipfsHttpClient.create({
const client = createIpfsHttpClient({
// use default api settings
protocol: 'https',
port: 443,
host: 'node0.delegate.ipfs.io' // In production you should setup your own delegates
}))
const cid = new CID('QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv')

for await (const { id, multiaddrs } of routing.findProviders(cid)) {
console.log('found peer', id, multiaddrs)
host: 'node0.delegate.ipfs.io'
})

const node = await createLibp2p({
peerRouting: [
delegatedContentRouting(client)
]
//.. other config
})
await node.start()

for await (const provider of node.contentRouting.findProviders('cid')) {
console.log('provider', provider)
}

await routing.provide(cid)
console.log('providing %s', cid.toBaseEncodedString())
```

## License
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,18 +143,20 @@
"any-signal": "^3.0.1",
"err-code": "^3.0.1",
"it-drain": "^1.0.5",
"multiformats": "^10.0.0",
"p-defer": "^4.0.0",
"p-queue": "^7.2.0"
},
"devDependencies": {
"aegir": "^37.5.3",
"go-ipfs": "^0.15.0",
"go-ipfs": "^0.16.0",
"ipfs-core-types": "^0.12.0",
"ipfs-http-client": "^58.0.0",
"ipfsd-ctl": "^12.0.2",
"it-all": "^1.0.6",
"it-drain": "^1.0.5",
"uint8arrays": "^3.0.0",
"timeout-abort-controller": "^3.0.0",
"uint8arrays": "^4.0.2",
"wherearewe": "^2.0.1"
},
"browser": {
Expand Down
127 changes: 123 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,138 @@ import PQueue from 'p-queue'
import defer from 'p-defer'
import errCode from 'err-code'
import anySignal from 'any-signal'
import type { IPFSHTTPClient, CID, HTTPClientExtraOptions } from 'ipfs-http-client'
import type { AbortOptions } from 'ipfs-core-types/src/utils'
import type { ContentRouting } from '@libp2p/interface-content-routing'
import type { PeerInfo } from '@libp2p/interface-peer-info'
import type { Startable } from '@libp2p/interfaces/startable'
import type { CID } from 'multiformats/cid'
import type { PeerId } from '@libp2p/interface-peer-id'

const log = logger('libp2p:delegated-content-routing')

const DEFAULT_TIMEOUT = 30e3 // 30 second default
const CONCURRENT_HTTP_REQUESTS = 4
const CONCURRENT_HTTP_REFS_REQUESTS = 2

export interface HTTPClientExtraOptions {
headers?: Record<string, string>
searchParams?: URLSearchParams
}

export enum EventTypes {
SENDING_QUERY = 0,
PEER_RESPONSE,
FINAL_PEER,
QUERY_ERROR,
PROVIDER,
VALUE,
ADDING_PEER,
DIALING_PEER
}

/**
* The types of messages set/received during DHT queries
*/
export enum MessageType {
PUT_VALUE = 0,
GET_VALUE,
ADD_PROVIDER,
GET_PROVIDERS,
FIND_NODE,
PING
}

export type MessageName = keyof typeof MessageType

export interface DHTRecord {
key: Uint8Array
value: Uint8Array
timeReceived?: Date
}

export interface SendingQueryEvent {
type: EventTypes.SENDING_QUERY
name: 'SENDING_QUERY'
}

export interface PeerResponseEvent {
from: PeerId
type: EventTypes.PEER_RESPONSE
name: 'PEER_RESPONSE'
messageType: MessageType
messageName: MessageName
providers: PeerInfo[]
closer: PeerInfo[]
record?: DHTRecord
}

export interface FinalPeerEvent {
peer: PeerInfo
type: EventTypes.FINAL_PEER
name: 'FINAL_PEER'
}

export interface QueryErrorEvent {
type: EventTypes.QUERY_ERROR
name: 'QUERY_ERROR'
error: Error
}

export interface ProviderEvent {
type: EventTypes.PROVIDER
name: 'PROVIDER'
providers: PeerInfo[]
}

export interface ValueEvent {
type: EventTypes.VALUE
name: 'VALUE'
value: Uint8Array
}

export interface AddingPeerEvent {
type: EventTypes.ADDING_PEER
name: 'ADDING_PEER'
peer: PeerId
}

export interface DialingPeerEvent {
peer: PeerId
type: EventTypes.DIALING_PEER
name: 'DIALING_PEER'
}

export type QueryEvent = SendingQueryEvent | PeerResponseEvent | FinalPeerEvent | QueryErrorEvent | ProviderEvent | ValueEvent | AddingPeerEvent | DialingPeerEvent

export interface DHTProvideOptions extends AbortOptions {
recursive?: boolean
}

export interface StatResult {
cid: CID
size: number
}

export interface Delegate {
getEndpointConfig: () => { protocol: string, host: string, port: string }

block: {
stat: (cid: CID, options?: AbortOptions) => Promise<StatResult>
}

dht: {
findProvs: (cid: CID, options?: HTTPClientExtraOptions & AbortOptions) => AsyncIterable<QueryEvent>
provide: (cid: CID, options?: HTTPClientExtraOptions & DHTProvideOptions) => AsyncIterable<QueryEvent>
put: (key: string | Uint8Array, value: Uint8Array, options?: HTTPClientExtraOptions & AbortOptions) => AsyncIterable<QueryEvent>
get: (key: string | Uint8Array, options?: HTTPClientExtraOptions & AbortOptions) => AsyncIterable<QueryEvent>
}
}

/**
* An implementation of content routing, using a delegated peer
*/
export class DelegatedContentRouting implements ContentRouting, Startable {
private readonly client: IPFSHTTPClient
class DelegatedContentRouting implements ContentRouting, Startable {
private readonly client: Delegate
private readonly httpQueue: PQueue
private readonly httpQueueRefs: PQueue
private started: boolean
Expand All @@ -29,7 +144,7 @@ export class DelegatedContentRouting implements ContentRouting, Startable {
/**
* Create a new DelegatedContentRouting instance
*/
constructor (client: IPFSHTTPClient) {
constructor (client: Delegate) {
if (client == null) {
throw new Error('missing ipfs http client')
}
Expand Down Expand Up @@ -180,3 +295,7 @@ export class DelegatedContentRouting implements ContentRouting, Startable {
})
}
}

export function delegatedContentRouting (client: Delegate): (components?: any) => ContentRouting {
return () => new DelegatedContentRouting(client)
}
Loading