denoland / dnt

Deno to npm package build tool.
MIT License
1.25k stars 40 forks source link

Error: no secure random source avaialble (crypto.getRandomValues) #193

Open brickpop opened 2 years ago

brickpop commented 2 years ago

Hi and thank you for the wonderful project!

Trying to compile the following:

import { Wallet } from "https://cdn.skypack.dev/@ethersproject/wallet";
const w = Wallet.createRandom();
// ...

Compilation will work but execution will fail because this NPM library attempts to detect whether window.crypto.getRandomBytes() or require("crypto").randomBytes is to be used and freaks out.

# Executing the artifact with Node

> node npm/script/mod.js 
WARNING: Missing strong random number source
Generating wallet
/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/logger@v5.6.0-sV1IhwbKBRUviels0nS9/dist=es2019,mode=imports/optimized/@ethersproject/logger.js:175
        throw this.makeError(message, code, params);
        ^

Error: no secure random source avaialble (operation="crypto.getRandomValues", code=UNSUPPORTED_OPERATION, version=random/5.6.1)
    at Logger.makeError (/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/logger@v5.6.0-sV1IhwbKBRUviels0nS9/dist=es2019,mode=imports/optimized/@ethersproject/logger.js:166:23)
    at Logger.throwError (/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/logger@v5.6.0-sV1IhwbKBRUviels0nS9/dist=es2019,mode=imports/optimized/@ethersproject/logger.js:175:20)
    at Object.getRandomValues (/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/random@v5.6.1-k8CesFUa147ccuvLyIO8/dist=es2019,mode=imports/optimized/@ethersproject/random.js:51:28)
    at randomBytes (/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/random@v5.6.1-k8CesFUa147ccuvLyIO8/dist=es2019,mode=imports/optimized/@ethersproject/random.js:62:12)
    at Function.createRandom (/var/home/user/dev/tests/dnt/npm/script/deps/cdn.skypack.dev/-/@ethersproject/wallet@v5.6.2-hbht5UfbVmWkq5PkNraB/dist=es2019,mode=imports/optimized/@ethersproject/wallet.js:166:51)
    at Object.<anonymous> (/var/home/user/dev/tests/dnt/npm/script/mod.js:30:30)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12) {
  reason: 'no secure random source avaialble',
  code: 'UNSUPPORTED_OPERATION',
  operation: 'crypto.getRandomValues'
}

Thank you!

brickpop commented 2 years ago

For reference, the build config is:

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: {
    deno: true,
  },
  package: {
    name: "eth-test",
    version: Deno.args[0],
    ...
  },
});
kitsonk commented 2 years ago

Can you try to add:

{
  shims: {
    custom: {
      package: "crypto/webcrypto",
      globalNames: ["crypto. getRandomValues"]
    }
  }
}

I am not entirely sure it will work, but it would be a start in the right direction.

dsherret commented 2 years ago

@brickpop in this scenario, you could use a "specifier to npm package" mapping.

https://github.com/denoland/dnt#specifier-to-npm-package-mappings

That said, since this is using skypack, I believe changing the specifier https://cdn.skypack.dev/@ethersproject/wallet to include the version (ex. https://cdn.skypack.dev/@ethersproject/wallet@5.6.2) will cause that to happen automatically.

I looked at the source that was causing the issue and I believe it would be hard for dnt to figure out how to handle that.

brickpop commented 2 years ago

@kitsonk didn't work. Tried several variants but compilation kept failing, didn't recognize package, etc.

Adding the Skypack explicit version to the URL as suggested by @dsherret did the trick, thank you! :sparkle: import { Wallet } from "https://cdn.skypack.dev/@ethersproject/wallet@5.6.2";

I wonder if it would be useful to have a section on the readme including common workarounds for Node/Browser quirks without an explicit shim?

brickpop commented 2 years ago

I'm still facing another error, but I assume this should land on a different issue?

> deno run npm/esm/mod.js
error: Relative import path "@deno/shim-deno" not prefixed with / or ./ or ../
    at file:///home/user/dev/tests/dnt/npm/esm/_dnt.shims.js:2:22

The head of the offending file looks like:

import { Deno } from "@deno/shim-deno";
export { Deno } from "@deno/shim-deno";          // << Fails here
import { TextEncoder, TextDecoder } from "util";
export { TextEncoder, TextDecoder } from "util";

I can create a separate issue if this is unrelated Thank you!

kitsonk commented 2 years ago

Why do you expect the npm/esm/mod.js to run under Deno? It has been transformed to work under Node.js, not under Deno.

brickpop commented 2 years ago

@kitsonk the script build folder definitely works with Node, but the esm build folder is meant to work on ESM compatible environments like web browsers or Deno itself.

It's not a big deal, on Deno you can always target the original URL but NPM packages are meant to bundle both Node and ESM versions of the same codebase.

kitsonk commented 2 years ago

But npm/esm/mod.js does work under esm compatible environments which support Node.js module resolution (which is basically Node.js). In order to get it work again in Deno (or a browser for example), you would need to use an import map, or using a further bundling tool (which is usually what is done to get ESM Node.js code to run in a browser or Deno).