..

How to Run xrpl.js on Cloudflare Workers (Fix for "Digest method not supported")

If you’re trying to use xrpl.js on Cloudflare Workers and getting this error:

Error: Digest method not supported
    at new Hash (node-internal:crypto_hash:50:25)
    at createHash (node-internal:crypto_hash:36:12)

…this post is for you. Here’s the problem and the workaround we used to get Wallet.fromSeed(), wallet.sign(), and the full xrpl.js signing flow working on Workers.


The problem

Everything works on next dev (or any Node.js environment). But the moment you deploy to Cloudflare Workers — whether directly or through a framework like OpenNext — any call to Wallet.fromSeed() or wallet.sign() blows up with "Digest method not supported".

The stack trace points to Node’s crypto.createHash() being called with sha512, sha256, or ripemd160.

Why this happens

Under the hood, xrpl.js depends on ripple-keypairs, which depends on @xrplf/isomorphic for hashing. That package is dual-implemented:

  • Node path: imports createHash from crypto and calls createHash("sha512") (and similar for sha256 / ripemd160).
  • Browser path: uses pure-JS implementations from @noble/hashes.

The switch between the two is controlled by the "browser" field in each sub-package’s package.json inside @xrplf/isomorphic. When a bundler’s target is “browser”, it resolves the pure-JS path; otherwise it resolves the Node path via "main".

Cloudflare Workers is neither Node nor a browser. It’s a V8 isolate with its own compatibility layer. When you enable the nodejs_compat flag (required for node:crypto to be available at all), Workers exposes crypto.createHash() — but depending on your compatibility date and Workers runtime version, not all digest algorithms may be supported. In our case (early 2025), ripemd160 was not supported, which caused the "Digest method not supported" error.

Note (April 2025 update): Cloudflare expanded node:crypto support significantly in April 2025. With nodejs_compat enabled and a compatibility date of 2024-09-23 or later, all node:crypto APIs are now fully supported (except DSA/DH key pairs and ed448/x448 curves). If you’re on a recent compatibility date, the error described here may no longer occur. That said, the pure-JS shim approach below is still a solid option — it removes the dependency on the Workers runtime’s Node compat layer entirely, works across all edge runtimes, and has zero risk of future breakage from compat flag changes.

Meanwhile, because Workers isn’t a browser target either, your bundler (webpack, Turbopack, esbuild, etc.) resolves @xrplf/isomorphic via the "main" field — the Node path — not the "browser" field. So you end up calling Node’s crypto.createHash() in a runtime that may not fully support it.

TL;DR: the bundler picks the Node code path, but the Workers runtime can’t (or couldn’t) actually run it.

The fix: alias to pure-JS shims

The workaround is to force your bundler to resolve the three hash modules from @xrplf/isomorphic to pure-JS implementations that don’t rely on Node’s crypto at all.

1. Install @noble/hashes

npm install @noble/hashes
# or
pnpm add @noble/hashes

2. Create shim files

Create a directory for the shims (e.g. src/lib/xrpl-shims/) with the following files:

wrapNoble.cjs — a tiny adapter that converts @noble/hashes output to the interface @xrplf/isomorphic consumers expect:

// wrapNoble.cjs
"use strict";

function wrapNoble(nobleFn) {
  return function hashData(data) {
    const input =
      typeof data === "string" ? new TextEncoder().encode(data) : data;
    return nobleFn(input);
  };
}

module.exports = { wrapNoble };

sha512.js — note the named export sha512, matching what @xrplf/isomorphic/sha512 exposes:

const { sha512 } = require("@noble/hashes/sha512");
const { wrapNoble } = require("./wrapNoble.cjs");
exports.sha512 = wrapNoble(sha512);

sha256.js

const { sha256 } = require("@noble/hashes/sha256");
const { wrapNoble } = require("./wrapNoble.cjs");
exports.sha256 = wrapNoble(sha256);

ripemd160.js

const { ripemd160 } = require("@noble/hashes/ripemd160");
const { wrapNoble } = require("./wrapNoble.cjs");
exports.ripemd160 = wrapNoble(ripemd160);

3. Configure resolve aliases in your bundler

Now tell your bundler to swap @xrplf/isomorphic/sha512 (and the others) for your shims. Here’s how it looks in next.config.mjs (supporting both webpack and turbopack):

import { resolve } from "path";

const shimDir = resolve("src/lib/xrpl-shims");

const xrplAliases = {
  "@xrplf/isomorphic/sha512": resolve(shimDir, "sha512.js"),
  "@xrplf/isomorphic/sha256": resolve(shimDir, "sha256.js"),
  "@xrplf/isomorphic/ripemd160": resolve(shimDir, "ripemd160.js"),
};

const nextConfig = {
  // ... your other config

  webpack(config) {
    Object.assign(config.resolve.alias, xrplAliases);
    return config;
  },

  // Turbopack (if you use it)
  experimental: {
    turbo: {
      resolveAlias: {
        "@xrplf/isomorphic/sha512": resolve(shimDir, "sha512.js"),
        "@xrplf/isomorphic/sha256": resolve(shimDir, "sha256.js"),
        "@xrplf/isomorphic/ripemd160": resolve(shimDir, "ripemd160.js"),
      },
    },
  },
};

export default nextConfig;

If you’re using a different framework or a raw esbuild/wrangler setup, the idea is the same — alias those three imports to your shim files.

4. Rebuild and deploy

After applying the aliases, rebuild and test:

# Next.js + OpenNext example
pnpm run build
pnpm run preview  # tests in Workers-like runtime

Wallet.fromSeed(), wallet.sign(), and any other xrpl.js crypto operation should now work without errors.


Why this works

By aliasing the three hash imports, the bundler never reaches the Node crypto.createHash() code path inside @xrplf/isomorphic. Instead, it bundles the pure-JS implementations from @noble/hashes, which run everywhere — Node, browsers, and Cloudflare Workers alike.

@noble/hashes is a well-audited, zero-dependency library that implements these algorithms in pure JavaScript. It’s actually the same library that @xrplf/isomorphic already uses for its browser build — we’re just making sure the bundler picks it for Workers too.


Bonus: avoid this class of bugs

If you’re building on Cloudflare Workers and using Node-ecosystem libraries, keep in mind:

  • Workers != Node. The Node compatibility layer is evolving fast but still not full parity. Always check your nodejs_compat flag and compatibility date.
  • Test in the Workers runtime before deploying. A quick wrangler dev or opennextjs-cloudflare preview in your CI pipeline catches these issues before they hit production.
  • Watch out for dual Node/browser packages. Libraries that use the "browser" field in package.json (or exports conditions) to switch implementations depend on the bundler resolving the right entry. In Workers — which is neither Node nor a browser — the bundler may pick the wrong one. Resolve aliases are your escape hatch.

References