aioipfs

aioipfs is an asynchronous Python client library for kubo (formerly called go-ipfs), which is the reference implementation of the IPFS (Interplanetary Filesystem) protocol.

aioipfs uses the aiohttp library to access kubo’s RPC endpoints.

Installation

You can use any Python version that supports asyncio and asynchronous generators (from Python version 3.6 to version 3.12).

pip install aioipfs

Support for CAR (Content-Addressable aRchives) decoding (with the ipfs-car-decoder package) can be enabled with the car extra:

pip install 'aioipfs[car]'

If you want to use orjson to decode JSON messages:

pip install 'aioipfs[orjson]'

To install the dependencies required by bohort, a REPL CLI tool to interact with kubo nodes:

pip install 'aioipfs[bohort]'

Checkout the bohort documentation here.

Async IPFS client

When creating a AsyncIPFS client instance it’s recommended to specify the node’s RPC API address with a multiaddr:

import aioipfs

client = aioipfs.AsyncIPFS(maddr='/ip4/127.0.0.1/tcp/5001')

client = aioipfs.AsyncIPFS(maddr='/dns4/localhost/tcp/5001')

The default constructor assumes that the kubo node you want to connect to is localhost on port 5001 (use the host and port keyword arguments to set different values):

client = aioipfs.AsyncIPFS()

client = aioipfs.AsyncIPFS(host='10.0.12.3', port=5003)

HTTPS RPC: if the node you’re connecting to uses the https protocol to serve the RPC API, specify https in the multiaddr, or force the URL scheme by passing scheme:

client = aioipfs.AsyncIPFS(maddr='/ip4/10.0.1.4/tcp/5001/https')

client = aioipfs.AsyncIPFS(host='10.0.1.4', scheme='https')

Maximum HTTP connections and read timeout parameters:

client = aioipfs.AsyncIPFS(host='localhost', port=5008, conns_max=20)

client = aioipfs.AsyncIPFS(host='localhost', port=5008, read_timeout=30)

RPC authentication credentials

Starting with version 0.25.0, kubo supports limiting access to certain parts of the RPC API by requiring the client to provide credentials via the HTTP Authorization header, either with a simple Basic Auth login and password, or with a token. kubo RPC Authorization documentation.

If the kubo server requires authentication, you can pass the RPC authentication credentials via the constructor’s auth keyword argument:

client = aioipfs.AsyncIPFS(auth=aioipfs.BasicAuth('john', 'password123'))

client = aioipfs.AsyncIPFS(auth=aioipfs.BearerAuth('my-secret-token'))

You can change the credentials at any time by setting the auth object attribute:

client.auth = aioipfs.BasicAuth('alice', 'anotherpass')

client.auth = None

A RPCAccessDenied exception will be raised if you are forbidden to use a certain API or if your credentials are invalid.

Async context manager

You can use an async context manager in your code:

async with aioipfs.AsyncIPFS() as client:
    async for reply in client.ping(peer_id):
        ...

Closing

When finished you should always call AsyncIPFS.close() on your client:

await client.close()

Content-Addressable aRchives decoding support

CAR

The Content Archive format is a way of packaging up content addressed data into archive files that can be easily stored and transferred. You can think of them like TAR files that are designed for storing collections of content addressed data.

Source: What is a Content Archive Specs: CAR Specs

If you’ve installed the ipfs-car-decoder package via the car extra, you can use various utility functions and APIs to decode the Content-Addressable aRchives generated by kubo, or to open .car files:

  • Use aioipfs.util.car_open() to open a .car archive file (this returns a FileByteStream)

  • Use aioipfs.util.car_bytes() to get the raw bytes content from a CAR stream. The first argument is the CAR stream, the second argument must be the CID of a UnixFS file:

    from pathlib import Path
    from aioipfs import util
    
    data = await util.car_bytes(
        util.car_open(Path('docs.car')),
        'bafybeiawyahkjt4kzrzc3bjylqupniukbpnbvys7pt536c64gxg7onq36m'
    )
    
  • Use the apis.dag.DagAPI.export() coroutine to export a DAG to a .car file:

    from pathlib import Path
    import aioipfs
    
    async with aioipfs.AsyncIPFS() as client:
        await client.dag.export(
            'bafybeiawyahkjt4kzrzc3bjylqupniukbpnbvys7pt536c64gxg7onq36m',
            output_path=Path('output.car')
        )
    
  • Use the apis.dag.DagAPI.export_to_directory() coroutine to export a UnixFS DAG to a CAR and unpack it to a directory on the filesystem. Example:

    from pathlib import Path
    import aioipfs
    
    async with aioipfs.AsyncIPFS() as client:
        await client.dag.export_to_directory(
            'bafybeiawyahkjt4kzrzc3bjylqupniukbpnbvys7pt536c64gxg7onq36m',
            Path('car-contents')
        )
    

API sectioning

The kubo (formerly called go-ipfs) RPC HTTP API provides many endpoints which allow to access the different subsystems of the IPFS daemon. You can read the RPC API specifications here.

Important: The aioipfs client API closely follows kubo’s RPC endpoints path hierarchy, as each subsystem has its own namespace/attribute inside the AsyncIPFS client object, for example:

etc …

All API functions will raise an APIError (or a more specific exception) if there’s an error raised during the request.

Core API

aioipfs.AsyncIPFS.core

Gives access to the CoreAPI

Adding files

Add files to the IPFS repository with the api.CoreAPI.add() async generator:

async for added in client.core.add('file1.txt', '/usr/local/src',
        recursive=True):
    print(added['Hash'])

async for added in client.core.add(['one', 'two', 'three'],
        wrap_with_directory=True):
    ...

cids = [entry['Hash'] async for entry in client.add(dir_path)]

Entries yielded by the generator are as returned by the IPFS daemon, dictionaries with Name, Hash and Size keys.

Since kubo v0.16.0, you can import a file and link the resulting object inside the MFS in the same RPC call, by using the to_files string argument, which should be the path in the MFS for the link:

async for added in client.core.add('file1.txt', to_files='/file1.txt'):
    print(added['Hash'])

Ignoring files with .gitignore or .ipfsignore

aioipfs supports the use of gitignore files to specify which files should not be imported in IPFS. Use the ignore_rules_path keyword argument to indicate the name of the file (relative to the directory you’re importing) containing the ignore rules:

async for added in client.core.add('directory', recursive=True,
                                   ignore_rules_path='.ipfsignore'):
    print(added['Hash'])

Adding bytes

Add some bytes with api.CoreAPI.add_bytes():

>>> entry = await client.core.add_bytes(b'ABCD')
{'Name': 'QmZ655k2oftYnsocBxqTWzDer3GNui2XQTtcA4ZUbhpz5N', 'Hash': 'QmZ655k2oftYnsocBxqTWzDer3GNui2XQTtcA4ZUbhpz5N', 'Size': '12'}

entry = await client.core.add_bytes('ABCD', to_files='/abcd')

Adding string data

Add a UTF-8 string with api.CoreAPI.add_str():

entry = await client.core.add_str('ABCD')

entry = await client.core.add_str('ABCD', to_files='/abcd')

Getting IPFS objects

Download IPFS objects with api.CoreAPI.get():

await client.core.get('QmRGqvWK44oWu8re5whp43P2M7j5XEDLHmPB3wncYFmCNg')

await client.core.get('QmRGqvWK44oWu8re5whp43P2M7j5XEDLHmPB3wncYFmCNg',
    dstdir='/tmp')

Cat

Use api.CoreAPI.cat() to get an object’s raw data:

bytes = await client.core.cat(cid)

Listing a path or CID

Use api.CoreAPI.ls() for listing:

listing = await client.core.ls(path)

Node information

Get IPFS node information:

info = await client.core.id()

Block API

aioipfs.AsyncIPFS.block

Gives access to the BlockAPI

Bitswap API

aioipfs.AsyncIPFS.bitswap

Gives access to the BitswapAPI

Bootstrap API

aioipfs.AsyncIPFS.bootstrap

Gives access to the BootstrapAPI

Config API

aioipfs.AsyncIPFS.config

Gives access to the ConfigAPI

CID API

aioipfs.AsyncIPFS.cid

Gives access to the CidAPI

DAG API

aioipfs.AsyncIPFS.dag

Gives access to the DagAPI

DHT API

aioipfs.AsyncIPFS.dht

Gives access to the DhtAPI

Diag API

aioipfs.AsyncIPFS.diag

Gives access to the DiagAPI

File API

aioipfs.AsyncIPFS.file

Gives access to the FileAPI

Files API

aioipfs.AsyncIPFS.files

Gives access to the FilesAPI

Filestore API

aioipfs.AsyncIPFS.filestore

Gives access to the FilestoreAPI

Key API

aioipfs.AsyncIPFS.key

Gives access to the KeyAPI

Log API

aioipfs.AsyncIPFS.log

Gives access to the LogAPI

Access the IPFS event log with:

import pprint
async for msg in client.log.tail():
    print(pprint.pprint(msg))

Multibase API

aioipfs.AsyncIPFS.multibase

Gives access to the MultibaseAPI

Name API

aioipfs.AsyncIPFS.name

Gives access to the NameAPI

Object API

aioipfs.AsyncIPFS.object

Gives access to the ObjectAPI

P2P API

aioipfs.AsyncIPFS.p2p

Gives access to the P2PAPI

There’s an API to easily dial a P2P service through an async context manager:

async with client.p2p.dial_service(
    '12D3KooWRd9Pt1Fri5F4W32uhGm8fBG4pvxEiFwgMru85zmajxcd',
    '/x/myservice') as ctx:
    if ctx.failed:
        # Dialing failed
        raise Exception('....')

    # The multiaddr is available as 'ctx.maddr'
    print(f'Multiaddr': {ctx.maddr}')

    # The host/port can be retrieved via maddr_host and maddr_port
    print(f'Host: {ctx.maddr_host}, port: {ctx.maddr_port}')

Example of dialing a remote http service (using ctx.httpUrl()):

async with client.p2p.dial_service(
    '12D3KooWRd9Pt1Fri5F4W32uhGm8fBG4pvxEiFwgMru85zmajxcd',
    '/x/http1') as ctx:
    async with aiohttp.ClientSession() as sess:
        async with sess.get(ctx.httpUrl('/')) as resp:
            print(await resp.read())

Pin API

aioipfs.AsyncIPFS.pin

Gives access to the PinAPI

Pinning a CID or an IPFS path:

async for pinned in client.pin.add(cid):
    print('Pin progress', pinned['Progress'])

Listing the pinned objects:

pinned = await client.pin.ls()

Unpin with:

await client.pin.rm(path)

Pin remote API

aioipfs.AsyncIPFS.pin.remote

Gives access to the PinRemoteAPI

Pubsub API

aioipfs.AsyncIPFS.pubsub

Gives access to the PubSubAPI

Refs API

aioipfs.AsyncIPFS.refs

Gives access to the RefsAPI

Repo API

aioipfs.AsyncIPFS.repo

Gives access to the RepoAPI

Routing API

aioipfs.AsyncIPFS.routing

Gives access to the RoutingAPI

Swarm API

aioipfs.AsyncIPFS.swarm

Gives access to the SwarmAPI

Swarm Peering API

aioipfs.AsyncIPFS.swarm.peering

Gives access to the SwarmPeeringAPI

TAR API

aioipfs.AsyncIPFS.tar

Gives access to the TarAPI

Indices and tables