Skip to content

Commit

Permalink
ts: Create a minified browser build (#1108)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeduan committed Dec 7, 2021
1 parent 105bb20 commit 0f8de4f
Show file tree
Hide file tree
Showing 15 changed files with 350 additions and 93 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -18,3 +18,4 @@ ts/docs/
cli/npm-package/anchor
cli/npm-package/*.tgz
docker-target
.rollup.cache/
14 changes: 12 additions & 2 deletions ts/package.json
Expand Up @@ -4,6 +4,7 @@
"description": "Anchor client",
"module": "./dist/esm/index.js",
"main": "./dist/cjs/index.js",
"browser": "./dist/browser/index.js",
"license": "(MIT OR Apache-2.0)",
"types": "dist/cjs/index.d.ts",
"homepage": "https://github.com/project-serum/anchor#readme",
Expand All @@ -21,8 +22,9 @@
"node": ">=11"
},
"scripts": {
"build": "rm -rf dist/ && yarn build:node",
"build": "rimraf dist/ && yarn build:node && yarn build:browser",
"build:node": "tsc && tsc -p tsconfig.cjs.json",
"build:browser": "rollup --config",
"lint:fix": "prettier src/** tests/** -w",
"lint": "prettier src/** tests/** --check",
"watch": "tsc -p tsconfig.cjs.json --watch",
Expand All @@ -36,7 +38,7 @@
"base64-js": "^1.5.1",
"bn.js": "^5.1.2",
"bs58": "^4.0.1",
"buffer-layout": "^1.2.0",
"buffer-layout": "^1.2.2",
"camelcase": "^5.3.1",
"crypto-hash": "^1.3.0",
"eventemitter3": "^4.0.7",
Expand All @@ -49,6 +51,10 @@
"devDependencies": {
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-node-resolve": "^13.0.6",
"@rollup/plugin-replace": "^3.0.0",
"@rollup/plugin-typescript": "^8.3.0",
"@types/bn.js": "^4.11.6",
"@types/bs58": "^4.0.1",
"@types/crypto-hash": "^1.1.2",
Expand All @@ -63,9 +69,13 @@
"jest-config": "27.3.1",
"lint-staged": "^10.5.0",
"prettier": "^2.1.2",
"rimraf": "^3.0.2",
"rollup": "^2.60.2",
"rollup-plugin-terser": "^7.0.2",
"ts-jest": "^27.0.7",
"ts-jest-resolver": "^2.0.0",
"ts-node": "^9.0.0",
"tslib": "^2.3.1",
"typedoc": "^0.22.10",
"typescript": "^4.5.2"
}
Expand Down
54 changes: 54 additions & 0 deletions ts/rollup.config.ts
@@ -0,0 +1,54 @@
import nodeResolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import replace from "@rollup/plugin-replace";
import commonjs from "@rollup/plugin-commonjs";
import { terser } from "rollup-plugin-terser";

const env = process.env.NODE_ENV;

export default {
input: "src/index.ts",
plugins: [
commonjs(),
nodeResolve({
browser: true,
extensions: [".js", ".ts"],
dedupe: ["bn.js", "buffer"],
preferBuiltins: false,
}),
typescript({
tsconfig: "./tsconfig.base.json",
moduleResolution: "node",
outDir: "types",
target: "es2019",
outputToFilesystem: false,
}),
replace({
preventAssignment: true,
values: {
"process.env.NODE_ENV": JSON.stringify(env),
"process.env.BROWSER": JSON.stringify(true),
},
}),
terser(),
],
external: [
"@project-serum/borsh",
"@solana/web3.js",
"assert",
"base64-js",
"bn.js",
"bs58",
"buffer",
"camelcase",
"eventemitter3",
"js-sha256",
"pako",
"toml",
],
output: {
file: "dist/browser/index.js",
format: "es",
sourcemap: true,
},
};
16 changes: 9 additions & 7 deletions ts/src/index.ts
@@ -1,11 +1,8 @@
import { isBrowser } from "./utils/common.js";

export { default as BN } from "bn.js";
export * as web3 from "@solana/web3.js";
export {
default as Provider,
getProvider,
setProvider,
NodeWallet as Wallet,
} from "./provider.js";
export { default as Provider, getProvider, setProvider } from "./provider.js";
export {
default as Coder,
InstructionCoder,
Expand All @@ -17,6 +14,11 @@ export {
export * from "./error.js";
export { Instruction } from "./coder/instruction.js";
export { Idl } from "./idl.js";
export { default as workspace } from "./workspace.js";

export * as utils from "./utils/index.js";
export * from "./program/index.js";

if (!isBrowser) {

This comment has been minimized.

Copy link
@zisko

zisko Dec 17, 2021

This breaks typescript autocomplete support for:
import * as anchor from '@project-serum/anchor'

to repro, anchor init and open the generated test file in vscode.

This comment has been minimized.

Copy link
@zisko

This comment has been minimized.

Copy link
@fanatid

fanatid Dec 17, 2021

Contributor

@zisko can you check #1137? Will 1137 fix an issue?

This comment has been minimized.

Copy link
@zisko

zisko Dec 17, 2021

I also don't know TS well enough, but I patched #1137 onto my node_modules and it did not fix the issue.

This comment has been minimized.

Copy link
@zisko

zisko Dec 17, 2021

(I'll make a comment there)

exports.workspace = require("./workspace.js").default;
exports.Wallet = require("./nodewallet.js").default;
}
40 changes: 40 additions & 0 deletions ts/src/nodewallet.ts
@@ -0,0 +1,40 @@
import { Buffer } from "buffer";
import { Keypair, PublicKey, Transaction } from "@solana/web3.js";
import { Wallet } from "./provider";

/**
* Node only wallet.
*/
export default class NodeWallet implements Wallet {
constructor(readonly payer: Keypair) {}

static local(): NodeWallet {
const process = require("process");
const payer = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(
require("fs").readFileSync(process.env.ANCHOR_WALLET, {
encoding: "utf-8",
})
)
)
);
return new NodeWallet(payer);
}

async signTransaction(tx: Transaction): Promise<Transaction> {
tx.partialSign(this.payer);
return tx;
}

async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
return txs.map((t) => {
t.partialSign(this.payer);
return t;
});
}

get publicKey(): PublicKey {
return this.payer.publicKey;
}
}
3 changes: 1 addition & 2 deletions ts/src/program/index.ts
@@ -1,6 +1,6 @@
import { inflate } from "pako";
import { PublicKey } from "@solana/web3.js";
import Provider from "../provider.js";
import Provider, { getProvider } from "../provider.js";
import { Idl, idlAddress, decodeIdlAccount } from "../idl.js";
import Coder from "../coder/index.js";
import NamespaceFactory, {
Expand All @@ -11,7 +11,6 @@ import NamespaceFactory, {
StateClient,
SimulateNamespace,
} from "./namespace/index.js";
import { getProvider } from "../index.js";
import { utf8 } from "../utils/bytes/index.js";
import { EventManager } from "./event.js";
import { Address, translateAddress } from "./common.js";
Expand Down
3 changes: 1 addition & 2 deletions ts/src/program/namespace/account.ts
Expand Up @@ -10,15 +10,14 @@ import {
Commitment,
GetProgramAccountsFilter,
} from "@solana/web3.js";
import Provider from "../../provider.js";
import Provider, { getProvider } from "../../provider.js";
import { Idl, IdlTypeDef } from "../../idl.js";
import Coder, {
ACCOUNT_DISCRIMINATOR_SIZE,
accountSize,
AccountsCoder,
} from "../../coder/index.js";
import { Subscription, Address, translateAddress } from "../common.js";
import { getProvider } from "../../index.js";
import { AllAccountsMap, IdlTypes, TypeDef } from "./types.js";
import * as pubkeyUtil from "../../utils/pubkey.js";
import * as rpcUtil from "../../utils/rpc.js";
Expand Down
3 changes: 1 addition & 2 deletions ts/src/program/namespace/state.ts
Expand Up @@ -6,15 +6,14 @@ import {
Commitment,
AccountMeta,
} from "@solana/web3.js";
import Provider from "../../provider.js";
import Provider, { getProvider } from "../../provider.js";
import { Idl, IdlInstruction, IdlStateMethod, IdlTypeDef } from "../../idl.js";
import Coder, { stateDiscriminator } from "../../coder/index.js";
import {
RpcNamespace,
InstructionNamespace,
TransactionNamespace,
} from "./index.js";
import { getProvider } from "../../index.js";
import { Subscription, validateAccounts, parseIdlErrors } from "../common.js";
import {
findProgramAddressSync,
Expand Down
44 changes: 5 additions & 39 deletions ts/src/provider.ts
@@ -1,7 +1,5 @@
import { Buffer } from "buffer";
import {
Connection,
Keypair,
Signer,
PublicKey,
Transaction,
Expand Down Expand Up @@ -46,11 +44,15 @@ export default class Provider {
* (This api is for Node only.)
*/
static local(url?: string, opts?: ConfirmOptions): Provider {
if (isBrowser) {
throw new Error(`Provider local is not available on browser.`);
}
opts = opts ?? Provider.defaultOptions();
const connection = new Connection(
url ?? "http://localhost:8899",
opts.preflightCommitment
);
const NodeWallet = require("./nodewallet.js").default;
const wallet = NodeWallet.local();
return new Provider(connection, wallet, opts);
}
Expand All @@ -73,6 +75,7 @@ export default class Provider {
}
const options = Provider.defaultOptions();
const connection = new Connection(url, options.commitment);
const NodeWallet = require("./nodewallet.js").default;
const wallet = NodeWallet.local();

return new Provider(connection, wallet, options);
Expand Down Expand Up @@ -223,43 +226,6 @@ export interface Wallet {
publicKey: PublicKey;
}

/**
* Node only wallet.
*/
export class NodeWallet implements Wallet {
constructor(readonly payer: Keypair) {}

static local(): NodeWallet {
const process = require("process");
const payer = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(
require("fs").readFileSync(process.env.ANCHOR_WALLET, {
encoding: "utf-8",
})
)
)
);
return new NodeWallet(payer);
}

async signTransaction(tx: Transaction): Promise<Transaction> {
tx.partialSign(this.payer);
return tx;
}

async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
return txs.map((t) => {
t.partialSign(this.payer);
return t;
});
}

get publicKey(): PublicKey {
return this.payer.publicKey;
}
}

// Copy of Connection.simulateTransaction that takes a commitment parameter.
async function simulateTransaction(
connection: Connection,
Expand Down
17 changes: 9 additions & 8 deletions ts/src/utils/bytes/utf8.ts
@@ -1,15 +1,16 @@
import { isBrowser } from "../common";

export function decode(array: Uint8Array): string {
const decoder =
typeof TextDecoder === "undefined"
? new (require("util").TextDecoder)("utf-8") // Node.
: new TextDecoder("utf-8"); // Browser.
const decoder = isBrowser
? new TextDecoder("utf-8") // Browser https://caniuse.com/textencoder.
: new (require("util").TextDecoder)("utf-8"); // Node.

return decoder.decode(array);
}

export function encode(input: string): Uint8Array {
const encoder =
typeof TextEncoder === "undefined"
? new (require("util").TextEncoder)("utf-8") // Node.
: new TextEncoder(); // Browser.
const encoder = isBrowser
? new TextEncoder() // Browser.
: new (require("util").TextEncoder)("utf-8"); // Node.
return encoder.encode(input);
}
3 changes: 2 additions & 1 deletion ts/src/utils/common.ts
Expand Up @@ -3,7 +3,8 @@
* false if in a Node process or electron app.
*/
export const isBrowser =
typeof window !== "undefined" && !window.process?.hasOwnProperty("type");
process.env.BROWSER ||
(typeof window !== "undefined" && !window.process?.hasOwnProperty("type"));

/**
* Splits an array into chunks
Expand Down
28 changes: 28 additions & 0 deletions ts/tsconfig.base.json
@@ -0,0 +1,28 @@
{
"include": [
"./src/**/*"
],
"compilerOptions": {
"sourceMap": true,
"declaration": true,
"declarationMap": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noImplicitAny": false,
"strictNullChecks": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"composite": true,
"baseUrl": ".",
"typeRoots": [
"types/",
"node_modules/@types"
],
"paths": {
"@solana/web3.js": [
"./node_modules/@solana/web3.js/lib"
]
}
}
}
4 changes: 1 addition & 3 deletions ts/tsconfig.cjs.json
@@ -1,10 +1,8 @@

{
"extends": "./tsconfig.json",
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"target": "es2019",

"outDir": "dist/cjs/",
"rootDir": "./src"
}
Expand Down

0 comments on commit 0f8de4f

Please sign in to comment.