327 lines
10 KiB
JavaScript
327 lines
10 KiB
JavaScript
'use strict';
|
|
|
|
var fs = require('fs');
|
|
var through = require('through');
|
|
|
|
var gulp = require("gulp");
|
|
var ts = require("gulp-typescript");
|
|
var tsProject = ts.createProject("tsconfig.json");
|
|
|
|
var browserify = require("browserify");
|
|
var source = require('vinyl-source-stream');
|
|
var tsify = require("tsify");
|
|
|
|
var sourcemaps = require('gulp-sourcemaps');
|
|
var uglify = require('gulp-uglify');
|
|
var buffer = require('vinyl-buffer');
|
|
|
|
function createTransform(transforms, show) {
|
|
if (!show) { show = { }; }
|
|
|
|
function padding(length) {
|
|
let pad = '';
|
|
while (pad.length < length) { pad += ' '; }
|
|
return pad;
|
|
}
|
|
|
|
function transformFile(path) {
|
|
for (var pattern in transforms) {
|
|
if (path.match(new RegExp('/' + pattern + '$'))) {
|
|
return transforms[pattern];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
return function(path, options) {
|
|
var data = '';
|
|
|
|
return through(function(chunk) {
|
|
data += chunk;
|
|
}, function () {
|
|
var transformed = transformFile(path);
|
|
var shortPath = path;
|
|
if (shortPath.substring(0, __dirname.length) == __dirname) {
|
|
shortPath = shortPath.substring(__dirname.length);
|
|
}
|
|
var size = fs.readFileSync(path).length;
|
|
if (transformed != null) {
|
|
if (show.transformed) {
|
|
console.log('Transformed:', shortPath, padding(70 - shortPath.length), size, padding(6 - String(size).length), '=>', transformed.length);
|
|
}
|
|
data = transformed;
|
|
} else if (shortPath === '/src.ts/utils/wordlist.ts') {
|
|
data += '\n\nexportWordlist = true;'
|
|
if (show.transformed) {
|
|
console.log('Transformed:', shortPath, padding(70 - shortPath.length), size, padding(6 - String(size).length), '=>', data.length);
|
|
}
|
|
} else {
|
|
if (show.preserved) {
|
|
console.log('Preserved: ', shortPath, padding(70 - shortPath.length), size);
|
|
}
|
|
}
|
|
this.queue(data);
|
|
this.queue(null);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bundled Library (browser)
|
|
*
|
|
* Source: src.ts/index.ts src.ts/{contracts,providers,utils,wallet}/*.ts src.ts/wordlists/lang-en.ts
|
|
* Target: dist/ethers{.min,}.js
|
|
*/
|
|
function taskBundle(name, options) {
|
|
var show = options.show || { };
|
|
|
|
// The elliptic package.json is only used for its version
|
|
var ellipticPackage = require('elliptic/package.json');
|
|
ellipticPackage = JSON.stringify({ version: ellipticPackage.version });
|
|
|
|
var version = require('./package.json').version;
|
|
|
|
var undef = "module.exports = undefined;";
|
|
var empty = "module.exports = {};";
|
|
|
|
// This is only used in getKeyPair, which we do not use; but we'll
|
|
// leave it in tact using the browser crypto functions
|
|
var brorand = "module.exports = function(length) { var result = new Uint8Array(length); (global.crypto || global.msCrypto).getRandomValues(result); return result; }";
|
|
|
|
// setImmediate is installed globally by our src.browser/shims.ts, loaded from src.ts/index.ts
|
|
var process = "module.exports = { browser: true };";
|
|
var timers = "module.exports = { setImmediate: global.setImmediate }; ";
|
|
|
|
function readShim(filename) {
|
|
return fs.readFileSync('./shims/' + filename + '.js').toString();
|
|
}
|
|
|
|
|
|
var transforms = {
|
|
|
|
// Remove the precomputed secp256k1 points
|
|
"elliptic/lib/elliptic/precomputed/secp256k1.js": undef,
|
|
|
|
// Remove curves we don't care about
|
|
"elliptic/curve/edwards.js": empty,
|
|
"elliptic/curve/mont.js": empty,
|
|
"elliptic/lib/elliptic/eddsa/.*": empty,
|
|
|
|
// We only use the version from this JSON package
|
|
"elliptic/package.json" : ellipticPackage,
|
|
|
|
// Remove RIPEMD160 and unneeded hashing algorithms
|
|
"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
|
|
"hash.js/lib/hash/sha/1.js": empty,
|
|
"hash.js/lib/hash/sha/224.js": empty,
|
|
"hash.js/lib/hash/sha/384.js": empty,
|
|
|
|
// Swap out borland for the random bytes we already have
|
|
"brorand/index.js": brorand,
|
|
|
|
"xmlhttprequest/lib/XMLHttpRequest.js": readShim("xmlhttprequest"),
|
|
|
|
// Used by sha3 if it exists; (so make it no exist)
|
|
"process/browser.js": process,
|
|
"timers-browserify/main.js": timers,
|
|
|
|
"ethers.js/utils/base64.js": readShim("base64"),
|
|
"ethers.js/providers/ipc-provider.js": readShim("empty"),
|
|
"ethers.js/utils/hmac.js": readShim("hmac"),
|
|
"ethers.js/utils/pbkdf2.js": readShim("pbkdf2"),
|
|
"ethers.js/utils/random-bytes.js": readShim("random-bytes"),
|
|
"ethers.js/utils/shims.js": readShim("shims"),
|
|
"ethers.js/wordlists/index.js": readShim("wordlists"),
|
|
|
|
};
|
|
|
|
gulp.task(name, function () {
|
|
|
|
var result = browserify({
|
|
basedir: '.',
|
|
debug: false,
|
|
entries: [ './index.js' ],
|
|
cache: { },
|
|
packageCache: {},
|
|
standalone: "ethers",
|
|
transform: [ [ createTransform(transforms, show), { global: true } ] ],
|
|
})
|
|
.bundle()
|
|
.pipe(source(options.filename))
|
|
|
|
if (options.minify) {
|
|
result = result.pipe(buffer())
|
|
.pipe(sourcemaps.init({ loadMaps: true }))
|
|
.pipe(uglify())
|
|
.pipe(sourcemaps.write('./'))
|
|
}
|
|
|
|
result = result.pipe(gulp.dest(options.dest));
|
|
|
|
return result;
|
|
});
|
|
}
|
|
|
|
// Creates dist/ethers.js
|
|
taskBundle("default", { filename: "ethers.js", dest: 'dist', show: { transformed: true, preserved: true }, minify: false });
|
|
|
|
// Creates dist/ethers.js
|
|
taskBundle("default-test", { filename: "ethers.js", dest: 'tests/dist', show: { transformed: true }, minify: false });
|
|
|
|
// Creates dist/ethers.min.js
|
|
taskBundle("minified", { filename: "ethers.min.js", dest: 'dist', minify: true });
|
|
|
|
// Creates dist/ethers.min.js
|
|
taskBundle("minified-test", { filename: "ethers.min.js", dest: 'tests/dist', minify: true });
|
|
|
|
/*
|
|
// Dump the TypeScript definitions to dist/types/
|
|
gulp.task("types", function() {
|
|
return gulp.src(['./src.ts/index.ts', './src.ts / * * / * . ts'])
|
|
.pipe(ts({
|
|
declaration: true,
|
|
esModuleInterop: true,
|
|
moduleResolution: "node",
|
|
lib: [ "es2015", "es5", "dom" ],
|
|
module: "commonjs",
|
|
outDir: './dist/types',
|
|
target: "es5",
|
|
}))
|
|
.dts
|
|
.pipe(gulp.dest("dist/types/"))
|
|
});
|
|
*/
|
|
|
|
/**
|
|
* Browser Friendly BIP39 Wordlists
|
|
*
|
|
* source: src.ts/wordlist/lang-*.ts
|
|
* target: dist/wordlist-*.js
|
|
*
|
|
* Since all of the functions these wordlists use is already
|
|
* available from the global ethers library, we use this to
|
|
* target the global ethers functions directly, rather than
|
|
* re-include them.
|
|
*/
|
|
function taskLang(locale) {
|
|
function transformBip39(path, options) {
|
|
var data = '';
|
|
|
|
return through(function(chunk) {
|
|
data += chunk;
|
|
}, function () {
|
|
var shortPath = path;
|
|
if (shortPath.substring(0, __dirname.length) == __dirname) {
|
|
shortPath = shortPath.substring(__dirname.length);
|
|
}
|
|
|
|
// Word list files...
|
|
if (shortPath.match(/^\/src\.ts\/wordlists\//)) {
|
|
shortPath = '/';
|
|
}
|
|
|
|
switch (shortPath) {
|
|
// Use the existing "ethers.errors"
|
|
case '/src.ts/errors.ts':
|
|
data = "module.exports = global.ethers.errors";
|
|
break;
|
|
|
|
// Use the existing "ethers.utils"
|
|
case '/src.ts/utils/bytes.ts':
|
|
case '/src.ts/utils/hash.ts':
|
|
case '/src.ts/utils/properties.ts':
|
|
case '/src.ts/utils/utf8.ts':
|
|
data = "module.exports = global.ethers.utils";
|
|
break;
|
|
|
|
// If it is the Wordlist class, register should export the wordlist
|
|
case '/src.ts/utils/wordlist.ts':
|
|
data += '\n\nexportWordlist = true;'
|
|
break;
|
|
|
|
// Do nothing
|
|
case '/':
|
|
break;
|
|
|
|
default:
|
|
throw new Error('unhandled file: ' + shortPath);
|
|
}
|
|
|
|
this.queue(data);
|
|
this.queue(null);
|
|
});
|
|
}
|
|
|
|
gulp.task("bip39-" + locale, function() {
|
|
return browserify({
|
|
basedir: '.',
|
|
debug: false,
|
|
entries: [ 'src.ts/wordlists/lang-' + locale + ".ts" ],
|
|
cache: {},
|
|
packageCache: {},
|
|
transform: [ [ transformBip39, { global: true } ] ],
|
|
})
|
|
.plugin(tsify)
|
|
.bundle()
|
|
.pipe(source("wordlist-" + locale + ".js"))
|
|
.pipe(buffer())
|
|
.pipe(uglify())
|
|
.pipe(gulp.dest("dist"));
|
|
});
|
|
}
|
|
|
|
taskLang("it");
|
|
taskLang("ja");
|
|
taskLang("ko");
|
|
taskLang("zh");
|
|
|
|
// Package up all the test cases into tests/dist/tests.json
|
|
gulp.task("tests", function() {
|
|
|
|
function readShim(filename) {
|
|
return fs.readFileSync('./tests/' + filename + '.js').toString();
|
|
}
|
|
|
|
var transforms = {
|
|
"tests/utils-ethers.js": readShim('utils-ethers-browser')
|
|
}
|
|
|
|
// Create a mock-fs module that can load our gzipped test cases
|
|
var data = {};
|
|
|
|
fs.readdirSync('tests/tests').forEach(function(filename) {
|
|
if (!filename.match(/\.json\.gz$/)) { return; }
|
|
filename = 'tests/tests/' + filename;
|
|
data['/' + filename] = fs.readFileSync(filename).toString('base64');
|
|
});
|
|
|
|
fs.readdirSync('tests/tests/easyseed-bip39').forEach(function(filename) {
|
|
if (!filename.match(/\.json$/)) { return; }
|
|
filename = 'tests/tests/easyseed-bip39/' + filename;
|
|
data['/' + filename] = fs.readFileSync(filename).toString('base64');
|
|
});
|
|
|
|
fs.readdirSync('tests/wordlist-generation').forEach(function(filename) {
|
|
if (!filename.match(/\.txt$/)) { return; }
|
|
filename = 'tests/wordlist-generation/' + filename;
|
|
data['/' + filename] = fs.readFileSync(filename).toString('base64');
|
|
});
|
|
|
|
fs.writeFileSync('./tests/dist/tests.json', JSON.stringify(data));
|
|
|
|
return browserify({
|
|
basedir: './',
|
|
debug: false,
|
|
entries: [ "./tests/browser.js" ],
|
|
cache: {},
|
|
packageCache: {},
|
|
standalone: "tests",
|
|
transform: [ [ createTransform(transforms), { global: true } ] ],
|
|
})
|
|
.bundle()
|
|
.pipe(source("tests.js"))
|
|
.pipe(gulp.dest("tests/dist/"));
|
|
});
|
|
|
|
|