2018-06-14 02:25:56 -04:00
'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' ) ;
2018-08-02 17:56:50 -04:00
function createTransform ( transforms , show ) {
if ( ! show ) { show = { } ; }
2018-07-23 02:56:40 -04:00
function padding ( length ) {
let pad = '' ;
while ( pad . length < length ) { pad += ' ' ; }
return pad ;
}
2018-06-21 20:24:30 -04:00
2018-07-23 02:56:40 -04:00
function transformFile ( path ) {
for ( var pattern in transforms ) {
if ( path . match ( new RegExp ( '/' + pattern + '$' ) ) ) {
return transforms [ pattern ] ;
}
}
return null ;
}
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
return function ( path , options ) {
var data = '' ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
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 ) {
2018-08-02 17:56:50 -04:00
if ( show . transformed ) {
console . log ( 'Transformed:' , shortPath , padding ( 70 - shortPath . length ) , size , padding ( 6 - String ( size ) . length ) , '=>' , transformed . length ) ;
}
2018-07-23 02:56:40 -04:00
data = transformed ;
2018-09-27 16:47:44 -04:00
} else if ( shortPath === '/src.ts/utils/wordlist.ts' ) {
2018-07-23 02:56:40 -04:00
data += '\n\nexportWordlist = true;'
2018-08-02 17:56:50 -04:00
if ( show . transformed ) {
console . log ( 'Transformed:' , shortPath , padding ( 70 - shortPath . length ) , size , padding ( 6 - String ( size ) . length ) , '=>' , data . length ) ;
}
2018-07-23 02:56:40 -04:00
} else {
2018-08-02 17:56:50 -04:00
if ( show . preserved ) {
console . log ( 'Preserved: ' , shortPath , padding ( 70 - shortPath . length ) , size ) ;
}
2018-07-23 02:56:40 -04:00
}
this . queue ( data ) ;
this . queue ( null ) ;
} ) ;
}
}
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
/ * *
* 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 ) {
2018-08-02 17:56:50 -04:00
var show = options . show || { } ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
// The elliptic package.json is only used for its version
var ellipticPackage = require ( 'elliptic/package.json' ) ;
ellipticPackage = JSON . stringify ( { version : ellipticPackage . version } ) ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
var version = require ( './package.json' ) . version ;
2018-06-18 05:42:41 -04:00
2018-07-23 02:56:40 -04:00
var undef = "module.exports = undefined;" ;
var empty = "module.exports = {};" ;
2018-06-14 02:25:56 -04:00
2018-07-30 18:59:52 -04:00
// 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; }" ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
// 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 }; " ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
function readShim ( filename ) {
return fs . readFileSync ( './shims/' + filename + '.js' ) . toString ( ) ;
}
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
var transforms = {
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
// Remove the precomputed secp256k1 points
"elliptic/lib/elliptic/precomputed/secp256k1.js" : undef ,
2018-06-24 04:03:21 -04:00
2018-07-23 02:56:40 -04:00
// Remove curves we don't care about
"elliptic/curve/edwards.js" : empty ,
"elliptic/curve/mont.js" : empty ,
"elliptic/lib/elliptic/eddsa/.*" : empty ,
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
// We only use the version from this JSON package
"elliptic/package.json" : ellipticPackage ,
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
// Remove RIPEMD160 and unneeded hashing algorithms
2019-02-01 18:39:50 -05:00
//"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
2018-07-23 02:56:40 -04:00
"hash.js/lib/hash/sha/1.js" : empty ,
"hash.js/lib/hash/sha/224.js" : empty ,
"hash.js/lib/hash/sha/384.js" : empty ,
2018-06-20 20:29:54 -04:00
2018-07-23 02:56:40 -04:00
// Swap out borland for the random bytes we already have
"brorand/index.js" : brorand ,
2018-06-20 20:29:54 -04:00
2018-07-23 02:56:40 -04:00
"xmlhttprequest/lib/XMLHttpRequest.js" : readShim ( "xmlhttprequest" ) ,
2018-06-20 20:29:54 -04:00
2018-07-23 02:56:40 -04:00
// Used by sha3 if it exists; (so make it no exist)
"process/browser.js" : process ,
"timers-browserify/main.js" : timers ,
2018-06-20 20:29:54 -04:00
2018-07-23 02:56:40 -04:00
"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" ) ,
2018-06-21 20:24:30 -04:00
2018-07-23 02:56:40 -04:00
} ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
gulp . task ( name , function ( ) {
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
var result = browserify ( {
basedir : '.' ,
debug : false ,
entries : [ './index.js' ] ,
cache : { } ,
packageCache : { } ,
standalone : "ethers" ,
2018-08-02 17:56:50 -04:00
transform : [ [ createTransform ( transforms , show ) , { global : true } ] ] ,
2018-07-23 02:56:40 -04:00
} )
. bundle ( )
. pipe ( source ( options . filename ) )
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
if ( options . minify ) {
result = result . pipe ( buffer ( ) )
. pipe ( sourcemaps . init ( { loadMaps : true } ) )
2018-11-09 14:36:21 -05:00
. pipe ( uglify ( {
output : { ascii _only : true }
} ) )
2018-07-23 02:56:40 -04:00
. pipe ( sourcemaps . write ( './' ) )
}
2018-06-14 02:25:56 -04:00
2018-08-01 18:05:19 -04:00
result = result . pipe ( gulp . dest ( options . dest ) ) ;
2018-06-14 02:25:56 -04:00
2018-07-23 02:56:40 -04:00
return result ;
} ) ;
2018-06-14 02:25:56 -04:00
}
2018-06-14 05:38:37 -04:00
// Creates dist/ethers.js
2018-08-02 17:56:50 -04:00
taskBundle ( "default" , { filename : "ethers.js" , dest : 'dist' , show : { transformed : true , preserved : true } , minify : false } ) ;
2018-08-01 18:05:19 -04:00
// Creates dist/ethers.js
2018-08-02 17:56:50 -04:00
taskBundle ( "default-test" , { filename : "ethers.js" , dest : 'tests/dist' , show : { transformed : true } , minify : false } ) ;
2018-08-01 18:05:19 -04:00
// Creates dist/ethers.min.js
taskBundle ( "minified" , { filename : "ethers.min.js" , dest : 'dist' , minify : true } ) ;
2018-06-14 05:38:37 -04:00
2018-06-18 05:42:41 -04:00
// Creates dist/ethers.min.js
2018-08-01 18:05:19 -04:00
taskBundle ( "minified-test" , { filename : "ethers.min.js" , dest : 'tests/dist' , minify : true } ) ;
2018-06-14 02:25:56 -04:00
2018-11-08 18:25:16 -05:00
gulp . task ( 'shims' , function ( ) {
var result = browserify ( {
basedir : '.' ,
debug : false ,
entries : [ './tests/shims/index.js' ] ,
cache : { } ,
packageCache : { } ,
standalone : "_shims" ,
insertGlobalVars : {
process : function ( ) { return ; } ,
}
} )
. bundle ( )
. pipe ( source ( 'shims.js' ) )
. pipe ( buffer ( ) )
2018-11-09 14:36:21 -05:00
. pipe ( uglify ( {
output : { ascii _only : true }
} ) )
2018-11-08 18:25:16 -05:00
. pipe ( gulp . dest ( 'dist' ) ) ;
return result ;
} ) ;
2018-07-30 18:59:52 -04:00
/ *
2018-07-23 19:21:42 -04:00
// Dump the TypeScript definitions to dist/types/
gulp . task ( "types" , function ( ) {
2018-07-30 18:59:52 -04:00
return gulp . src ( [ './src.ts/index.ts' , './src.ts / * * / * . ts' ] )
2018-06-20 20:29:54 -04:00
. pipe ( ts ( {
declaration : true ,
esModuleInterop : true ,
moduleResolution : "node" ,
lib : [ "es2015" , "es5" , "dom" ] ,
2018-06-24 04:03:21 -04:00
module : "commonjs" ,
2018-07-30 18:59:52 -04:00
outDir : './dist/types' ,
2018-06-24 04:03:21 -04:00
target : "es5" ,
2018-06-20 20:29:54 -04:00
} ) )
. dts
2018-07-30 18:59:52 -04:00
. pipe ( gulp . dest ( "dist/types/" ) )
2018-06-20 20:29:54 -04:00
} ) ;
2018-07-30 18:59:52 -04:00
* /
2018-06-20 20:29:54 -04:00
2018-06-21 20:24:30 -04:00
/ * *
* Browser Friendly BIP39 Wordlists
*
* source : src . ts / wordlist / lang - * . ts
* target : dist / wordlist - * . js
*
2018-07-23 02:56:40 -04:00
* 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 .
2018-06-21 20:24:30 -04:00
* /
2018-06-20 20:29:54 -04:00
function taskLang ( locale ) {
2018-07-23 02:56:40 -04:00
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 ) {
2018-09-27 16:47:44 -04:00
// Use the existing "ethers.errors"
case '/src.ts/errors.ts' :
data = "module.exports = global.ethers.errors" ;
2018-07-23 02:56:40 -04:00
break ;
2018-09-27 16:47:44 -04:00
// Use the existing "ethers.utils"
2018-07-23 02:56:40 -04:00
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 ;
2018-09-27 16:47:44 -04:00
// 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 ;
2018-07-23 02:56:40 -04:00
default :
throw new Error ( 'unhandled file: ' + shortPath ) ;
}
this . queue ( data ) ;
this . queue ( null ) ;
} ) ;
}
2018-06-20 20:29:54 -04:00
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 ( ) )
2018-11-09 14:36:21 -05:00
. pipe ( uglify ( {
output : { ascii _only : true }
} ) )
2018-06-20 20:29:54 -04:00
. pipe ( gulp . dest ( "dist" ) ) ;
} ) ;
}
2018-10-03 19:58:45 -04:00
taskLang ( "es" ) ;
taskLang ( "fr" ) ;
2018-06-20 20:29:54 -04:00
taskLang ( "it" ) ;
taskLang ( "ja" ) ;
taskLang ( "ko" ) ;
taskLang ( "zh" ) ;
2018-06-14 02:25:56 -04:00
2018-06-14 05:38:37 -04:00
// Package up all the test cases into tests/dist/tests.json
2018-06-14 02:25:56 -04:00
gulp . task ( "tests" , function ( ) {
2018-07-23 02:56:40 -04:00
function readShim ( filename ) {
return fs . readFileSync ( './tests/' + filename + '.js' ) . toString ( ) ;
}
var transforms = {
"tests/utils-ethers.js" : readShim ( 'utils-ethers-browser' )
}
2018-06-14 02:25:56 -04:00
// Create a mock-fs module that can load our gzipped test cases
var data = { } ;
2018-06-20 20:29:54 -04:00
2018-06-14 02:25:56 -04:00
fs . readdirSync ( 'tests/tests' ) . forEach ( function ( filename ) {
if ( ! filename . match ( /\.json\.gz$/ ) ) { return ; }
filename = 'tests/tests/' + filename ;
data [ '/' + filename ] = fs . readFileSync ( filename ) . toString ( 'base64' ) ;
} ) ;
2018-06-20 20:29:54 -04:00
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' ) ;
} ) ;
2018-07-16 00:25:13 -04:00
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' ) ;
} ) ;
2018-06-14 02:25:56 -04:00
fs . writeFileSync ( './tests/dist/tests.json' , JSON . stringify ( data ) ) ;
return browserify ( {
basedir : './' ,
debug : false ,
entries : [ "./tests/browser.js" ] ,
cache : { } ,
packageCache : { } ,
2018-07-23 02:56:40 -04:00
standalone : "tests" ,
transform : [ [ createTransform ( transforms ) , { global : true } ] ] ,
2018-06-14 02:25:56 -04:00
} )
. bundle ( )
. pipe ( source ( "tests.js" ) )
. pipe ( gulp . dest ( "tests/dist/" ) ) ;
} ) ;
2018-06-14 05:38:37 -04:00