From ae692d0a7ab517c85f0204b549b5b02e3f7b2d2e Mon Sep 17 00:00:00 2001 From: Will Scott Date: Fri, 22 Mar 2019 17:44:38 -0700 Subject: [PATCH] browser vs react-native --- lib/browser.js | 12 +++ lib/bytes-browser.js | 158 ++++++++++++++++++++++++++++++++++++++ lib/bytes.js | 3 +- package.json | 1 + src/browser.js | 13 ++++ src/bytes-browser.js | 177 +++++++++++++++++++++++++++++++++++++++++++ src/bytes.js | 8 +- 7 files changed, 363 insertions(+), 9 deletions(-) create mode 100644 lib/browser.js create mode 100644 lib/bytes-browser.js create mode 100644 src/browser.js create mode 100644 src/bytes-browser.js diff --git a/lib/browser.js b/lib/browser.js new file mode 100644 index 0000000..845aadb --- /dev/null +++ b/lib/browser.js @@ -0,0 +1,12 @@ +module.exports = { + account: require("./account.js"), + nat: require("./nat.js"), + bytes: require("./bytes-browser.js"), + hash: require("./hash.js"), + RLP: require("./rlp.js"), + abi: require("./abi.js"), + transaction: require("./transaction.js"), + rpc: require("./rpc.js"), + desubits: require("./desubits.js"), + passphrase: require("./passphrase.js") +}; \ No newline at end of file diff --git a/lib/bytes-browser.js b/lib/bytes-browser.js new file mode 100644 index 0000000..6b3c8a7 --- /dev/null +++ b/lib/bytes-browser.js @@ -0,0 +1,158 @@ +const A = require("./array.js"); + +const at = (bytes, index) => parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16); + +const random = bytes => { + let rnd; + if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) rnd = window.crypto.getRandomValues(new Uint8Array(bytes));else throw "Safe random numbers not available."; + let hex = "0x"; + for (let i = 0; i < bytes; ++i) hex += ("00" + rnd[i].toString(16)).slice(-2); + return hex; +}; + +const length = a => (a.length - 2) / 2; + +const flatten = a => "0x" + a.reduce((r, s) => r + s.slice(2), ""); + +const slice = (i, j, bs) => "0x" + bs.slice(i * 2 + 2, j * 2 + 2); + +const reverse = hex => { + let rev = "0x"; + for (let i = 0, l = length(hex); i < l; ++i) { + rev += hex.slice((l - i) * 2, (l - i + 1) * 2); + } + return rev; +}; + +const pad = (l, hex) => hex.length === l * 2 + 2 ? hex : pad(l, "0x" + "0" + hex.slice(2)); + +const padRight = (l, hex) => hex.length === l * 2 + 2 ? hex : padRight(l, hex + "0"); + +const toArray = hex => { + let arr = []; + for (let i = 2, l = hex.length; i < l; i += 2) arr.push(parseInt(hex.slice(i, i + 2), 16)); + return arr; +}; + +const fromArray = arr => { + let hex = "0x"; + for (let i = 0, l = arr.length; i < l; ++i) { + let b = arr[i]; + hex += (b < 16 ? "0" : "") + b.toString(16); + } + return hex; +}; + +const toUint8Array = hex => new Uint8Array(toArray(hex)); + +const fromUint8Array = arr => fromArray([].slice.call(arr, 0)); + +const fromNumber = num => { + let hex = num.toString(16); + return hex.length % 2 === 0 ? "0x" + hex : "0x0" + hex; +}; + +const toNumber = hex => parseInt(hex.slice(2), 16); + +const concat = (a, b) => a.concat(b.slice(2)); + +const fromNat = bn => bn === "0x0" ? "0x" : bn.length % 2 === 0 ? bn : "0x0" + bn.slice(2); + +const toNat = bn => bn[2] === "0" ? "0x" + bn.slice(3) : bn; + +const fromAscii = ascii => { + let hex = "0x"; + for (let i = 0; i < ascii.length; ++i) hex += ("00" + ascii.charCodeAt(i).toString(16)).slice(-2); + return hex; +}; + +const toAscii = hex => { + let ascii = ""; + for (let i = 2; i < hex.length; i += 2) ascii += String.fromCharCode(parseInt(hex.slice(i, i + 2), 16)); + return ascii; +}; + +// From https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 +const fromString = s => { + const makeByte = uint8 => { + const b = uint8.toString(16); + return b.length < 2 ? "0" + b : b; + }; + let bytes = "0x"; + for (let ci = 0; ci != s.length; ci++) { + let c = s.charCodeAt(ci); + if (c < 128) { + bytes += makeByte(c); + continue; + } + if (c < 2048) { + bytes += makeByte(c >> 6 | 192); + } else { + if (c > 0xd7ff && c < 0xdc00) { + if (++ci == s.length) return null; + let c2 = s.charCodeAt(ci); + if (c2 < 0xdc00 || c2 > 0xdfff) return null; + c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff); + bytes += makeByte(c >> 18 | 240); + bytes += makeByte(c >> 12 & 63 | 128); + } else { + // c <= 0xffff + bytes += makeByte(c >> 12 | 224); + } + bytes += makeByte(c >> 6 & 63 | 128); + } + bytes += makeByte(c & 63 | 128); + } + return bytes; +}; + +const toString = bytes => { + let s = ''; + let i = 0; + let l = length(bytes); + while (i < l) { + let c = at(bytes, i++); + if (c > 127) { + if (c > 191 && c < 224) { + if (i >= l) return null; + c = (c & 31) << 6 | at(bytes, i) & 63; + } else if (c > 223 && c < 240) { + if (i + 1 >= l) return null; + c = (c & 15) << 12 | (at(bytes, i) & 63) << 6 | at(bytes, ++i) & 63; + } else if (c > 239 && c < 248) { + if (i + 2 >= l) return null; + c = (c & 7) << 18 | (at(bytes, i) & 63) << 12 | (at(bytes, ++i) & 63) << 6 | at(bytes, ++i) & 63; + } else return null; + ++i; + } + if (c <= 0xffff) s += String.fromCharCode(c);else if (c <= 0x10ffff) { + c -= 0x10000; + s += String.fromCharCode(c >> 10 | 0xd800); + s += String.fromCharCode(c & 0x3FF | 0xdc00); + } else return null; + } + return s; +}; + +module.exports = { + random, + length, + concat, + flatten, + slice, + reverse, + pad, + padRight, + fromAscii, + toAscii, + fromString, + toString, + fromNumber, + toNumber, + fromNat, + toNat, + fromArray, + toArray, + fromUint8Array, + toUint8Array +}; \ No newline at end of file diff --git a/lib/bytes.js b/lib/bytes.js index 94c136c..79ebebb 100644 --- a/lib/bytes.js +++ b/lib/bytes.js @@ -3,8 +3,7 @@ const A = require("./array.js"); const at = (bytes, index) => parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16); const random = bytes => { - let rnd; - if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) rnd = window.crypto.getRandomValues(new Uint8Array(bytes));else if (typeof require !== "undefined") rnd = require("c" + "rypto").randomBytes(bytes);else throw "Safe random numbers not available."; + let rnd = require("crypto").randomBytes(bytes); let hex = "0x"; for (let i = 0; i < bytes; ++i) hex += ("00" + rnd[i].toString(16)).slice(-2); return hex; diff --git a/package.json b/package.json index 7c1f868..cb7ebbb 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.2.8", "description": "Lightweight Ethereum libraries", "main": "lib/index.js", + "browser": "lib/browser.js", "scripts": { "build": "babel src --out-dir=lib", "test": "mocha test/test.js" diff --git a/src/browser.js b/src/browser.js new file mode 100644 index 0000000..e7e06de --- /dev/null +++ b/src/browser.js @@ -0,0 +1,13 @@ +module.exports = { + account: require("./account.js"), + nat: require("./nat.js"), + bytes: require("./bytes-browser.js"), + hash: require("./hash.js"), + RLP: require("./rlp.js"), + abi: require("./abi.js"), + transaction: require("./transaction.js"), + rpc: require("./rpc.js"), + desubits: require("./desubits.js"), + passphrase: require("./passphrase.js") + } + \ No newline at end of file diff --git a/src/bytes-browser.js b/src/bytes-browser.js new file mode 100644 index 0000000..e859c3f --- /dev/null +++ b/src/bytes-browser.js @@ -0,0 +1,177 @@ +const A = require("./array.js"); + +const at = (bytes, index) => + parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16); + +const random = bytes => { + let rnd; + if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) + rnd = window.crypto.getRandomValues(new Uint8Array(bytes)); + else + throw "Safe random numbers not available."; + let hex = "0x"; + for (let i = 0; i < bytes; ++i) + hex += ("00" + rnd[i].toString(16)).slice(-2); + return hex; +}; + +const length = a => + (a.length - 2) / 2; + +const flatten = (a) => + "0x" + a.reduce((r,s) => r + s.slice(2), ""); + +const slice = (i,j,bs) => + "0x" + bs.slice(i*2+2,j*2+2); + +const reverse = hex => { + let rev = "0x"; + for (let i = 0, l = length(hex); i < l; ++i) { + rev += hex.slice((l-i)*2, (l-i+1)*2); + } + return rev; +} + +const pad = (l,hex) => + hex.length === l*2+2 ? hex : pad(l,"0x"+"0"+hex.slice(2)); + +const padRight = (l,hex) => + hex.length === l*2+2 ? hex : padRight(l,hex+"0"); + +const toArray = hex => { + let arr = []; + for (let i = 2, l = hex.length; i < l; i += 2) + arr.push(parseInt(hex.slice(i, i + 2), 16)); + return arr; +} + +const fromArray = arr => { + let hex = "0x"; + for (let i = 0, l = arr.length; i < l; ++i) { + let b = arr[i]; + hex += (b < 16 ? "0" : "") + b.toString(16); + } + return hex; +} + +const toUint8Array = hex => + new Uint8Array(toArray(hex)); + +const fromUint8Array = arr => + fromArray([].slice.call(arr, 0)); + +const fromNumber = num => { + let hex = num.toString(16); + return hex.length % 2 === 0 ? "0x" + hex : "0x0" + hex ; +}; + +const toNumber = hex => + parseInt(hex.slice(2), 16); + +const concat = (a, b) => + a.concat(b.slice(2)); + +const fromNat = bn => + bn === "0x0" ? "0x" : bn.length % 2 === 0 ? bn : "0x0" + bn.slice(2); + +const toNat = bn => + bn[2] === "0" ? "0x" + bn.slice(3) : bn; + +const fromAscii = ascii => { + let hex = "0x"; + for (let i = 0; i < ascii.length; ++i) + hex += ("00" + ascii.charCodeAt(i).toString(16)).slice(-2); + return hex; +}; + +const toAscii = hex => { + let ascii = ""; + for (let i = 2; i < hex.length; i += 2) + ascii += String.fromCharCode(parseInt(hex.slice(i, i + 2), 16)); + return ascii; +}; + +// From https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 +const fromString = s => { + const makeByte = uint8 => { + const b = uint8.toString(16); + return b.length < 2 ? "0" + b : b; + }; + let bytes = "0x"; + for (let ci = 0; ci != s.length; ci++) { + let c = s.charCodeAt(ci); + if (c < 128) { + bytes += makeByte(c); + continue; + } + if (c < 2048) { + bytes += makeByte(c >> 6 | 192); + } else { + if (c > 0xd7ff && c < 0xdc00) { + if (++ci == s.length) return null; + let c2 = s.charCodeAt(ci); + if (c2 < 0xdc00 || c2 > 0xdfff) return null; + c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff); + bytes += makeByte(c >> 18 | 240); + bytes += makeByte(c>> 12 & 63 | 128); + } else { // c <= 0xffff + bytes += makeByte(c >> 12 | 224); + } + bytes += makeByte(c >> 6 & 63 | 128); + } + bytes += makeByte(c & 63 | 128); + } + return bytes; +}; + +const toString = (bytes) => { + let s = ''; + let i = 0; + let l = length(bytes); + while (i < l) { + let c = at(bytes, i++); + if (c > 127) { + if (c > 191 && c < 224) { + if (i >= l) return null; + c = (c & 31) << 6 | at(bytes, i) & 63; + } else if (c > 223 && c < 240) { + if (i + 1 >= l) return null; + c = (c & 15) << 12 | (at(bytes, i) & 63) << 6 | at(bytes, ++i) & 63; + } else if (c > 239 && c < 248) { + if (i+2 >= l) return null; + c = (c & 7) << 18 | (at(bytes, i) & 63) << 12 | (at(bytes, ++i) & 63) << 6 | at(bytes, ++i) & 63; + } else return null; + ++i; + } + if (c <= 0xffff) s += String.fromCharCode(c); + else if (c <= 0x10ffff) { + c -= 0x10000; + s += String.fromCharCode(c >> 10 | 0xd800) + s += String.fromCharCode(c & 0x3FF | 0xdc00) + } else return null; + } + return s; +}; + +module.exports = { + random, + length, + concat, + flatten, + slice, + reverse, + pad, + padRight, + fromAscii, + toAscii, + fromString, + toString, + fromNumber, + toNumber, + fromNat, + toNat, + fromArray, + toArray, + fromUint8Array, + toUint8Array +} diff --git a/src/bytes.js b/src/bytes.js index 857da70..7572003 100644 --- a/src/bytes.js +++ b/src/bytes.js @@ -4,13 +4,7 @@ const at = (bytes, index) => parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16); const random = bytes => { - let rnd; - if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) - rnd = window.crypto.getRandomValues(new Uint8Array(bytes)); - else if (typeof require !== "undefined") - rnd = require("c" + "rypto").randomBytes(bytes); - else - throw "Safe random numbers not available."; + let rnd = require("crypto").randomBytes(bytes); let hex = "0x"; for (let i = 0; i < bytes; ++i) hex += ("00" + rnd[i].toString(16)).slice(-2);