@exodus/ethereum-api 0.1.0 → 0.1.1

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.
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.fetchBalance = fetchBalance;
7
+ exports.fetchTxlist = fetchTxlist;
8
+ exports.fetchTxlistinternal = fetchTxlistinternal;
9
+ exports.tokenBalance = tokenBalance;
10
+
11
+ var _assert = _interopRequireDefault(require("assert"));
12
+
13
+ var _request2 = _interopRequireDefault(require("./request"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+
17
+ const isValidResponseCheck = x => x.status === '1' && x.message === 'OK' || x.message === 'No transactions found';
18
+
19
+ const _request = async (...args) => (0, _request2.default)(isValidResponseCheck, 'account', ...args);
20
+
21
+ async function fetchBalance(address) {
22
+ const balance = await _request('balance', {
23
+ address
24
+ });
25
+ const isValid = /^[0-9]+$/.test(balance);
26
+ if (!isValid) throw new RangeError(`Invalid balance: ${balance}`);
27
+ return balance;
28
+ }
29
+
30
+ async function fetchTxlist(address, options) {
31
+ const params = {
32
+ startblock: 0,
33
+ endblock: 'latest',
34
+ ...options,
35
+ address
36
+ };
37
+ const txlist = await _request('txlist', params); // simple check
38
+
39
+ (0, _assert.default)(Array.isArray(txlist), `Invalid transactions: ${txlist}`);
40
+ return txlist;
41
+ }
42
+
43
+ async function fetchTxlistinternal(address, options) {
44
+ const params = {
45
+ startblock: 0,
46
+ endblock: 'latest',
47
+ ...options,
48
+ address
49
+ };
50
+ const txlist = await _request('txlistinternal', params); // simple check
51
+
52
+ (0, _assert.default)(Array.isArray(txlist), `Invalid transactions: ${txlist}`);
53
+ return txlist;
54
+ }
55
+
56
+ async function tokenBalance(token, address) {
57
+ const params = {
58
+ [token.length === 42 ? 'contractaddress' : 'tokenname']: token,
59
+ address,
60
+ tag: 'latest'
61
+ };
62
+ const balance = await _request('tokenbalance', params);
63
+ const isValid = /^[0-9]+$/.test(balance);
64
+ if (!isValid) throw new RangeError(`Invalid balance: ${balance}`);
65
+ return balance;
66
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.filterTxsSent = filterTxsSent;
7
+ exports.filterTxsReceived = filterTxsReceived;
8
+ exports.ethCall = exports.ws = exports.setApiKey = exports.getLogs = exports.gasPrice = exports.getCode = exports.estimateGas = exports.getTransactionReceipt = exports.getTransactionCount = exports.sendRawTransaction = exports.tokenBalance = exports.fetchTxlistinternal = exports.fetchTxlist = exports.fetchBalance = exports.ETHERSCAN_WS_URL = void 0;
9
+
10
+ var _account = require("./account");
11
+
12
+ var _proxy = require("./proxy");
13
+
14
+ var _request = require("./request");
15
+
16
+ var _logs = require("./logs");
17
+
18
+ var _ws = _interopRequireDefault(require("./ws"));
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ const ETHERSCAN_WS_URL = 'wss://socket.etherscan.io/wshandler';
23
+ exports.ETHERSCAN_WS_URL = ETHERSCAN_WS_URL;
24
+ const fetchBalance = _account.fetchBalance;
25
+ exports.fetchBalance = fetchBalance;
26
+ const fetchTxlist = _account.fetchTxlist;
27
+ exports.fetchTxlist = fetchTxlist;
28
+ const fetchTxlistinternal = _account.fetchTxlistinternal;
29
+ exports.fetchTxlistinternal = fetchTxlistinternal;
30
+ const tokenBalance = _account.tokenBalance;
31
+ exports.tokenBalance = tokenBalance;
32
+ const sendRawTransaction = _proxy.sendRawTransaction;
33
+ exports.sendRawTransaction = sendRawTransaction;
34
+ const getTransactionCount = _proxy.getTransactionCount;
35
+ exports.getTransactionCount = getTransactionCount;
36
+ const getTransactionReceipt = _proxy.getTransactionReceipt;
37
+ exports.getTransactionReceipt = getTransactionReceipt;
38
+ const estimateGas = _proxy.estimateGas;
39
+ exports.estimateGas = estimateGas;
40
+ const getCode = _proxy.getCode;
41
+ exports.getCode = getCode;
42
+ const gasPrice = _proxy.gasPrice;
43
+ exports.gasPrice = gasPrice;
44
+ const getLogs = _logs.getLogs;
45
+ exports.getLogs = getLogs;
46
+ const setApiKey = _request.setEtherscanApiKey;
47
+ exports.setApiKey = setApiKey;
48
+ const ws = (0, _ws.default)(ETHERSCAN_WS_URL);
49
+ exports.ws = ws;
50
+ const ethCall = _proxy.ethCall;
51
+ exports.ethCall = ethCall;
52
+
53
+ function filterTxsSent(addr, etherscanTxs) {
54
+ return etherscanTxs.filter(tx => tx.from.toLowerCase() === addr.toLowerCase());
55
+ }
56
+
57
+ function filterTxsReceived(addr, etherscanTxs) {
58
+ return etherscanTxs.filter(tx => tx.to.toLowerCase() === addr.toLowerCase());
59
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getLogs = getLogs;
7
+
8
+ var _assert = _interopRequireDefault(require("assert"));
9
+
10
+ var _request2 = _interopRequireDefault(require("./request"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ const isValidResponseCheck = x => x.status === '1' && x.message === 'OK' || x.message === 'No records found';
15
+
16
+ const _request = async (...args) => (0, _request2.default)(isValidResponseCheck, 'logs', ...args);
17
+
18
+ async function getLogs(address, fromBlock, toBlock, options) {
19
+ const params = { ...options,
20
+ address,
21
+ fromBlock,
22
+ toBlock
23
+ };
24
+ const events = await _request('getLogs', params); // simple check
25
+
26
+ (0, _assert.default)(Array.isArray(events), `Invalid transactions: ${events}`);
27
+ return events;
28
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sendRawTransaction = sendRawTransaction;
7
+ exports.getTransactionCount = getTransactionCount;
8
+ exports.getTransactionReceipt = getTransactionReceipt;
9
+ exports.estimateGas = estimateGas;
10
+ exports.getCode = getCode;
11
+ exports.gasPrice = gasPrice;
12
+ exports.ethCall = ethCall;
13
+
14
+ var _request2 = _interopRequireDefault(require("./request"));
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ const isValidResponseCheck = x => x.result !== undefined;
19
+
20
+ const _request = async (...args) => (0, _request2.default)(isValidResponseCheck, 'proxy', ...args);
21
+
22
+ async function sendRawTransaction(data) {
23
+ const txhash = await _request('eth_sendRawTransaction', {
24
+ hex: '0x' + data
25
+ });
26
+ const isValidTxHash = /^0x[0-9a-fA-F]{64}$/.test(txhash);
27
+ if (!isValidTxHash) throw new Error(`Invalid tx hash: ${txhash}`);
28
+ return txhash.slice(2);
29
+ }
30
+
31
+ async function getTransactionCount(address) {
32
+ return _request('eth_getTransactionCount', {
33
+ address
34
+ });
35
+ }
36
+
37
+ async function getTransactionReceipt(txhash) {
38
+ return _request('eth_getTransactionReceipt', {
39
+ txhash
40
+ });
41
+ }
42
+
43
+ async function estimateGas(data) {
44
+ return _request('eth_estimateGas', data);
45
+ }
46
+
47
+ async function getCode(address) {
48
+ const code = await _request('eth_getCode', {
49
+ address
50
+ });
51
+ const isValidCode = /^0x[0-9a-fA-F]*$/.test(code) && code.length % 2 === 0;
52
+ if (!isValidCode) throw new Error(`Invalid address code: ${code}`);
53
+ return code;
54
+ }
55
+
56
+ async function gasPrice() {
57
+ const price = await _request('eth_gasPrice');
58
+ const isValidPrice = /^0x[0-9a-fA-F]+$/.test(price);
59
+ if (!isValidPrice) throw new Error(`Invalid price: ${price}`);
60
+ return price;
61
+ }
62
+
63
+ async function ethCall(data) {
64
+ return _request('eth_call', data);
65
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setEtherscanApiKey = setEtherscanApiKey;
7
+ exports.default = void 0;
8
+
9
+ var _ms = _interopRequireDefault(require("ms"));
10
+
11
+ var _makeConcurrent = _interopRequireDefault(require("make-concurrent"));
12
+
13
+ var _fetchival = _interopRequireDefault(require("fetchival"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+
17
+ // The module in desktop explicitly sets node-fetch. Do we need this?
18
+ // import fetch from '../fetch'
19
+ // fetchival.fetch = fetch
20
+ const ETHERSCAN_API_URL = 'https://api.etherscan.io/api';
21
+ const DEFAULT_ETHERSCAN_API_KEY = 'XM3VGRSNW1TMSIR14I9MVFP15X74GNHTRI';
22
+ let etherscanApiKey = DEFAULT_ETHERSCAN_API_KEY;
23
+
24
+ function setEtherscanApiKey(apiKey) {
25
+ etherscanApiKey = apiKey || DEFAULT_ETHERSCAN_API_KEY;
26
+ }
27
+
28
+ var _default = (0, _makeConcurrent.default)(async function (isValidResponseCheck, module, action, params = {}) {
29
+ const queryParams = { ...params,
30
+ module,
31
+ action,
32
+ apiKey: etherscanApiKey
33
+ };
34
+ const data = await (0, _fetchival.default)(ETHERSCAN_API_URL, {
35
+ timeout: (0, _ms.default)('15s')
36
+ }).get(queryParams);
37
+ if (!isValidResponseCheck(data)) throw new Error(`Invalid response: ${JSON.stringify(data)}`);
38
+ return data.result;
39
+ }, {
40
+ concurrency: 3
41
+ });
42
+
43
+ exports.default = _default;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = createWebSocket;
7
+
8
+ var _events = require("events");
9
+
10
+ var _ms = _interopRequireDefault(require("ms"));
11
+
12
+ var _websocket = _interopRequireDefault(require("../websocket"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const RECONNECT_INTERVAL = (0, _ms.default)('10s');
17
+ const PING_INTERVAL = (0, _ms.default)('20s');
18
+
19
+ function createWebSocket(url) {
20
+ const addresses = new Set();
21
+ const events = new _events.EventEmitter().setMaxListeners(20);
22
+ const pingMessage = JSON.stringify({
23
+ event: 'ping'
24
+ });
25
+ let ws;
26
+ let wsOpened = false;
27
+ let opened = false;
28
+ let openTimeoutId;
29
+ let pingIntervalId;
30
+
31
+ function subscribeAddress(address) {
32
+ const data = JSON.stringify({
33
+ event: 'txlist',
34
+ address
35
+ });
36
+ ws.send(data);
37
+ }
38
+
39
+ function onMessage(data) {
40
+ data = JSON.parse(data);
41
+
42
+ switch (data.event) {
43
+ case 'txlist':
44
+ for (const tx of data.result) events.emit(`address-${data.address}`, tx);
45
+
46
+ break;
47
+
48
+ case 'subscribe-txlist':
49
+ const match = data.message.toLowerCase().match(/0x[0-9a-f]{40}/);
50
+ if (match && data.status === '1') events.emit(`address-${match[0]}-subscribed`);else ws.close();
51
+ break;
52
+ }
53
+ }
54
+
55
+ function isOpened() {
56
+ return wsOpened;
57
+ }
58
+
59
+ function open() {
60
+ opened = true;
61
+ clearTimeout(openTimeoutId);
62
+ if (ws) return;
63
+ ws = new _websocket.default(url);
64
+ ws.on('message', data => {
65
+ try {
66
+ onMessage(data);
67
+ } catch (err) {}
68
+ });
69
+ ws.once('open', () => {
70
+ for (const address of addresses.values()) subscribeAddress(address);
71
+
72
+ pingIntervalId = setInterval(() => ws && ws.send(pingMessage), PING_INTERVAL);
73
+ wsOpened = true;
74
+ events.emit('open');
75
+ });
76
+ ws.once('close', () => {
77
+ ws = null;
78
+ clearInterval(pingIntervalId);
79
+ if (opened) openTimeoutId = setTimeout(open, RECONNECT_INTERVAL);
80
+ wsOpened = false;
81
+ events.emit('close');
82
+ });
83
+ }
84
+
85
+ function close() {
86
+ opened = false;
87
+ clearTimeout(openTimeoutId);
88
+ if (!ws) return;
89
+ ws.close();
90
+ ws = null;
91
+ }
92
+
93
+ function watch(address) {
94
+ address = address.toLowerCase();
95
+ if (addresses.has(address)) return;
96
+ addresses.add(address);
97
+ if (wsOpened) subscribeAddress(address);
98
+ }
99
+
100
+ return {
101
+ events,
102
+ isOpened,
103
+ open,
104
+ close,
105
+ watch
106
+ };
107
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.etc = exports.eth = void 0;
7
+
8
+ var _api = require("./api");
9
+
10
+ const EXODUS_ETH_SERVER_URL = 'https://eth.a.exodus.io/wallet/v1/';
11
+ const EXODUS_ETC_SERVER_URL = 'https://etc.a.exodus.io/wallet/v1/'; // allow self-signed certs
12
+ // process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
13
+
14
+ const eth = (0, _api.create)(EXODUS_ETH_SERVER_URL);
15
+ exports.eth = eth;
16
+ const etc = (0, _api.create)(EXODUS_ETC_SERVER_URL);
17
+ exports.etc = etc;
@@ -5,15 +5,16 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = createWebSocket;
7
7
 
8
- var _events = require("events");
8
+ var _ms = _interopRequireDefault(require("ms"));
9
9
 
10
- var _websocket = _interopRequireDefault(require("./websocket"));
10
+ var _events = require("events");
11
11
 
12
- var _ms = _interopRequireDefault(require("ms"));
12
+ var _websocket = _interopRequireDefault(require("../websocket"));
13
13
 
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
 
16
16
  const RECONNECT_INTERVAL = (0, _ms.default)('10s');
17
+ const PING_INTERVAL = (0, _ms.default)('10s');
17
18
 
18
19
  function createWebSocket(getURL) {
19
20
  const addresses = new Set();
@@ -70,7 +71,7 @@ function createWebSocket(getURL) {
70
71
  for (const address of addresses.values()) subscribeAddress(address);
71
72
 
72
73
  subscribeGasPrice();
73
- pingIntervalId = setInterval(() => ws.ping(), (0, _ms.default)('10s'));
74
+ pingIntervalId = setInterval(() => ws.ping(), PING_INTERVAL);
74
75
  events.emit('open');
75
76
  };
76
77
 
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ /* global fetch */
9
+ var _default = fetch; // fetch already exists in react-native
10
+
11
+ exports.default = _default;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ /* global fetch */
9
+ var _default = fetch; // fetch already exists in react-native
10
+
11
+ exports.default = _default;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ var _default = _nodeFetch.default;
13
+ exports.default = _default;
package/lib/index.js CHANGED
@@ -4,53 +4,40 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  var _exportNames = {
7
- eth: true,
8
- etc: true,
9
- createWebSocket: true
7
+ etherscan: true
10
8
  };
11
- Object.defineProperty(exports, "createWebSocket", {
12
- enumerable: true,
13
- get: function () {
14
- return _ws.default;
15
- }
16
- });
17
- exports.etc = exports.eth = void 0;
9
+ exports.etherscan = void 0;
10
+
11
+ var etherscan = _interopRequireWildcard(require("./etherscan"));
12
+
13
+ exports.etherscan = etherscan;
18
14
 
19
- var _api = require("./api");
15
+ var _withFallback = require("./with-fallback");
20
16
 
21
- Object.keys(_api).forEach(function (key) {
17
+ Object.keys(_withFallback).forEach(function (key) {
22
18
  if (key === "default" || key === "__esModule") return;
23
19
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
24
20
  Object.defineProperty(exports, key, {
25
21
  enumerable: true,
26
22
  get: function () {
27
- return _api[key];
23
+ return _withFallback[key];
28
24
  }
29
25
  });
30
26
  });
31
27
 
32
- var _withFallback = require("./with-fallback");
28
+ var _exodusEthServer = require("./exodus-eth-server");
33
29
 
34
- Object.keys(_withFallback).forEach(function (key) {
30
+ Object.keys(_exodusEthServer).forEach(function (key) {
35
31
  if (key === "default" || key === "__esModule") return;
36
32
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
37
33
  Object.defineProperty(exports, key, {
38
34
  enumerable: true,
39
35
  get: function () {
40
- return _withFallback[key];
36
+ return _exodusEthServer[key];
41
37
  }
42
38
  });
43
39
  });
44
40
 
45
- var _ws = _interopRequireDefault(require("./ws"));
46
-
47
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48
-
49
- const EXODUS_ETH_SERVER_URL = 'https://eth.a.exodus.io/wallet/v1/';
50
- const EXODUS_ETC_SERVER_URL = 'https://etc.a.exodus.io/wallet/v1/'; // allow self-signed certs
51
- // process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
41
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
52
42
 
53
- const eth = (0, _api.create)(EXODUS_ETH_SERVER_URL);
54
- exports.eth = eth;
55
- const etc = (0, _api.create)(EXODUS_ETC_SERVER_URL);
56
- exports.etc = etc;
43
+ 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; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Ethereum Api",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -14,10 +14,11 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "fetchival": "0.3.3",
17
+ "make-concurrent": "4.0.0",
17
18
  "ms": "^2.1.1",
18
19
  "url": "0.10.3",
19
20
  "url-join": "4.0.0",
20
21
  "ws": "6.1.0"
21
22
  },
22
- "gitHead": "4deb44ad3f254f99315cbc777ac758f7f443c821"
23
+ "gitHead": "8a2481e4de93011fe76652287b80500f1b5115aa"
23
24
  }
File without changes