Compare commits

...

21 Commits

Author SHA1 Message Date
Richard Moore
22dee96f51 Updated dist files. 2020-09-26 03:27:47 -04:00
Richard Moore
0c614b7097 CI: Refactored changelog admin script. 2020-09-26 03:25:54 -04:00
Richard Moore
f0a5869c53 Add more accurate intrinsic gas cost to ABI calls with specified gas property (#1058). 2020-09-26 02:17:05 -04:00
Richard Moore
5cd1668e0d Better errors for unconfigured ENS names (#1066). 2020-09-26 01:23:43 -04:00
Richard Moore
0b061d68cc CI: Fixed reaxct-native tests with new scripts. 2020-09-23 15:53:42 -04:00
Richard Moore
ffa4a2d054 CI: Fix test cases. 2020-09-23 01:00:30 -04:00
Richard Moore
f8072a8004 Build: Added node 8 support. 2020-09-23 00:23:02 -04:00
Richard Moore
4306b3563a Updated CLI solc to versin 0.7.1. 2020-09-23 00:00:21 -04:00
Richard Moore
c4de88af6f Docs: Fix typo (#1044). 2020-09-22 23:51:59 -04:00
Richard Moore
9486185ceb Updated dist files. 2020-09-22 23:18:45 -04:00
Richard Moore
261eb04e97 Ignore metadata files in each package. 2020-09-22 22:57:17 -04:00
Richard Moore
832bd6c908 Refactored admin scripts. 2020-09-22 22:54:48 -04:00
Richard Moore
05844caf85 Extended Karma testing timeout managed by tests. 2020-09-21 22:44:37 -04:00
Richard Moore
f7e82fcb46 Started refactoring admin scripts into TypeScript. 2020-09-21 01:14:06 -04:00
Richard Moore
27b3af0a7b Removed dead files. 2020-09-17 17:17:15 -04:00
Richard Moore
f733fac875 Custom API key for Etherscan during tests (#824). 2020-09-17 03:44:29 -04:00
Richard Moore
1097a1b020 Replaced lerna with admin hoist and link scripts. 2020-09-17 03:40:55 -04:00
Richard Moore
ea422d63b3 Replaced lerna with admin hoist and link scripts. 2020-09-17 03:39:25 -04:00
Richard Moore
a3821f6c4b Updated dist files. 2020-09-16 19:44:55 -04:00
Richard Moore
de8a717b4c Refactored provider test cases to more reliable CI. 2020-09-16 19:38:01 -04:00
Richard Moore
86e0269a86 Extend Karma timeout for new provider tests. 2020-09-16 11:00:29 -04:00
460 changed files with 16842 additions and 22190 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
node_modules/
packages/*/node_modules
.package_node_modules/
obsolete/
.DS_Store
.tmp/

View File

@@ -3,6 +3,13 @@ Changelog
This change log is managed by `admin/cmds/update-versions` but may be manually updated.
ethers/v5.0.15 (2020-09-26 03:22)
---------------------------------
- Add more accurate intrinsic gas cost to ABI calls with specified gas property. ([#1058](https://github.com/ethers-io/ethers.js/issues/1058); [f0a5869](https://github.com/ethers-io/ethers.js/commit/f0a5869c53475e55a5f47d8651f609fff45dc9a7))
- Better errors for unconfigured ENS names. ([#1066](https://github.com/ethers-io/ethers.js/issues/1066); [5cd1668](https://github.com/ethers-io/ethers.js/commit/5cd1668e0d29099c5b7ce1fdc1d0e8a41af1a249))
- Updated CLI solc to versin 0.7.1. ([4306b35](https://github.com/ethers-io/ethers.js/commit/4306b3563a171baa9d7bf4872475a13c3434f834))
ethers/v5.0.14 (2020-09-16 02:39)
---------------------------------
@@ -122,4 +129,3 @@ ethers/v5.0.0 (2020-06-12 19:58)
- Preserve config canary string. ([7157816](https://github.com/ethers-io/ethers.js/commit/7157816fa53f660d750811b293e3b1d5a2f70bd4))
- Updated docs. ([9e4c7e6](https://github.com/ethers-io/ethers.js/commit/9e4c7e609d9eeb5f2a11d6a90bfa9d32ee696431))

View File

@@ -1,5 +0,0 @@
"use strict";
const { setupBuild } = require("../build");
setupBuild(false);

View File

@@ -1,37 +0,0 @@
const { setupBuild } = require("../build");
const { loadPackage, savePackage } = require("../local");
const arg = process.argv[2];
(async function() {
process.argv.slice(2).forEach((arg) => {
console.log("Setting Option:", arg);
switch(arg) {
case "esm":
setupBuild(true);
break;
case "cjs":
setupBuild(false);
break;
// This will remove the browser field entirely, so make sure
// to set esm of cjs first as they will restore the browser
// field
case "browser-lang-all": {
const info = loadPackage("wordlists");
delete info.browser;
savePackage("wordlists", info);
break;
}
default:
console.log("Unknown option:", arg);
return 1;
}
});
return 0;
})().then((result) => {
process.exit(result);
});

View File

@@ -1,16 +0,0 @@
"use stricT";
const depgraph = require("../depgraph");
const { log } = require("../log");
const { loadJson, resolve, saveJson } = require("../utils");
(async function() {
log(`<bold:Updating dependency-graph build order (tsconfig.project.json)...>`);
let ordered = depgraph.getOrdered(true);
let path = resolve("tsconfig.project.json")
let projectConfig = loadJson(path);
projectConfig.references = ordered.map((name) => ({ path: ("./packages/" + name) }));
saveJson(path, projectConfig);
})();

View File

@@ -1,30 +0,0 @@
"use strict";
const fs = require("fs");
const { resolve } = require("path");
const sourceEthers = fs.readFileSync(resolve(__dirname, "../../packages/ethers/src.ts/ethers.ts")).toString();
const targets = sourceEthers.match(/export\s*{\s*((.|\s)*)}/)[1].trim();
const output = `"use strict";
// To modify this file, you must update ./admin/cmds/update-exports.js
import * as ethers from "./ethers";
try {
const anyGlobal = (window as any);
if (anyGlobal._ethers == null) {
anyGlobal._ethers = ethers;
}
} catch (error) { }
export { ethers };
export {
${ targets }
} from "./ethers";
`;
fs.writeFileSync(resolve(__dirname, "../../packages/ethers/src.ts/index.ts"), output);

View File

@@ -9,7 +9,7 @@ The [Cryptographic Hash Functions](link-wiki-cryptographichash)
are a specific family of hash functions.
_property: ethers.utils.id(text) => string<[[DataHexString]]<32>> @<utils-id> @SRC<hash>
The Ethereum Identity function computs the [KECCAK256](link-wiki-sha3) hash of the //text// bytes.
The Ethereum Identity function computes the [KECCAK256](link-wiki-sha3) hash of the //text// bytes.
_property: ethers.utils.keccak256(aBytesLike) => string<[[DataHexString]]<32>> @<utils-keccak256> @SRC<keccak256>
Returns the [KECCAK256](link-wiki-sha3) digest //aBytesLike//.

View File

@@ -7,7 +7,7 @@ module.exports = function(config) {
{ pattern: "./packages/ethers/dist/ethers-all.esm.min.js", type: "module" },
{ pattern: "./packages/tests/dist/tests.esm.js", type: "module" }
],
reporters: ['karma'],
reporters: [ 'karma' ],
plugins: [
'karma-mocha',
'karma-chrome-launcher',
@@ -18,7 +18,7 @@ module.exports = function(config) {
browsers: [ 'ChromeHeadless', "HeadlessLittleLiar" ],
autoWatch: false,
singleRun: true,
browserNoActivityTimeout: 60000,
browserNoActivityTimeout: 3600000,
customLaunchers: {
HeadlessLittleLiar: {
base: 'ChromeHeadless',

View File

@@ -18,24 +18,24 @@ module.exports = function(config) {
browsers: [ 'ChromeHeadless', "HeadlessLittleLiar" ],
autoWatch: false,
singleRun: true,
browserNoActivityTimeout: 600000,
browserNoActivityTimeout: 3600000,
customLaunchers: {
HeadlessLittleLiar: {
base: 'ChromeHeadless',
// https://peter.sh/experiments/chromium-command-line-switches/
flags: [
'--disable-extensions',
'--disable-extensions',
// Enable this to help debug CORS issues (otherwise fetch throws a useless TypeError)
//'--disable-web-security',
// Enable this to help debug CORS issues (otherwise fetch throws a useless TypeError)
//'--disable-web-security',
'--enable-automation',
'--enable-automation',
// Cloudflare will block (on the testnet endpoints) any traffic
// from a headless chome (based on the user agent), so we lie
// This was take from Safari, because that is what I had on-hand
'--user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15']
// Cloudflare will block (on the testnet endpoints) any traffic
// from a headless chome (based on the user agent), so we lie
// This was take from Safari, because that is what I had on-hand
'--user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15']
}
},
/*

View File

@@ -0,0 +1 @@
*.js

3
misc/admin/auto-build.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
npx tsc -w

1
misc/admin/lib/build.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export declare function setupBuild(buildModule: boolean): void;

48
misc/admin/lib/build.js Normal file
View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("./path");
const utils_1 = require("./utils");
function setupConfig(outDir, moduleType, targetType) {
// Configure the tsconfit.package.json...
const path = path_1.resolve("tsconfig.package.json");
const content = utils_1.loadJson(path);
content.compilerOptions.module = moduleType;
content.compilerOptions.target = targetType;
utils_1.saveJson(path, content, true);
// Configure the browser field for every pacakge, copying the
// browser.umd filed for UMD and browser.esm for ESM
path_1.dirnames.forEach((dirname) => {
const filename = path_1.getPackageJsonPath(dirname);
const info = utils_1.loadJson(filename);
if (info._ethers_nobuild) {
return;
}
if (targetType === "es2015") {
if (info["browser.esm"]) {
info.browser = info["browser.esm"];
}
}
else if (targetType === "es5") {
if (info["browser.umd"]) {
info.browser = info["browser.umd"];
}
}
else {
throw new Error("unsupported target");
}
utils_1.saveJson(filename, info, true);
let path = path_1.resolve("packages", dirname, "tsconfig.json");
let content = utils_1.loadJson(path);
content.compilerOptions.outDir = outDir;
utils_1.saveJson(path, content, true);
});
}
function setupBuild(buildModule) {
if (buildModule) {
setupConfig("./lib.esm/", "es2015", "es2015");
}
else {
setupConfig("./lib/", "commonjs", "es5");
}
}
exports.setupBuild = setupBuild;

1
misc/admin/lib/changelog.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export declare function generate(): Promise<string>;

106
misc/admin/lib/changelog.js Normal file
View File

@@ -0,0 +1,106 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const local = __importStar(require("./local"));
const log_1 = require("./log");
const npm = __importStar(require("./npm"));
const path_1 = require("./path");
const run_1 = require("./run");
const utils_1 = require("./utils");
const changelogPath = path_1.resolve("CHANGELOG.md");
function generate() {
return __awaiter(this, void 0, void 0, function* () {
const lines = fs_1.default.readFileSync(changelogPath).toString().trim().split("\n");
let firstLine = null;
const versions = Object.keys(lines.reduce((accum, line, index) => {
const match = line.match(/^ethers\/v([^ ]*)/);
if (match) {
if (firstLine == null) {
firstLine = index;
}
accum[match[1]] = true;
}
return accum;
}, {}));
const version = local.getPackage("ethers").version;
;
const published = yield npm.getPackage("ethers");
if (versions.indexOf(version) >= 0) {
const line = `Version ${version} already in CHANGELOG. Please edit before committing.`;
console.log(log_1.colorify.red(utils_1.repeat("=", line.length)));
console.log(log_1.colorify.red(line));
console.log(log_1.colorify.red(utils_1.repeat("=", line.length)));
}
const gitResult = yield run_1.run("git", ["log", (published.gitHead + "..")]);
if (!gitResult.ok) {
console.log(gitResult);
throw new Error("Error running git log");
}
let changes = [];
gitResult.stdout.split("\n").forEach((line) => {
if (line.toLowerCase().substring(0, 6) === "commit") {
changes.push({
commit: line.substring(6).trim(),
date: null,
body: ""
});
}
else if (line.toLowerCase().substring(0, 5) === "date:") {
changes[changes.length - 1].date = utils_1.getDateTime(new Date(line.substring(5).trim()));
}
else if (line.substring(0, 1) === " ") {
line = line.trim();
if (line === "") {
return;
}
changes[changes.length - 1].body += line + " ";
}
});
const output = [];
for (let i = 0; i < firstLine; i++) {
output.push(lines[i]);
}
const newTitle = `ethers/v${version} (${utils_1.getDateTime(new Date())})`;
output.push(newTitle);
output.push(utils_1.repeat("-", newTitle.length));
output.push("");
changes.forEach((change) => {
let body = change.body.trim();
let linkMatch = body.match(/(\((.*#.*)\))/);
let commit = `[${change.commit.substring(0, 7)}](https://github.com/ethers-io/ethers.js/commit/${change.commit})`;
let link = commit;
if (linkMatch) {
body = body.replace(/ *(\(.*#.*)\) */, "");
link = linkMatch[2].replace(/#([0-9]+)/g, (all, issue) => {
return `[#${issue}](https://github.com/ethers-io/ethers.js/issues/${issue})`;
}) + "; " + commit;
}
output.push(` - ${body} (${link})`);
});
output.push("");
for (let i = firstLine; i < lines.length; i++) {
output.push(lines[i]);
}
return output.join("\n");
});
}
exports.generate = generate;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,81 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const semver_1 = __importDefault(require("semver"));
const path_1 = require("../path");
const local = __importStar(require("../local"));
const log_1 = require("../log");
const npm = __importStar(require("../npm"));
const utils_1 = require("../utils");
(function () {
return __awaiter(this, void 0, void 0, function* () {
const progress = log_1.getProgressBar(log_1.colorify.bold("Bumping package.json versions"));
const latestVersions = {};
let updated = false;
const output = [];
// For each package, detect diff between tarball and remote
for (let i = 0; i < path_1.dirnames.length; i++) {
progress(i / path_1.dirnames.length);
const dirname = path_1.dirnames[i];
const pLocal = local.getPackage(dirname);
const pNpm = yield npm.getPackage(dirname);
const tarballHash = local.computeTarballHash(dirname);
let version = pNpm.version;
if (tarballHash !== pNpm.tarballHash) {
version = semver_1.default.inc(version, "patch");
output.push([
" ",
log_1.colorify.blue(pLocal.name),
utils_1.repeat(" ", 47 - pLocal.name.length - pNpm.version.length),
pNpm.version,
log_1.colorify.bold(" => "),
log_1.colorify.green(version)
].join(""));
local.updateJson(path_1.getPackageJsonPath(dirname), { gitHead: undefined, tarballHash, version }, true);
updated = true;
}
latestVersions[pLocal.name] = version;
// Write out the _version.ts
if (!pLocal._ethers_nobuild) {
const code = "export const version = " + JSON.stringify(dirname + "/" + pLocal.version) + ";\n";
fs_1.default.writeFileSync(path_1.resolve(path_1.getPackagePath(dirname), "src.ts/_version.ts"), code);
}
}
progress(1);
if (updated) {
const filename = path_1.resolve("packages/ethers/package.json");
const info = utils_1.loadJson(filename);
Object.keys(info.dependencies).forEach((name) => {
const version = latestVersions[name];
if (name == null) {
return;
}
info.dependencies[name] = version;
});
utils_1.saveJson(filename, info);
}
output.forEach((line) => { console.log(line); });
});
})().catch((error) => {
console.log(`Error running ${process.argv[0]}: ${error.message}`);
process.exit(1);
});

1
misc/admin/lib/cmds/echo.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const log_1 = require("../log");
console.log(log_1.colorify.bold(process.argv[2] || "no message"));

1
misc/admin/lib/cmds/hoist.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,26 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("../path");
const local_1 = require("../local");
const log_1 = require("../log");
(function () {
return __awaiter(this, void 0, void 0, function* () {
const dependencies = local_1.getDependencies(null, (name) => {
return !path_1.isEthers(name);
});
console.log(log_1.colorify.bold(`Hoisting ${Object.keys(dependencies).length} dependencies into root package...`));
local_1.updateJson(path_1.dirs.rootPackageJsonPath, { dependencies });
});
})().catch((error) => {
console.log(`Error running ${process.argv[0]}: ${error.message}`);
process.exit(1);
});

1
misc/admin/lib/cmds/link.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,65 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const local_1 = require("../local");
const log_1 = require("../log");
const path_2 = require("../path");
const utils_1 = require("../utils");
function link(existing, path) {
try {
const current = fs_1.default.readlinkSync(path);
// Alerady linked
if (current === existing) {
return;
}
fs_1.default.unlinkSync(path);
}
catch (error) {
if (error.code !== "ENOENT") {
throw error;
}
}
// Link
const dir = path_1.dirname(path);
utils_1.mkdir(dir);
fs_1.default.symlinkSync(existing, path);
}
(function () {
return __awaiter(this, void 0, void 0, function* () {
console.log(log_1.colorify.bold(`Linking ${path_2.packages.length} package node_modules rat nests...`));
const nodeModulesBase = path_1.resolve(path_2.dirs.root, ".package_node_modules");
// Make a symlink in the ROOT/node_mpdules to each package in this repo
path_2.packages.forEach((name) => {
// e.g. /node_modules/@ethersproject/abi => /packages/abi
link(path_2.getPackagePath(name), path_1.resolve(path_2.dirs.root, "node_modules", name));
// e.g. /packages/abi/node_modules => /.package_node_modules/abi/
const nodeModules = path_1.resolve(nodeModulesBase, path_2.getDirname(name));
utils_1.mkdir(nodeModules);
link(nodeModules, path_1.resolve(path_2.getPackagePath(name), "node_modules"));
});
path_2.packages.forEach((name) => {
const nodeModules = path_1.resolve(nodeModulesBase, path_2.getDirname(name));
const deps = local_1.getDependencies(name);
Object.keys(deps).forEach((name) => {
link(path_1.resolve(path_2.dirs.root, "node_modules", name), path_1.resolve(nodeModules, name));
});
});
});
})().catch((error) => {
console.log(`Error running ${process.argv[0]}: ${error.message}`);
process.exit(1);
});
;

View File

@@ -0,0 +1 @@
declare const major: any;

View File

@@ -1,15 +1,13 @@
"use strict";
const { major } = require("semver");
// This should be used like `node npm-skip-node8 || COMMAND`.
// - If node 8, this script returns true, skipping COMMAND
// - Otherwise, return false, running COMMAND
if (major(process.version) > 8) {
// Node >8; return "false" (wrt to shell scripting)
process.exit(1);
} else {
}
else {
// Node 8; return "true" (wrt to shell scripting)
process.exit(0);
}

8
misc/admin/lib/cmds/serve-docs.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
/// <reference types="node" />
import { Server } from "http";
export declare function getMime(filename: string): string;
export declare type Options = {
port?: number;
redirects?: Record<string, string>;
};
export declare function start(root: string, options: Options): Server;

View File

@@ -0,0 +1,96 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const http_1 = require("http");
const path_1 = require("path");
function getMime(filename) {
switch (filename.split('.').pop().toLowerCase()) {
case 'css': return 'text/css';
case 'doctree': return 'application/x-doctree';
case 'eot': return 'application/vnd.ms-fontobject';
case 'gif': return 'image/gif';
case 'html': return 'text/html';
case 'js': return 'application/javascript';
case 'jpg': return 'image/jpeg';
case 'jpeg': return 'image/jpeg';
case 'md': return 'text/markdown';
case 'pickle': return 'application/x-pickle';
case 'png': return 'image/png';
case 'svg': return 'image/svg+xml';
case 'ttf': return 'application/x-font-ttf';
case 'txt': return 'text/plain';
case 'woff': return 'application/font-woff';
}
console.log('NO MIME', filename);
return "application/octet-stream";
}
exports.getMime = getMime;
function start(root, options) {
if (root == null) {
throw new Error("root required");
}
if (options == null) {
options = {};
}
if (options.port == null) {
options.port = 8000;
}
root = path_1.resolve(root);
const server = http_1.createServer((req, resp) => {
// Follow redirects in options
if (options.redirects && options.redirects[req.url]) {
resp.writeHead(301, { Location: options.redirects[req.url] });
resp.end();
return;
}
let filename = path_1.resolve(root, "." + req.url);
// Make sure we aren't crawling out of our sandbox
if (req.url[0] !== "/" || filename.substring(0, filename.length) !== filename) {
resp.writeHead(403);
resp.end();
return;
}
try {
const stat = fs_1.default.statSync(filename);
if (stat.isDirectory()) {
// Redirect bare directory to its path (i.e. "/foo" => "/foo/")
if (req.url[req.url.length - 1] !== "/") {
resp.writeHead(301, { Location: req.url + "/" });
resp.end();
return;
}
filename += "/index.html";
}
const content = fs_1.default.readFileSync(filename);
resp.writeHead(200, {
"Content-Length": content.length,
"Content-Type": getMime(filename)
});
resp.end(content);
return;
}
catch (error) {
if (error.code === "ENOENT") {
resp.writeHead(404, {});
resp.end();
return;
}
resp.writeHead(500, {});
resp.end();
return;
}
});
server.listen(options.port, () => {
console.log(`Server running on: http://localhost:${options.port}`);
});
return server;
}
exports.start = start;
start(path_1.resolve(__dirname, "../../docs"), {
redirects: {
"/": "/v5/"
}
});

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,45 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const build_1 = require("../build");
const log_1 = require("../log");
const path_1 = require("../path");
const utils_1 = require("../utils");
(function () {
return __awaiter(this, void 0, void 0, function* () {
process.argv.slice(2).forEach((arg) => {
console.log(log_1.colorify.bold("Setting Option:"), arg);
switch (arg) {
case "esm":
build_1.setupBuild(true);
break;
case "cjs":
build_1.setupBuild(false);
break;
// This will remove the browser field entirely, so make sure
// to set esm of cjs first as they will restore the browser
// field
case "browser-lang-all": {
const filename = path_1.getPackageJsonPath("wordlists");
const info = utils_1.loadJson(filename);
delete info.browser;
utils_1.saveJson(filename, info, true);
break;
}
default:
throw new Error(`Unknown option: ${JSON.stringify(arg)}`);
}
});
});
})().catch((error) => {
console.log(`Error running ${process.argv[0]}: ${error.message}`);
process.exit(1);
});

1
misc/admin/lib/cmds/set-config.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,27 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const config_1 = require("../config");
const log_1 = require("../log");
if (process.argv.length !== 3) {
console.log("Usage: set-config KEY");
process.exit(1);
}
const key = process.argv[2];
(function () {
return __awaiter(this, void 0, void 0, function* () {
const value = yield log_1.getPassword("Value: ");
yield config_1.config.set(key, value);
});
})().catch((error) => {
console.log(`Error running ${process.argv[0]}: ${error.message}`);
process.exit(1);
});

1
misc/admin/lib/cmds/spell-check.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,227 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const typescript_1 = __importDefault(require("typescript"));
const log_1 = require("../log");
const Words = fs_1.default.readFileSync("/usr/share/dict/words").toString().split("\n").reduce((accum, word) => {
accum[word.toLowerCase()] = true;
return accum;
}, {});
`
// Words missing from the dictionary
accessing addresses aligned autofill called cancelled changed censored
clamping compiled computed configured consumed creating decoded decoding
decreased decrypt decrypted decrypting deployed deploying deprecated detected
discontinued earliest email enabled encoded encoding encrypt
encrypted encrypting entries euro exceeded existing expected
expired failed fetches formatted formatting funding generated
hardened has highly ignoring implemented implementer imported including instantiate
joined keyword labelled larger lookup matches mined modified modifies multi
named needed nested neutered numeric offline optimizer overriding owned packed
padded parsed parsing passed placeholder processing properties prototyping reached
recommended recovered redacted remaining replaced required
serializes shared signed signing skipped stored supported tagging targetted
throttled transactions uninstall unstake unsubscribe using verifies website
// Overly Specific Words
bech BIP BIP39 BIP44 btc bzz crypto eip etc hashes hmac icap
keccak ltc namehash ripemd RLP scrypt secp sha xdai
blockhash
bitcoin ethereum finney gwei kwei mwei satoshi szabo wei weth
crowdsale hexlify hd hdnode underpriced
boolean int struct tuple uint
nonpayable
jumpdest mstore shr shl xor
// Classes
ABIEncoder testcase numberish Wordlist
// Common Code Strings
abi addr api app arg arrayify asm basex bigint bignumber bn byte
bytecode callback calldata checksum ciphertext cli codepoint commify config
contenthash ctr ctrl debug dd dklen eexist encseed eof ethaddr
ethseed ethers eval exec filename func gz hid http https hw iv
info init ipc json kdf kdfparams labelhash lang lib mm multihash nfc
nfkc nfd nfkd nodehash notok nowait nullish oob opcode pbkdf pc plugin
pragma pre prf repl rpc sighash topichash solc stdin stdout subclasses
subnode timeout todo txt ufixed utc utf util url uuid vm vs websocket
wikipedia wx xe xpriv xpub xx yyyy zlib
// AbiV2
abiv
// Query parameters
apikey asc endblock startblock
alchemyapi Cloudflare Etherscan INFURA IPFS MetaMask Nodesmith
Trezor ledgerhq axic bitcoinjs browserify easyseed ethereumjs
goerli homestead kotti kovan mainnet morden mordor rinkeby
ropsten testnet
// Demo words
args foo eth foo foobar ll localhost passwd ricmoo tx xxx yna
// nameprep tags
ALCat BiDi LCat nameprep
// Lanauge Codes (and short binary data)
cn cz en es fr it ja tw zh zh_cn zh_tw
OYAa IJBEJqXZJ
`.split("\n").filter((l) => (l.substring(0, 2) != "/\/")).join("\n").split(/\s+/g).forEach((word) => {
word = word.trim();
if (word === "") {
return;
}
Words[word.toLowerCase()] = true;
});
function getStrings(source) {
const sourceFile = typescript_1.default.createSourceFile("filename.ts", source, typescript_1.default.ScriptTarget.Latest);
const result = [];
function add(value, pos) {
const lineNo = sourceFile.getLineAndCharacterOfPosition(pos).line + 1;
result.push({ value, lineNo });
}
//let lastClass = null, lastEnum = null;
function visit(node, depth) {
switch (node.kind) {
//case ts.SyntaxKind.TemplateExpression:
// if (node.head) { visit(node.head); }
// console.dir(node, { depth: null });
// break;
case typescript_1.default.SyntaxKind.TemplateHead:
case typescript_1.default.SyntaxKind.TemplateMiddle:
case typescript_1.default.SyntaxKind.TemplateTail:
case typescript_1.default.SyntaxKind.StringLiteral:
case typescript_1.default.SyntaxKind.NoSubstitutionTemplateLiteral:
add(node.text, node.pos);
break;
}
typescript_1.default.forEachChild(node, (node) => { return visit(node, depth + 1); });
}
visit(sourceFile, 0);
return result;
}
const Include = new RegExp("packages/.*/src.ts/.*\.ts$");
const Exclude = new RegExp("/node_modules/|src.ts/.*browser.*");
function getAllStrings(path) {
const Root = path_1.resolve(__dirname, path);
const readdir = function (path) {
if (path.match(Exclude)) {
return [];
}
const stat = fs_1.default.statSync(path);
if (stat.isDirectory()) {
return fs_1.default.readdirSync(path).reduce((result, filename) => {
readdir(path_1.resolve(path, filename)).forEach((file) => {
result.push(file);
});
return result;
}, []);
}
if (path.match(Include)) {
const source = fs_1.default.readFileSync(path).toString();
return [{ filename: path.substring(Root.length), values: getStrings(source) }];
}
return [];
};
return readdir(Root);
}
function checkWord(word) {
word = word.toLowerCase();
// A word
if (Words[word]) {
return true;
}
// Simple Plural
if (word.match(/.*s$/) && Words[word.substring(0, word.length - 1)]) {
return true;
}
// Hex string
if (word.match(/^(0x)?[0-9a-f]*$/i)) {
return true;
}
return false;
}
function starts(text, prefix) {
return (text.substring(0, prefix.length) === prefix);
}
(function () {
return __awaiter(this, void 0, void 0, function* () {
console.log(log_1.colorify.bold("Spell checking source code strings..."));
let count = 0;
getAllStrings(path_1.resolve(__dirname, "../../../../packages")).forEach((file) => {
if (starts(file.filename, "/testcases/src.ts/generation-scripts")) {
return;
}
if (starts(file.filename, "/asm/src.ts/opcodes.ts")) {
return;
}
file.values.forEach((entry) => {
function problem(word) {
count++;
console.log({
filename: file.filename,
word: JSON.stringify(word),
sentence: JSON.stringify(entry.value.substring(0, 80)),
line: entry.lineNo
});
}
const value = entry.value.trim();
// Emptry space
if (value === "") {
return;
}
// Prolly a require
if (value.match(/^@ethersproject\/[a-z0-9-]+$/)) {
return;
}
if (value.substring(0, 2) === "./") {
return;
}
// Prolly encoded binary data
if (value.indexOf(" ") === -1 && value.length > 20) {
return;
}
if (checkWord(value)) {
return;
}
value.replace(/([a-z+])([A-Z])/g, (all, first, secondLetter) => {
return first + " " + secondLetter;
}).replace(/((?:0x)?[A-Za-z]+)/gi, (all, word) => {
if (checkWord(word)) {
return "";
}
problem(word);
return "";
});
;
});
});
if (count) {
console.log(`Found ${count} typos.`);
process.exit(1);
}
process.exit(0);
});
})().catch((error) => {
console.log(error);
process.exit(1);
});

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,24 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const changelog_1 = require("../changelog");
const log_1 = require("../log");
const path_1 = require("../path");
(function () {
return __awaiter(this, void 0, void 0, function* () {
console.log(log_1.colorify.bold("Updating CHANGELOG.md..."));
fs_1.default.writeFileSync(path_1.resolve("CHANGELOG.md"), yield changelog_1.generate());
});
})();

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,25 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const depgraph_1 = require("../depgraph");
const path_1 = require("../path");
const local_1 = require("../local");
(function () {
return __awaiter(this, void 0, void 0, function* () {
const ordered = depgraph_1.getOrdered(true);
local_1.updateJson(path_1.resolve("tsconfig.project.json"), {
references: ordered.map((name) => ({ path: ("./packages/" + name) }))
});
});
})().catch((error) => {
console.log(error);
process.exit(1);
});

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,38 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const log_1 = require("../log");
const path_1 = require("../path");
const sourceEthers = fs_1.default.readFileSync(path_1.resolve("packages/ethers/src.ts/ethers.ts")).toString();
const targets = sourceEthers.match(/export\s*{\s*((.|\s)*)}/)[1].trim();
////////////////////
// Begin template
////////////////////
const output = `"use strict";
// To modify this file, you must update ./misc/admin/lib/cmds/update-exports.js
import * as ethers from "./ethers";
try {
const anyGlobal = (window as any);
if (anyGlobal._ethers == null) {
anyGlobal._ethers = ethers;
}
} catch (error) { }
export { ethers };
export {
${targets}
} from "./ethers";
`;
////////////////////
// End template
////////////////////
console.log(log_1.colorify.bold(`Flattening exports...`));
fs_1.default.writeFileSync(path_1.resolve("packages/ethers/src.ts/index.ts"), output);

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,33 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
//import { getGitTag } from "../git";
const local_1 = require("../local");
const log_1 = require("../log");
const path_1 = require("../path");
(function () {
return __awaiter(this, void 0, void 0, function* () {
const progress = log_1.getProgressBar(log_1.colorify.bold("Updating package.json hashes"));
// Updating all tarball hashes now that versions have been updated
for (let i = 0; i < path_1.dirnames.length; i++) {
progress(i / path_1.dirnames.length);
const dirname = path_1.dirnames[i];
//const gitHead = await getGitTag(resolve("packages", dirname));
const tarballHash = local_1.computeTarballHash(dirname);
local_1.updateJson(path_1.getPackageJsonPath(dirname), { tarballHash }, true);
}
progress(1);
});
})().catch((error) => {
console.log(error);
process.exit(1);
});
;

6
misc/admin/lib/config.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export declare const config: {
get: (key: string) => Promise<string>;
set: (key: string, value: string) => void;
keys: () => Promise<string[]>;
lock: () => void;
};

129
misc/admin/lib/config.js Normal file
View File

@@ -0,0 +1,129 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = require("crypto");
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = require("path");
const aes_js_1 = __importDefault(require("aes-js"));
const scrypt_js_1 = __importDefault(require("scrypt-js"));
const log_1 = require("./log");
function getRandomBytes(length) {
const result = new Uint8Array(length);
result.set(crypto_1.randomBytes(length));
return result;
}
function computeHmac(key, data) {
return "0x" + crypto_1.createHmac("sha512", key).update(data).digest("hex");
}
function getScrypt(message, password, salt) {
return __awaiter(this, void 0, void 0, function* () {
const progress = log_1.getProgressBar(message);
return yield scrypt_js_1.default.scrypt(Buffer.from(password), Buffer.from(salt), (1 << 17), 8, 1, 64, progress);
});
}
class Config {
constructor(filename) {
this.salt = null;
this.dkey = null;
this.values = {};
this.canary = "";
this.filename = filename;
}
load() {
return __awaiter(this, void 0, void 0, function* () {
if (this.dkey) {
return;
}
let data = null;
if (fs_1.default.existsSync(this.filename)) {
data = JSON.parse(fs_1.default.readFileSync(this.filename).toString());
}
else {
data = {
salt: Buffer.from(getRandomBytes(32)).toString("hex")
};
}
this.canary = data.canary || "";
this.salt = data.salt;
const password = yield log_1.getPassword(log_1.colorify.bold("Password (config-store): "));
this.dkey = yield getScrypt(log_1.colorify.bold("Unlocking config"), password, this.salt);
if (data.ciphertext) {
const ciphertext = Buffer.from(data.ciphertext, "base64");
const iv = Buffer.from(data.iv, "base64");
const aes = new aes_js_1.default.ModeOfOperation.ctr(this.dkey.slice(0, 32), new aes_js_1.default.Counter(iv));
const plaintext = aes.decrypt(ciphertext);
const hmac = computeHmac(this.dkey.slice(32, 64), plaintext);
if (hmac !== data.hmac) {
console.log(log_1.colorify.red("Incorrect password."));
throw new Error("wrong password");
}
this.values = JSON.parse(Buffer.from(plaintext).toString());
}
});
}
keys() {
return __awaiter(this, void 0, void 0, function* () {
yield this.load();
return Object.keys(this.values);
});
}
save() {
this.values._junk = Buffer.from(getRandomBytes(16 + Math.floor(Math.random() * 48))).toString("base64");
const plaintext = Buffer.from(JSON.stringify(this.values));
const iv = Buffer.from(getRandomBytes(16));
const hmac = computeHmac(this.dkey.slice(32, 64), plaintext);
const aes = new aes_js_1.default.ModeOfOperation.ctr(this.dkey.slice(0, 32), new aes_js_1.default.Counter(iv));
const ciphertext = Buffer.from(aes.encrypt(plaintext));
const data = {
ciphertext: ciphertext.toString("base64"),
iv: iv.toString("base64"),
salt: this.salt,
hmac: hmac,
canary: this.canary
};
fs_1.default.writeFileSync(this.filename, JSON.stringify(data, null, 2));
}
get(key) {
return __awaiter(this, void 0, void 0, function* () {
yield this.load();
return this.values[key];
});
}
set(key, value) {
return __awaiter(this, void 0, void 0, function* () {
yield this.load();
this.values[key] = value;
this.save();
});
}
lock() {
this.salt = this.dkey = null;
}
}
const _config = new Config(path_1.resolve(os_1.default.homedir(), ".ethers-dist"));
exports.config = {
get: function (key) {
return _config.get(key);
},
set: function (key, value) {
_config.set(key, value);
},
keys: function () {
return _config.keys();
},
lock: function () {
_config.lock();
}
};

2
misc/admin/lib/depgraph.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare function getOrdered(skipNobuild?: boolean): Array<string>;
export declare function sort(dirnames: Array<string>): void;

101
misc/admin/lib/depgraph.js Normal file
View File

@@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("./path");
const local_1 = require("./local");
class OrderedSet {
constructor() {
this._keys = [];
this._values = {};
}
add(key) {
this._values[key] = true;
this._keys = null;
}
contains(key) {
return !!this._values[key];
}
_sort() {
if (this._keys != null) {
return;
}
this._keys = Object.keys(this._values);
this._keys.sort();
}
get length() {
this._sort();
return this._keys.length;
}
get(index) {
this._sort();
return this._keys[index];
}
}
function getOrdered(skipNobuild) {
const packages = {};
const filenames = {};
// Maps packages to names to list of dependencies; { [ name:string]: Array<name: string> }
const deps = {};
let addDeps = (name, depends) => {
Object.keys(depends).forEach((dep) => {
// Not a package we manage
if (packages[dep] == null) {
return;
}
deps[name].add(dep);
});
};
for (let i = 0; i < path_1.dirnames.length; i++) {
let dirname = path_1.dirnames[i];
let info = local_1.getPackage(dirname);
if (skipNobuild && info._ethers_nobuild) {
continue;
}
packages[info.name] = info;
filenames[info.name] = dirname;
}
Object.keys(packages).forEach((name) => {
let info = packages[name];
deps[info.name] = new OrderedSet();
addDeps(info.name, info.dependencies || {});
addDeps(info.name, info.devDependencies || {});
});
let ordered = [];
let remaining = Object.keys(deps);
let isSatisfied = (name) => {
for (let i = 0; i < deps[name].length; i++) {
if (ordered.indexOf(deps[name].get(i)) === -1) {
return false;
}
}
return true;
};
while (remaining.length) {
let bail = true;
for (let i = 0; i < remaining.length; i++) {
if (!isSatisfied(remaining[i])) {
continue;
}
bail = false;
ordered.push(remaining[i]);
remaining.splice(i, 1);
break;
}
if (bail) {
throw new Error("Nothing processed; circular dependencies...");
}
}
return ordered.map((name) => filenames[name]);
}
exports.getOrdered = getOrdered;
function sort(dirnames) {
let ordered = getOrdered();
dirnames.sort((a, b) => {
let ai = ordered.indexOf(local_1.getPackage(a).name);
let bi = ordered.indexOf(local_1.getPackage(b).name);
if (ai === -1 || bi === -1) {
throw new Error("unknown dirname - " + [a, b].join(", "));
}
return ai - bi;
});
}
exports.sort = sort;

16
misc/admin/lib/geturl.d.ts vendored Normal file
View File

@@ -0,0 +1,16 @@
export declare type GetUrlResponse = {
statusCode: number;
statusMessage: string;
headers: {
[key: string]: string;
};
body: Uint8Array;
};
export declare type Options = {
method?: string;
body?: Uint8Array;
headers?: {
[key: string]: string;
};
};
export declare function getUrl(href: string, options?: Options): Promise<GetUrlResponse>;

100
misc/admin/lib/geturl.js Normal file
View File

@@ -0,0 +1,100 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const http_1 = __importDefault(require("http"));
const https_1 = __importDefault(require("https"));
const url_1 = require("url");
function getResponse(request) {
return new Promise((resolve, reject) => {
request.once("response", (resp) => {
const response = {
statusCode: resp.statusCode,
statusMessage: resp.statusMessage,
headers: Object.keys(resp.headers).reduce((accum, name) => {
let value = resp.headers[name];
if (Array.isArray(value)) {
value = value.join(", ");
}
accum[name] = value;
return accum;
}, {}),
body: null
};
//resp.setEncoding("utf8");
resp.on("data", (chunk) => {
if (response.body == null) {
response.body = new Uint8Array(0);
}
const body = new Uint8Array(response.body.length + chunk.length);
body.set(response.body, 0);
body.set(chunk, response.body.length);
response.body = body;
});
resp.on("end", () => {
resolve(response);
});
resp.on("error", (error) => {
/* istanbul ignore next */
error.response = response;
reject(error);
});
});
request.on("error", (error) => { reject(error); });
});
}
// The URL.parse uses null instead of the empty string
function nonnull(value) {
if (value == null) {
return "";
}
return value;
}
function getUrl(href, options) {
return __awaiter(this, void 0, void 0, function* () {
if (options == null) {
options = {};
}
// @TODO: Once we drop support for node 8, we can pass the href
// firectly into request and skip adding the components
// to this request object
const url = url_1.parse(href);
const request = {
protocol: nonnull(url.protocol),
hostname: nonnull(url.hostname),
port: nonnull(url.port),
path: (nonnull(url.pathname) + nonnull(url.search)),
method: (options.method || "GET"),
headers: (options.headers || {}),
};
let req = null;
switch (nonnull(url.protocol)) {
case "http:":
req = http_1.default.request(request);
break;
case "https:":
req = https_1.default.request(request);
break;
default:
/* istanbul ignore next */
throw new Error(`unsupported protocol ${url.protocol}`);
}
if (options.body) {
req.write(Buffer.from(options.body));
}
req.end();
const response = yield getResponse(req);
return response;
});
}
exports.getUrl = getUrl;

1
misc/admin/lib/git.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export declare function getGitTag(filename: string): Promise<string>;

32
misc/admin/lib/git.js Normal file
View File

@@ -0,0 +1,32 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const run_1 = require("./run");
// Returns the most recent git commit hash for a given filename
function getGitTag(filename) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield run_1.run("git", ["log", "-n", "1", "--", filename]);
if (!result.ok) {
throw new Error(`git log error`);
}
let log = result.stdout.trim();
if (!log) {
return null;
}
const hashMatch = log.match(/^commit\s+([0-9a-f]{40})\n/i);
if (!hashMatch) {
return null;
}
return hashMatch[1];
});
}
exports.getGitTag = getGitTag;
//getGitTag("/Users/ricmoo/Development/ethers/ethers.js/packages/abi").then(console.log);

19
misc/admin/lib/local.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
export declare type Package = {
dependencies: {
[name: string]: string;
};
devDependencies: {
[name: string]: string;
};
gitHead: string;
name: string;
version: string;
tarballHash: string;
location: "remote" | "local";
_ethers_nobuild: boolean;
};
export declare function getPackage(name: string): Package;
export declare function updateJson(path: string, replace: Record<string, any>, sort?: boolean): void;
export declare function getDependencies(name?: string, filter?: (name: string) => boolean): Record<string, string>;
export declare function getPackList(name: string): Array<string>;
export declare function computeTarballHash(name: string): string;

137
misc/admin/lib/local.js Normal file
View File

@@ -0,0 +1,137 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("./path");
const run_1 = require("./run");
const utils_1 = require("./utils");
function getPackage(name) {
const value = utils_1.loadJson(path_1.getPackageJsonPath(name));
return {
name: value.name,
version: value.version,
dependencies: (value.dependencies || {}),
devDependencies: (value.dependencies || {}),
location: "local",
tarballHash: (value.tarballHash || null),
gitHead: (value.gitHead || null),
_ethers_nobuild: !!value._ethers_nobuild,
};
}
exports.getPackage = getPackage;
function updateJson(path, replace, sort) {
const values = utils_1.loadJson(path);
Object.keys(replace).forEach((key) => {
const value = replace[key];
if (value === undefined) {
delete values[key];
}
else {
values[key] = replace[key];
}
});
utils_1.saveJson(path, values, !!sort);
}
exports.updateJson = updateJson;
function getDependencies(name, filter) {
if (name) {
return utils_1.sortRecords(getPackage(name).dependencies);
}
// Find all versions for each package dependency
const deps = path_1.dirnames.reduce((accum, dirname) => {
const deps = getPackage(dirname).dependencies;
Object.keys(deps).forEach((name) => {
if (filter && !filter(name)) {
return;
}
if (!accum[name]) {
accum[name] = {};
}
accum[name][deps[name]] = true;
});
return accum;
}, {});
// Make sure each package dependency only has 1 version
return utils_1.sortRecords(Object.keys(deps).reduce((accum, name) => {
const versions = Object.keys(deps[name]);
if (versions.length > 1) {
throw new Error(`cannot depend on multiple versions for ${JSON.stringify(name)}: ${versions.map(v => JSON.stringify(v)).join(", ")}`);
}
accum[name] = versions[0];
return accum;
}, {}));
}
exports.getDependencies = getDependencies;
function getPackList(name) {
const result = run_1.run("npm", ["pack", "--json", path_1.getPackagePath(name), "--dry-run"]);
if (!result.ok) {
const error = new Error(`failed to run npm pack: ${name}`);
error.result = result;
throw error;
}
return JSON.parse(result.stdout)[0].files.map((info) => info.path);
}
exports.getPackList = getPackList;
/*
export function getTarball(name: string): Buffer {
const files = getPackList(name).map((name) => `./${ name }`);
files.sort((a, b) => {
const compsA = a.split("/"), compsB = b.split("/");
while (true) {
const a = compsA.shift(), b = compsB.shift();
if (a === b) { continue; }
if (compsA.length === 0 && compsB.length === 0) {
if (a < b) { return -1; }
if (a > b) { return 1; }
break;
}
if (compsA.length === 0) { return -1; }
if (compsB.length === 0) { return 1; }
if (a < b) { return -1; }
if (a > b) { return 1; }
}
return 0;
});
return tar.create({
sync: true,
cwd: getPackagePath(name),
prefix: "package/",
gzip: true,
portable: true,
// Provide a specific date in the 1980s for the benefit of zip,
// which is confounded by files dated at the Unix epoch 0.
mtime: new Date('1985-10-26T08:15:00.000Z'),
}, files).read();
}
*/
function computeTarballHash(name) {
// Sort the files to get a consistent hash
const files = getPackList(name);
files.sort();
// Compute the hash for each file
const packageRoot = path_1.getPackagePath(name);
const hashes = files.reduce((accum, filename) => {
let content = fs_1.default.readFileSync(path_1.resolve(packageRoot, filename));
// The package.json includes the hash, so we need to nix it to get a consistent hash
if (filename === "package.json") {
const info = JSON.parse(content.toString());
delete info.gitHead;
delete info.tarballHash;
content = Buffer.from(JSON.stringify(info, null, 2));
}
accum[filename] = utils_1.sha256(content);
return accum;
}, {});
return utils_1.sha256(Buffer.from("{" + files.map((filename) => {
return `${JSON.stringify(filename)}:"${hashes[filename]}"`;
}).join(",") + "}"));
}
exports.computeTarballHash = computeTarballHash;

12
misc/admin/lib/log.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
export declare function getProgressBar(action: string): (percent: number) => void;
export declare type ColorifyFunc = (text: string) => string;
export declare const colorify: {
[format: string]: ColorifyFunc;
};
export declare type PromptOptions = {
choice?: Array<string>;
defaultChoice?: string;
mask?: string;
};
export declare function getPrompt(prompt: string, options: PromptOptions): Promise<string>;
export declare function getPassword(prompt: string): Promise<string>;

149
misc/admin/lib/log.js Normal file
View File

@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("./utils");
// See: https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
let disableColor = !(process.stdout.isTTY);
function getProgressBar(action) {
let lastProgress = -1;
return function (percent) {
const progress = Math.trunc(percent * 100);
if (disableColor) {
if (lastProgress === -1) {
console.log(action + "...");
}
lastProgress = progress;
return;
}
//process.stdin.setRawMode(false);
//process.stdin.pause();
if (progress === lastProgress || lastProgress === 100) {
return;
}
lastProgress = progress;
(process.stdout).clearLine();
(process.stdout).cursorTo(0);
process.stdout.write(action + "... " + progress + "%");
if (percent === 1) {
process.stdout.write('\n');
}
return;
};
}
exports.getProgressBar = getProgressBar;
const colorSequences = {
blue: "\x1b[34m",
cyan: "\x1b[36m",
green: "\x1b[32m",
magenta: "\x1b[35m",
red: "\x1b[31m",
yellow: "\x1b[33m",
bold: ""
};
function getColor(color) {
if (!color || color === "normal") {
return "\x1b[0m";
}
return "\x1b[1m" + colorSequences[color];
}
function _colorify(format) {
return function (text) {
if (disableColor) {
return text;
}
return getColor(format) + text.replace(/[^ -~]+/g, "") + getColor();
};
}
exports.colorify = Object.freeze({
bold: _colorify("bold"),
blue: _colorify("blue"),
green: _colorify("green"),
red: _colorify("red"),
});
function _getPrompt(prompt, options, callback) {
process.stdout.write(prompt);
let stdin = process.stdin;
stdin.resume();
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('utf8');
let message = '';
let respond = (ctrlC, message) => {
process.stdout.write('\n');
stdin.setRawMode(false);
stdin.pause();
stdin.removeListener('data', handler);
callback(ctrlC, message);
};
function handler(chr) {
chr = String(chr);
switch (chr) {
// Enter (ish)
case "\n":
case "\r":
case "\u0004":
if (options.choice) {
if (options.defaultChoice) {
respond(null, options.defaultChoice);
}
}
else {
respond(null, message);
}
break;
// Backspace
case "\u007f":
if (message.length > 0 && options.choice == null) {
message = message.substring(0, message.length - 1);
(process.stdout).clearLine();
(process.stdout).cursorTo(0);
if (options.mask) {
process.stdout.write(prompt + utils_1.repeat(options.mask, message.length));
}
else {
process.stdout.write(prompt + message);
}
}
break;
// Ctrl-C
case "\u0003":
process.stdout.write('\n[ CTRL-C ]');
respond(true, null);
break;
// Any other character
default:
if (options.choice) {
if (options.choice.indexOf(chr) >= 0) {
process.stdout.write(chr);
respond(null, chr);
}
}
else {
// More passsword characters
if (options.mask) {
process.stdout.write('*');
}
else {
process.stdout.write(chr);
}
message += chr;
}
break;
}
}
stdin.on('data', handler);
}
function getPrompt(prompt, options) {
return new Promise((resolve, reject) => {
_getPrompt(prompt, options, (ctrlC, password) => {
if (ctrlC) {
return reject(new Error("cancelled"));
}
resolve(password);
});
});
}
exports.getPrompt = getPrompt;
function getPassword(prompt) {
return getPrompt(prompt, { mask: "*" });
}
exports.getPassword = getPassword;

2
misc/admin/lib/npm.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
import { Package } from "./local";
export declare function getPackage(name: string, version?: string): Promise<Package>;

62
misc/admin/lib/npm.js Normal file
View File

@@ -0,0 +1,62 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const semver_1 = __importDefault(require("semver"));
const geturl_1 = require("./geturl");
const local_1 = require("./local");
const cache = {};
function getPackageInfo(name) {
return __awaiter(this, void 0, void 0, function* () {
// Convert dirname to package if needed
name = local_1.getPackage(name).name;
if (!cache[name]) {
try {
const result = yield geturl_1.getUrl("http:/" + "/registry.npmjs.org/" + name);
cache[name] = JSON.parse(Buffer.from(result.body).toString("utf8"));
}
catch (error) {
if (error.status === 404) {
return null;
}
throw error;
}
}
return cache[name] || null;
});
}
function getPackage(name, version) {
return __awaiter(this, void 0, void 0, function* () {
const infos = yield getPackageInfo(name);
if (infos == null) {
return null;
}
if (version == null) {
const versions = Object.keys(infos.versions);
versions.sort(semver_1.default.compare);
version = versions.pop();
}
const info = infos.versions[version];
return {
dependencies: (info.dependencies || {}),
devDependencies: (info.devDependencies || {}),
gitHead: info.gitHead,
location: "remote",
name: info.name,
tarballHash: info.tarballHash,
version: info.version,
_ethers_nobuild: !!info._ethers_nobuild,
};
});
}
exports.getPackage = getPackage;

13
misc/admin/lib/path.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
export declare const root: string;
export declare function resolve(...args: Array<string>): string;
export declare const dirs: Readonly<{
rootPackageJsonPath: string;
packages: string;
root: string;
}>;
export declare const dirnames: ReadonlyArray<string>;
export declare const packages: ReadonlyArray<string>;
export declare function getPackagePath(name: string): string;
export declare function getDirname(name: string): string;
export declare function getPackageJsonPath(name: string): string;
export declare function isEthers(name: string): boolean;

58
misc/admin/lib/path.js Normal file
View File

@@ -0,0 +1,58 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
exports.root = path_1.resolve(__dirname, "../../../");
function resolve(...args) {
args.unshift(exports.root);
return path_1.resolve.apply(null, args);
}
exports.resolve = resolve;
const pathRootPackageJsonPath = resolve("package.json");
const pathPackages = resolve("packages");
exports.dirs = Object.freeze({
rootPackageJsonPath: pathRootPackageJsonPath,
packages: pathPackages,
root: exports.root,
});
exports.dirnames = Object.freeze(fs_1.default.readdirSync(exports.dirs.packages).filter((dirname) => {
return (dirname[0] !== ".");
}));
const packageLookup = exports.dirnames.reduce((accum, dirname) => {
const packagePath = path_1.resolve(exports.dirs.packages, dirname);
const packageJsonPath = path_1.resolve(packagePath, "package.json");
const info = JSON.parse(fs_1.default.readFileSync(packageJsonPath).toString());
const packageName = info.name;
const version = info.version;
accum[packageName] = accum[dirname] = {
dirname, packageName, packagePath, packageJsonPath, version
};
return accum;
}, {});
exports.packages = Object.freeze(exports.dirnames.map((dirname) => packageLookup[dirname].packageName));
function getPackageInfo(name) {
const value = packageLookup[name];
if (!value) {
throw new Error(`unknown package: ${name}`);
}
return value;
}
function getPackagePath(name) {
return getPackageInfo(name).packagePath;
}
exports.getPackagePath = getPackagePath;
function getDirname(name) {
return getPackageInfo(name).dirname;
}
exports.getDirname = getDirname;
function getPackageJsonPath(name) {
return getPackageInfo(name).packageJsonPath;
}
exports.getPackageJsonPath = getPackageJsonPath;
function isEthers(name) {
return !!packageLookup[name];
}
exports.isEthers = isEthers;

10
misc/admin/lib/run.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types="node" />
export declare type RunResult = {
stderr: string | null;
_stderr: string | Buffer;
stdout: string;
_stdout: string | Buffer;
status: number;
ok: boolean;
};
export declare function run(progname: string, args?: Array<string>, currentWorkingDirectory?: string): RunResult;

64
misc/admin/lib/run.js Normal file
View File

@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
function run(progname, args, currentWorkingDirectory) {
if (args == null) {
args = [];
}
const options = {};
if (currentWorkingDirectory) {
options.cwd = currentWorkingDirectory;
}
const child = child_process_1.spawnSync(progname, args, options);
const result = {
_stderr: child.stderr,
stderr: (child.stderr.toString() || null),
_stdout: child.stdout,
stdout: child.stdout.toString(),
status: child.status,
ok: (child.stderr.length === 0 && child.status === 0)
};
if (child.error) {
(child.error).result = result;
throw child.error;
}
return result;
/*
const result: RunResult = {
stderr: null,
_stderr: Buffer.from([]),
stdout: null,
_stdout: Buffer.from([]),
status: null,
ok: false,
};
proc.stderr.on("data", (data) => {
result._stderr = Buffer.concat([ result._stderr, data ]);
});
proc.stdout.on("data", (data) => {
result._stdout = Buffer.concat([ result._stdout, data ]);
});
proc.on("error", (error) => {
result.stderr = result._stderr.toString("utf8");
result.stdout = result._stdout.toString("utf8");
(<any>error).result = result;
console.log("Error:", error);
reject(error);
});
proc.on("close", (code) => {
result.stderr = result._stderr.toString("utf8");
result.stdout = result._stdout.toString("utf8");
result.status = code;
result.ok = (result._stderr.length === 0 && code === 0);
resolve(result);
});
});
*/
}
exports.run = run;

10
misc/admin/lib/utils.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types="node" />
export declare function repeat(char: string, length: number): string;
export declare function sha256(content: Buffer): string;
export declare function sortRecords(record: Record<string, any>): Record<string, any>;
export declare function atomicWrite(path: string, value: string | Uint8Array): void;
export declare function loadJson(path: string): any;
export declare function saveJson(filename: string, data: any, sort?: boolean): any;
export declare function resolveProperties(props: Record<string, Promise<any>>): Promise<Record<string, any>>;
export declare function mkdir(path: string): void;
export declare function getDateTime(date: Date): string;

125
misc/admin/lib/utils.js Normal file
View File

@@ -0,0 +1,125 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const crypto_1 = require("crypto");
function repeat(char, length) {
if (char.length === 0) {
return "";
}
let output = char;
while (output.length < length) {
output = output + output;
}
return output.substring(0, length);
}
exports.repeat = repeat;
function sha256(content) {
const hasher = crypto_1.createHash("sha256");
hasher.update(content);
return "0x" + hasher.digest("hex");
}
exports.sha256 = sha256;
function sortRecords(record) {
const keys = Object.keys(record);
keys.sort();
return keys.reduce((accum, name) => {
accum[name] = record[name];
return accum;
}, {});
}
exports.sortRecords = sortRecords;
function atomicWrite(path, value) {
const tmp = path_1.resolve(__dirname, "../../../.atomic-tmp");
fs_1.default.writeFileSync(tmp, value);
fs_1.default.renameSync(tmp, path);
}
exports.atomicWrite = atomicWrite;
function loadJson(path) {
return JSON.parse(fs_1.default.readFileSync(path).toString());
}
exports.loadJson = loadJson;
function saveJson(filename, data, sort) {
let replacer = undefined;
if (sort) {
replacer = (key, value) => {
if (Array.isArray(value)) {
// pass
}
else if (value && typeof (value) === "object") {
const keys = Object.keys(value);
keys.sort();
return keys.reduce((accum, key) => {
accum[key] = value[key];
return accum;
}, {});
}
return value;
};
}
atomicWrite(filename, JSON.stringify(data, replacer, 2) + "\n");
}
exports.saveJson = saveJson;
function resolveProperties(props) {
return __awaiter(this, void 0, void 0, function* () {
const keys = Object.keys(props);
const promises = yield Promise.all(keys.map((k) => props[k]));
return keys.reduce((accum, key, index) => {
accum[key] = promises[index];
return accum;
}, {});
});
}
exports.resolveProperties = resolveProperties;
// Node 8 does not support recursive mkdir... Remove this in v6.
function mkdir(path) {
let bail = 0;
const dirs = [];
while (path !== "/") {
if (bail++ > 50) {
throw new Error("something bad happened...");
}
if (fs_1.default.existsSync(path)) {
break;
}
dirs.push(path);
path = path_1.dirname(path);
}
while (dirs.length) {
fs_1.default.mkdirSync(dirs.pop());
}
}
exports.mkdir = mkdir;
function zpad(value, length) {
if (length == null) {
length = 2;
}
const str = String(value);
return repeat("0", length - str.length) + str;
}
function getDate(date) {
return [
date.getFullYear(),
zpad(date.getMonth() + 1),
zpad(date.getDate())
].join("-");
}
function getDateTime(date) {
return getDate(date) + " " + [
zpad(date.getHours()),
zpad(date.getMinutes() + 1)
].join(":");
}
exports.getDateTime = getDateTime;

View File

@@ -0,0 +1,47 @@
import { dirnames, getPackageJsonPath, resolve } from "./path";
import { loadJson, saveJson } from "./utils";
function setupConfig(outDir: string, moduleType: string, targetType: string) {
// Configure the tsconfit.package.json...
const path = resolve("tsconfig.package.json");
const content = loadJson(path);
content.compilerOptions.module = moduleType;
content.compilerOptions.target = targetType;
saveJson(path, content, true);
// Configure the browser field for every pacakge, copying the
// browser.umd filed for UMD and browser.esm for ESM
dirnames.forEach((dirname) => {
const filename = getPackageJsonPath(dirname)
const info = loadJson(filename);
if (info._ethers_nobuild) { return; }
if (targetType === "es2015") {
if (info["browser.esm"]) {
info.browser = info["browser.esm"];
}
} else if (targetType === "es5") {
if (info["browser.umd"]) {
info.browser = info["browser.umd"];
}
} else {
throw new Error("unsupported target");
}
saveJson(filename, info, true);
let path = resolve("packages", dirname, "tsconfig.json");
let content = loadJson(path);
content.compilerOptions.outDir = outDir;
saveJson(path, content, true);
});
}
export function setupBuild(buildModule: boolean): void {
if (buildModule) {
setupConfig("./lib.esm/", "es2015", "es2015");
} else {
setupConfig("./lib/", "commonjs", "es5");
}
}

View File

@@ -0,0 +1,90 @@
import fs from "fs";
import * as local from "./local";
import { colorify } from "./log";
import * as npm from "./npm";
import { resolve } from "./path";
import { run } from "./run";
import { getDateTime, repeat } from "./utils";
const changelogPath = resolve("CHANGELOG.md");
export async function generate(): Promise<string> {
const lines = fs.readFileSync(changelogPath).toString().trim().split("\n");
let firstLine: number = null;
const versions: Array<string> = Object.keys(lines.reduce((accum, line, index) => {
const match = line.match(/^ethers\/v([^ ]*)/);
if (match) {
if (firstLine == null) { firstLine = index; }
accum[match[1]] = true;
}
return accum;
}, <Record<string, boolean>>{ }));
const version = local.getPackage("ethers").version;;
const published = await npm.getPackage("ethers");
if (versions.indexOf(version) >= 0) {
const line = `Version ${ version } already in CHANGELOG. Please edit before committing.`;
console.log(colorify.red(repeat("=", line.length)));
console.log(colorify.red(line));
console.log(colorify.red(repeat("=", line.length)));
}
const gitResult = await run("git", [ "log", (published.gitHead + "..") ]);
if (!gitResult.ok) {
console.log(gitResult);
throw new Error("Error running git log");
}
let changes: Array<{ body: string, commit: string, date: string }> = [ ];
gitResult.stdout.split("\n").forEach((line) => {
if (line.toLowerCase().substring(0, 6) === "commit") {
changes.push({
commit: line.substring(6).trim(),
date: null,
body: ""
});
} else if (line.toLowerCase().substring(0, 5) === "date:") {
changes[changes.length - 1].date = getDateTime(new Date(line.substring(5).trim()));
} else if (line.substring(0, 1) === " ") {
line = line.trim();
if (line === "") { return; }
changes[changes.length - 1].body += line + " ";
}
});
const output: Array<string> = [ ];
for (let i = 0; i < firstLine; i++) {
output.push(lines[i]);
}
const newTitle = `ethers/v${ version } (${ getDateTime(new Date()) })`;
output.push(newTitle);
output.push(repeat("-", newTitle.length));
output.push("");
changes.forEach((change) => {
let body = change.body.trim();
let linkMatch = body.match(/(\((.*#.*)\))/)
let commit = `[${ change.commit.substring(0, 7) }](https://github.com/ethers-io/ethers.js/commit/${ change.commit })`;
let link = commit;
if (linkMatch) {
body = body.replace(/ *(\(.*#.*)\) */, "");
link = linkMatch[2].replace(/#([0-9]+)/g, (all, issue) => {
return `[#${ issue }](https://github.com/ethers-io/ethers.js/issues/${ issue })`;
}) + "; " + commit;
}
output.push(` - ${ body } (${ link })`);
});
output.push("");
for (let i = firstLine; i < lines.length; i++) {
output.push(lines[i]);
}
return output.join("\n");
}

View File

@@ -0,0 +1,75 @@
import fs from "fs";
import semver from "semver";
import { dirnames, getPackageJsonPath, getPackagePath, resolve } from "../path";
import * as local from "../local";
import { colorify, getProgressBar } from "../log";
import * as npm from "../npm";
import { loadJson, repeat, saveJson } from "../utils";
(async function() {
const progress = getProgressBar(colorify.bold("Bumping package.json versions"));
const latestVersions: Record<string, string> = { };
let updated = false;
const output: Array<string> = [ ];
// For each package, detect diff between tarball and remote
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
const dirname = dirnames[i];
const pLocal = local.getPackage(dirname);
const pNpm = await npm.getPackage(dirname);
const tarballHash = local.computeTarballHash(dirname);
let version = pNpm.version;
if (tarballHash !== pNpm.tarballHash) {
version = semver.inc(version, "patch");
output.push([
" ",
colorify.blue(pLocal.name),
repeat(" ", 47 - pLocal.name.length - pNpm.version.length),
pNpm.version,
colorify.bold(" => "),
colorify.green(version)
].join(""));
local.updateJson(getPackageJsonPath(dirname), { gitHead: undefined, tarballHash, version }, true);
updated = true;
}
latestVersions[pLocal.name] = version;
// Write out the _version.ts
if (!pLocal._ethers_nobuild) {
const code = "export const version = " + JSON.stringify(dirname + "/" + pLocal.version) + ";\n";
fs.writeFileSync(resolve(getPackagePath(dirname), "src.ts/_version.ts"), code);
}
}
progress(1);
if (updated) {
const filename = resolve("packages/ethers/package.json")
const info = loadJson(filename);
Object.keys(info.dependencies).forEach((name) => {
const version = latestVersions[name];
if (name == null) { return; }
info.dependencies[name] = version;
});
saveJson(filename, info);
}
output.forEach((line) => { console.log(line); });
})().catch((error) => {
console.log(`Error running ${ process.argv[0] }: ${ error.message }`);
process.exit(1);
});

View File

@@ -0,0 +1,3 @@
import { colorify } from "../log";
console.log(colorify.bold(process.argv[2] || "no message"));

View File

@@ -0,0 +1,17 @@
import { dirs, isEthers } from "../path";
import { getDependencies, updateJson } from "../local";
import { colorify } from "../log";
(async function() {
const dependencies = getDependencies(null, (name: string) => {
return !isEthers(name);
});
console.log(colorify.bold(`Hoisting ${ Object.keys(dependencies).length } dependencies into root package...`));
updateJson(dirs.rootPackageJsonPath, { dependencies });
})().catch((error) => {
console.log(`Error running ${ process.argv[0] }: ${ error.message }`);
process.exit(1);
});

View File

@@ -0,0 +1,56 @@
import fs from "fs";
import { dirname, resolve } from "path";
import { getDependencies } from "../local";
import { colorify } from "../log";
import { dirs, getDirname, getPackagePath, packages } from "../path";
import { mkdir } from "../utils";
function link(existing: string, path: string): void {
try {
const current = fs.readlinkSync(path);
// Alerady linked
if (current === existing) { return; }
fs.unlinkSync(path);
} catch (error) {
if (error.code !== "ENOENT") { throw error; }
}
// Link
const dir = dirname(path);
mkdir(dir);
fs.symlinkSync(existing, path);
}
(async function() {
console.log(colorify.bold(`Linking ${ packages.length } package node_modules rat nests...`));
const nodeModulesBase = resolve(dirs.root, ".package_node_modules");
// Make a symlink in the ROOT/node_mpdules to each package in this repo
packages.forEach((name) => {
// e.g. /node_modules/@ethersproject/abi => /packages/abi
link(getPackagePath(name), resolve(dirs.root, "node_modules", name));
// e.g. /packages/abi/node_modules => /.package_node_modules/abi/
const nodeModules = resolve(nodeModulesBase, getDirname(name));
mkdir(nodeModules);
link(nodeModules, resolve(getPackagePath(name), "node_modules"));
});
packages.forEach((name) => {
const nodeModules = resolve(nodeModulesBase, getDirname(name));
const deps = getDependencies(name);
Object.keys(deps).forEach((name) => {
link(resolve(dirs.root, "node_modules", name), resolve(nodeModules, name));
});
});
})().catch((error) => {
console.log(`Error running ${ process.argv[0] }: ${ error.message }`);
process.exit(1);
});;

View File

@@ -0,0 +1,16 @@
"use strict";
const { major } = require("semver");
// This should be used like `node npm-skip-node8 || COMMAND`.
// - If node 8, this script returns true, skipping COMMAND
// - Otherwise, return false, running COMMAND
if (major(process.version) > 8) {
// Node >8; return "false" (wrt to shell scripting)
process.exit(1);
} else {
// Node 8; return "true" (wrt to shell scripting)
process.exit(0);
}

View File

@@ -0,0 +1,105 @@
import fs from "fs";
import { createServer, Server } from "http";
import { resolve } from "path";
export function getMime(filename: string): string {
switch (filename.split('.').pop().toLowerCase()) {
case 'css': return 'text/css';
case 'doctree': return 'application/x-doctree';
case 'eot': return 'application/vnd.ms-fontobject';
case 'gif': return 'image/gif';
case 'html': return 'text/html';
case 'js': return 'application/javascript';
case 'jpg': return 'image/jpeg';
case 'jpeg': return 'image/jpeg';
case 'md': return 'text/markdown';
case 'pickle': return 'application/x-pickle';
case 'png': return 'image/png';
case 'svg': return 'image/svg+xml';
case 'ttf': return 'application/x-font-ttf';
case 'txt': return 'text/plain';
case 'woff': return 'application/font-woff';
}
console.log('NO MIME', filename);
return "application/octet-stream";
}
export type Options = {
port?: number;
redirects?: Record<string, string>;
};
export function start(root: string, options: Options): Server {
if (root == null) { throw new Error("root required"); }
if (options == null) { options = { }; }
if (options.port == null) { options.port = 8000; }
root = resolve(root);
const server = createServer((req, resp) => {
// Follow redirects in options
if (options.redirects && options.redirects[req.url]) {
resp.writeHead(301, { Location: options.redirects[req.url] });
resp.end();
return;
}
let filename = resolve(root, "." + req.url);
// Make sure we aren't crawling out of our sandbox
if (req.url[0] !== "/" || filename.substring(0, filename.length) !== filename) {
resp.writeHead(403);
resp.end();
return;
}
try {
const stat = fs.statSync(filename);
if (stat.isDirectory()) {
// Redirect bare directory to its path (i.e. "/foo" => "/foo/")
if (req.url[req.url.length - 1] !== "/") {
resp.writeHead(301, { Location: req.url + "/" });
resp.end();
return;
}
filename += "/index.html";
}
const content = fs.readFileSync(filename);
resp.writeHead(200, {
"Content-Length": content.length,
"Content-Type": getMime(filename)
});
resp.end(content);
return;
} catch (error) {
if (error.code === "ENOENT") {
resp.writeHead(404, { });
resp.end();
return;
}
resp.writeHead(500, { });
resp.end();
return;
}
});
server.listen(options.port, () => {
console.log(`Server running on: http://localhost:${ options.port }`);
});
return server;
}
start(resolve(__dirname, "../../docs"), {
redirects: {
"/": "/v5/"
}
});

View File

@@ -0,0 +1,36 @@
import { setupBuild } from "../build";
import { colorify } from "../log";
import { getPackageJsonPath } from "../path";
import { loadJson, saveJson } from "../utils";
(async function() {
process.argv.slice(2).forEach((arg) => {
console.log(colorify.bold("Setting Option:"), arg);
switch(arg) {
case "esm":
setupBuild(true);
break;
case "cjs":
setupBuild(false);
break;
// This will remove the browser field entirely, so make sure
// to set esm of cjs first as they will restore the browser
// field
case "browser-lang-all": {
const filename = getPackageJsonPath("wordlists");
const info = loadJson(filename);
delete info.browser;
saveJson(filename, info, true);
break;
}
default:
throw new Error(`Unknown option: ${ JSON.stringify(arg) }`);
}
});
})().catch((error) => {
console.log(`Error running ${ process.argv[0] }: ${ error.message }`);
process.exit(1);
});

View File

@@ -0,0 +1,18 @@
import { config } from "../config";
import { getPassword } from "../log";
if (process.argv.length !== 3) {
console.log("Usage: set-config KEY");
process.exit(1);
}
const key = process.argv[2];
(async function() {
const value = await getPassword("Value: ");
await config.set(key, value);
})().catch((error) => {
console.log(`Error running ${ process.argv[0] }: ${ error.message }`);
process.exit(1);
});

View File

@@ -1,18 +1,21 @@
"use strict";
const { resolve } = require("path");
const fs = require("fs");
import fs from "fs";
import { resolve } from "path";
import ts from "typescript";
import { colorify } from "../log";
const Words = fs.readFileSync("/usr/share/dict/words").toString().split("\n").reduce((accum, word) => {
accum[word.toLowerCase()] = true;
return accum;
}, { });
}, <Record<string, boolean>>{ });
`
// Words missing from the dictionary
accessing addresses aligned autofill called cancelled changed censored
clamping compiled computed configured consumed creating decoded decoding
decrypt decrypted decrypting deployed deploying deprecated detected
decreased decrypt decrypted decrypting deployed deploying deprecated detected
discontinued earliest email enabled encoded encoding encrypt
encrypted encrypting entries euro exceeded existing expected
expired failed fetches formatted formatting funding generated
@@ -47,9 +50,9 @@ bytecode callback calldata checksum ciphertext cli codepoint commify config
contenthash ctr ctrl debug dd dklen eexist encseed eof ethaddr
ethseed ethers eval exec filename func gz hid http https hw iv
info init ipc json kdf kdfparams labelhash lang lib mm multihash nfc
nfkc nfd nfkd nodehash notok nullish oob opcode pbkdf pc plugin pragma pre prf
repl rpc sighash topichash solc stdin stdout subclasses subnode
timeout todo txt ufixed utc utf util url uuid vm vs websocket
nfkc nfd nfkd nodehash notok nowait nullish oob opcode pbkdf pc plugin
pragma pre prf repl rpc sighash topichash solc stdin stdout subclasses
subnode timeout todo txt ufixed utc utf util url uuid vm vs websocket
wikipedia wx xe xpriv xpub xx yyyy zlib
// AbiV2
@@ -79,20 +82,28 @@ OYAa IJBEJqXZJ
Words[word.toLowerCase()] = true;
});
const ts = require("typescript");
type Bar = {
value: string;
lineNo: number;
}
function getStrings(source) {
const sourceFile = ts.createSourceFile("filename.ts", source);
type Foo = {
filename: string;
values: Array<Bar>;
};
const result = [ ];
function getStrings(source: string): Array<Bar> {
const sourceFile = ts.createSourceFile("filename.ts", source, ts.ScriptTarget.Latest);
function add(value, pos) {
const result: Array<Bar> = [ ];
function add(value: string, pos: number): void {
const lineNo = sourceFile.getLineAndCharacterOfPosition(pos).line + 1;
result.push({ value, lineNo });
}
let lastClass = null, lastEnum = null;
function visit(node, depth) {
//let lastClass = null, lastEnum = null;
function visit(node: ts.Node, depth: number): void {
switch (node.kind) {
//case ts.SyntaxKind.TemplateExpression:
// if (node.head) { visit(node.head); }
@@ -103,7 +114,7 @@ function getStrings(source) {
case ts.SyntaxKind.TemplateTail:
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
add(node.text, node.pos);
add((<ts.LiteralLikeNode>node).text, node.pos);
break;
}
@@ -118,10 +129,11 @@ function getStrings(source) {
const Include = new RegExp("packages/.*/src.ts/.*\.ts$");
const Exclude = new RegExp("/node_modules/|src.ts/.*browser.*");
function getAllStrings(path) {
function getAllStrings(path: string): Array<Foo> {
const Root = resolve(__dirname, path);
const readdir = function(path) {
const readdir = function(path: string): Array<Foo> {
if (path.match(Exclude)) { return [ ]; }
const stat = fs.statSync(path);
@@ -145,7 +157,7 @@ function getAllStrings(path) {
return readdir(Root);
}
function checkWord(word) {
function checkWord(word: string): boolean {
word = word.toLowerCase();
// A word
@@ -156,20 +168,24 @@ function checkWord(word) {
// Hex string
if (word.match(/^(0x)?[0-9a-f]*$/i)) { return true; }
return false;
}
function starts(text, prefix) {
function starts(text: string, prefix: string): boolean {
return (text.substring(0, prefix.length) === prefix);
}
(async function() {
console.log(colorify.bold("Spell checking source code strings..."));
let count = 0;
getAllStrings(resolve(__dirname, "../../packages")).forEach((file) => {
getAllStrings(resolve(__dirname, "../../../../packages")).forEach((file: Foo) => {
if (starts(file.filename, "/testcases/src.ts/generation-scripts")) { return; }
if (starts(file.filename, "/asm/src.ts/opcodes.ts")) { return; }
file.values.forEach((entry) => {
function problem(word) {
function problem(word: string): void {
count++;
console.log({
filename: file.filename,
@@ -196,16 +212,23 @@ function starts(text, prefix) {
value.replace(/([a-z+])([A-Z])/g, (all, first, secondLetter) => {
return first + " " + secondLetter;
}).replace(/((?:0x)?[A-Za-z]+)/gi, (all, word) => {
if (checkWord(word)) { return; }
if (checkWord(word)) { return ""; }
problem(word);
return "";
});;
});
});
if (count) {
console.log(`Found ${ count } typos.`);
process.exit(1)
}
process.exit(0)
})();
process.exit(0)
})().catch((error) => {
console.log(error);
process.exit(1);
});

View File

@@ -0,0 +1,10 @@
import fs from "fs";
import { generate } from "../changelog";
import { colorify } from "../log";
import { resolve } from "../path";
(async function() {
console.log(colorify.bold("Updating CHANGELOG.md..."));
fs.writeFileSync(resolve("CHANGELOG.md"), await generate());
})();

View File

@@ -0,0 +1,15 @@
import { getOrdered } from "../depgraph";
import { resolve } from "../path";
import { updateJson } from "../local";
(async function() {
const ordered = getOrdered(true);
updateJson(resolve("tsconfig.project.json"), {
references: ordered.map((name) => ({ path: ("./packages/" + name) }))
});
})().catch((error) => {
console.log(error);
process.exit(1);
});

View File

@@ -0,0 +1,42 @@
"use strict";
import fs from "fs";
import { colorify } from "../log";
import { resolve } from "../path";
const sourceEthers = fs.readFileSync(resolve("packages/ethers/src.ts/ethers.ts")).toString();
const targets = sourceEthers.match(/export\s*{\s*((.|\s)*)}/)[1].trim();
////////////////////
// Begin template
////////////////////
const output = `"use strict";
// To modify this file, you must update ./misc/admin/lib/cmds/update-exports.js
import * as ethers from "./ethers";
try {
const anyGlobal = (window as any);
if (anyGlobal._ethers == null) {
anyGlobal._ethers = ethers;
}
} catch (error) { }
export { ethers };
export {
${ targets }
} from "./ethers";
`;
////////////////////
// End template
////////////////////
console.log(colorify.bold(`Flattening exports...`))
fs.writeFileSync(resolve("packages/ethers/src.ts/index.ts"), output);

View File

@@ -0,0 +1,27 @@
//import { getGitTag } from "../git";
import { computeTarballHash, updateJson } from "../local";
import { colorify, getProgressBar } from "../log";
import { dirnames, getPackageJsonPath } from "../path";
(async function() {
const progress = getProgressBar(colorify.bold("Updating package.json hashes"));
// Updating all tarball hashes now that versions have been updated
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
const dirname = dirnames[i];
//const gitHead = await getGitTag(resolve("packages", dirname));
const tarballHash = computeTarballHash(dirname);
updateJson(getPackageJsonPath(dirname), { tarballHash }, true);
}
progress(1);
})().catch((error) => {
console.log(error);
process.exit(1);
});;

134
misc/admin/src.ts/config.ts Normal file
View File

@@ -0,0 +1,134 @@
import { createHmac, randomBytes } from "crypto";
import fs from "fs";
import os from "os";
import { resolve } from "path";
import AES from "aes-js";
import scrypt from "scrypt-js";
import { colorify, getPassword, getProgressBar } from "./log";
function getRandomBytes(length: number): Uint8Array {
const result = new Uint8Array(length);
result.set(randomBytes(length));
return result;
}
function computeHmac(key: Uint8Array, data: Uint8Array): string {
return "0x" + createHmac("sha512", key, ).update(data).digest("hex");
}
async function getScrypt(message: string, password: string, salt: Uint8Array): Promise<Uint8Array> {
const progress = getProgressBar(message);
return await scrypt.scrypt(Buffer.from(password), Buffer.from(salt), (1 << 17), 8, 1, 64, progress);
}
class Config {
private salt: Uint8Array;
private dkey: Uint8Array;
private values: Record<string, string>;
private canary: string;
private filename: string;
constructor(filename: string) {
this.salt = null;
this.dkey = null;
this.values = { };
this.canary = "";
this.filename = filename;
}
async load(): Promise<void> {
if (this.dkey) { return; }
let data: any = null;
if (fs.existsSync(this.filename)) {
data = JSON.parse(fs.readFileSync(this.filename).toString());
} else {
data = {
salt: Buffer.from(getRandomBytes(32)).toString("hex")
};
}
this.canary = data.canary || "";
this.salt = data.salt;
const password = await getPassword(colorify.bold("Password (config-store): "));
this.dkey = await getScrypt(colorify.bold("Unlocking config"), password, this.salt);
if (data.ciphertext) {
const ciphertext = Buffer.from(data.ciphertext, "base64");
const iv = Buffer.from(data.iv, "base64");
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const plaintext = aes.decrypt(ciphertext);
const hmac = computeHmac(this.dkey.slice(32, 64), plaintext);
if (hmac !== data.hmac) {
console.log(colorify.red("Incorrect password."));
throw new Error("wrong password");
}
this.values = JSON.parse(Buffer.from(plaintext).toString());
}
}
async keys(): Promise<Array<string>> {
await this.load();
return Object.keys(this.values);
}
save(): void {
this.values._junk = Buffer.from(getRandomBytes(16 + Math.floor(Math.random() * 48))).toString("base64")
const plaintext = Buffer.from(JSON.stringify(this.values));
const iv = Buffer.from(getRandomBytes(16));
const hmac = computeHmac(this.dkey.slice(32, 64), plaintext);
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const ciphertext = Buffer.from(aes.encrypt(plaintext));
const data = {
ciphertext: ciphertext.toString("base64"),
iv: iv.toString("base64"),
salt: this.salt,
hmac: hmac,
canary: this.canary
};
fs.writeFileSync(this.filename, JSON.stringify(data, null, 2));
}
async get(key: string): Promise<string> {
await this.load();
return this.values[key];
}
async set(key: string, value: string): Promise<void> {
await this.load();
this.values[key] = value;
this.save();
}
lock(): void {
this.salt = this.dkey = null;
}
}
const _config = new Config(resolve(os.homedir(), ".ethers-dist"));
export const config = {
get: function(key: string) {
return _config.get(key);
},
set: function(key: string, value: string) {
_config.set(key, value);
},
keys: function() {
return _config.keys();
},
lock: function() {
_config.lock();
}
};

View File

@@ -0,0 +1,110 @@
import { dirnames } from "./path";
import { getPackage, Package } from "./local";
class OrderedSet {
_keys: Array<string>;
_values: Record<string, boolean>
constructor() {
this._keys = [ ];
this._values = { };
}
add(key: string): void {
this._values[key] = true;
this._keys = null;
}
contains(key: string): boolean {
return !!this._values[key];
}
_sort(): void {
if (this._keys != null) { return; }
this._keys = Object.keys(this._values);
this._keys.sort();
}
get length(): number {
this._sort();
return this._keys.length;
}
get(index: number): string {
this._sort();
return this._keys[index];
}
}
export function getOrdered(skipNobuild?: boolean): Array<string> {
const packages: Record<string, Package > = { };
const filenames: Record<string, string> = { };
// Maps packages to names to list of dependencies; { [ name:string]: Array<name: string> }
const deps: Record<string, OrderedSet> = { };
let addDeps = (name: string, depends: Record<string, string>) => {
Object.keys(depends).forEach((dep) => {
// Not a package we manage
if (packages[dep] == null) { return; }
deps[name].add(dep);
});
}
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
let info = getPackage(dirname);
if (skipNobuild && info._ethers_nobuild) { continue; }
packages[info.name] = info;
filenames[info.name] = dirname;
}
Object.keys(packages).forEach((name) => {
let info = packages[name];
deps[info.name] = new OrderedSet();
addDeps(info.name, info.dependencies || { });
addDeps(info.name, info.devDependencies || { });
});
let ordered: Array<string> = [ ];
let remaining = Object.keys(deps);
let isSatisfied = (name: string) => {
for (let i = 0; i < deps[name].length; i++) {
if (ordered.indexOf(deps[name].get(i)) === -1) { return false; }
}
return true;
}
while (remaining.length) {
let bail = true;
for (let i = 0; i < remaining.length; i++) {
if (!isSatisfied(remaining[i])) { continue; }
bail = false;
ordered.push(remaining[i]);
remaining.splice(i, 1);
break;
}
if (bail) {
throw new Error("Nothing processed; circular dependencies...");
}
}
return ordered.map((name) => filenames[name]);
}
export function sort(dirnames: Array<string>): void {
let ordered = getOrdered();
dirnames.sort((a, b) => {
let ai = ordered.indexOf(getPackage(a).name);
let bi = ordered.indexOf(getPackage(b).name);
if (ai === -1 || bi === -1) {
throw new Error("unknown dirname - " + [a, b].join(", "));
}
return ai - bi;
});
}

106
misc/admin/src.ts/geturl.ts Normal file
View File

@@ -0,0 +1,106 @@
import http from "http";
import https from "https";
import { parse } from "url"
export type GetUrlResponse = {
statusCode: number,
statusMessage: string;
headers: { [ key: string] : string };
body: Uint8Array;
};
export type Options = {
method?: string,
body?: Uint8Array
headers?: { [ key: string] : string },
};
function getResponse(request: http.ClientRequest): Promise<GetUrlResponse> {
return new Promise((resolve, reject) => {
request.once("response", (resp: http.IncomingMessage) => {
const response: GetUrlResponse = {
statusCode: resp.statusCode,
statusMessage: resp.statusMessage,
headers: Object.keys(resp.headers).reduce((accum, name) => {
let value = resp.headers[name];
if (Array.isArray(value)) {
value = value.join(", ");
}
accum[name] = value;
return accum;
}, <{ [ name: string ]: string }>{ }),
body: null
};
//resp.setEncoding("utf8");
resp.on("data", (chunk: Uint8Array) => {
if (response.body == null) { response.body = new Uint8Array(0); }
const body = new Uint8Array(response.body.length + chunk.length);
body.set(response.body, 0);
body.set(chunk, response.body.length);
response.body = body;
});
resp.on("end", () => {
resolve(response);
});
resp.on("error", (error) => {
/* istanbul ignore next */
(<any>error).response = response;
reject(error);
});
});
request.on("error", (error) => { reject(error); });
});
}
// The URL.parse uses null instead of the empty string
function nonnull(value: string): string {
if (value == null) { return ""; }
return value;
}
export async function getUrl(href: string, options?: Options): Promise<GetUrlResponse> {
if (options == null) { options = { }; }
// @TODO: Once we drop support for node 8, we can pass the href
// firectly into request and skip adding the components
// to this request object
const url = parse(href);
const request = {
protocol: nonnull(url.protocol),
hostname: nonnull(url.hostname),
port: nonnull(url.port),
path: (nonnull(url.pathname) + nonnull(url.search)),
method: (options.method || "GET"),
headers: (options.headers || { }),
};
let req: http.ClientRequest = null;
switch (nonnull(url.protocol)) {
case "http:":
req = http.request(request);
break;
case "https:":
req = https.request(request);
break;
default:
/* istanbul ignore next */
throw new Error(`unsupported protocol ${ url.protocol }`);
}
if (options.body) {
req.write(Buffer.from(options.body));
}
req.end();
const response = await getResponse(req);
return response;
}

16
misc/admin/src.ts/git.ts Normal file
View File

@@ -0,0 +1,16 @@
import { run } from "./run";
// Returns the most recent git commit hash for a given filename
export async function getGitTag(filename: string): Promise<string> {
const result = await run("git", [ "log", "-n", "1", "--", filename ]);
if (!result.ok) { throw new Error(`git log error`); }
let log = result.stdout.trim();
if (!log) { return null; }
const hashMatch = log.match(/^commit\s+([0-9a-f]{40})\n/i);
if (!hashMatch) { return null; }
return hashMatch[1];
}
//getGitTag("/Users/ricmoo/Development/ethers/ethers.js/packages/abi").then(console.log);

148
misc/admin/src.ts/local.ts Normal file
View File

@@ -0,0 +1,148 @@
import fs from "fs";
import { dirnames, getPackageJsonPath, getPackagePath, resolve } from "./path";
import { run } from "./run";
import { loadJson, saveJson, sha256, sortRecords } from "./utils";
export type Package = {
dependencies: { [ name: string ]: string };
devDependencies: { [ name: string ]: string };
gitHead: string;
name: string;
version: string;
tarballHash: string;
location: "remote" | "local";
_ethers_nobuild: boolean;
};
export function getPackage(name: string): Package {
const value = loadJson(getPackageJsonPath(name));
return {
name: value.name,
version: value.version,
dependencies: (value.dependencies || { }),
devDependencies: (value.dependencies || { }),
location: "local",
tarballHash: (value.tarballHash || null),
gitHead: (value.gitHead || null),
_ethers_nobuild: !!value._ethers_nobuild,
};
}
export function updateJson(path: string, replace: Record<string, any>, sort?: boolean): void {
const values = loadJson(path);
Object.keys(replace).forEach((key) => {
const value = replace[key];
if (value === undefined) {
delete values[key];
} else {
values[key] = replace[key];
}
});
saveJson(path, values, !!sort);
}
export function getDependencies(name?: string, filter?: (name: string) => boolean): Record<string, string> {
if (name) {
return sortRecords(getPackage(name).dependencies);
}
// Find all versions for each package dependency
const deps = dirnames.reduce((accum, dirname) => {
const deps = getPackage(dirname).dependencies;
Object.keys(deps).forEach((name) => {
if (filter && !filter(name)) { return; }
if (!accum[name]) { accum[name] = { }; }
accum[name][deps[name]] = true;
});
return accum;
}, <Record<string, Record<string, boolean>>>{});
// Make sure each package dependency only has 1 version
return sortRecords(Object.keys(deps).reduce((accum, name) => {
const versions = Object.keys(deps[name]);
if (versions.length > 1) {
throw new Error(`cannot depend on multiple versions for ${ JSON.stringify(name) }: ${ versions.map(v => JSON.stringify(v)).join(", ") }`);
}
accum[name] = versions[0];
return accum;
}, <Record<string, string>>{ }));
}
export function getPackList(name: string): Array<string> {
const result = run("npm", [ "pack", "--json", getPackagePath(name), "--dry-run" ]);
if (!result.ok) {
const error = new Error(`failed to run npm pack: ${ name }`);
(<any>error).result = result;
throw error;
}
return JSON.parse(result.stdout)[0].files.map((info: { path: string }) => info.path);
}
/*
export function getTarball(name: string): Buffer {
const files = getPackList(name).map((name) => `./${ name }`);
files.sort((a, b) => {
const compsA = a.split("/"), compsB = b.split("/");
while (true) {
const a = compsA.shift(), b = compsB.shift();
if (a === b) { continue; }
if (compsA.length === 0 && compsB.length === 0) {
if (a < b) { return -1; }
if (a > b) { return 1; }
break;
}
if (compsA.length === 0) { return -1; }
if (compsB.length === 0) { return 1; }
if (a < b) { return -1; }
if (a > b) { return 1; }
}
return 0;
});
return tar.create({
sync: true,
cwd: getPackagePath(name),
prefix: "package/",
gzip: true,
portable: true,
// Provide a specific date in the 1980s for the benefit of zip,
// which is confounded by files dated at the Unix epoch 0.
mtime: new Date('1985-10-26T08:15:00.000Z'),
}, files).read();
}
*/
export function computeTarballHash(name: string): string {
// Sort the files to get a consistent hash
const files = getPackList(name);
files.sort();
// Compute the hash for each file
const packageRoot = getPackagePath(name);
const hashes = files.reduce((accum, filename) => {
let content = fs.readFileSync(resolve(packageRoot, filename));
// The package.json includes the hash, so we need to nix it to get a consistent hash
if (filename === "package.json") {
const info = JSON.parse(content.toString());
delete info.gitHead;
delete info.tarballHash;
content = Buffer.from(JSON.stringify(info, null, 2));
}
accum[filename] = sha256(content);
return accum;
}, <Record<string, string>>{ });
return sha256(Buffer.from("{" + files.map((filename) => {
return `${ JSON.stringify(filename) }:"${ hashes[filename] }"`
}).join(",") + "}"));
}

167
misc/admin/src.ts/log.ts Normal file
View File

@@ -0,0 +1,167 @@
import { repeat } from "./utils";
// See: https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
let disableColor = !(process.stdout.isTTY);
export function getProgressBar(action: string): (percent: number) => void {
let lastProgress = -1;
return function(percent: number): void {
const progress = Math.trunc(percent * 100);
if (disableColor) {
if (lastProgress === -1) {
console.log(action + "...");
}
lastProgress = progress;
return;
}
//process.stdin.setRawMode(false);
//process.stdin.pause();
if (progress === lastProgress || lastProgress === 100) { return; }
lastProgress = progress;
(<any>(process.stdout)).clearLine();
(<any>(process.stdout)).cursorTo(0);
process.stdout.write(action + "... " + progress + "%");
if (percent === 1) {
process.stdout.write('\n');
}
return;
}
}
const colorSequences: Record<string, string> = {
blue: "\x1b[34m",
cyan: "\x1b[36m",
green: "\x1b[32m",
magenta: "\x1b[35m",
red: "\x1b[31m",
yellow: "\x1b[33m",
bold: ""
};
function getColor(color?: string): string {
if (!color || color === "normal") { return "\x1b[0m"; }
return "\x1b[1m" + colorSequences[color];
}
export type ColorifyFunc = (text: string) => string;
function _colorify(format: string): ColorifyFunc {
return function (text: string): string {
if (disableColor) { return text; }
return getColor(format) + text.replace(/[^ -~]+/g, "") + getColor();
}
}
export const colorify: { [ format: string ]: ColorifyFunc } = Object.freeze({
bold: _colorify("bold"),
blue: _colorify("blue"),
green: _colorify("green"),
red: _colorify("red"),
});
export type PromptOptions = {
choice?: Array<string>;
defaultChoice?: string;
mask?: string;
};
function _getPrompt(prompt: string, options: PromptOptions, callback: (ctrlC: boolean, message: string) => void) {
process.stdout.write(prompt);
let stdin = process.stdin;
stdin.resume();
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('utf8');
let message = '';
let respond = (ctrlC: boolean, message: string) => {
process.stdout.write('\n');
stdin.setRawMode(false);
stdin.pause();
stdin.removeListener('data', handler);
callback(ctrlC, message);
}
function handler(chr: string): void {
chr = String(chr);
switch (chr) {
// Enter (ish)
case "\n":
case "\r":
case "\u0004":
if (options.choice) {
if (options.defaultChoice) {
respond(null, options.defaultChoice);
}
} else {
respond(null, message);
}
break;
// Backspace
case "\u007f":
if (message.length > 0 && options.choice == null) {
message = message.substring(0, message.length - 1);
(<any>(process.stdout)).clearLine();
(<any>(process.stdout)).cursorTo(0);
if (options.mask) {
process.stdout.write(prompt + repeat(options.mask, message.length));
} else {
process.stdout.write(prompt + message);
}
}
break;
// Ctrl-C
case "\u0003":
process.stdout.write('\n[ CTRL-C ]');
respond(true, null);
break;
// Any other character
default:
if (options.choice) {
if (options.choice.indexOf(chr) >= 0) {
process.stdout.write(chr);
respond(null, chr);
}
} else {
// More passsword characters
if (options.mask) {
process.stdout.write('*');
} else {
process.stdout.write(chr);
}
message += chr;
}
break;
}
}
stdin.on('data', handler);
}
export function getPrompt(prompt: string, options: PromptOptions): Promise<string> {
return new Promise((resolve, reject) => {
_getPrompt(prompt, options, (ctrlC, password) => {
if (ctrlC) {
return reject(new Error("cancelled"));
}
resolve(password);
});
});
}
export function getPassword(prompt: string): Promise<string> {
return getPrompt(prompt, { mask: "*" });
}

48
misc/admin/src.ts/npm.ts Normal file
View File

@@ -0,0 +1,48 @@
import semver from "semver";
import { getUrl } from "./geturl";
import { Package, getPackage as _getPackage } from "./local";
const cache: Record<string, any> = { };
async function getPackageInfo(name: string): Promise<any> {
// Convert dirname to package if needed
name = _getPackage(name).name;
if (!cache[name]) {
try {
const result = await getUrl("http:/" + "/registry.npmjs.org/" + name);
cache[name] = JSON.parse(Buffer.from(result.body).toString("utf8"));
} catch (error) {
if (error.status === 404) { return null; }
throw error;
}
}
return cache[name] || null;
}
export async function getPackage(name: string, version?: string): Promise<Package> {
const infos = await getPackageInfo(name);
if (infos == null) { return null; }
if (version == null) {
const versions = Object.keys(infos.versions);
versions.sort(semver.compare);
version = versions.pop();
}
const info = infos.versions[version];
return {
dependencies: (info.dependencies || {}),
devDependencies: (info.devDependencies || {}),
gitHead: info.gitHead,
location: "remote",
name: info.name,
tarballHash: info.tarballHash,
version : info.version,
_ethers_nobuild: !!info._ethers_nobuild,
};
}

70
misc/admin/src.ts/path.ts Normal file
View File

@@ -0,0 +1,70 @@
import fs from "fs";
import { resolve as _resolve } from "path";
export const root: string = _resolve(__dirname, "../../../");
export function resolve(...args: Array<string>): string {
args.unshift(root);
return _resolve.apply(null, args);
}
const pathRootPackageJsonPath: string = resolve("package.json");
const pathPackages: string = resolve("packages");
export const dirs = Object.freeze({
rootPackageJsonPath: pathRootPackageJsonPath,
packages: pathPackages,
root,
});
type PackageInfo = {
dirname: string;
packageName: string;
packagePath: string;
packageJsonPath: string;
version: string;
};
export const dirnames: ReadonlyArray<string> = Object.freeze(fs.readdirSync(dirs.packages).filter((dirname) => {
return (dirname[0] !== ".");
}));
const packageLookup = dirnames.reduce((accum, dirname) => {
const packagePath = _resolve(dirs.packages, dirname);
const packageJsonPath = _resolve(packagePath, "package.json");
const info = JSON.parse(fs.readFileSync(packageJsonPath).toString());
const packageName = info.name;
const version = info.version;
accum[packageName] = accum[dirname] = {
dirname, packageName, packagePath, packageJsonPath, version
};
return accum;
}, <{ [ name: string ]: PackageInfo }>{ });
export const packages: ReadonlyArray<string> = Object.freeze(dirnames.map((dirname) => packageLookup[dirname].packageName));
function getPackageInfo(name: string): PackageInfo {
const value = packageLookup[name];
if (!value) { throw new Error(`unknown package: ${ name }`); }
return value;
}
export function getPackagePath(name: string): string {
return getPackageInfo(name).packagePath;
}
export function getDirname(name: string): string {
return getPackageInfo(name).dirname;
}
export function getPackageJsonPath(name: string): string {
return getPackageInfo(name).packageJsonPath;
}
export function isEthers(name: string) {
return !!packageLookup[name];
}

74
misc/admin/src.ts/run.ts Normal file
View File

@@ -0,0 +1,74 @@
import { spawnSync } from "child_process";
export type RunResult = {
stderr: string | null;
_stderr: string | Buffer;
stdout: string;
_stdout: string | Buffer;
status: number;
ok: boolean;
};
export function run(progname: string, args?: Array<string>, currentWorkingDirectory?: string): RunResult {
if (args == null) { args = [ ]; }
const options: any = { };
if (currentWorkingDirectory) { options.cwd = currentWorkingDirectory; }
const child = spawnSync(progname, args, options);
const result = {
_stderr: child.stderr,
stderr: (child.stderr.toString() || null),
_stdout: child.stdout,
stdout: child.stdout.toString(),
status: child.status,
ok: (child.stderr.length === 0 && child.status === 0)
};
if (child.error) {
(<any>(child.error)).result = result;
throw child.error;
}
return result;
/*
const result: RunResult = {
stderr: null,
_stderr: Buffer.from([]),
stdout: null,
_stdout: Buffer.from([]),
status: null,
ok: false,
};
proc.stderr.on("data", (data) => {
result._stderr = Buffer.concat([ result._stderr, data ]);
});
proc.stdout.on("data", (data) => {
result._stdout = Buffer.concat([ result._stdout, data ]);
});
proc.on("error", (error) => {
result.stderr = result._stderr.toString("utf8");
result.stdout = result._stdout.toString("utf8");
(<any>error).result = result;
console.log("Error:", error);
reject(error);
});
proc.on("close", (code) => {
result.stderr = result._stderr.toString("utf8");
result.stdout = result._stdout.toString("utf8");
result.status = code;
result.ok = (result._stderr.length === 0 && code === 0);
resolve(result);
});
});
*/
}

106
misc/admin/src.ts/utils.ts Normal file
View File

@@ -0,0 +1,106 @@
import fs from "fs";
import { dirname, resolve } from "path";
import { createHash } from "crypto";
export function repeat(char: string, length: number): string {
if (char.length === 0) { return ""; }
let output = char;
while (output.length < length) { output = output + output; }
return output.substring(0, length);
}
export function sha256(content: Buffer): string {
const hasher = createHash("sha256");
hasher.update(content);
return "0x" + hasher.digest("hex");
}
export function sortRecords(record: Record<string, any>): Record<string, any> {
const keys = Object.keys(record);
keys.sort();
return keys.reduce((accum, name) => {
accum[name] = record[name];
return accum;
}, <Record<string, any>>{ });
}
export function atomicWrite(path: string, value: string | Uint8Array): void {
const tmp = resolve(__dirname, "../../../.atomic-tmp");
fs.writeFileSync(tmp, value);
fs.renameSync(tmp, path);
}
export function loadJson(path: string): any {
return JSON.parse(fs.readFileSync(path).toString());
}
export function saveJson(filename: string, data: any, sort?: boolean): any {
let replacer: (key: string, value: any) => any = undefined;
if (sort) {
replacer = (key, value) => {
if (Array.isArray(value)) {
// pass
} else if (value && typeof(value) === "object") {
const keys = Object.keys(value);
keys.sort();
return keys.reduce((accum, key) => {
accum[key] = value[key];
return accum;
}, <Record<string, any>>{});
}
return value;
};
}
atomicWrite(filename, JSON.stringify(data, replacer, 2) + "\n");
}
export async function resolveProperties(props: Record<string, Promise<any>>): Promise<Record<string, any>> {
const keys = Object.keys(props);
const promises = await Promise.all(keys.map((k) => props[k]));
return keys.reduce((accum, key, index) => {
accum[key] = promises[index];
return accum;
}, <Record<string, any>>{});
}
// Node 8 does not support recursive mkdir... Remove this in v6.
export function mkdir(path: string): void {
let bail = 0;
const dirs = [ ];
while (path !== "/") {
if (bail++ > 50) { throw new Error("something bad happened..."); }
if (fs.existsSync(path)) { break; }
dirs.push(path);
path = dirname(path);
}
while (dirs.length) {
fs.mkdirSync(dirs.pop());
}
}
function zpad(value: number, length?: number): string {
if (length == null) { length = 2; }
const str = String(value);
return repeat("0", length - str.length) + str;
}
function getDate(date: Date): string {
return [
date.getFullYear(),
zpad(date.getMonth() + 1),
zpad(date.getDate())
].join("-");
}
export function getDateTime(date: Date): string {
return getDate(date) + " " + [
zpad(date.getHours()) ,
zpad(date.getMinutes() + 1)
].join(":");
}

39
misc/admin/thirdparty.d.ts vendored Normal file
View File

@@ -0,0 +1,39 @@
declare module "aes-js" {
export class Counter {
constructor(iv: Uint8Array);
}
export namespace ModeOfOperation {
class cbc{
constructor(key: Uint8Array, iv: Uint8Array);
decrypt(data: Uint8Array): Uint8Array;
encrypt(data: Uint8Array): Uint8Array;
}
class ctr{
constructor(key: Uint8Array, counter: Counter);
decrypt(data: Uint8Array): Uint8Array;
encrypt(data: Uint8Array): Uint8Array;
}
}
export namespace padding {
export namespace pkcs7 {
export function strip(data: Uint8Array): Uint8Array;
}
}
}
declare module "tar" {
export type CreateOptions = {
sync?: boolean,
cwd?: string,
prefix?: string,
gzip?: boolean,
portable?: boolean,
mtime?: Date
};
export interface Readable {
read(): Buffer;
}
export function create(options: CreateOptions, files: Array<string>): Readable;
}

31
misc/admin/tsconfig.json Normal file
View File

@@ -0,0 +1,31 @@
{
"compilerOptions": {
"esModuleInterop": true,
"lib": ["es2015", "es5", "dom"],
"module": "commonjs",
"target": "es2015",
"moduleResolution": "node",
"outDir": "./lib/",
"declaration": true,
"preserveSymlinks": true,
"preserveWatchOutput": true,
"pretty": false,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true
},
"include": [
"./thirdparty.d.ts",
"./src.ts/*.ts",
"./src.ts/cmds/*.ts"
],
"exclude": [ ]
}

19521
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,58 +6,60 @@
"url": "git://github.com/ethers-io/ethers.js.git"
},
"scripts": {
"postinstall": "npm run bootstrap",
"auto-build": "node ./admin/cmds/reset-build.js && npm run build -- -w",
"auto-build-esm": "node ./admin/cmds/set-option esm && npm run build -- -w",
"bootstrap": "node ./admin/cmds/reset-build.js && node ./admin/cmds/update-depgraph && lerna bootstrap --hoist",
"preinstall": "npm run bootstrap-hoist",
"postinstall": "node ./misc/admin/lib/cmds/update-depgraph && npm run bootstrap-link",
"bootstrap-hoist": "node ./misc/admin/lib/cmds/hoist",
"bootstrap-link": "node ./misc/admin/lib/cmds/link",
"auto-build": "node ./misc/admin/lib/cmds/set-build-option cjs && npm run build -- -w",
"auto-build-esm": "node ./misc/admin/lib/cmds/set-build-option esm && npm run build -- -w",
"build": "tsc --build ./tsconfig.project.json",
"_build-cjs": "node ./admin/cmds/set-option cjs && npm run build",
"_build-esm": "node ./admin/cmds/set-option esm && npm run build",
"build-all": "node ./admin/cmds/update-exports.js && npm run _build-esm && npm run _build-cjs && npm run _dist",
"_dist-ancillary": "node ./admin/cmds/set-option esm && rollup -c rollup-ancillary.config.js",
"_dist-umd": "node ./admin/cmds/set-option cjs browser-lang-all && rollup -c && mv ./packages/ethers/dist/ethers.umd.min.js ./packages/ethers/dist/ethers-all.umd.min.js && node ./admin/cmds/set-option cjs && rollup -c",
"_dist-esm": "node ./admin/cmds/set-option esm browser-lang-all && rollup -c --configModule && mv ./packages/ethers/dist/ethers.esm.min.js ./packages/ethers/dist/ethers-all.esm.min.js && node ./admin/cmds/set-option esm && rollup -c --configModule",
"_dist-all": "npm run _dist-esm && npm run _dist-ancillary && npm run _dist-umd",
"_dist": "node admin/cmds/npm-skip-node8.js || npm run _dist-all",
"clean": "node ./admin/cmds/reset-build.js && tsc --build --clean ./tsconfig.project.json",
"dist-shims": "cd packages/shims && npm run dist",
"_dist-test-esm": "rollup -c rollup-tests.config.js --configModule",
"_dist-test-umd": "rollup -c rollup-tests.config.js",
"_build-cjs": "node ./misc/admin/lib/cmds/echo 'Building CommonJS libraries...' && node ./misc/admin/lib/cmds/set-build-option cjs && npm run build",
"_build-esm": "node ./misc/admin/lib/cmds/echo 'Building ES modules libraries...' && node ./misc/admin/lib/cmds/set-build-option esm && npm run build",
"clean": "node ./misc/admin/lib/cmds/echo 'Cleaning all build files...' && rm -rf packages/*/lib packages/*/lib.esm packages/*/node_modules packages/*/dist/*.js packages/*/tsconfig.tsbuildinfo node_modules .package_node_modules package-lock.json",
"_test-esm-dist": "rollup -c rollup-tests.config.js --configModule",
"_test-umd-dist": "rollup -c rollup-tests.config.js",
"_test-browser-umd": "karma start --single-run --browsers HeadlessLittleLiar karma-umd.conf.js",
"_test-browser-esm": "karma start --single-run --browsers HeadlessLittleLiar karma-esm.conf.js",
"test-browser-umd": "npm run _dist-test-umd && npm run _test-browser-umd",
"test-browser-esm": "npm run _dist-test-esm && npm run _test-browser-esm",
"test-node": "mocha --no-colors --reporter ./packages/tests/reporter ./packages/tests/lib/test-*.js",
"test-react": "npm run _dist-test-umd && npm run dist-shims && pushd misc/ReactNativeTestApp && ./run-tests.sh && popd",
"test": "npm run build-all && npm run test-node",
"test-browser-umd": "npm run _test-umd-dist && npm run _test-browser-umd",
"test-browser-esm": "npm run _test-esm-dist && npm run _test-browser-esm",
"test-coverage": "nyc --report-dir=output --reporter=lcov --reporter=text mocha --reporter ./packages/tests/reporter-keepalive ./packages/tests/lib/test-*.js | tee output/summary.txt",
"lock-versions": "node ./admin/cmds/lock-versions",
"test-node": "mocha --no-colors --reporter ./packages/tests/reporter ./packages/tests/lib/test-*.js",
"test-react": "npm run _test-umd-dist && npm run build-dist-shims && pushd misc/ReactNativeTestApp && ./run-tests.sh && popd",
"test": "npm run build-all && npm run test-node",
"build-docs": "flatworm docs.wrm docs",
"serve-docs": "node ./admin/cmds/serve-docs.js",
"serve-docs": "node ./misc/admin/lib/cmds/serve-docs.js",
"test-docs": "npm run build-docs && npm run serve-docs",
"upload-docs": " node ./admin/cmds/upload-docs.js",
"spell-check": "node admin/cmds/spell-check.js",
"_admin_prepare": "npm run clean && npm run bootstrap && npm run build && node ./admin/cmds/update-exports.js",
"update-versions": "npm run spell-check && npm run _admin_prepare && node ./admin/cmds/update-versions",
"publish-all": "node ./admin/cmds/publish",
"sync-github": "node ./admin/cmds/cache-github"
"TODO-upload-docs": " node ./admin/cmds/upload-docs.js",
"spell-check": "node ./misc/admin/lib/cmds/spell-check.js",
"build-dist-ancillary": "node ./misc/admin/lib/cmds/set-build-option esm && rollup -c rollup-ancillary.config.js",
"build-dist-shims": "browserify ./packages/shims/src/index.js -o ./packages/shims/dist/index.js && uglifyjs --compress --mangle --output ./packages/shims/dist/index.min.js -- ./packages/shims/dist/index.js",
"build-dist-umd": "node ./misc/admin/lib/cmds/set-build-option cjs browser-lang-all && rollup -c && mv ./packages/ethers/dist/ethers.umd.min.js ./packages/ethers/dist/ethers-all.umd.min.js && node ./misc/admin/lib/cmds/set-build-option cjs && rollup -c",
"build-dist-esm": "node ./misc/admin/lib/cmds/set-build-option esm browser-lang-all && rollup -c --configModule && mv ./packages/ethers/dist/ethers.esm.min.js ./packages/ethers/dist/ethers-all.esm.min.js && node ./misc/admin/lib/cmds/set-build-option esm && rollup -c --configModule",
"_build-dist": "node ./misc/admin/lib/cmds/echo 'Building dist files...' && npm run build-dist-shims && npm run build-dist-esm && npm run build-dist-ancillary && npm run build-dist-umd",
"build-dist": "node ./misc/admin/lib/cmds/npm-skip-node8.js || npm run _build-dist",
"build-libs": "node ./misc/admin/lib/cmds/update-exports.js && npm run _build-cjs && npm run _build-esm && node ./misc/admin/lib/cmds/set-build-option cjs && node packages/asm/generate.js && chmod 755 packages/*/lib/bin/*.js",
"build-all": "npm run build-libs && npm run build-dist",
"update-versions": "npm run clean && npm install && npm run spell-check && npm run build-all && node ./misc/admin/lib/cmds/bump-versions && npm run build-all && node ./misc/admin/lib/cmds/update-hashes && node ./misc/admin/lib/cmds/update-changelog",
"TODO-publish-all": "node ./admin/cmds/publish",
"TODO-sync-github": "node ./admin/cmds/cache-github"
},
"devDependencies": {
"@erquhart/rollup-plugin-node-builtins": "2.1.5",
"@types/assert": "^1.4.1",
"@types/mocha": "^5.2.0",
"@types/node": "^12.7.4",
"@types/semver": "^7.3.4",
"aes-js": "3.0.0",
"aws-sdk": "2.137.0",
"browserify": "16.2.3",
"diff": "4.0.1",
"flatworm": "0.0.2-beta.4",
"jison": "^0.4.18",
"karma": "5.1.0",
"karma-chrome-launcher": "3.1.0",
"karma-mocha": "2.0.1",
"lerna": "3.22.1",
"libnpmpublish": "1.1.3",
"libnpmpublish": "3.0.1",
"mocha": "^7.1.1",
"npm-packlist": "1.4.1",
"nyc": "15.1.0",
"rollup": "1.20.1",
"rollup-plugin-commonjs": "10.0.2",
@@ -68,7 +70,27 @@
"rollup-pluginutils": "2.8.1",
"scrypt-js": "3.0.1",
"semver": "^5.6.0",
"tar": "4.4.8",
"typescript": "3.8.3"
"typescript": "3.8.3",
"uglify-es": "3.3.9"
},
"dependencies": {
"@babel/parser": "7.8.4",
"@babel/types": "7.8.3",
"@ledgerhq/hw-app-eth": "5.3.0",
"@ledgerhq/hw-transport": "5.3.0",
"@ledgerhq/hw-transport-u2f": "5.3.0",
"@types/mocha": "^5.2.0",
"aes-js": "3.0.0",
"bech32": "1.1.4",
"bn.js": "^4.4.0",
"browserify-zlib": "^0.2.0",
"elliptic": "6.5.3",
"hash.js": "1.1.3",
"js-sha3": "0.5.7",
"mime-types": "2.1.11",
"scrypt-js": "3.0.1",
"solc": "0.7.1",
"solidity-parser-antlr": "^0.3.2",
"ws": "7.2.3"
}
}

View File

@@ -1,3 +1,4 @@
.DS_Store
tsconfig.json
src.ts/
tsconfig.tsbuildinfo

View File

@@ -1 +1 @@
export declare const version = "abi/5.0.5";
export declare const version = "abi/5.0.6";

View File

@@ -1,2 +1,2 @@
export const version = "abi/5.0.5";
export const version = "abi/5.0.6";
//# sourceMappingURL=_version.js.map

View File

@@ -1 +1 @@
export declare const version = "abi/5.0.5";
export declare const version = "abi/5.0.6";

View File

@@ -1,4 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.version = "abi/5.0.5";
exports.version = "abi/5.0.6";
//# sourceMappingURL=_version.js.map

View File

@@ -31,7 +31,7 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"tarballHash": "0x72e2d79207141b5d847504c349b75add9d423a8bd4408eda0a14933e6ea4d803",
"tarballHash": "0x5b932b3bf61ca5d2e09dcadec286bd2d06023608801f8e01bba2fb8c86d8b54b",
"types": "./lib/index.d.ts",
"version": "5.0.5"
"version": "5.0.6"
}

View File

@@ -1 +1 @@
export const version = "abi/5.0.5";
export const version = "abi/5.0.6";

View File

@@ -1,12 +1,12 @@
{
"extends": "../../tsconfig.package.json",
"compilerOptions": {
"rootDir": "./src.ts",
"outDir": "./lib/"
"outDir": "./lib/",
"rootDir": "./src.ts"
},
"exclude": [],
"extends": "../../tsconfig.package.json",
"include": [
"./src.ts/*.ts",
"./src.ts/coders/*.ts"
],
"exclude": []
]
}

View File

@@ -1,3 +1,4 @@
.DS_Store
tsconfig.json
src.ts/
tsconfig.tsbuildinfo

View File

@@ -1 +1 @@
export declare const version = "abstract-provider/5.0.4";
export declare const version = "abstract-provider/5.0.5";

Some files were not shown because too many files have changed in this diff Show More