@exodus/ethereum-lib 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/constants.js +11 -0
- package/lib/encode.js +21 -1
- package/lib/index.js +39 -0
- package/lib/unsigned-tx/create-and-sign-tx.js +17 -0
- package/lib/unsigned-tx/create-unsigned-tx.js +70 -0
- package/lib/unsigned-tx/index.js +39 -0
- package/lib/unsigned-tx/parse-unsigned-tx.js +69 -0
- package/lib/unsigned-tx/sign-unsigned-tx.js +25 -0
- package/lib/utils.js +47 -0
- package/package.json +6 -3
package/lib/constants.js
ADDED
package/lib/encode.js
CHANGED
|
@@ -4,8 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.validate = validate;
|
|
7
|
+
exports.hasChecksum = hasChecksum;
|
|
7
8
|
exports.encodePrivate = encodePrivate;
|
|
8
9
|
exports.encodePublic = encodePublic;
|
|
10
|
+
exports.isValidPrivate = isValidPrivate;
|
|
11
|
+
exports.encodePublicFromPrivate = encodePublicFromPrivate;
|
|
9
12
|
|
|
10
13
|
var _ethereumjsUtil = _interopRequireDefault(require("ethereumjs-util"));
|
|
11
14
|
|
|
@@ -15,10 +18,15 @@ function validate(address) {
|
|
|
15
18
|
if (typeof address !== 'string') return false; // https://github.com/ethereumjs/ethereumjs-util/issues/54
|
|
16
19
|
|
|
17
20
|
if (address.slice(0, 2) !== '0x' || address.length !== 42) return false;
|
|
18
|
-
if (
|
|
21
|
+
if (!hasChecksum(address)) return true;
|
|
19
22
|
return _ethereumjsUtil.default.isValidChecksumAddress(address);
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
function hasChecksum(address) {
|
|
26
|
+
if (/^0x[0-9A-F]{40}$/.test(address) || /^0x[0-9a-f]{40}$/.test(address)) return false;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
function encodePrivate(privKey) {
|
|
23
31
|
return '0x' + privKey.toString('hex');
|
|
24
32
|
}
|
|
@@ -27,4 +35,16 @@ function encodePublic(compressedPubKey) {
|
|
|
27
35
|
const hash160bits = _ethereumjsUtil.default.publicToAddress(compressedPubKey, true);
|
|
28
36
|
|
|
29
37
|
return _ethereumjsUtil.default.toChecksumAddress(hash160bits.toString('hex'));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isValidPrivate(privateKey) {
|
|
41
|
+
if (privateKey.length !== 32 || !_ethereumjsUtil.default.isValidPrivate(privateKey)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function encodePublicFromPrivate(privateKey) {
|
|
49
|
+
return _ethereumjsUtil.default.toChecksumAddress(_ethereumjsUtil.default.privateToAddress(privateKey).toString('hex'));
|
|
30
50
|
}
|
package/lib/index.js
CHANGED
|
@@ -37,4 +37,43 @@ Object.keys(_encode).forEach(function (key) {
|
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
var _unsignedTx = require("./unsigned-tx");
|
|
41
|
+
|
|
42
|
+
Object.keys(_unsignedTx).forEach(function (key) {
|
|
43
|
+
if (key === "default" || key === "__esModule") return;
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
45
|
+
Object.defineProperty(exports, key, {
|
|
46
|
+
enumerable: true,
|
|
47
|
+
get: function () {
|
|
48
|
+
return _unsignedTx[key];
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
var _utils = require("./utils");
|
|
54
|
+
|
|
55
|
+
Object.keys(_utils).forEach(function (key) {
|
|
56
|
+
if (key === "default" || key === "__esModule") return;
|
|
57
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
58
|
+
Object.defineProperty(exports, key, {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
get: function () {
|
|
61
|
+
return _utils[key];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
var _constants = require("./constants");
|
|
67
|
+
|
|
68
|
+
Object.keys(_constants).forEach(function (key) {
|
|
69
|
+
if (key === "default" || key === "__esModule") return;
|
|
70
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
71
|
+
Object.defineProperty(exports, key, {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
get: function () {
|
|
74
|
+
return _constants[key];
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
40
79
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = createAndSignTx;
|
|
7
|
+
|
|
8
|
+
var _createUnsignedTx = _interopRequireDefault(require("./create-unsigned-tx"));
|
|
9
|
+
|
|
10
|
+
var _signUnsignedTx = _interopRequireDefault(require("./sign-unsigned-tx"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
function createAndSignTx(input, privateKey) {
|
|
15
|
+
const unsignedTx = (0, _createUnsignedTx.default)(input);
|
|
16
|
+
return (0, _signUnsignedTx.default)(unsignedTx, privateKey);
|
|
17
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = createUnsignedTx;
|
|
7
|
+
|
|
8
|
+
var _ethereumjsUtil = _interopRequireDefault(require("ethereumjs-util"));
|
|
9
|
+
|
|
10
|
+
var _utils = require("../utils");
|
|
11
|
+
|
|
12
|
+
var _constants = require("../constants");
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
function createUnsignedTx({
|
|
17
|
+
baseAsset,
|
|
18
|
+
asset,
|
|
19
|
+
address,
|
|
20
|
+
amount,
|
|
21
|
+
nonce,
|
|
22
|
+
txInput,
|
|
23
|
+
gasLimit,
|
|
24
|
+
gasPrice,
|
|
25
|
+
privateKey,
|
|
26
|
+
fromAddress,
|
|
27
|
+
chainId
|
|
28
|
+
}) {
|
|
29
|
+
if (txInput) {
|
|
30
|
+
txInput = _ethereumjsUtil.default.toBuffer(txInput); // If txInput is already a Buffer, then it is passed through
|
|
31
|
+
} else {
|
|
32
|
+
txInput = Buffer.alloc(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!chainId) chainId = _constants.CHAIN_IDS[baseAsset.name]; // mainnet
|
|
36
|
+
|
|
37
|
+
const isEthereumToken = (0, _utils._isEthereumToken)(asset);
|
|
38
|
+
const to = isEthereumToken ? asset.contract.addresses.current : address;
|
|
39
|
+
let value = (0, _utils.currency2buffer)(isEthereumToken ? baseAsset.currency.ZERO : amount); // TODO: check: present on desktop missing on mobile. This insures we never have a buffer specifying 0.
|
|
40
|
+
// In ETH, a buffer of zero length and a buffer specifying 0 imply different things
|
|
41
|
+
|
|
42
|
+
if (value.equals(Buffer.from([0]))) value = Buffer.alloc(0);
|
|
43
|
+
|
|
44
|
+
if (!fromAddress) {
|
|
45
|
+
if (privateKey) fromAddress = _ethereumjsUtil.default.bufferToHex(_ethereumjsUtil.default.privateToAddress(privateKey));else throw new Error('createTx: Must pass fromAddress or privateKey in options');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const txData = {
|
|
49
|
+
nonce: nonce === 0 ? Buffer.alloc(0) : _ethereumjsUtil.default.intToBuffer(nonce),
|
|
50
|
+
// mobile: { nonce: ethUtil.intToBuffer(nonce) }
|
|
51
|
+
gasPrice: (0, _utils.currency2buffer)(gasPrice.toBase()),
|
|
52
|
+
// mobile: { gasPrice: currency2buffer(gasPrice) }
|
|
53
|
+
gasLimit: _ethereumjsUtil.default.intToBuffer(gasLimit),
|
|
54
|
+
to,
|
|
55
|
+
value,
|
|
56
|
+
data: txInput,
|
|
57
|
+
chainId
|
|
58
|
+
};
|
|
59
|
+
const txMeta = {
|
|
60
|
+
assetName: asset.name,
|
|
61
|
+
// TODO: We should move away from putting the PK into txMeta, it is a bad practice. It is a potential PK exposure risk if the wrong PK gets included here.
|
|
62
|
+
privateKey,
|
|
63
|
+
// Used for importing private key
|
|
64
|
+
fee: baseAsset.currency.baseUnit(gasPrice.toBase().toNumber() * gasLimit)
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
txData,
|
|
68
|
+
txMeta
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "createUnsignedTx", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _createUnsignedTx.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "parseUnsignedTx", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _parseUnsignedTx.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "signUnsignedTx", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _signUnsignedTx.default;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "createAndSignTx", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _createAndSignTx.default;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
var _createUnsignedTx = _interopRequireDefault(require("./create-unsigned-tx"));
|
|
32
|
+
|
|
33
|
+
var _parseUnsignedTx = _interopRequireDefault(require("./parse-unsigned-tx"));
|
|
34
|
+
|
|
35
|
+
var _signUnsignedTx = _interopRequireDefault(require("./sign-unsigned-tx"));
|
|
36
|
+
|
|
37
|
+
var _createAndSignTx = _interopRequireDefault(require("./create-and-sign-tx"));
|
|
38
|
+
|
|
39
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = parseUnsignedTx;
|
|
7
|
+
|
|
8
|
+
var ethUtil = _interopRequireWildcard(require("ethereumjs-util"));
|
|
9
|
+
|
|
10
|
+
var _assets = _interopRequireDefault(require("@exodus/assets"));
|
|
11
|
+
|
|
12
|
+
var _utils = require("../utils");
|
|
13
|
+
|
|
14
|
+
var _constants = require("../constants");
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
19
|
+
|
|
20
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
21
|
+
|
|
22
|
+
function parseUnsignedTx(unsignedTx) {
|
|
23
|
+
const {
|
|
24
|
+
txData,
|
|
25
|
+
txMeta: {
|
|
26
|
+
assetName
|
|
27
|
+
}
|
|
28
|
+
} = unsignedTx;
|
|
29
|
+
const asset = _assets.default[assetName];
|
|
30
|
+
const isEthereumToken = (0, _utils._isEthereumToken)(asset);
|
|
31
|
+
const baseAsset = isEthereumToken ? _assets.default.ethereum : asset;
|
|
32
|
+
const gasPrice = (0, _utils.buffer2currency)({
|
|
33
|
+
asset: baseAsset,
|
|
34
|
+
value: txData.gasPrice
|
|
35
|
+
});
|
|
36
|
+
const gasLimit = ethUtil.bufferToInt(txData.gasLimit);
|
|
37
|
+
let {
|
|
38
|
+
to,
|
|
39
|
+
chainId,
|
|
40
|
+
data
|
|
41
|
+
} = txData;
|
|
42
|
+
let amount;
|
|
43
|
+
const fee = gasPrice.mul(gasLimit);
|
|
44
|
+
|
|
45
|
+
if (isEthereumToken) {
|
|
46
|
+
const parsed = asset.contract.transfer.parse(data);
|
|
47
|
+
to = parsed.to;
|
|
48
|
+
amount = parsed.amount;
|
|
49
|
+
} else {
|
|
50
|
+
amount = (0, _utils.buffer2currency)({
|
|
51
|
+
asset: baseAsset,
|
|
52
|
+
value: txData.value
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (chainId !== _constants.CHAIN_IDS[baseAsset.name]) {
|
|
57
|
+
throw new Error(`invalid chainId ${chainId} for asset ${assetName}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
baseAsset,
|
|
62
|
+
asset,
|
|
63
|
+
from: null,
|
|
64
|
+
// TODO: how?
|
|
65
|
+
to,
|
|
66
|
+
amount,
|
|
67
|
+
fee
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = signUnsignedTx;
|
|
7
|
+
|
|
8
|
+
var _ethereumjsTx = _interopRequireDefault(require("ethereumjs-tx"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
function signUnsignedTx(unsignedTx, privateKey) {
|
|
13
|
+
const {
|
|
14
|
+
txData
|
|
15
|
+
} = unsignedTx;
|
|
16
|
+
const tx = new _ethereumjsTx.default(txData);
|
|
17
|
+
tx.sign(privateKey); // serialize and get txId
|
|
18
|
+
|
|
19
|
+
const rawTx = tx.serialize();
|
|
20
|
+
const txId = tx.hash().toString('hex');
|
|
21
|
+
return {
|
|
22
|
+
rawTx,
|
|
23
|
+
txId
|
|
24
|
+
};
|
|
25
|
+
}
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buffer2currency = buffer2currency;
|
|
7
|
+
exports.currency2buffer = currency2buffer;
|
|
8
|
+
exports._isEthereumToken = void 0;
|
|
9
|
+
|
|
10
|
+
var _baseX = _interopRequireDefault(require("base-x"));
|
|
11
|
+
|
|
12
|
+
var ethUtil = _interopRequireWildcard(require("ethereumjs-util"));
|
|
13
|
+
|
|
14
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
15
|
+
|
|
16
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
const base10 = (0, _baseX.default)('0123456789');
|
|
21
|
+
const base16 = (0, _baseX.default)('0123456789abcdef');
|
|
22
|
+
|
|
23
|
+
const _isEthereumToken = asset => asset.assetType === 'ETHEREUM_ERC20';
|
|
24
|
+
|
|
25
|
+
exports._isEthereumToken = _isEthereumToken;
|
|
26
|
+
|
|
27
|
+
function buffer2currency({
|
|
28
|
+
asset,
|
|
29
|
+
value
|
|
30
|
+
}) {
|
|
31
|
+
return asset.currency.baseUnit(base10.encode(value)).toDefault();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function currency2buffer(value) {
|
|
35
|
+
const b10Value = value.toBase().floor() // probably not necessary, but to be safe
|
|
36
|
+
.toString({
|
|
37
|
+
unit: false
|
|
38
|
+
});
|
|
39
|
+
const hexValue = base16.encode(base10.decode(b10Value));
|
|
40
|
+
|
|
41
|
+
if (hexValue.includes('.')) {
|
|
42
|
+
// <-- probably not necessary anymore
|
|
43
|
+
throw new RangeError(`${value.toBase().toString()} can not be converted to Buffer`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return Buffer.from(ethUtil.padToEven(hexValue), 'hex');
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Ethereum Library",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -14,10 +14,13 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@exodus/asset-lib": "^3.2.0",
|
|
17
|
+
"@exodus/models": "^8.2.0",
|
|
18
|
+
"base-x": "3.0.4",
|
|
19
|
+
"ethereumjs-tx": "1.3.7",
|
|
17
20
|
"ethereumjs-util": "5.2.0"
|
|
18
21
|
},
|
|
19
22
|
"devDependencies": {
|
|
20
|
-
"@exodus/assets": "
|
|
23
|
+
"@exodus/assets": "8.0.x"
|
|
21
24
|
},
|
|
22
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "c4340f5add8720d732046aa58488b71cdc092678"
|
|
23
26
|
}
|