/drand-client

🎲 A JavaScript client to the drand randomness beacon network.

Primary LanguageTypeScriptOtherNOASSERTION

drand client

A JavaScript client to the drand randomness beacon network.

⚠️ This client does not yet support full/partial chain verification.

Table of Contents

Install

In the browser or Deno you can grab and use the client from a CDN e.g. https://cdn.jsdelivr.net/npm/drand-client/drand.js.

In Node.js, install with:

npm install drand-client

Usage

The drand-client supports multiple transports, although only HTTP is available currently.

Browser

<script type="module">
  import Client, { HTTP } from 'https://cdn.jsdelivr.net/npm/drand-client/drand.js'

  const chainHash = '8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce' // (hex encoded)
  const urls = [
    'https://api.drand.sh',
    'https://drand.cloudflare.com'
    // ...
  ]

  async function main() {
    const options = { chainHash }

    const client = await Client.wrap(HTTP.forURLs(urls, chainHash), options)

    // e.g. use the client to get the latest randomness round:
    const res = await client.get()

    console.log(res.round, res.randomness)
  }

  main()
</script>

Deno

Usage in Deno is the same as the browser, minus the HTML <script> tag. Ensure you run your script with the --allow-net flag e.g. deno run --allow-net client.js.

Node.js

If you'd like to run it in Node.js, add fetch and AbortController as globals e.g.

import Client, { HTTP } from 'drand-client'
import fetch from 'node-fetch'
import AbortController from 'abort-controller'

global.fetch = fetch
global.AbortController = AbortController

// Use as per browser example...

From common.js:

const fetch = require('node-fetch')
const AbortController = require('abort-controller')
const { default: Client, HTTP } = await import('drand-client')

global.fetch = fetch
global.AbortController = AbortController

// Use as per browser example...

API

import Client, { HTTP } from 'https://cdn.jsdelivr.net/npm/drand-client/drand.js'

Client.wrap([]Client | Promise<[]Client>, options?: object): Promise<Client>

Wrap provides a single entrypoint for wrapping concrete client implementation(s) with configured aggregation, caching, and retry logic.

  • options.chainHash: string - hex encoded hash of the chain information, it uniquely identifies the drand chain. It is used as a root of trust for validation of the first round of randomness.
  • options.chainInfo: object - the chain information, as returned by the /info JSON HTTP API endpoint. Can be passed instead of options.chainHash.
  • options.disableBeaconVerification: boolean - disables verification of randomness beacons as they arrive (not recommended). Note that verification is performed by a compiled WASM module which is loaded on demand (default: false).
  • options.insecure: boolean - indicate the client should be allowed to provide randomness when the root of trust is not fully provided in a validate-able way (default: false).

Note: When using the client you should use the chainHash or chainInfo option in order for your client to validate the randomness it receives is from the correct chain. You may use the insecure option to bypass this validation but it is not recommended!

e.g.

const client = await Client.wrap([/* ... */], options)

client.get(round?: number, options?: object): Promise<object>

Returns the randomness at round or an error. Requesting round = 0 will return randomness for the most recent known round, bounded at minimum to client.roundAt(Date.now()).

  • options.noCache: boolean - bypass the cache.
  • options.signal: AbortSignal - a signal obtained from an AbortController that can be used to abort the request.

e.g.

const round = 1
const res = await client.get(round)
/*
{
  "round": 367,
  "signature": "b62dd642e939191af1f9e15bef0f0b0e9562a5f570a12a231864afe468377e2a6424a92ccfc34ef1471cbd58c37c6b020cf75ce9446d2aa1252a090250b2b1441f8a2a0d22208dcc09332eaa0143c4a508be13de63978dbed273e3b9813130d5",
  "previous_signature": "afc545efb57f591dbdf833c339b3369f569566a93e49578db46b6586299422483b7a2d595814046e2847494b401650a0050981e716e531b6f4b620909c2bf1476fd82cf788a110becbc77e55746a7cccd47fb171e8ae2eea2a22fcc6a512486d",
  "randomness": "d7aed3686bf2be657e6d38c20999831308ee6244b68c8825676db580e7e3bec6"
}
*/

client.info(options?: object): Promise<object>

Info returns the parameters of the chain this client is connected to. The public key, when it started, and how frequently it updates.

  • options.noCache: boolean - bypass the cache.
  • options.signal: AbortSignal - a signal obtained from an AbortController that can be used to abort the request.

e.g.

const info = await client.info()
/*
{
  "public_key": "aaddd53d2c92454b698c52495990162bc999778a32fd570dad2ef3de2915a5b397d80ec5508919e84cd10944955b7318",
  "period": 10,
  "genesis_time": 1592226590,
  "hash": "c599c267a0dd386606f7d6132da8327d57e1004760897c9dd4fb8495c29942b2"
}
*/

client.watch(options?: object): AsyncIterable<object>

Watch returns an async iterable that yields new randomness beacons as they become available.

  • options.signal: AbortSignal - a signal obtained from an AbortController that can be used to abort the request.

e.g.

for await (const res of client.watch()) {
    console.log(res)
}
// See output example from .get

client.roundAt(time): number

Returns the round number for the passed time (in milliseconds from Unix epoch).

client.close(): Promise

Halts the client, any background processes it runs and any in-flight get, watch or info requests.

new HTTP(url: string, chainInfo: object, options?: object)

Creates a new HTTP client when the chain info is already known.

HTTP.forURLs([]string, chainHash): Promise<[]Client>

Provides a shortcut for creating a set of HTTP clients for a set of URLs.

Publishing

This repo automatically publishes to npmjs.com as drand-client if changes hit the master branch with an updated version number.

Contribute

Feel free to dive in! Open an issue or submit PRs.

License

This project is dual-licensed under Apache 2.0 and MIT terms: