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

Create a minified browser build compatible with next.js #1108

Merged
merged 11 commits into from
Dec 7, 2021
1 change: 1 addition & 0 deletions ts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.rollup.cache/
jeduan marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 12 additions & 2 deletions ts/package.json
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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) {
exports.workspace = require("./workspace.js");
exports.Wallet = require("./nodewallet.js");
}
39 changes: 39 additions & 0 deletions ts/src/nodewallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Buffer } from "buffer";
import { Keypair, PublicKey, Transaction } from "@solana/web3.js";
import { Wallet } from "./provider";
/**
jeduan marked this conversation as resolved.
Show resolved Hide resolved
* 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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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");
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");
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
Original file line number Diff line number Diff line change
@@ -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
jeduan marked this conversation as resolved.
Show resolved Hide resolved
: 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@

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

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