Digital World JS SDK (digital-world-js-sdk)
digital-world-js-sdk is a JavaScript library for communicating with a
Digital World Gateway
and Dwsa RPC. While
primarily intended for applications built on Node.js or in the browser, it can
be adapted for use in other environments with some tinkering.
The library provides:
- a networking layer API for Gateway endpoints (REST-based),
- a networking layer for Dwsa RPC (JSONRPC-based).
- facilities for building and signing transactions, for communicating with a Digital World Gateway instance, and for submitting transactions or querying network history.
Jump to:
- Installation: details on hitting the ground running
- Usage: links to documentation and a variety of workarounds for non-traditional JavaScript environments
- CLI: generate TypeScript bindings for Digital World smart contracts
- Developing: contribute to the project!
- License
Installation
Using npm, pnpm, or yarn to include digital-world-sdk in your own project:
npm install --save @digitalworld/digital-world-sdk# orpnpm add @digitalworld/digital-world-sdk# oryarn add @digitalworld/digital-world-sdkThen, require or import it in your JavaScript code:
var DigitalWorldSdk = require("@digitalworld/digital-world-sdk");// orimport * as DigitalWorldSdk from "@digitalworld/digital-world-sdk";(Preferably, you would only import the pieces you need to enable tree-shaking and lower your final bundle sizes.)
Browsers
You can use a CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/digital-world-sdk/{version}/digital-world-sdk.js"></script>Custom Installation
The default bundle uses a native-fetch HTTP client with no axios dependency. If
you need the axios transport (for example, to match the behavior of older SDK
versions), set the USE_AXIOS environment variable to true when building.
Build with Axios
pnpm run build:lib:axiosThis will create digital-world-sdk-axios.js in dist/. Consumers can also import
the axios-backed entry from Node via @digitalworld/digital-world-sdk/axios.
Migrating from @digitalworld/digital-world-base
@digitalworld/digital-world-base is now folded into @digitalworld/digital-world-sdk. Its classes
and functions are bundled in and re-exported from the top level, so the SDK is
the only package you need.
This only matters if you import @digitalworld/digital-world-base directly. If you depend
on @digitalworld/digital-world-sdk and never installed the base package separately, skip
this section. The fold-in landed in @digitalworld/digital-world-sdk v16.0.0; on earlier
versions the SDK still depends on the separate base package, so don’t remove it
there.
To migrate:
-
Install
@digitalworld/digital-world-sdkif you don’t already (see Installation). -
Update your imports. The symbols you import keep their names, so a project-wide find and replace of
"@digitalworld/digital-world-base"with"@digitalworld/digital-world-sdk"usually does it:// beforeimport { Keypair, TransactionBuilder, Asset } from "@digitalworld/digital-world-base";// afterimport { Keypair, TransactionBuilder, Asset } from "@digitalworld/digital-world-sdk"; -
Uninstall the base package:
Terminal window npm uninstall @digitalworld/digital-world-base
Don’t keep both packages installed. Two copies of the base library cause
confusing runtime errors, such as instanceof checks failing on values that
look correct.
Versioning and compatibility
Always use the latest @digitalworld/digital-world-sdk. The Digital World Network upgrades its
protocol periodically, and an older SDK may fail to decode newer data (for
example, newer XDR). You can check the protocol a network currently runs in the
current_protocol_version field of its Gateway root (for example
dex.digitalworld.global for Mainnet; Testnet
exposes its own).
These docs and the API reference cover the latest version only. To read docs for
an older version, find its Git tag on the
releases page and browse
the docs/ directory at that ref on GitLab. The release notes there mark the
breaking changes in each version.
Usage with React Native
The SDK works in React Native, but its JavaScript runtime doesn’t ship a couple of things the SDK expects from Node. You’ll need to provide them in your app’s entry file:
- A global
Buffer. XDR encoding/decoding relies onBuffer. Install a polyfill and assign it toglobal.Buffer. - A Web Crypto random source.
Keypair.random()and DWP-10 challenge generation callcrypto.getRandomValues(), which React Native doesn’t provide out of the box. Add a polyfill that registers it on the global scope, imported once before any SDK code runs.
Modern React Native uses Metro with autolinking, so beyond adding the two polyfills above, no manual native linking or custom resolver config is required.
If you use Gateway streaming (server.…().stream()), be aware it depends on an
EventSource, which is now an included dependency and will work in any runtimes
that support fetch,
ReadableStream,
TextDecoder,
URL,
Event,
MessageEvent,
EventTarget.
React Native apps using the Hermes engine may need to polyfill broken typed
array methods such as subarray, since this compatibility is no longer
provided by @stellar/js-xdr (npm package). If you run into issues, consider a polyfill such
as @exodus/patch-broken-hermes-typed-arrays.
Usage with Expo managed workflows
Expo has the same two requirements as React Native above — a global Buffer and
a crypto.getRandomValues() source. Install polyfills for both (use
npx expo install so versions are matched to your Expo SDK) and import them at
the top of your entry point (by default App.js) before any SDK code.
Once crypto.getRandomValues() is available, Keypair.random() works normally
— the manual expo-random workaround from older Expo SDKs is no longer needed.
Usage with CloudFlare Workers
The SDK defaults to a native-fetch HTTP client, so Gateway and RPC requests
work in the Workers runtime without an HTTP adapter. The things to watch for
are:
- Node compatibility. The SDK relies on
Buffer. Enable thenodejs_compatflag in yourwrangler.tomlso Node built-ins are available. - Streaming. Gateway’s
.stream()depends onEventSource; long-lived streaming connections don’t fit the Workers request model well, so prefer polling (.call()/.cursor()) for Gateway data in a Worker.
CLI
The SDK includes a command-line tool for generating TypeScript bindings from Digital World smart contracts. These bindings provide fully-typed client code with IDE autocompletion and compile-time type checking.
Running the CLI
# Using npx (no installation required)npx @digitalworld/digital-world-sdk generate [options]
# Or if installed globallydigital-world-js generate [options]Generating Bindings
You can generate bindings from three different sources:
From a local WASM file
npx @digitalworld/digital-world-sdk generate \ --wasm ./path/to/wasm_file/my_contract.wasm \ --output-dir ./my-contract-client \ --contract-name my-contractFrom a WASM hash on the network
# testnet and localnet have default RPC URLsnpx @digitalworld/digital-world-sdk generate \ --wasm-hash <hex-encoded-hash> \ --network testnet \ --output-dir ./my-contract-client \ --contract-name my-contractFrom a deployed contract ID
npx @digitalworld/digital-world-sdk generate \ --contract-id CABC...XYZ \ --network testnet \ --output-dir ./my-contract-clientWith custom RPC server options
For mainnet or when connecting to RPC servers that require authentication:
# Mainnet requires --rpc-url (no default)npx @digitalworld/digital-world-sdk generate \ --contract-id CABC...XYZ \ --rpc-url https://my-rpc-provider.com \ --network mainnet \ --output-dir ./my-contract-client
# With custom timeout and headers for authenticated RPC serversnpx @digitalworld/digital-world-sdk generate \ --contract-id CABC...XYZ \ --rpc-url https://my-rpc-server.com \ --network mainnet \ --output-dir ./my-contract-client \ --timeout 30000 \ --headers '{"Authorization": "Bearer my-token"}'
# localnet with default RPC URL auto-enables --allow-httpnpx @digitalworld/digital-world-sdk generate \ --contract-id CABC...XYZ \ --network localnet \ --output-dir ./my-contract-client
# When overriding the default URL, you must specify --allow-http if using HTTPnpx @digitalworld/digital-world-sdk generate \ --contract-id CABC...XYZ \ --rpc-url http://my-local-server:8000/rpc \ --network localnet \ --output-dir ./my-contract-client \ --allow-httpCLI Options
| Option | Description |
|---|---|
--wasm <path> | Path to a local WASM file |
--wasm-hash <hash> | Hex-encoded hash of WASM blob on the network |
--contract-id <id> | Contract ID of a deployed contract |
--rpc-url <url> | Dwsa RPC server URL (has defaults for testnet/localnet, required for mainnet) |
--network <network> | Network to use: testnet, mainnet, or localnet (required for network sources) |
--output-dir <dir> | Output directory for generated bindings (required) |
--contract-name <name> | Name for the generated package (derived from filename if not provided) |
--overwrite | Overwrite existing files in the output directory |
--allow-http | Allow insecure HTTP connections to RPC server (default: false) |
--timeout <ms> | RPC request timeout in milliseconds |
--headers <json> | Custom headers as JSON object (e.g., '{"Authorization": "Bearer token"}') |
Default RPC URLs
When using --network, the CLI provides default RPC URLs for most networks:
| Network | Default RPC URL |
|---|---|
testnet | https://rpc.digitalworld.global |
localnet | http://localhost:8000/rpc (auto-enables --allow-http only when using default URL) |
mainnet | None - you must provide --rpc-url (find providers) |
Generated Output
The CLI generates a complete npm package structure:
my-contract-client/├── src/│ ├── index.ts # Barrel exports│ ├── client.ts # Typed Client class with contract methods│ └── types.ts # TypeScript interfaces for contract types├── package.json├── tsconfig.json├── README.md└── .gitignoreUsing Generated Bindings
After generating, you can use the bindings in your project:
import { Client } from "./my-contract-client";
const client = new Client({ contractId: "CABC...XYZ", networkPassphrase: Networks.TESTNET, rpcUrl: "https://rpc.digitalworld.global", publicKey: keypair.publicKey(), ...basicNodeSigner(keypair, Networks.TESTNET),});
// Fully typed method calls with IDE autocompletionconst result = await client.transfer({ from: "GABC...", to: "GDEF...", amount: 1000n,});Developing
So you want to contribute to the library: welcome! Whether you’re working on a fork or want to make an upstream request, the dev-test loop is pretty straightforward.
- Clone the repo:
git clone <repository-url>- Install Node
Because we support the oldest maintenance version of Node, please install and
develop on the version pinned in .nvmrc (currently Node 22) so you
don’t get surprised when your code works locally but breaks in CI.
Here’s how to install nvm if you haven’t: https://github.com/creationix/nvm
nvm installIf you work on several projects that use different Node versions, you might it helpful to install this automatic version manager: https://github.com/wbyoung/avn
- Enable Corepack
corepack enable- Install dependencies inside digital-world-js-sdk folder:
cd digital-world-js-sdkpnpm install- Observe the project’s code style
While you’re making changes, make sure to run the linter to catch any linting errors (in addition to making sure your text editor supports ESLint) and conform to the project’s code style.
pnpm run fmtBuilding
You can build the developer version (unoptimized, commented, with source maps, etc.) or the production bundles:
pnpm run build# orpnpm run build:prodTesting
To run all tests:
pnpm run testTo run a specific set of tests:
pnpm run test:nodepnpm run test:browserpnpm run test:integrationTo generate and check the documentation site:
# generate the docs site (reference pages, llms bundles, and the Astro site under dist/site)pnpm run docs
# preview the built site in a browserpnpm docs:preview
# the preview server prints the local URL (default http://localhost:4321)
# for a live-reloading dev server instead, use:pnpm docs:devMiscellaneous
License
digital-world-js-sdk is licensed under an Apache-2.0 license.