cosmos / cosmjs

The Swiss Army knife to power JavaScript based client solutions ranging from Web apps/explorers over browser extensions to server-side clients like faucets/scrapers.
https://cosmos.github.io/cosmjs/
Apache License 2.0
649 stars 333 forks source link

How to generate browser bundle for cosmjs/stargate #921

Open chibie opened 2 years ago

chibie commented 2 years ago

I'm trying to sign and broadcast transactions to cosmos network (cosmoshub-4) using Keplr wallet extension which depends on SigningStargateClient provided by cosmjs/stargate.

How can I generate a bundled+minified version of cosmjs/stargate package to ensure execution of the code snippet below without installing the available npm package ?

await window.keplr.enable(chainId);

const offlineSigner = window.getOfflineSigner(chainId);
const accounts = await offlineSigner.getAccounts();

// Initialize the gaia api with the offline signer that is injected by Keplr extension.
const cosmJS = new SigningStargateClient(
    "https://lcd-cosmoshub.keplr.app/rest",
    accounts[0].address,
    offlineSigner,
);
ethanfrey commented 2 years ago

Thank you for providing an example code.

For context, this question was raised on discord in pa

They were looking to bindle cosmjs with browserify and I said we couldn't even begin to help without a clear acceptance criteria. The goals now look rather clear. The above must run in a browser (directly in a <script> tag) and only require one import before of some "bundled" cosmjs/stargate package.

I cannot help personally, but maybe this makes sense for another dev, ideally one who had some browserify experience.

clockworkgr commented 2 years ago

still unclear why you don't want to use the npm package and your app's standard bundling flow (unless you're using vite to build....there are some issues there unfortunately).

In any case, have you tried building your own standalone bundle? e.g. creating a new package with something as simple as:

const stargate = require('@cosmjs/stargate');
window.SigningStargateClient = stargate.SigningStargateClient;

and running browserify on that ?

also , just noticed on your code snippet that you're using the constructor directly...It is actually protected and you should use the static methods provided...e.g.

const cosmjs = await SigningStargateClient.connectWithSigner(...)

If you were using TS it would have complained

webmaster128 commented 2 years ago

As mentioned above, CosmJS is not usable in a browser without a bundler. Right now, CosmJS ships CommonJS modules that only run natively in Node.js. We might switch to es6 modules at some point, but that basically requires us to drop Node.js 12 support or build each package twice. This can be done but unlikely to happen any time soon. Even if we had es6 builds, I wonder how the different packages would find each other.

So bundling everything for the web is your best bet. All the frontend frameworks have solutions for that built in. Browserify or Webpack can also be used as standalone tools to do that. I don't have much experience with that. It works well for Create React App apps and our Webpack bundled browser tests.

dsudit01 commented 1 year ago

still unclear why you don't want to use the npm package and your app's standard bundling flow (unless you're using vite to build....there are some issues there unfortunately).

In any case, have you tried building your own standalone bundle? e.g. creating a new package with something as simple as:

const stargate = require('@cosmjs/stargate');
window.SigningStargateClient = stargate.SigningStargateClient;

and running browserify on that ?

also , just noticed on your code snippet that you're using the constructor directly...It is actually protected and you should use the static methods provided...e.g.

const cosmjs = await SigningStargateClient.connectWithSigner(...)

If you were using TS it would have complained

Is there a solution for vite at this point?

clockworkgr commented 1 year ago

still unclear why you don't want to use the npm package and your app's standard bundling flow (unless you're using vite to build....there are some issues there unfortunately). In any case, have you tried building your own standalone bundle? e.g. creating a new package with something as simple as:

const stargate = require('@cosmjs/stargate');
window.SigningStargateClient = stargate.SigningStargateClient;

and running browserify on that ? also , just noticed on your code snippet that you're using the constructor directly...It is actually protected and you should use the static methods provided...e.g.

const cosmjs = await SigningStargateClient.connectWithSigner(...)

If you were using TS it would have complained

Is there a solution for vite at this point?

As long as you use a plugin to add node globals/buffer/stream polyfills it should work fine.

e.g. vite.config.ts

import { nodeResolve } from "@rollup/plugin-node-resolve";
import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [nodeResolve()],

  optimizeDeps: {
    esbuildOptions: {
      define: {
        global: "globalThis",
      },
      plugins: [
        NodeGlobalsPolyfillPlugin({
          buffer: true,
        }),
      ],
    },
  },
});