@certik/skynet 0.10.7 → 0.10.10

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/snowflake.js CHANGED
@@ -1,36 +1,36 @@
1
- const snowflake = require("snowflake-sdk");
2
- const { promisify } = require("util");
3
- const { ensureAndGet } = require("./env");
4
-
5
- async function getConnection(options) {
6
- const connection = snowflake.createConnection({
7
- account: ensureAndGet("SKYNET_SNOWFLAKE_ACCOUNT"),
8
- username: ensureAndGet("SKYNET_SNOWFLAKE_USERNAME"),
9
- password: ensureAndGet("SKYNET_SNOWFLAKE_PASSWORD"),
10
- ...options,
11
- });
12
- return await promisify(connection.connect).bind(connection)();
13
- }
14
-
15
- async function executeSql(options, sql, binds) {
16
- const connection = await getConnection(options);
17
- return await new Promise((resolve, reject) => {
18
- connection.execute({
19
- sqlText: sql,
20
- binds: binds,
21
- complete: (err, statement, rows) => {
22
- // console.log(statement.getSqlText());
23
- if (err) {
24
- reject(err);
25
- } else {
26
- resolve(rows);
27
- }
28
- },
29
- });
30
- });
31
- }
32
-
33
- module.exports = {
34
- getConnection,
35
- executeSql,
36
- };
1
+ const snowflake = require("snowflake-sdk");
2
+ const { promisify } = require("util");
3
+ const { ensureAndGet } = require("./env");
4
+
5
+ async function getConnection(options) {
6
+ const connection = snowflake.createConnection({
7
+ account: ensureAndGet("SKYNET_SNOWFLAKE_ACCOUNT"),
8
+ username: ensureAndGet("SKYNET_SNOWFLAKE_USERNAME"),
9
+ password: ensureAndGet("SKYNET_SNOWFLAKE_PASSWORD"),
10
+ ...options,
11
+ });
12
+ return await promisify(connection.connect).bind(connection)();
13
+ }
14
+
15
+ async function executeSql(options, sql, binds) {
16
+ const connection = await getConnection(options);
17
+ return await new Promise((resolve, reject) => {
18
+ connection.execute({
19
+ sqlText: sql,
20
+ binds: binds,
21
+ complete: (err, statement, rows) => {
22
+ // console.log(statement.getSqlText());
23
+ if (err) {
24
+ reject(err);
25
+ } else {
26
+ resolve(rows);
27
+ }
28
+ },
29
+ });
30
+ });
31
+ }
32
+
33
+ module.exports = {
34
+ getConnection,
35
+ executeSql,
36
+ };
package/sqs.js CHANGED
@@ -1,12 +1,12 @@
1
- const { SQS } = require("aws-sdk");
2
- const { getAWSAccessKeyId, getAWSSecretAccessKey, getAWSRegion } = require("./env");
3
-
4
- function getSQS() {
5
- return new SQS({
6
- accessKeyId: getAWSAccessKeyId(),
7
- secretAccessKey: getAWSSecretAccessKey(),
8
- region: getAWSRegion(),
9
- });
10
- }
11
-
12
- module.exports = { getSQS };
1
+ const { SQS } = require("aws-sdk");
2
+ const { getAWSAccessKeyId, getAWSSecretAccessKey, getAWSRegion } = require("./env");
3
+
4
+ function getSQS() {
5
+ return new SQS({
6
+ accessKeyId: getAWSAccessKeyId(),
7
+ secretAccessKey: getAWSSecretAccessKey(),
8
+ region: getAWSRegion(),
9
+ });
10
+ }
11
+
12
+ module.exports = { getSQS };
package/token.js CHANGED
@@ -1,46 +1,46 @@
1
- const { getEnvironment } = require("./env");
2
- const { getPriceClosestTo } = require("./price");
3
- const BigNumber = require("bignumber.js");
4
-
5
- const TOKEN_PRICE_TABLE_NAME = `skynet-${getEnvironment()}-token-prices`;
6
- const TOKEN_PRICE_CACHE = {};
7
-
8
- async function getTokenPriceAt(tokenAddress, timestamp, useCache = true) {
9
- // to avoid huge amount of dynamodb query
10
- // "ceil" timestamp to the closest proximate timestamp
11
- // 100_000 seconds ~= a bit more than 1 day 86_400 seconds
12
- // and use cache
13
- const proximateTimestamp = timestamp + 100_000 - (timestamp % 100_000);
14
-
15
- if (useCache && TOKEN_PRICE_CACHE[tokenAddress] && TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp]) {
16
- return TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp];
17
- }
18
-
19
- const price = await getPriceClosestTo(TOKEN_PRICE_TABLE_NAME, tokenAddress, proximateTimestamp);
20
-
21
- if (useCache) {
22
- if (!TOKEN_PRICE_CACHE[tokenAddress]) {
23
- TOKEN_PRICE_CACHE[tokenAddress] = {};
24
- }
25
-
26
- TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp] = price;
27
- }
28
-
29
- return price;
30
- }
31
-
32
- function toNativeDecimal(bigNumber, decimals) {
33
- const dividend = new BigNumber(10).exponentiatedBy(new BigNumber(decimals));
34
- return new BigNumber(bigNumber).multipliedBy(dividend);
35
- }
36
-
37
- function toHumanDecimal(bigNumber, decimals) {
38
- const dividend = new BigNumber(10).exponentiatedBy(new BigNumber(decimals));
39
- return new BigNumber(bigNumber).dividedBy(dividend);
40
- }
41
-
42
- module.exports = {
43
- getTokenPriceAt,
44
- toNativeDecimal,
45
- toHumanDecimal,
46
- };
1
+ const { getEnvironment } = require("./env");
2
+ const { getPriceClosestTo } = require("./price");
3
+ const BigNumber = require("bignumber.js");
4
+
5
+ const TOKEN_PRICE_TABLE_NAME = `skynet-${getEnvironment()}-token-prices`;
6
+ const TOKEN_PRICE_CACHE = {};
7
+
8
+ async function getTokenPriceAt(tokenAddress, timestamp, useCache = true) {
9
+ // to avoid huge amount of dynamodb query
10
+ // "ceil" timestamp to the closest proximate timestamp
11
+ // 100_000 seconds ~= a bit more than 1 day 86_400 seconds
12
+ // and use cache
13
+ const proximateTimestamp = timestamp + 100_000 - (timestamp % 100_000);
14
+
15
+ if (useCache && TOKEN_PRICE_CACHE[tokenAddress] && TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp]) {
16
+ return TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp];
17
+ }
18
+
19
+ const price = await getPriceClosestTo(TOKEN_PRICE_TABLE_NAME, tokenAddress, proximateTimestamp);
20
+
21
+ if (useCache) {
22
+ if (!TOKEN_PRICE_CACHE[tokenAddress]) {
23
+ TOKEN_PRICE_CACHE[tokenAddress] = {};
24
+ }
25
+
26
+ TOKEN_PRICE_CACHE[tokenAddress][proximateTimestamp] = price;
27
+ }
28
+
29
+ return price;
30
+ }
31
+
32
+ function toNativeDecimal(bigNumber, decimals) {
33
+ const dividend = new BigNumber(10).exponentiatedBy(new BigNumber(decimals));
34
+ return new BigNumber(bigNumber).multipliedBy(dividend);
35
+ }
36
+
37
+ function toHumanDecimal(bigNumber, decimals) {
38
+ const dividend = new BigNumber(10).exponentiatedBy(new BigNumber(decimals));
39
+ return new BigNumber(bigNumber).dividedBy(dividend);
40
+ }
41
+
42
+ module.exports = {
43
+ getTokenPriceAt,
44
+ toNativeDecimal,
45
+ toHumanDecimal,
46
+ };
package/transaction.js CHANGED
@@ -1,41 +1,41 @@
1
- const fetch = require("node-fetch");
2
- const { PROTOCOLS } = require("./const");
3
- const { exponentialRetry } = require("./availability");
4
-
5
- async function getTxReceipt(protocol, txHash, verbose = false) {
6
- let { endpoint } = PROTOCOLS[protocol];
7
-
8
- const body = {
9
- jsonrpc: "2.0",
10
- method: "eth_getTransactionReceipt",
11
- params: [txHash],
12
- id: 1
13
- };
14
-
15
- const response = await exponentialRetry(
16
- () => {
17
- return fetch(endpoint, {
18
- method: "POST",
19
- headers: { "Content-Type": "application/json" },
20
- body: JSON.stringify(body)
21
- });
22
- },
23
- {
24
- maxRetry: 6,
25
- test: r => r.ok,
26
- verbose
27
- }
28
- );
29
-
30
- if (!response.ok) {
31
- return null;
32
- }
33
-
34
- const { result } = await response.json();
35
-
36
- return result;
37
- }
38
-
39
- module.exports = {
40
- getTxReceipt
41
- };
1
+ const fetch = require("node-fetch");
2
+ const { PROTOCOLS } = require("./const");
3
+ const { exponentialRetry } = require("./availability");
4
+
5
+ async function getTxReceipt(protocol, txHash, verbose = false) {
6
+ let { endpoint } = PROTOCOLS[protocol];
7
+
8
+ const body = {
9
+ jsonrpc: "2.0",
10
+ method: "eth_getTransactionReceipt",
11
+ params: [txHash],
12
+ id: 1
13
+ };
14
+
15
+ const response = await exponentialRetry(
16
+ () => {
17
+ return fetch(endpoint, {
18
+ method: "POST",
19
+ headers: { "Content-Type": "application/json" },
20
+ body: JSON.stringify(body)
21
+ });
22
+ },
23
+ {
24
+ maxRetry: 6,
25
+ test: r => r.ok,
26
+ verbose
27
+ }
28
+ );
29
+
30
+ if (!response.ok) {
31
+ return null;
32
+ }
33
+
34
+ const { result } = await response.json();
35
+
36
+ return result;
37
+ }
38
+
39
+ module.exports = {
40
+ getTxReceipt
41
+ };
package/util.js CHANGED
@@ -1,67 +1,67 @@
1
- // Inclusive endAt
2
- function partition(startAt, endAt, numGroups) {
3
- if (numGroups === 0 || startAt > endAt) {
4
- return [];
5
- } else if (startAt === endAt) {
6
- return [[startAt, endAt]];
7
- }
8
-
9
- const span = endAt - startAt + 1;
10
- const step = Math.max(Math.floor(span / numGroups), 1);
11
- const adjustedStep = span % step === 0 ? step : step + 1;
12
-
13
- return [[startAt, startAt + adjustedStep - 1], ...partition(startAt + adjustedStep, endAt, numGroups - 1)];
14
- }
15
-
16
- // Inclusive range
17
- function range(startAt, endAt, step) {
18
- let arr = [];
19
-
20
- for (let i = startAt; i <= endAt; i += step) {
21
- arr.push([i, Math.min(endAt, i + step - 1)]);
22
- }
23
-
24
- return arr;
25
- }
26
-
27
- function arrayGroup(array, groupSize) {
28
- const groups = [];
29
-
30
- for (let i = 0; i < array.length; i += groupSize) {
31
- groups.push(array.slice(i, i + groupSize));
32
- }
33
-
34
- return groups;
35
- }
36
-
37
- // return an array with numbers of given inclusive range
38
- // given 1, 5
39
- // return [1, 2, 3, 4, 5]
40
- function fillRange(start, end) {
41
- let result = [];
42
-
43
- for (let i = start; i <= end; i++) {
44
- result.push(i);
45
- }
46
-
47
- return result;
48
- }
49
-
50
- function chunk(array, count) {
51
- if (count == null || count < 1) return [];
52
- var result = [];
53
- var i = 0,
54
- length = array.length;
55
- while (i < length) {
56
- result.push(array.slice(i, (i += count)));
57
- }
58
- return result;
59
- }
60
-
61
- module.exports = {
62
- arrayGroup,
63
- partition,
64
- range,
65
- fillRange,
66
- chunk
67
- };
1
+ // Inclusive endAt
2
+ function partition(startAt, endAt, numGroups) {
3
+ if (numGroups === 0 || startAt > endAt) {
4
+ return [];
5
+ } else if (startAt === endAt) {
6
+ return [[startAt, endAt]];
7
+ }
8
+
9
+ const span = endAt - startAt + 1;
10
+ const step = Math.max(Math.floor(span / numGroups), 1);
11
+ const adjustedStep = span % step === 0 ? step : step + 1;
12
+
13
+ return [[startAt, startAt + adjustedStep - 1], ...partition(startAt + adjustedStep, endAt, numGroups - 1)];
14
+ }
15
+
16
+ // Inclusive range
17
+ function range(startAt, endAt, step) {
18
+ let arr = [];
19
+
20
+ for (let i = startAt; i <= endAt; i += step) {
21
+ arr.push([i, Math.min(endAt, i + step - 1)]);
22
+ }
23
+
24
+ return arr;
25
+ }
26
+
27
+ function arrayGroup(array, groupSize) {
28
+ const groups = [];
29
+
30
+ for (let i = 0; i < array.length; i += groupSize) {
31
+ groups.push(array.slice(i, i + groupSize));
32
+ }
33
+
34
+ return groups;
35
+ }
36
+
37
+ // return an array with numbers of given inclusive range
38
+ // given 1, 5
39
+ // return [1, 2, 3, 4, 5]
40
+ function fillRange(start, end) {
41
+ let result = [];
42
+
43
+ for (let i = start; i <= end; i++) {
44
+ result.push(i);
45
+ }
46
+
47
+ return result;
48
+ }
49
+
50
+ function chunk(array, count) {
51
+ if (count == null || count < 1) return [];
52
+ var result = [];
53
+ var i = 0,
54
+ length = array.length;
55
+ while (i < length) {
56
+ result.push(array.slice(i, (i += count)));
57
+ }
58
+ return result;
59
+ }
60
+
61
+ module.exports = {
62
+ arrayGroup,
63
+ partition,
64
+ range,
65
+ fillRange,
66
+ chunk
67
+ };
package/web3.js CHANGED
@@ -1,117 +1,117 @@
1
- const Web3 = require("web3");
2
- const { PROTOCOLS } = require("./const");
3
- const { MULTICALL } = require("./abi");
4
- const { chunk } = require("./util");
5
- const MULTICALL_CHUNK_SIZE = 400;
6
-
7
- function newWeb3ByProtocol(protocol) {
8
- if (!Object.keys(PROTOCOLS).includes(protocol)) {
9
- return null;
10
- }
11
-
12
- return new Web3(PROTOCOLS[protocol].endpoint);
13
- }
14
-
15
- function normalizeCallParams(params) {
16
- if (params === undefined) {
17
- return [];
18
- }
19
-
20
- if (Array.isArray(params)) {
21
- return params;
22
- }
23
-
24
- return [params];
25
- }
26
-
27
- async function singleCall(protocol, abi, target, params) {
28
- const web3 = newWeb3ByProtocol(protocol);
29
-
30
- if (!web3) {
31
- throw new Error(`unsupported protocol`);
32
- }
33
-
34
- const contract = new web3.eth.Contract([abi], target);
35
- const functionSignature = web3.eth.abi.encodeFunctionSignature(abi);
36
- const method = contract.methods[functionSignature];
37
-
38
- const result = await method(...normalizeCallParams(params)).call();
39
-
40
- return result;
41
- }
42
-
43
- // limiter if provided, should be an instance of Bottleneck, which is part of bottleneck package
44
- async function multiCall({ protocol, limiter = null, target, abi, calls }) {
45
- const web3 = newWeb3ByProtocol(protocol);
46
-
47
- if (!web3) {
48
- throw new Error(`unsupported protocol`);
49
- }
50
-
51
- const multiCallProviderAddress = PROTOCOLS[protocol].multiCallProvider;
52
-
53
- if (!multiCallProviderAddress) {
54
- throw new Error("protocol doesn't support multicall yet");
55
- }
56
-
57
- if (calls.length === 0) return { callCount: 0, output: [] };
58
-
59
- const multiCallContract = new web3.eth.Contract(MULTICALL, multiCallProviderAddress);
60
-
61
- let maybeRateLimitedCallChunk = async (callChunk) => {
62
- const txs = callChunk.map((call) => ({
63
- delegateCall: false,
64
- revertOnError: false,
65
- gasLimit: 0,
66
- target: call.target || target,
67
- value: 0,
68
- data: web3.eth.abi.encodeFunctionCall(abi, normalizeCallParams(call.params)),
69
- }));
70
-
71
- const response = await multiCallContract.methods.multiCall(txs).call();
72
-
73
- return response._results.map((res, idx) => {
74
- const input = {
75
- target: callChunk[idx].target || target,
76
- params: normalizeCallParams(callChunk[idx].params),
77
- };
78
-
79
- try {
80
- const callResult = web3.eth.abi.decodeParameters(abi.outputs, res);
81
-
82
- return {
83
- input,
84
- success: response._successes[idx],
85
- // according to SDK doc, if there's only one, return result directly
86
- output: abi.outputs.length === 1 ? callResult[0] : callResult,
87
- };
88
- } catch (decodeErr) {
89
- console.log("decode err", abi.name, callChunk[idx].target || target, callChunk[idx].params, decodeErr.message);
90
-
91
- return {
92
- input,
93
- success: false,
94
- output: null,
95
- };
96
- }
97
- });
98
- };
99
-
100
- if (limiter) {
101
- maybeRateLimitedCallChunk = limiter.wrap(maybeRateLimitedCallChunk);
102
- }
103
-
104
- const callChunks = chunk(calls, MULTICALL_CHUNK_SIZE);
105
-
106
- const responses = (
107
- await Promise.all(callChunks.map(async (callChunk) => await maybeRateLimitedCallChunk(callChunk)))
108
- ).flat();
109
-
110
- return { actualCallCount: callChunks.length, output: responses };
111
- }
112
-
113
- module.exports = {
114
- newWeb3ByProtocol,
115
- singleCall,
116
- multiCall,
117
- };
1
+ const Web3 = require("web3");
2
+ const { PROTOCOLS } = require("./const");
3
+ const { MULTICALL } = require("./abi");
4
+ const { chunk } = require("./util");
5
+ const MULTICALL_CHUNK_SIZE = 400;
6
+
7
+ function newWeb3ByProtocol(protocol) {
8
+ if (!Object.keys(PROTOCOLS).includes(protocol)) {
9
+ return null;
10
+ }
11
+
12
+ return new Web3(PROTOCOLS[protocol].endpoint);
13
+ }
14
+
15
+ function normalizeCallParams(params) {
16
+ if (params === undefined) {
17
+ return [];
18
+ }
19
+
20
+ if (Array.isArray(params)) {
21
+ return params;
22
+ }
23
+
24
+ return [params];
25
+ }
26
+
27
+ async function singleCall(protocol, abi, target, params) {
28
+ const web3 = newWeb3ByProtocol(protocol);
29
+
30
+ if (!web3) {
31
+ throw new Error(`unsupported protocol`);
32
+ }
33
+
34
+ const contract = new web3.eth.Contract([abi], target);
35
+ const functionSignature = web3.eth.abi.encodeFunctionSignature(abi);
36
+ const method = contract.methods[functionSignature];
37
+
38
+ const result = await method(...normalizeCallParams(params)).call();
39
+
40
+ return result;
41
+ }
42
+
43
+ // limiter if provided, should be an instance of Bottleneck, which is part of bottleneck package
44
+ async function multiCall({ protocol, limiter = null, target, abi, calls }) {
45
+ const web3 = newWeb3ByProtocol(protocol);
46
+
47
+ if (!web3) {
48
+ throw new Error(`unsupported protocol`);
49
+ }
50
+
51
+ const multiCallProviderAddress = PROTOCOLS[protocol].multiCallProvider;
52
+
53
+ if (!multiCallProviderAddress) {
54
+ throw new Error("protocol doesn't support multicall yet");
55
+ }
56
+
57
+ if (calls.length === 0) return { callCount: 0, output: [] };
58
+
59
+ const multiCallContract = new web3.eth.Contract(MULTICALL, multiCallProviderAddress);
60
+
61
+ let maybeRateLimitedCallChunk = async (callChunk) => {
62
+ const txs = callChunk.map((call) => ({
63
+ delegateCall: false,
64
+ revertOnError: false,
65
+ gasLimit: 0,
66
+ target: call.target || target,
67
+ value: 0,
68
+ data: web3.eth.abi.encodeFunctionCall(abi, normalizeCallParams(call.params)),
69
+ }));
70
+
71
+ const response = await multiCallContract.methods.multiCall(txs).call();
72
+
73
+ return response._results.map((res, idx) => {
74
+ const input = {
75
+ target: callChunk[idx].target || target,
76
+ params: normalizeCallParams(callChunk[idx].params),
77
+ };
78
+
79
+ try {
80
+ const callResult = web3.eth.abi.decodeParameters(abi.outputs, res);
81
+
82
+ return {
83
+ input,
84
+ success: response._successes[idx],
85
+ // according to SDK doc, if there's only one, return result directly
86
+ output: abi.outputs.length === 1 ? callResult[0] : callResult,
87
+ };
88
+ } catch (decodeErr) {
89
+ console.log("decode err", abi.name, callChunk[idx].target || target, callChunk[idx].params, decodeErr.message);
90
+
91
+ return {
92
+ input,
93
+ success: false,
94
+ output: null,
95
+ };
96
+ }
97
+ });
98
+ };
99
+
100
+ if (limiter) {
101
+ maybeRateLimitedCallChunk = limiter.wrap(maybeRateLimitedCallChunk);
102
+ }
103
+
104
+ const callChunks = chunk(calls, MULTICALL_CHUNK_SIZE);
105
+
106
+ const responses = (
107
+ await Promise.all(callChunks.map(async (callChunk) => await maybeRateLimitedCallChunk(callChunk)))
108
+ ).flat();
109
+
110
+ return { actualCallCount: callChunks.length, output: responses };
111
+ }
112
+
113
+ module.exports = {
114
+ newWeb3ByProtocol,
115
+ singleCall,
116
+ multiCall,
117
+ };