uniswap-v2-loader 5.0.26 → 6.0.0
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/.github/workflows/test.yml +1 -1
- package/README.md +105 -64
- package/package.json +1 -1
- package/src/index.js +30 -13
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
run: npm i -g .
|
|
36
36
|
|
|
37
37
|
- name: Test CLI load first 4 pairs from Uniswap V2 using 2 workers
|
|
38
|
-
run: uniswap-v2-loader --to=
|
|
38
|
+
run: uniswap-v2-loader --to=3 --multicall_size=2 --workers=2
|
|
39
39
|
|
|
40
40
|
- name: Run ESM tests
|
|
41
41
|
run: npm run test-esm
|
package/README.md
CHANGED
|
@@ -1,51 +1,121 @@
|
|
|
1
1
|
# <picture><source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/npm/uniswap-v2-loader@5.0.1/logo-dark.svg"><img alt="calp.pro icon" src="https://cdn.jsdelivr.net/npm/uniswap-v2-loader@5.0.1/logo-light.svg" height="32" align="absmiddle"></picture> uniswap-v2-loader [](https://coveralls.io/github/calp-pro/uniswap-v2-loader)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
**Fast DeFi AMM pools loader.** Optimized for **Multi-core CPUs** with smart **disk-cache**.<br>
|
|
4
|
+
This package is a loader that allows you to download protocol addresses yourself.<br>
|
|
5
|
+
If you want to instantly get all addresses (pools and their tokens), use the packages from the next section.<br>
|
|
6
|
+
Those packages check for updates every hour and republish the package with updated data.
|
|
6
7
|
|
|
7
8
|
## Uniswap V2 based protocols
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
- **Uniswap V2**
|
|
10
|
+
* `0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f` fabric [contract](https://etherscan.io/address/0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f)
|
|
11
|
+
* pre-loaded CSV dump: [uniswap-v2-dump](https://github.com/calp-pro/uniswap-v2-dump)
|
|
12
|
+
- **SushiSwap**
|
|
13
|
+
* `0xc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac` fabric [contract](https://etherscan.io/address/0xc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac)
|
|
14
|
+
* pre-loaded CSV dump: [sushiswap-dump](https://github.com/calp-pro/sushiswap-dump)
|
|
15
|
+
- **PancakeSwap**
|
|
16
|
+
* `0x1097053fd2ea711dad45caccc45eff7548fcb362` fabric [contract](https://etherscan.io/address/0x1097053fd2ea711dad45caccc45eff7548fcb362)
|
|
17
|
+
* pre-loaded CSV dump: [pancakeswap-dump](https://github.com/calp-pro/pancakeswap-dump)
|
|
18
|
+
- **ShibaSwap**
|
|
19
|
+
* `0x115934131916c8b277dd010ee02de363c09d037c` fabric [contract](https://etherscan.io/address/0x115934131916c8b277dd010ee02de363c09d037c)
|
|
20
|
+
* pre-loaded CSV dump: [shibaswap-dump](https://github.com/calp-pro/shibaswap-dump)
|
|
21
|
+
- **DefiSwap**
|
|
22
|
+
* `0x9deb29c9a4c7a88a3c0257393b7f3335338d9a9d` fabric [contract](https://etherscan.io/address/0x9deb29c9a4c7a88a3c0257393b7f3335338d9a9d)
|
|
23
|
+
* pre-loaded CSV dump: [defiswap-dump](https://github.com/calp-pro/defiswap-dump)
|
|
24
|
+
- **EtherVista**
|
|
25
|
+
* `0x9a27cb5ae0b2cee0bb71f9a85c0d60f3920757b4` fabric [contract](https://etherscan.io/address/0x9a27cb5ae0b2cee0bb71f9a85c0d60f3920757b4)
|
|
26
|
+
* pre-loaded CSV dump: [ethervista-dump](https://github.com/calp-pro/ethervista-dump)
|
|
27
|
+
- **RadioShack**
|
|
28
|
+
* `0x91fae1bc94a9793708fbc66adcb59087c46dee10` fabric [contract](https://etherscan.io/address/0x91fae1bc94a9793708fbc66adcb59087c46dee10)
|
|
29
|
+
* pre-loaded CSV dump: [radioshack-dump](https://github.com/calp-pro/radioshack-dump)
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
- CLI
|
|
33
|
+
* ```
|
|
34
|
+
npm i -g uniswap-v2-loader
|
|
35
|
+
```
|
|
36
|
+
- Node.js API
|
|
37
|
+
* ```
|
|
38
|
+
npm i --save uniswap-v2-loader
|
|
39
|
+
```
|
|
18
40
|
|
|
19
41
|
## CLI
|
|
20
42
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
43
|
+
uniswap-v2-loader --from=1 --to=3
|
|
44
|
+
```
|
|
45
|
+
Output:
|
|
46
|
+
```
|
|
24
47
|
2,0x12ede161c702d1494612d19f05992f43aa6a26fb,0x06af07097c9eeb7fd685c692751d5c66db49c215,0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
|
|
25
48
|
3,0xa478c2975ab1ea89e8196811f51a7b7ade33eb11,0x6b175474e89094c44da98b954eedeac495271d0f,0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
|
|
26
49
|
```
|
|
27
50
|
|
|
28
|
-
## API
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
## API
|
|
52
|
+
Methods:
|
|
53
|
+
- `load(config)`
|
|
54
|
+
* return `Promise(<Pair>[])`
|
|
55
|
+
- `subscribe(callback, config)`
|
|
56
|
+
* Continuous synchronization engine. Performs initial load and subsequently polls for new pairs.
|
|
57
|
+
* return unsubscribe function
|
|
58
|
+
|
|
59
|
+
<i>where `config` is common `Object` with set of parameters to loader.</i>
|
|
60
|
+
|
|
61
|
+
`config` is an Object (key/value)
|
|
62
|
+
- `from`
|
|
63
|
+
* Start index (inclusive).
|
|
64
|
+
* Type: `number`
|
|
65
|
+
* Default: `0`
|
|
66
|
+
- `to`
|
|
67
|
+
* End index (inclusive).
|
|
68
|
+
* Type: `number`
|
|
69
|
+
* Default: `undefined`
|
|
70
|
+
- `filename`
|
|
71
|
+
* CSV cache path.
|
|
72
|
+
* Type: `string`
|
|
73
|
+
* Default: *OS cache folder*
|
|
74
|
+
- `factory`
|
|
75
|
+
* Smart contract factory address.
|
|
76
|
+
* Type: `string`
|
|
77
|
+
* Default: `0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f`
|
|
78
|
+
- `key`
|
|
79
|
+
* Alchemy API Key
|
|
80
|
+
* Type: `string`
|
|
81
|
+
* Default: `FZBvlPrOxtgaKBBkry3SH0W1IqH4Y5tu`
|
|
82
|
+
- `multicall_size`
|
|
83
|
+
* RPC batch size per multicall request.
|
|
84
|
+
* Type:`number`
|
|
85
|
+
* Default: `50`
|
|
86
|
+
- `workers`
|
|
87
|
+
* Number of parallel worker threads.
|
|
88
|
+
* Type: `number`
|
|
89
|
+
* Default: `CPU - 1`
|
|
90
|
+
- `progress`
|
|
91
|
+
* Each loaded pair execute this callback: `(id, total, pair) => {}`.
|
|
92
|
+
* Callback arguments:
|
|
93
|
+
- `id` fabric index of pair contract (int)
|
|
94
|
+
- `total` total amount of pairs at fabric at current moment
|
|
95
|
+
- `pair` instance of `Pair`(`{id: number, pair: string, token0: string, token1: string}`)
|
|
96
|
+
* Type: `function`
|
|
97
|
+
* Default: `undefined`
|
|
98
|
+
- `abort_signal`
|
|
99
|
+
* Signal to cancel loading and release workers.
|
|
100
|
+
* Type: `AbortSignal`
|
|
101
|
+
* Default: `undefined`
|
|
102
|
+
- `update_timeout`
|
|
103
|
+
* Polling interval in milliseconds. Used only in `subscribe`
|
|
104
|
+
* Type: `number`
|
|
105
|
+
* Default: `5000`
|
|
106
|
+
|
|
107
|
+
### Schema `Pair`
|
|
108
|
+
Standardized liquidity pool object.
|
|
32
109
|
|
|
33
|
-
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `factory` | `string` | Smart contract factory address. | `0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f` |
|
|
40
|
-
| `key` | `string` | Alchemy API Key | `FZBvlPrOxtgaKBBkry3SH0W1IqH4Y5tu` |
|
|
41
|
-
| `multicall_size` | `number` | RPC batch size per multicall request. | `50` |
|
|
42
|
-
| `workers` | `number` | Number of parallel worker threads. | `CPU - 1` |
|
|
43
|
-
| `progress` | `function` | Progress callback: `(current, total) => {}`. | `undefined` |
|
|
44
|
-
| `abort_signal` | `AbortSignal` | Signal to cancel loading and release workers. | `undefined` |
|
|
110
|
+
| Property | Type | Description |
|
|
111
|
+
| :--- | :--- | :--- |
|
|
112
|
+
| `id` | `number` | Numeric index of the pair in the factory |
|
|
113
|
+
| `pair` | `string` | DEX pair address |
|
|
114
|
+
| `token0` | `string` | Token address |
|
|
115
|
+
| `token1` | `string` | Token address |
|
|
45
116
|
|
|
46
|
-
**Returns**: `Promise<Pair[]>`
|
|
47
117
|
|
|
48
|
-
**Example
|
|
118
|
+
**Example `<Pair>[]`**
|
|
49
119
|
```json
|
|
50
120
|
[
|
|
51
121
|
{
|
|
@@ -57,8 +127,6 @@ High-performance parallel fetcher for liquidity pairs. Efficiently synchronizes
|
|
|
57
127
|
]
|
|
58
128
|
```
|
|
59
129
|
|
|
60
|
-
---
|
|
61
|
-
|
|
62
130
|
### Smart Cross-Platform Caching
|
|
63
131
|
The loader automatically identifies the optimal persistent storage path for your operating system to ensure zero-configuration caching:
|
|
64
132
|
- **Linux:** `$XDG_CACHE_HOME` or `~/.cache/`
|
|
@@ -67,35 +135,8 @@ The loader automatically identifies the optimal persistent storage path for your
|
|
|
67
135
|
|
|
68
136
|
Cache files are named following the pattern `${package_name}_{factory_address}.csv`.
|
|
69
137
|
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
### `subscribe(callback, params)`
|
|
73
|
-
Continuous synchronization engine. Performs initial load and subsequently polls for new pairs.
|
|
74
|
-
|
|
75
|
-
**Parameters**
|
|
76
|
-
| Name | Type | Description | Default |
|
|
77
|
-
| :--- | :--- | :--- | :--- |
|
|
78
|
-
| `callback` | `function` | Invoked with updated `Pair[]` array. | **Required** |
|
|
79
|
-
| `params` | `object` | All options from `load()` plus `update_timeout`. | - |
|
|
80
|
-
| `update_timeout` | `number` | Polling interval in milliseconds. | `5000` |
|
|
81
|
-
|
|
82
|
-
**Returns**: `function` (Stop/Unsubscribe function)
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
### Schema: `Pair`
|
|
87
|
-
Standardized liquidity pool object.
|
|
88
|
-
|
|
89
|
-
| Property | Type | Description |
|
|
90
|
-
| :--- | :--- | :--- |
|
|
91
|
-
| `id` | `number` | Global index of the pair in the factory. |
|
|
92
|
-
| `pair` | `string` | Ethereum address of the liquidity pool. |
|
|
93
|
-
| `token0` | `string` | Address of the first asset. |
|
|
94
|
-
| `token1` | `string` | Address of the second asset. |
|
|
95
|
-
|
|
96
|
-
---
|
|
97
138
|
|
|
98
|
-
## Usage
|
|
139
|
+
## API Usage
|
|
99
140
|
```javascript
|
|
100
141
|
const { load } = require('uniswap-v2-loader')
|
|
101
142
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -39,12 +39,12 @@ const load = (params = {}) => {
|
|
|
39
39
|
}, [])
|
|
40
40
|
: []
|
|
41
41
|
|
|
42
|
-
if (to >= 0 && pairs.length
|
|
42
|
+
if (to >= 0 && to <= pairs.length - 1) {
|
|
43
43
|
if (progress)
|
|
44
|
-
for (var i = from; i
|
|
44
|
+
for (var i = from; i <= to; i++)
|
|
45
45
|
progress(pairs[i].id, to, pairs[i])
|
|
46
46
|
|
|
47
|
-
return Promise.resolve(pairs.slice(
|
|
47
|
+
return Promise.resolve(pairs.slice(from, to + 1))
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
return (to
|
|
@@ -61,17 +61,24 @@ const load = (params = {}) => {
|
|
|
61
61
|
})
|
|
62
62
|
}).then(
|
|
63
63
|
_ => {
|
|
64
|
-
if (_.ok) return _.json().then(_ =>
|
|
64
|
+
if (_.ok) return _.json().then(_ => {
|
|
65
|
+
const total_pools = Number(_.result)
|
|
66
|
+
if (total_pools > 0) {
|
|
67
|
+
const last_id = total_pools - 1
|
|
68
|
+
return last_id
|
|
69
|
+
}
|
|
70
|
+
return 0
|
|
71
|
+
})
|
|
65
72
|
throw 'fail start'
|
|
66
73
|
},
|
|
67
74
|
_ => {
|
|
68
75
|
throw 'fetch failed'
|
|
69
76
|
}
|
|
70
77
|
)
|
|
71
|
-
).then(
|
|
78
|
+
).then(last_id => {
|
|
72
79
|
const start_loading_from = pairs.length
|
|
73
80
|
? Math.max(from, pairs[pairs.length - 1].id + 1)
|
|
74
|
-
:
|
|
81
|
+
: from
|
|
75
82
|
|
|
76
83
|
var next_pair_order = pairs.length
|
|
77
84
|
? pairs[pairs.length - 1].id + 1
|
|
@@ -79,11 +86,11 @@ const load = (params = {}) => {
|
|
|
79
86
|
|
|
80
87
|
if (progress)
|
|
81
88
|
for (var i = from; i < start_loading_from; i++)
|
|
82
|
-
progress(pairs[i].id,
|
|
89
|
+
progress(pairs[i].id, last_id + 1, pairs[i])
|
|
83
90
|
|
|
84
91
|
const onpair = pair => {
|
|
85
92
|
pairs[pair.id] = pair
|
|
86
|
-
if (progress) progress(pair.id,
|
|
93
|
+
if (progress && pair.id >= from) progress(pair.id, last_id + 1, pair)
|
|
87
94
|
var _
|
|
88
95
|
while (_ = pairs[next_pair_order]) {
|
|
89
96
|
fs.appendFileSync(filename, `${_.id},${_.pair},${_.token0},${_.token1}\n`)
|
|
@@ -93,15 +100,20 @@ const load = (params = {}) => {
|
|
|
93
100
|
|
|
94
101
|
if (!workers) {
|
|
95
102
|
const ids = []
|
|
96
|
-
for (var i = start_loading_from; i
|
|
103
|
+
for (var i = start_loading_from; i <= last_id; i++)
|
|
97
104
|
ids.push(i)
|
|
98
105
|
return require('./loader')({ ids, factory, key, multicall_size, abort_signal }, onpair)
|
|
99
|
-
.then(() =>
|
|
106
|
+
.then(() => {
|
|
107
|
+
if (from && to) return pairs.filter(({id}) => id >= from && id <= to)
|
|
108
|
+
if (from) return pairs.filter(({id}) => id >= from)
|
|
109
|
+
if (to) return pairs.filter(({id}) => id <= to)
|
|
110
|
+
return pairs
|
|
111
|
+
})
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
const missed = Array(workers).fill(null).map(() => [])
|
|
103
115
|
|
|
104
|
-
for (var i = start_loading_from, iw = 0; i
|
|
116
|
+
for (var i = start_loading_from, iw = 0; i <= last_id; i++)
|
|
105
117
|
missed[iw++ % workers].push(i)
|
|
106
118
|
|
|
107
119
|
cluster.setupPrimary({ exec: path.join(__dirname, 'loader.js') })
|
|
@@ -121,7 +133,12 @@ const load = (params = {}) => {
|
|
|
121
133
|
y()
|
|
122
134
|
})
|
|
123
135
|
}))
|
|
124
|
-
).then(() =>
|
|
136
|
+
).then(() => {
|
|
137
|
+
if (from && to) return pairs.filter(({id}) => id >= from && id <= to)
|
|
138
|
+
if (from) return pairs.filter(({id}) => id >= from)
|
|
139
|
+
if (to) return pairs.filter(({id}) => id <= to)
|
|
140
|
+
return pairs
|
|
141
|
+
})
|
|
125
142
|
})
|
|
126
143
|
.catch(() => abort_signal?.aborted ? pairs : new Promise(resolve => setTimeout(() => resolve(load(params)), 1000)))
|
|
127
144
|
}
|
|
@@ -139,7 +156,7 @@ module.exports.subscribe = (callback, params = {}) => {
|
|
|
139
156
|
const update = pairs =>
|
|
140
157
|
timeout = setTimeout(
|
|
141
158
|
() =>
|
|
142
|
-
load({...params, pairs, from: pairs.length})
|
|
159
|
+
subscribed && load({...params, pairs, from: pairs.length})
|
|
143
160
|
.then(pairs => {
|
|
144
161
|
if (!subscribed) return
|
|
145
162
|
callback(pairs)
|