# @tbd54566975/dwn-sdk-js

> A reference implementation of https://identity.foundation/decentralized-web-node/spec/

Latest version **0.5.2** (published 2024-10-23) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @tbd54566975/dwn-sdk-js
pnpm add @tbd54566975/dwn-sdk-js
yarn add @tbd54566975/dwn-sdk-js
bun add @tbd54566975/dwn-sdk-js
```

## Health

**Score 35/100 (D)** — status: maintenance-mode.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; large bundle; pre 1.0.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.5.2 |
| Published | 2024-10-23 |
| First published | 2022-09-19 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >= 18 |
| Dependencies | 27 |
| Unpacked size | 9.8 MB |
| Known vulnerabilities | 0 (+5 in 3 direct dependencies) |
| Install scripts | no |
| Maintainers | tbd-releases, kendallweihe, shamilovtim, frankhinek, michaelneale, csuwildcat, mistermoe, alrubinger, nitroneal, mktbd, henrytsai |

## Links

- npm: https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js
- Repository: https://github.com/TBD54566975/dwn-sdk-js
- Homepage: https://github.com/TBD54566975/dwn-sdk-js#readme
- Issues: https://github.com/TBD54566975/dwn-sdk-js/issues
- npm.io page: https://npm.io/package/@tbd54566975/dwn-sdk-js

## Dependencies (27)

- [ms](https://npm.io/package/ms.md) 2.1.3
- [ajv](https://npm.io/package/ajv.md) 8.12.0
- [uuid](https://npm.io/package/uuid.md) 8.3.2
- [level](https://npm.io/package/level.md) 8.0.0
- [ulidx](https://npm.io/package/ulidx.md) 2.1.0
- [lodash](https://npm.io/package/lodash.md) 4.17.21
- [varint](https://npm.io/package/varint.md) 6.0.0
- [eciesjs](https://npm.io/package/eciesjs.md) 0.4.5
- [lru-cache](https://npm.io/package/lru-cache.md) 9.1.2
- [@web5/dids](https://npm.io/package/@web5/dids.md) ^1.1.3
- [cross-fetch](https://npm.io/package/cross-fetch.md) 4.0.0
- [randombytes](https://npm.io/package/randombytes.md) 2.1.0
- [uint8arrays](https://npm.io/package/uint8arrays.md) 5.1.0
- [multiformats](https://npm.io/package/multiformats.md) 11.0.2
- [@noble/curves](https://npm.io/package/@noble/curves.md) 1.4.2
- [@ipld/dag-cbor](https://npm.io/package/@ipld/dag-cbor.md) 9.0.3
- [@noble/ciphers](https://npm.io/package/@noble/ciphers.md) 0.5.3
- [@noble/ed25519](https://npm.io/package/@noble/ed25519.md) 2.0.0
- [abstract-level](https://npm.io/package/abstract-level.md) 1.0.3
- [blockstore-core](https://npm.io/package/blockstore-core.md) 4.2.0
- [interface-store](https://npm.io/package/interface-store.md) 5.1.2
- [readable-stream](https://npm.io/package/readable-stream.md) 4.5.2
- [@noble/secp256k1](https://npm.io/package/@noble/secp256k1.md) 2.0.0
- [interface-blockstore](https://npm.io/package/interface-blockstore.md) 5.2.3
- [ipfs-unixfs-exporter](https://npm.io/package/ipfs-unixfs-exporter.md) 13.1.5
- [ipfs-unixfs-importer](https://npm.io/package/ipfs-unixfs-importer.md) 15.1.5
- [@js-temporal/polyfill](https://npm.io/package/@js-temporal/polyfill.md) 0.4.4

## Recent versions

- 0.5.2 (latest) — 2024-10-23
- 0.5.2-unstable-2024-10-23-01-39-0e90301 (unstable) — 2024-10-23
- 0.5.1-unstable-2024-10-23-39-12-6a1ff24 — 2024-10-23
- 0.5.1-unstable-2024-10-16-51-51-04216e4 — 2024-10-16
- 0.5.1-unstable-2024-10-16-20-51-fe6ca82 — 2024-10-16
- 0.5.1-unstable-2024-10-16-16-02-30de237 — 2024-10-16
- 0.5.1-unstable-2024-10-16-45-06-85a35c8 — 2024-10-16
- 0.5.1-unstable-2024-10-15-33-47-7012f5d — 2024-10-15
- 0.5.1-unstable-2024-10-09-19-29-0a043f2 — 2024-10-09
- 0.5.1-unstable-2024-10-08-32-58-30f8b69 — 2024-10-08
- 0.5.1 — 2024-10-08
- 0.5.1-unstable-2024-10-08-25-57-e983cd8 — 2024-10-08
- 0.5.0 — 2024-10-07
- 0.5.0-unstable-2024-10-07-53-54-475270d — 2024-10-07
- 0.4.7-unstable-2024-10-04-16-20-d667090 — 2024-10-04
- … 517 more at https://npm.io/package/@tbd54566975/dwn-sdk-js/versions

## README

<!-- @format -->
# Decentralized Web Node (DWN) SDK <!-- omit in toc -->

[![NPM](https://img.shields.io/npm/v/@tbd54566975/dwn-sdk-js.svg?logo=npm)](https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js)
[![codecov](https://codecov.io/github/TBD54566975/dwn-sdk-js/graphs/badge.svg)](https://codecov.io/github/TBD54566975/dwn-sdk-js)
[![Build Status](https://img.shields.io/github/actions/workflow/status/TBD54566975/dwn-sdk-js/npm-publish-unstable.yml?branch=main&logo=github)](https://github.com/tbd54566975/dwn-sdk-js/actions/workflows/npm-publish-unstable.yml)
[![License](https://img.shields.io/npm/l/@tbd54566975/dwn-sdk-js.svg?logo=apache)](https://github.com/tbd54566975/dwn-sdk-js/blob/main/LICENSE)
[![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg?logo=discord)](https://discord.com/channels/937858703112155166/1068273971432280196)


- [Introduction](#introduction)
- [Installation](#installation)
- [Additional Steps](#additional-steps)
  - [Node.js \<= 18](#nodejs--18)
  - [React Native](#react-native)
  - [Usage in Browser:](#usage-in-browser)
    - [Vanilla HTML / JS](#vanilla-html--js)
    - [Webpack \>= 5](#webpack--5)
    - [Vite](#vite)
    - [esbuild](#esbuild)
- [Usage](#usage)
- [Release/Build Process](#releasebuild-process)
  - [Stable Build](#stable-build)
  - [Unstable Build](#unstable-build)
- [Some projects that use this library:](#some-projects-that-use-this-library)
- [Architecture](#architecture)
- [Project Resources](#project-resources)

## 🎉 Hacktoberfest 2024 🎉

`dwn-sdk-js` is a participating project in Hacktoberfest 2024! We’re so excited for your contributions, and have created a wide variety of issues so that anyone can contribute. Whether you're a seasoned developer or a first-time open source contributor, there's something for everyone.

### To get started:
1. Read the [contributing guide](https://github.com/TBD54566975/dwn-sdk-js/blob/main/CONTRIBUTING.md).
2. Read the [code of conduct](https://github.com/TBD54566975/dwn-sdk-js/blob/main/CODE_OF_CONDUCT.md).
3. Choose a task from this project's Hacktoberfest issues in our [Project Hub](https://github.com/TBD54566975/dwn-sdk-js/issues/806) and follow the instructions. Each issue has the 🏷️ `hacktoberfest` label.

Have questions? Connecting with us in our [Discord community](https://discord.gg/tbd) in the `#hacktoberfest` project channel.

---

## Introduction

This repository contains a reference implementation of Decentralized Web Node (DWN) as per the [specification](https://identity.foundation/decentralized-web-node/spec/). This specification is in a draft state and very much so a WIP. For the foreseeable future, a lot of the work on DWN will be split across this repo and the [repo that houses the specification](https://github.com/decentralized-identity/decentralized-web-node). The current implementation does not include all interfaces described in the DWN spec, but is enough to begin building test applications.

This project is used as a dependency by several other projects.

Proposals and issues for the specification itself should be submitted as pull requests to the [spec repo](https://github.com/decentralized-identity/decentralized-web-node).

## Running online environment

Interested in contributing instantly? You can make your updates directly without cloning in the running CodeSandbox environment.

[![Button to click to edit code in CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/github/TBD54566975/dwn-sdk-js/main)

## Installation

If you are interested in using DWNs and web5 in your web app, you probably want to look at web5-js, instead of this repository. Head on over here: https://github.com/TBD54566975/web5-js.

For advanced users wishing to use this repo directly:

```bash
npm install @tbd54566975/dwn-sdk-js
```

## Additional Steps

This package has dependency on [`@noble/ed25519`](https://github.com/paulmillr/noble-ed25519#usage) and [`@noble/secp256k1`](https://github.com/paulmillr/noble-secp256k1#usage) v2, additional steps are needed for some environments:

### Node.js <= 18

```js
// node.js 18 and earlier,  needs globalThis.crypto polyfill
import { webcrypto } from "node:crypto";
// @ts-ignore
if (!globalThis.crypto) globalThis.crypto = webcrypto;
```

### React Native
Usage of DWN SDK in react native requires a bit of set up at the moment. To simplify, we've [published an npm package](https://www.npmjs.com/package/@tbd54566975/web5-react-native-polyfills) that can be used to set everything up. Follow the instructions to get started.

### Usage in Browser:

`dwn-sdk-js` requires 2 polyfills: `crypto` and `stream`. we recommend using `crypto-browserify` and `stream-browserify`. Both of these polyfills can be installed using npm. e.g. `npm install --save crypto-browserify stream-browserify`

#### Vanilla HTML / JS

DWN SDK includes a polyfilled distribution that can imported in a `module` script tag. e.g.

```html
<!DOCTYPE html>
<html lang="en">
<body>
  <script type="module">
     // Import necessary modules from external sources using ES6 modules.
    import { Dwn, DataStream, DidKeyResolver, Jws, RecordsWrite } from 'https://cdn.jsdelivr.net/npm/@tbd54566975/dwn-sdk-js@0.1.1/dist/bundles/dwn.js'
    import { MessageStoreLevel, DataStoreLevel, EventLogLevel } from 'https://cdn.jsdelivr.net/npm/@tbd54566975/dwn-sdk-js@0.1.1/dist/bundles/level-stores.js'

    // Create instances of various components from the imported modules.
    const messageStore = new MessageStoreLevel();
    const dataStore = new DataStoreLevel();
    const eventLog = new EventLogLevel();
    const dwn = await Dwn.create({ messageStore, dataStore, eventLog });

    // Generate a did:key DID (Decentralized Identifier).
    const didKey = await TestDataGenerator.generateDidKeyPersona();

    // Create some data to be stored.
    const encoder = new TextEncoder();
    const data = encoder.encode('Hello, World!');

    // Create a RecordsWrite message to be stored in DWN.
    const recordsWrite = await RecordsWrite.create({
      data,
      dataFormat: 'application/json',
      published: true,
      schema: 'yeeter/post',  // Specify a schema for the data.
      signer: Jws.createSigner(didKey) // Sign the data using the generated DID key.
    });

    // Create a readable stream from the data to be stored.
    const dataStream = DataStream.fromBytes(data);
    // Process the RecordsWrite message using the DWN instance.
    const result = await dwn.processMessage(didKey.did, recordsWrite.message, { dataStream });

    // Log the processing result status and perform an assertion.
    console.log(result.status);
    console.assert(result.status.code === 202)

    // Close the DWN instance, freeing up resources.
    await dwn.close()

  </script>
</body>

</html>
```

#### Webpack >= 5

Add the following to the top level of your webpack config (`webpack.config.js`)

```js
resolve: {
  fallback: {
    stream: require.resolve("stream-browserify"),
    crypto: require.resolve("crypto-browserify")
  }
}
```

#### Vite
Add the following to the top level of your vite config (`vite.config.js`)

```js
define: {
  global: 'globalThis'
},
resolve: {
  alias: {
    'crypto': 'crypto-browserify',
    'stream': 'stream-browserify'
  }
}
```

#### esbuild
We recommend using `node-stdlib-browser` instead of `crypto-browserify` and `stream-browserify` individually. Example usage:

```js
import esbuild from 'esbuild'
import stdLibBrowser from 'node-stdlib-browser'
import polyfillProviderPlugin from 'node-stdlib-browser/helpers/esbuild/plugin'

import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);

// Build the project using esbuild.
esbuild.build({
  entryPoints: ['dwn-sdk-test.js'],
  platform: 'browser',
  bundle: true,
  format: 'esm',
  outfile: 'dist/dwn-sdk-test.js',

  // Inject the specified shim for Node.js standard library browser compatibility.
  inject      : [require.resolve('node-stdlib-browser/helpers/esbuild/shim')],
  // Use the polyfillProviderPlugin to provide polyfills for Node.js standard library.
  plugins     : [polyfillProviderPlugin(stdLibBrowser)],
  // Define 'global' as 'globalThis' to ensure compatibility with global objects.
  define      : {
    'global': 'globalThis'
  }
})
```

## Usage

[API docs](https://tbd54566975.github.io/dwn-sdk-js/)

```ts

import { Dwn, DataStream, DidKeyResolver, Jws, RecordsWrite } from '@tbd54566975/dwn-sdk-js';
import { DataStoreLevel, EventLogLevel, MessageStoreLevel } from '@tbd54566975/dwn-sdk-js/stores';

// Initialize the required stores and components for the DWN SDK.
const messageStore = new MessageStoreLevel();
const dataStore = new DataStoreLevel();
const eventLog = new EventLogLevel();
const dwn = await Dwn.create({ messageStore, dataStore, eventLog });

// Generate a did:key DID (Decentralized Identifier).
const didKey = await TestDataGenerator.generateDidKeyPersona();

// Create some data to be stored.
const encoder = new TextEncoder();
const data = encoder.encode('Hello, World!');

// Create a RecordsWrite message to be stored in the DWN.
const recordsWrite = await RecordsWrite.create({
  data,
  dataFormat: 'application/json',
  published: true, // Mark the data as published.
  schema: 'yeeter/post', // Specify a schema for the data.
  signer: Jws.createSigner(didKey) // Sign the data using the generated DID key.
});

// Create a readable stream from the data to be stored.
const dataStream = DataStream.fromBytes(data);
// Process the RecordsWrite message using the DWN instance.
const result = await dwn.processMessage(didKey.did, recordsWrite.message, { dataStream });
// Log the processing result status.
console.log(result.status);

```

With a web wallet installed:

```javascript
const result = await window.web5.dwn.processMessage({
  method: "RecordsQuery",
  message: {
    filter: {
      schema: "http://some-schema-registry.org/todo",
    },
    dateSort: "createdAscending",
  },
});
```

### Custom Tenant Gating
By default, all DIDs are allowed as tenants. A custom tenant gate implementation can be provided when initializing the DWN.
```ts
import { ActiveTenantCheckResult, Dwn, TenantGate, DataStoreLevel, EventLogLevel, MessageStoreLevel } from '@tbd54566975/dwn-sdk-js';

// Define a custom implementation of the TenantGate interface.
class CustomTenantGate implements TenantGate {
  public async isActiveTenant(did): Promise<ActiveTenantCheckResult> {
    // Custom implementation
  }
}

// Initialize the required stores and components for the DWN SDK.
const messageStore = new MessageStoreLevel();
const dataStore = new DataStoreLevel();
const eventLog = new EventLogLevel();
// Create an instance of the custom TenantGate.
const tenantGate = new CustomTenantGate();
// Create a DWN instance with configured stores, logs, and the custom TenantGate.
const dwn = await Dwn.create({ messageStore, dataStore, eventLog, tenantGate });
```

### Custom Signature Signer
If you have the private key readily available, it is recommended to use the built-in `PrivateKeySigner`. Otherwise, you can implement a customer signer to interface with external signing service, API, HSM, TPM etc and use it for signing your DWN messages:

```ts
// Create a custom signer implementing the Signer interface.
class CustomSigner implements Signer {
  public keyId = 'did:example:alice#key1'; // Specify the key ID.
  public algorithm = 'EdDSA'; // Specify the signing algorithm (valid `alg` value published).
  https://www.iana.org/assignments/jose/jose.xhtml
  public async sign (content: Uint8Array): Promise<Uint8Array> {
    ... // custom signing logic
  }
}

// Create an instance of the custom signer for authorization.
const signer = new CustomSigner();

// Define options for creating a RecordsWrite message.
const options: RecordsWriteOptions = {
  ...
  signer // Use the custom signer for authorization.
};

// Create a RecordsWrite message with the specified options.
const recordsWrite = await RecordsWrite.create(options);
```


## Release/Build Process

The DWN JS SDK releases builds to [npmjs.com](https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js). There are two build types: stable build and unstable build.

### Stable Build

This is triggered manually by:

1.  Increment `version` in `package.json` in [Semantic Versioning (semver)](https://semver.org/) format.
2.  Merge the change into `main` branch
3.  Create a release from GitHub.

An official build with version matching the `package.json` will be published to [npmjs.com](https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js).

### Unstable Build

Every push to the `main` branch will automatically trigger an unstable build to [npmjs.com](https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js) for developers to experiment and test.

The version string contains the date as well as the commit hash of the last change.

An example version string:

`0.0.26-unstable-2023-03-16-36ec2ce`

- `0.0.26` came from `version` in `package.json`
- `2023-03-16` indicates the date of March 16th 2023
- `36ec2ce` is the commit hash of the last change

## Some projects that use this library:

- [Web5 JS SDK](https://github.com/TBD54566975/web5-js)
- [Example CLI](https://github.com/TBD54566975/dwn-cli)
- [Example with a web wallet](https://github.com/TBD54566975/incubating-web5-labs/)
- [Server side aggregator](https://github.com/TBD54566975/dwn-server)

## Architecture

<img src="./images/dwn-architecture.png" alt="Architecture diagram of DWN SDN" width="700">

> NOTE: The diagram is a conceptual view of the architecture, the actual component abstraction and names in source file may differ.

## Project Resources

| Resource                                                                                     | Description                                                                   |
| -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [CODEOWNERS](https://github.com/TBD54566975/dwn-sdk-js/blob/main/CODEOWNERS)                 | Outlines the project lead(s)                                                  |
| [CODE_OF_CONDUCT.md](https://github.com/TBD54566975/dwn-sdk-js/blob/main/CODE_OF_CONDUCT.md) | Expected behavior for project contributors, promoting a welcoming environment |
| [CONTRIBUTING.md](https://github.com/TBD54566975/dwn-sdk-js/blob/main/CONTRIBUTING.md)       | Developer guide to build, test, run, access CI, chat, discuss, file issues    |
| [GOVERNANCE.md](https://github.com/TBD54566975/dwn-sdk-js/blob/main/GOVERNANCE.md)           | Project governance                                                            |
| [LICENSE](https://github.com/TBD54566975/dwn-sdk-js/blob/main/LICENSE)                       | Apache License, Version 2.0                                                   |
| [Q_AND_A.md](https://github.com/TBD54566975/dwn-sdk-js/blob/main/Q_AND_A.md)                 | Questions and answers on DWN                                                  |

---
_Source: https://npm.io/package/@tbd54566975/dwn-sdk-js · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
