Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sodium.randombytes_buf is not a function #882

Closed
mattdesl opened this issue May 20, 2021 · 33 comments
Closed

sodium.randombytes_buf is not a function #882

mattdesl opened this issue May 20, 2021 · 33 comments
Labels
bug Something isn't working

Comments

@mattdesl
Copy link

mattdesl commented May 20, 2021

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"
  }
...
@mattdesl mattdesl added the bug Something isn't working label May 20, 2021
@Innkst
Copy link
Contributor

Innkst commented May 20, 2021

This is most likely related to airgap-it/beacon-sdk#138

@dribnet
Copy link

dribnet commented Jun 17, 2021

Confirming that this appears to be a beacon-sdk issue as I get the same results with the taquito-less version (beacon-sdk 2.2.9):

import { DAppClient } from "@airgap/beacon-sdk";

const dAppClient = new DAppClient({ name: "Beacon Docs" });

sync();

async function sync() {
  try {
    console.log("Requesting permissions...");
    const permissions = await dAppClient.requestPermissions();
    console.log("Got permissions:", permissions.address);
  } catch (error) {
    console.log("Got error:", error);
  }
}

I wasn't able to get the package.json aliases to work for me either, so my only solution for now is to roll back taquito to 6.x as that was the last version without this issue:

    "@taquito/beacon-wallet": "^6.4.0-ledger.0",
    "@taquito/taquito": "^6.4.0-ledger.0",

@crcdng
Copy link

crcdng commented Jul 22, 2021

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.

@clemsos
Copy link
Contributor

clemsos commented Oct 13, 2021

same issue with vitejs / sveltekit here

@BerkeleyTrue
Copy link

same issue in a clojurescript project using shadow-cljs build system.

@CoffeeW-1337
Copy link

Any news ?

@souljorje
Copy link
Contributor

Same with vue2 + vite

@BerkeleyTrue
Copy link

I was able to get it to build correctly using the following

    "@airgap/beacon-sdk": "^2.4.0-beta.2",
    "@taquito/beacon-wallet": "^10.2.1",
    "@taquito/taquito": "^10.2.1",

@souljorje
Copy link
Contributor

@BerkeleyTrue, how did you override @airgap/beacon-sdk version used by @taquito?

@BerkeleyTrue
Copy link

@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.

@souljorje
Copy link
Contributor

souljorje commented Dec 22, 2021

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/[email protected], and for node polyfills vite-compatible-readable-stream and buffer.

npm i @airgap/[email protected] 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
airgap-it/beacon-sdk#138 (comment) - @airgap/[email protected]
vitejs/vite#3817 (comment) - polyfills
nodejs/readable-stream#439 (comment) - vite-compatible-readable-stream
originjs/vite-plugins#9 - transformMixedEsModules: true

@clemsos
Copy link
Contributor

clemsos commented Dec 22, 2021

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
Copy link
Contributor

@clemsos check update, now it works 100%!

@clemsos
Copy link
Contributor

clemsos commented Dec 23, 2021

@souljorje yes it works ! lifesaver, thx

@kevinelliott
Copy link

@souljorje A lifesaver. I'm getting a isBuild is not defined over here.

@kevinelliott
Copy link

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

@cryi
Copy link
Contributor

cryi commented Mar 22, 2022

Hi, I had same issue. Solution in #882 (comment) 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 sodium.randombytes_buf is not a function #882 (comment)
  2. download browserified version of from unpkg. For latest it is [email protected].
  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.

@claudebarde
Copy link
Contributor

I have a working app with Svelte, Vitejs, Taquito, and the Beacon wallet at this address => https://github.com/claudebarde/taquito-bundlers-testing/tree/main/vitejs
If you check the repo, you will see that I am still trying to make it work with SvelteKit 😅 I'll post an update here when I manage to make it work!

@claudebarde
Copy link
Contributor

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!

@melMass
Copy link

melMass commented Apr 5, 2022

If anyone wants to give it a try and report any issue, that would be awesome!

Yes!! This is the most straight forward way, I can confirm it works in svelte kit!

@claudebarde
Copy link
Contributor

@melMass Have you been able to build the app?
I posted my comment before trying to build the app and it doesn't build 😅 First, I get this error message:
SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list (32034:11)
It looks like an issue coming from the Beacon SDK. When I try to remove all the "use strict" from the walletbeacon.min.js file, I get this error:
'DAppClient' is not exported by src/walletbeacon.min.js, imported by node_modules/@taquito/beacon-wallet/dist/taquito-beacon-wallet.es6.js (maybe because the BeaconWallet library doesn't use the minified file but the Node module?)
It's very frustrating to be stuck with Webpack or old versions of Svelte to make the Beacon SDK work.

@melMass
Copy link

melMass commented Apr 7, 2022

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;

@claudebarde
Copy link
Contributor

Right, I added the adapter for Netlify and that's when things went sideways! It looks like it builds properly with the auto adapter, thanks!

@claudebarde
Copy link
Contributor

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?

@cryi
Copy link
Contributor

cryi commented May 9, 2022

@claudebarde check my older comment. I edited the code to work with version 3. Or at least it works for me 😄

Just copy walletbeacon.dapp.min.js from @airgap/beacon-dapp/dist/ to your src/vendor and adjust vite config as mentioned in the comment.

@souljorje
Copy link
Contributor

souljorje commented Jul 7, 2022

@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

@itsnamangoyal
Copy link

@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

@xat
Copy link

xat commented Jul 11, 2022

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.

@claudebarde
Copy link
Contributor

@xat That looks like a good idea, I will try it with other projects I had problems with, thanks!

@melMass
Copy link

melMass commented Jul 11, 2022

@xat In svelte we can't "require" AFAIK 🥲

@jfbloom22
Copy link

#882 (comment) 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: airgap-it/beacon-sdk#380

@melMass
Copy link

melMass commented Aug 23, 2022

Just for another reference in the latest Svelte Kit beta (1.0.0-next.429) and @airgap/beacon-sdk 3.1.3, note that the reason my node_modules are two levels up (../..) is because this project is part of an NX monorepo. Use ./ for non-monorepo :

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import path from 'path';
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';

export default ({ command }) => {
  const isBuild = command === 'build';
  const devOnlyResolve = isBuild ? {} : {
		"@airgap/beacon-dapp": path.resolve(__dirname, `../../node_modules/@airgap/beacon-dapp/dist/cjs/index.js`),
		"@airgap/beacon-sdk": path.resolve(__dirname, `../../node_modules/@airgap/beacon-sdk/dist/cjs/index.js`),
	}

  return defineConfig({
    plugins: [
      sveltekit(),
     ],
    server: {
      port: 3004,
    },

    resolve: {
      alias: {
        ...devOnlyResolve,
        "readable-stream": "vite-compatible-readable-stream",
        stream: "vite-compatible-readable-stream"
      }
    },
    define: {
      global: "globalThis"
    },
    optimizeDeps: {
      commonjsOptions: {
        transformMixedEsModules: true
      },
	  esbuildOptions: {
        // Enable esbuild polyfill plugins
        plugins: isBuild ? [] : [
          NodeGlobalsPolyfillPlugin({
             process: true,
             buffer: true
           }),
        ]
      }
    },
    build: {
      target: "esnext",
      commonjsOptions: {
        transformMixedEsModules: true
      },
    }
  });
}

@michaelkernaghan
Copy link
Collaborator

it was a beacon issue and then a vite issue, but there is not an issue with Taquito.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests