taquito: sodium.randombytes_buf is not a function

Description When trying to use the wallet in the frontend with a bundler (tested: parcel, browserify) I can’t get the app to work at all. It seems like it’s an issue with the way __importStar is working in the ES5/CJS build from beacon-sdk module; it does not pull in the entire libsodium object, but a clone of it with less functions.

Steps To Reproduce Paste this in a new main.js file:

import { TezosToolkit } from "@taquito/taquito";
import { BeaconWallet } from "@taquito/beacon-wallet";

const provider = "https://mainnet.smartpy.io";
const NETWORK = "mainnet";

sync();

async function sync() {
  const wallet = new BeaconWallet({
    name: "MyAwesomeDapp",
  });
}

And create an index.html file:

<body><script src="./main.js"></script></body>

Now run from terminal:

npx parcel main.js --open

In console you will get an error:

TypeError: sodium.crypto_generichash is not a function

EDIT: This is fixed with parcel by adding the following in your app’s package.json (not sure if browserslist is really needed, but the rest resolves to ES Module imports instead of CJS outputs).

...
  "browserslist": "last 2 Chrome versions",
  "alias": {
    "@airgap/beacon-sdk": "./node_modules/@airgap/beacon-sdk/dist/esm/index.js",
    "@taquito/beacon-wallet": "./node_modules/@taquito/beacon-wallet/dist/taquito-beacon-wallet.es5.js",
    "@taquito/signer": "./node_modules/@taquito/signer/dist/taquito-signer.es5.js",
    "@taquito/taquito": "./node_modules/@taquito/taquito/dist/taquito.es5.js"
  }
...

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 6
  • Comments: 33 (17 by maintainers)

Most upvoted comments

Hi, I had same issue. Solution in https://github.com/ecadlabs/taquito/issues/882#issuecomment-999753605 works well, but in case you would like to use stable version of beacon-sdk instead of beta, it can be done as follows:

  1. Install vite-compatible-readable-stream as mentioned in https://github.com/ecadlabs/taquito/issues/882#issuecomment-999753605
  2. download browserified version of from unpkg. For latest it is beacon-sdk@2.3.10.
  3. place it somewhere whitin your project. For me it was src/vendor/walletbeacon.min.js
  4. add resolves to vite.config.js as follows:
import { defineConfig, mergeConfig } from 'vite';

export default ({ command }) => {
	const isBuild = env.command === 'build';
	const devOnlyResolve = isBuild ? {} : {
		"@airgap/beacon-dapp": `./src/vendor/walletbeacon.dapp.min.js`,
	}
	return defineConfig({
                  // ... 
		  resolve: {
			  alias: {
                                  ...devOnlyResolve,
				  // polyfills
				  'readable-stream': 'vite-compatible-readable-stream',
	                           stream: 'vite-compatible-readable-stream',
			  },
		  },
		  // ... 
	});
}

This fixed vite dev setup for me. Build works out of box for me so the resolve is applied only to for dev.

Vite solution

Setup

"vite": "^2.7.6"
"vue": "^2.6.14"
"@taquito/beacon-wallet": "^9.1.0"
"@taquito/taquito": "^9.1.0"
"@airgap/beacon-sdk": "2.4.0-beta.2"

Also works with @taquito/beacon-wallet@11 & @taquito/taquito@11, but bundles: @taquito/taquito@9: 382.79 KiB @taquito/taquito@11: 560.05 KiB @taquito/beacon-wallet is same.

Steps

  1. Install @airgap/beacon-sdk@2.4.0-beta.2, and for node polyfills vite-compatible-readable-stream and buffer.

npm i @airgap/beacon-sdk@2.4.0-beta.2 vite-compatible-readable-stream buffer

  1. Adjust build config and add aliases to vite.config.js
import { defineConfig, mergeConfig } from 'vite';

export default ({ command }) => {
    const isBuild = command === 'build';
	return defineConfig({
		  build: {
            	target: 'esnext',
            	commonjsOptions: {
                	transformMixedEsModules: true,
            	},
          },
		  resolve: {
			  alias: {
				  // dedupe @airgap/beacon-sdk
				  // I almost have no idea why it needs `cjs` on dev and `esm` on build, but this is how it works 🤷‍♂️
				  '@airgap/beacon-sdk': path.resolve(__dirname, `./node_modules/@airgap/beacon-sdk/dist/${isBuild ? 'esm' : 'cjs'}/index.js`),
				  // polyfills
				  'readable-stream': 'vite-compatible-readable-stream',
	               stream: 'vite-compatible-readable-stream',
			  },
		  },
	});
}
  1. Polyfill global & Buffer in index.html
<html>
    <head>
		<script>
            const global = globalThis;
        </script>
        <script type="module">
            import { Buffer } from 'buffer';
            window.Buffer = Buffer;
        </script>
	</head>
	<!-- ... -->
</html>

Voila!

Why da hell it it needs cjs on dev and esm on build… Seems like it’s Vite issue, gotta open one there.

P.S. I advice to use dynamic imports for @airgap/beacon-sdk & @taquito stuff to care about your bundle.

Related https://github.com/airgap-it/beacon-sdk/issues/138#issuecomment-974860143 - @airgap/beacon-sdk@2.4.0-beta.2 https://github.com/vitejs/vite/issues/3817#issuecomment-864450199 - polyfills https://github.com/nodejs/readable-stream/issues/439#issuecomment-940643578 - vite-compatible-readable-stream https://github.com/originjs/vite-plugins/issues/9 - transformMixedEsModules: true

I had the same problem in a Remix codebase. Got it working by using require instead of import and by polyfilling Buffer in the client code:

import { Buffer } from 'buffer';

if (typeof document !== 'undefined' && !window.Buffer) {
  window.Buffer = Buffer;
}

const { DAppClient, NetworkType, PermissionScope } = require('@airgap/beacon-sdk');
const { BeaconWallet } = require('@taquito/beacon-wallet');

By using require, the CJS build of beacon-sdk is used, instead of the ESM build.

It looks like I made SvelteKit work! The @airgap/beacon-sdk/ package contains a minified version of the code, so I am using this one in the svelte.config.js file:

import adapter from "@sveltejs/adapter-auto";
import preprocess from "svelte-preprocess";
import path from "path";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  // Consult https://github.com/sveltejs/svelte-preprocess
  // for more information about preprocessors
  preprocess: preprocess(),

  kit: {
    adapter: adapter(),
    vite: {
      resolve: {
        alias: {
          "@airgap/beacon-sdk": path.resolve(
            path.resolve(),
	   `./node_modules/@airgap/beacon-sdk/dist/walletbeacon.min.js`
          ),
          // polyfills
          "readable-stream": "vite-compatible-readable-stream",
          stream: "vite-compatible-readable-stream"
        }
      }
    }
  }
};

export default config;

The dapp builds in dev mode (haven’t tested in prod for now) and I was able to send a transaction to a contract on Hangzhounet with this config. If anyone wants to give it a try and report any issue, that would be awesome!

same issue with vitejs / sveltekit here

Version 3 of the Beacon SDK broke all the workarounds that were found on my side 😬 Anybody noticed the same problem coming back after updating the version of the Beacon SDK/Taquito for Svelte/SvelteKit/ViteJs?

@souljorje yes it works ! lifesaver, thx

@clemsos check update, now it works 100%!

https://github.com/ecadlabs/taquito/issues/882#issuecomment-1075096459 worked for me. I updated it to beacon-sdk version 3.1.3. I am using VUE 3 and Vite 3.2.37.

If anyone has insight into what the beacon devs might look into, please comment here: https://github.com/airgap-it/beacon-sdk/issues/380

@claudebarde some additions to my last #882 (comment) and it works:

"vite": "^2.9.8"
"@taquito/beacon-wallet": "^13.0.1"
"@taquito/taquito": "^13.0.1"
"@airgap/beacon-sdk": "^3.1.3"
// vite.config.js

import replace from 'rollup-plugin-re';

import { defineConfig, mergeConfig } from 'vite';

export default ({ command }) => {
    const isBuild = command === 'build';
	return defineConfig({
        plugins: [
          {
          ...replace({
            include: ['node_modules/@airgap/**'],
            replaces: {
              /**
               * damn curcus with this beacon-sdk...
               * qr doesn't work on dev, but at least the whole wallet works
               */
              ...isBuild
                ? {
                  "import * as qrcode from 'qrcode-generator';": "import qrcode from 'qrcode-generator';",
                }
                : {
                  'var libsodium_wrappers_1 = require("libsodium-wrappers")': 'var libsodium_wrappers_1 = require("libsodium-wrappers").default',
                },
            },
          }),
          enforce: 'pre',
        },
    ],
	optimizeDeps: {
      include: [
        '@airgap/beacon-sdk',
        '@taquito/beacon-wallet',
        '@taquito/taquito',
      ]
	}
};

related airgap-it/beacon-sdk#345

This made wallet work on build, but still can’t use it on dev Can you help me out on #1729

Hi Claude!

It does work indeed! I’m using SvelteKit (no webpack)


import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';
import path, { dirname } from 'path'
import { fileURLToPath } from 'url'

const filePath = dirname(fileURLToPath(import.meta.url))
const sassPath = `${filePath}/src/styles/`


/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://github.com/sveltejs/svelte-preprocess
	// for more information about preprocessors
	preprocess: preprocess({

	}),

	kit: {
		adapter: adapter(),
		vite: {
			resolve: {
				alias: {
					"$styles": path.resolve("./src/styles"),
					"@airgap/beacon-sdk": path.resolve(
						path.resolve(),
						`./node_modules/@airgap/beacon-sdk/dist/walletbeacon.min.js`
					),
					// polyfills
					"readable-stream": "vite-compatible-readable-stream",
					stream: "vite-compatible-readable-stream"
				},
			},
				optimizeDeps: {
					esbuildOptions: {
						define: {
							global: 'globalThis',
							'process': JSON.stringify({
								env: {
									NODE_DEBUG: '',
								}
							}),
						}
					}
				}
			}
		}
	};

	export default config;

@souljorje Oops, my error, I didn’t see your const definition above. Thanks!

yes, works on dev but throws on build for me as well. > Uncaught TypeError: Cannot read properties of undefined (reading 'TRANSPORT_P2P_PEERS_DAPP')

@souljorje I don’t remember that being an issue. Here is a link to the code where I create the client and wallet. (warning: clojure ahead)

https://github.com/Trewaters/ACDao/blob/feat-init-app/src/tequito/core.cljs

It worked fine. Although, I didn’t get further than connecting a wallet.

Just a remark:

  "browserslist": "last 2 Chrome versions",
  "alias": {
    "@airgap/beacon-sdk": "./node_modules/@airgap/beacon-sdk/dist/esm/index.js",
    "@taquito/beacon-wallet": "./node_modules/@taquito/beacon-wallet/dist/taquito-beacon-wallet.es5.js",
    "@taquito/signer": "./node_modules/@taquito/signer/dist/taquito-signer.es5.js",
    "@taquito/taquito": "./node_modules/@taquito/taquito/dist/taquito.es5.js"
  }

did not fix the problem for me (“@taquito/taquito”: “^9.2.0”, “@taquito/beacon-wallet”: “^9.2.0”).

This bug should be a failing test and a showstopper.