# Decentralized Web Node (DWN) SDK [](https://www.npmjs.com/package/@tbd54566975/dwn-sdk-js) [](https://codecov.io/github/TBD54566975/dwn-sdk-js) [](https://github.com/tbd54566975/dwn-sdk-js/actions/workflows/npm-publish-unstable.yml) [](https://github.com/tbd54566975/dwn-sdk-js/blob/main/LICENSE) [](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) ## 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. [](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
``` #### 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
> 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 |