jaelis-node 1.9.0 → 2.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/README.md +147 -433
- package/bin/jaelis-node.js +79 -504
- package/lib/index.js +31 -2740
- package/lib/node.js +271 -0
- package/lib/rpc.js +315 -0
- package/lib/storage.js +198 -0
- package/lib/sync.js +366 -0
- package/package.json +19 -53
- package/config/default.json +0 -74
- package/config/mainnet.json +0 -30
- package/config/testnet.json +0 -26
- package/lib/JAELIS-VM/lib/adapters/evm-adapter.js +0 -454
- package/lib/JAELIS-VM/lib/adapters/index.js +0 -411
- package/lib/JAELIS-VM/lib/adapters/svm-adapter.js +0 -457
- package/lib/JAELIS-VM/lib/compiler/jir-compiler.js +0 -1097
- package/lib/JAELIS-VM/lib/execution/engine.js +0 -1183
- package/lib/JAELIS-VM/lib/index.js +0 -440
- package/lib/JAELIS-VM/lib/integration/jaelis-integration.js +0 -543
- package/lib/JAELIS-VM/lib/serialization/serializer.js +0 -819
- package/lib/JAELIS-VM/lib/state/state-manager.js +0 -1116
- package/lib/JAELIS-VM/lib/translator/bytecode-translator.js +0 -1222
- package/lib/JAELIS-VM/lib/unified/cross-chain-deploy.js +0 -1678
- package/lib/JAELIS-VM/lib/unified/cross-chain-state.js +0 -836
- package/lib/JAELIS-VM/lib/unified/dynamic-contracts.js +0 -1127
- package/lib/JAELIS-VM/lib/unified/index.js +0 -456
- package/lib/JAELIS-VM/lib/unified/jaelis-abi.js +0 -1150
- package/lib/JAELIS-VM/lib/unified/unified-compiler.js +0 -1350
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.package-lock.json +0 -127
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/README.md +0 -1
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/package.json +0 -17
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/README.md +0 -1
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/package.json +0 -17
- package/lib/JAELIS-VM/node_modules/cbor-extract/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/cbor-extract/README.md +0 -5
- package/lib/JAELIS-VM/node_modules/cbor-extract/bin/download-prebuilds.js +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-extract/binding.gyp +0 -60
- package/lib/JAELIS-VM/node_modules/cbor-extract/index.js +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-extract/package.json +0 -50
- package/lib/JAELIS-VM/node_modules/cbor-extract/src/extract.cpp +0 -198
- package/lib/JAELIS-VM/node_modules/cbor-x/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/cbor-x/README.md +0 -380
- package/lib/JAELIS-VM/node_modules/cbor-x/SECURITY.md +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-x/benchmark.md +0 -73
- package/lib/JAELIS-VM/node_modules/cbor-x/browser.js +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.d.ts +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.js +0 -1300
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs +0 -1244
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs +0 -2509
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js +0 -2508
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs +0 -2629
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js +0 -3343
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.d.ts +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.js +0 -1231
- package/lib/JAELIS-VM/node_modules/cbor-x/index.d.ts +0 -79
- package/lib/JAELIS-VM/node_modules/cbor-x/index.js +0 -3
- package/lib/JAELIS-VM/node_modules/cbor-x/iterators.js +0 -85
- package/lib/JAELIS-VM/node_modules/cbor-x/node-index.js +0 -24
- package/lib/JAELIS-VM/node_modules/cbor-x/package.json +0 -94
- package/lib/JAELIS-VM/node_modules/cbor-x/rollup.config.js +0 -88
- package/lib/JAELIS-VM/node_modules/cbor-x/stream.js +0 -61
- package/lib/JAELIS-VM/node_modules/cbor-x/webpack.config.js +0 -19
- package/lib/JAELIS-VM/node_modules/detect-libc/LICENSE +0 -201
- package/lib/JAELIS-VM/node_modules/detect-libc/README.md +0 -163
- package/lib/JAELIS-VM/node_modules/detect-libc/index.d.ts +0 -14
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/detect-libc.js +0 -313
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/elf.js +0 -39
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/filesystem.js +0 -51
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/process.js +0 -24
- package/lib/JAELIS-VM/node_modules/detect-libc/package.json +0 -44
- package/lib/JAELIS-VM/node_modules/msgpackr/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr/README.md +0 -372
- package/lib/JAELIS-VM/node_modules/msgpackr/SECURITY.md +0 -11
- package/lib/JAELIS-VM/node_modules/msgpackr/benchmark.md +0 -67
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs +0 -2407
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js +0 -2406
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs +0 -3320
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js +0 -4540
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs +0 -1250
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.cts +0 -91
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.ts +0 -91
- package/lib/JAELIS-VM/node_modules/msgpackr/index.js +0 -5
- package/lib/JAELIS-VM/node_modules/msgpackr/iterators.js +0 -87
- package/lib/JAELIS-VM/node_modules/msgpackr/node-index.js +0 -25
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.cts +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.ts +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.js +0 -1141
- package/lib/JAELIS-VM/node_modules/msgpackr/package.json +0 -104
- package/lib/JAELIS-VM/node_modules/msgpackr/rollup.config.js +0 -88
- package/lib/JAELIS-VM/node_modules/msgpackr/stream.js +0 -57
- package/lib/JAELIS-VM/node_modules/msgpackr/struct.js +0 -815
- package/lib/JAELIS-VM/node_modules/msgpackr/test-worker.js +0 -3
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.cts +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.ts +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.js +0 -1221
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/README.md +0 -5
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/bin/download-prebuilds.js +0 -13
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/binding.gyp +0 -63
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/index.js +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/README.md +0 -58
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/bin.js +0 -82
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/build-test.js +0 -19
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/index.js +0 -6
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/node-gyp-build.js +0 -236
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/optional.js +0 -7
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/package.json +0 -32
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/package.json +0 -50
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/src/extract.cpp +0 -274
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/README.md +0 -58
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/bin.js +0 -77
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/build-test.js +0 -19
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/index.js +0 -224
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/optional.js +0 -7
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/package.json +0 -32
- package/lib/JAELIS-VM/package-lock.json +0 -284
- package/lib/JAELIS-VM/package.json +0 -38
- package/lib/JAELIS-VM/test/comprehensive.test.js +0 -267
- package/lib/JAELIS-VM/test/cross-chain-test.js +0 -470
- package/lib/JAELIS-VM/test/unified-vm-test.js +0 -459
- package/lib/JAELIS-VM/test/unified.test.js +0 -166
- package/lib/JAELIS-VM/test/vm.test.js +0 -599
- package/lib/settlement-server.js +0 -999
- package/lib/vm/index.js +0 -397
package/lib/storage.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAELIS Local Storage
|
|
3
|
+
*
|
|
4
|
+
* LevelDB-based storage for synced blocks and state.
|
|
5
|
+
* This is local storage only - no JAELIS internal code.
|
|
6
|
+
*
|
|
7
|
+
* Storage Keys:
|
|
8
|
+
* - block:{number} → Block data
|
|
9
|
+
* - tx:{hash} → Transaction data
|
|
10
|
+
* - meta:latestBlock → Latest synced block number
|
|
11
|
+
*
|
|
12
|
+
* @version 2.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const { Level } = require('level');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
|
|
21
|
+
class Storage {
|
|
22
|
+
constructor(dataDir) {
|
|
23
|
+
this.dataDir = dataDir;
|
|
24
|
+
this.dbPath = path.join(dataDir, 'blocks');
|
|
25
|
+
this.db = null;
|
|
26
|
+
this.initialized = false;
|
|
27
|
+
|
|
28
|
+
// In-memory cache for fast reads
|
|
29
|
+
this.blockCache = new Map();
|
|
30
|
+
this.txCache = new Map();
|
|
31
|
+
this.latestBlock = 0;
|
|
32
|
+
|
|
33
|
+
// Cache limits
|
|
34
|
+
this.maxCacheSize = 1000;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initialize storage
|
|
39
|
+
*/
|
|
40
|
+
async initialize() {
|
|
41
|
+
// Create data directory if it doesn't exist
|
|
42
|
+
if (!fs.existsSync(this.dataDir)) {
|
|
43
|
+
fs.mkdirSync(this.dataDir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Open LevelDB
|
|
47
|
+
this.db = new Level(this.dbPath, {
|
|
48
|
+
keyEncoding: 'utf8',
|
|
49
|
+
valueEncoding: 'json'
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await this.db.open();
|
|
53
|
+
|
|
54
|
+
// Load latest block number
|
|
55
|
+
try {
|
|
56
|
+
this.latestBlock = await this.db.get('meta:latestBlock');
|
|
57
|
+
} catch (e) {
|
|
58
|
+
if (e.code === 'LEVEL_NOT_FOUND') {
|
|
59
|
+
this.latestBlock = 0;
|
|
60
|
+
} else {
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.initialized = true;
|
|
66
|
+
console.log(`[STORAGE] Initialized at ${this.dbPath}`);
|
|
67
|
+
console.log(`[STORAGE] Latest block: ${this.latestBlock}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Close storage
|
|
72
|
+
*/
|
|
73
|
+
async close() {
|
|
74
|
+
if (this.db) {
|
|
75
|
+
await this.db.close();
|
|
76
|
+
this.db = null;
|
|
77
|
+
}
|
|
78
|
+
this.initialized = false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Save block to storage
|
|
83
|
+
*/
|
|
84
|
+
async saveBlock(block) {
|
|
85
|
+
if (!block || !block.number) return;
|
|
86
|
+
|
|
87
|
+
const blockNumber = typeof block.number === 'string'
|
|
88
|
+
? parseInt(block.number, 16)
|
|
89
|
+
: block.number;
|
|
90
|
+
|
|
91
|
+
// Save block
|
|
92
|
+
await this.db.put(`block:${blockNumber}`, block);
|
|
93
|
+
|
|
94
|
+
// Save transactions
|
|
95
|
+
if (block.transactions) {
|
|
96
|
+
for (const tx of block.transactions) {
|
|
97
|
+
if (typeof tx === 'object' && tx.hash) {
|
|
98
|
+
await this.db.put(`tx:${tx.hash}`, tx);
|
|
99
|
+
this._addToCache(this.txCache, tx.hash, tx);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Update latest block
|
|
105
|
+
if (blockNumber > this.latestBlock) {
|
|
106
|
+
this.latestBlock = blockNumber;
|
|
107
|
+
await this.db.put('meta:latestBlock', this.latestBlock);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Add to cache
|
|
111
|
+
this._addToCache(this.blockCache, blockNumber, block);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get block by number
|
|
116
|
+
*/
|
|
117
|
+
async getBlock(blockNumber) {
|
|
118
|
+
// Check cache first
|
|
119
|
+
if (this.blockCache.has(blockNumber)) {
|
|
120
|
+
return this.blockCache.get(blockNumber);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const block = await this.db.get(`block:${blockNumber}`);
|
|
125
|
+
this._addToCache(this.blockCache, blockNumber, block);
|
|
126
|
+
return block;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
if (e.code === 'LEVEL_NOT_FOUND') {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
throw e;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get transaction by hash
|
|
137
|
+
*/
|
|
138
|
+
async getTransaction(txHash) {
|
|
139
|
+
// Check cache first
|
|
140
|
+
if (this.txCache.has(txHash)) {
|
|
141
|
+
return this.txCache.get(txHash);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const tx = await this.db.get(`tx:${txHash}`);
|
|
146
|
+
this._addToCache(this.txCache, txHash, tx);
|
|
147
|
+
return tx;
|
|
148
|
+
} catch (e) {
|
|
149
|
+
if (e.code === 'LEVEL_NOT_FOUND') {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
throw e;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Get latest block number
|
|
158
|
+
*/
|
|
159
|
+
getLatestBlockNumber() {
|
|
160
|
+
return this.latestBlock;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get storage stats
|
|
165
|
+
*/
|
|
166
|
+
async getStats() {
|
|
167
|
+
return {
|
|
168
|
+
dataDir: this.dataDir,
|
|
169
|
+
latestBlock: this.latestBlock,
|
|
170
|
+
blockCacheSize: this.blockCache.size,
|
|
171
|
+
txCacheSize: this.txCache.size
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Add item to cache with LRU eviction
|
|
177
|
+
*/
|
|
178
|
+
_addToCache(cache, key, value) {
|
|
179
|
+
// Evict oldest if at capacity
|
|
180
|
+
if (cache.size >= this.maxCacheSize) {
|
|
181
|
+
const firstKey = cache.keys().next().value;
|
|
182
|
+
cache.delete(firstKey);
|
|
183
|
+
}
|
|
184
|
+
cache.set(key, value);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Clear all data (for testing)
|
|
189
|
+
*/
|
|
190
|
+
async clear() {
|
|
191
|
+
await this.db.clear();
|
|
192
|
+
this.blockCache.clear();
|
|
193
|
+
this.txCache.clear();
|
|
194
|
+
this.latestBlock = 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = { Storage };
|
package/lib/sync.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JAELIS Sync Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles WebSocket connection to JAELIS main network.
|
|
5
|
+
* Syncs blocks and relays transactions.
|
|
6
|
+
*
|
|
7
|
+
* Protocol:
|
|
8
|
+
* - Subscribe to newHeads for real-time blocks
|
|
9
|
+
* - Batch sync for catching up
|
|
10
|
+
* - Automatic reconnection
|
|
11
|
+
*
|
|
12
|
+
* @version 2.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const EventEmitter = require('events');
|
|
18
|
+
const WebSocket = require('ws');
|
|
19
|
+
const https = require('https');
|
|
20
|
+
const http = require('http');
|
|
21
|
+
|
|
22
|
+
class SyncManager extends EventEmitter {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
super();
|
|
25
|
+
|
|
26
|
+
this.wsEndpoint = options.wsEndpoint;
|
|
27
|
+
this.rpcEndpoint = options.rpcEndpoint;
|
|
28
|
+
this.storage = options.storage;
|
|
29
|
+
this.chainId = options.chainId;
|
|
30
|
+
|
|
31
|
+
// WebSocket state
|
|
32
|
+
this.ws = null;
|
|
33
|
+
this.isConnected = false;
|
|
34
|
+
this.reconnectAttempts = 0;
|
|
35
|
+
this.maxReconnectAttempts = 10;
|
|
36
|
+
this.reconnectDelay = 1000;
|
|
37
|
+
|
|
38
|
+
// Sync state
|
|
39
|
+
this.subscriptionId = null;
|
|
40
|
+
this.isSyncing = false;
|
|
41
|
+
this.networkHeight = 0;
|
|
42
|
+
this.localHeight = 0;
|
|
43
|
+
|
|
44
|
+
// Request tracking
|
|
45
|
+
this.pendingRequests = new Map();
|
|
46
|
+
this.requestId = 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Start sync manager
|
|
51
|
+
*/
|
|
52
|
+
async start() {
|
|
53
|
+
// Get local height
|
|
54
|
+
this.localHeight = await this.storage.getLatestBlockNumber();
|
|
55
|
+
|
|
56
|
+
// Connect WebSocket
|
|
57
|
+
await this._connect();
|
|
58
|
+
|
|
59
|
+
// Get network height and start sync
|
|
60
|
+
await this._initialSync();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Stop sync manager
|
|
65
|
+
*/
|
|
66
|
+
async stop() {
|
|
67
|
+
if (this.ws) {
|
|
68
|
+
this.ws.close();
|
|
69
|
+
this.ws = null;
|
|
70
|
+
}
|
|
71
|
+
this.isConnected = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Connect to WebSocket
|
|
76
|
+
*/
|
|
77
|
+
async _connect() {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
try {
|
|
80
|
+
this.ws = new WebSocket(this.wsEndpoint);
|
|
81
|
+
|
|
82
|
+
this.ws.on('open', () => {
|
|
83
|
+
this.isConnected = true;
|
|
84
|
+
this.reconnectAttempts = 0;
|
|
85
|
+
this.emit('connected');
|
|
86
|
+
this._subscribeToNewHeads();
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
this.ws.on('message', (data) => {
|
|
91
|
+
this._handleMessage(JSON.parse(data.toString()));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
this.ws.on('close', () => {
|
|
95
|
+
this.isConnected = false;
|
|
96
|
+
this.emit('disconnected');
|
|
97
|
+
this._scheduleReconnect();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
this.ws.on('error', (error) => {
|
|
101
|
+
if (!this.isConnected) {
|
|
102
|
+
reject(error);
|
|
103
|
+
}
|
|
104
|
+
this.emit('error', error);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
} catch (error) {
|
|
108
|
+
reject(error);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Schedule reconnection
|
|
115
|
+
*/
|
|
116
|
+
_scheduleReconnect() {
|
|
117
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
118
|
+
console.error('[SYNC] Max reconnection attempts reached');
|
|
119
|
+
this.emit('maxReconnectReached');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.reconnectAttempts++;
|
|
124
|
+
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000);
|
|
125
|
+
|
|
126
|
+
console.log(`[SYNC] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
127
|
+
|
|
128
|
+
setTimeout(async () => {
|
|
129
|
+
try {
|
|
130
|
+
await this._connect();
|
|
131
|
+
await this._initialSync();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('[SYNC] Reconnection failed:', error.message);
|
|
134
|
+
}
|
|
135
|
+
}, delay);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Subscribe to new block headers
|
|
140
|
+
*/
|
|
141
|
+
_subscribeToNewHeads() {
|
|
142
|
+
const id = this.requestId++;
|
|
143
|
+
this.ws.send(JSON.stringify({
|
|
144
|
+
jsonrpc: '2.0',
|
|
145
|
+
id,
|
|
146
|
+
method: 'jaelis_subscribe',
|
|
147
|
+
params: ['newHeads']
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Handle incoming WebSocket message
|
|
153
|
+
*/
|
|
154
|
+
_handleMessage(data) {
|
|
155
|
+
// Subscription notification
|
|
156
|
+
if (data.method === 'jaelis_subscription') {
|
|
157
|
+
this._handleSubscription(data.params);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Response to request
|
|
162
|
+
if (data.id !== undefined) {
|
|
163
|
+
const pending = this.pendingRequests.get(data.id);
|
|
164
|
+
if (pending) {
|
|
165
|
+
this.pendingRequests.delete(data.id);
|
|
166
|
+
if (data.error) {
|
|
167
|
+
pending.reject(new Error(data.error.message));
|
|
168
|
+
} else {
|
|
169
|
+
pending.resolve(data.result);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Handle subscription notification
|
|
177
|
+
*/
|
|
178
|
+
async _handleSubscription(params) {
|
|
179
|
+
const { subscription, result } = params;
|
|
180
|
+
|
|
181
|
+
// New block header
|
|
182
|
+
if (result && result.number) {
|
|
183
|
+
const blockNumber = parseInt(result.number, 16);
|
|
184
|
+
this.networkHeight = blockNumber;
|
|
185
|
+
|
|
186
|
+
// Fetch full block and store
|
|
187
|
+
try {
|
|
188
|
+
const block = await this._fetchBlock(blockNumber);
|
|
189
|
+
if (block) {
|
|
190
|
+
await this.storage.saveBlock(block);
|
|
191
|
+
this.localHeight = blockNumber;
|
|
192
|
+
this.emit('block', block);
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('[SYNC] Failed to fetch block:', error.message);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Initial sync - catch up to network height
|
|
202
|
+
*/
|
|
203
|
+
async _initialSync() {
|
|
204
|
+
// Get network height
|
|
205
|
+
this.networkHeight = await this._getNetworkHeight();
|
|
206
|
+
|
|
207
|
+
if (this.localHeight >= this.networkHeight) {
|
|
208
|
+
console.log(`[SYNC] Already synced at block ${this.localHeight}`);
|
|
209
|
+
this.emit('synced');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
console.log(`[SYNC] Syncing from block ${this.localHeight} to ${this.networkHeight}`);
|
|
214
|
+
this.isSyncing = true;
|
|
215
|
+
this.emit('syncing', { syncing: true, currentBlock: this.localHeight, highestBlock: this.networkHeight });
|
|
216
|
+
|
|
217
|
+
// Batch sync
|
|
218
|
+
const BATCH_SIZE = 25;
|
|
219
|
+
let current = this.localHeight + 1;
|
|
220
|
+
|
|
221
|
+
while (current <= this.networkHeight) {
|
|
222
|
+
const batchEnd = Math.min(current + BATCH_SIZE - 1, this.networkHeight);
|
|
223
|
+
|
|
224
|
+
// Fetch batch
|
|
225
|
+
const promises = [];
|
|
226
|
+
for (let i = current; i <= batchEnd; i++) {
|
|
227
|
+
promises.push(this._fetchBlock(i));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const blocks = await Promise.all(promises);
|
|
231
|
+
|
|
232
|
+
// Store blocks
|
|
233
|
+
for (const block of blocks) {
|
|
234
|
+
if (block) {
|
|
235
|
+
await this.storage.saveBlock(block);
|
|
236
|
+
this.localHeight = parseInt(block.number, 16);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Progress update
|
|
241
|
+
const progress = Math.round((this.localHeight / this.networkHeight) * 100);
|
|
242
|
+
console.log(`[SYNC] Progress: ${progress}% (block ${this.localHeight}/${this.networkHeight})`);
|
|
243
|
+
this.emit('syncing', { syncing: true, currentBlock: this.localHeight, highestBlock: this.networkHeight, progress });
|
|
244
|
+
|
|
245
|
+
current = batchEnd + 1;
|
|
246
|
+
|
|
247
|
+
// Small delay to avoid overwhelming the network
|
|
248
|
+
await new Promise(r => setTimeout(r, 100));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
this.isSyncing = false;
|
|
252
|
+
console.log('[SYNC] Sync complete');
|
|
253
|
+
this.emit('synced');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get current network height via HTTP RPC
|
|
258
|
+
*/
|
|
259
|
+
async _getNetworkHeight() {
|
|
260
|
+
const result = await this._httpRpc('jaelis_blockNumber', []);
|
|
261
|
+
return parseInt(result, 16);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Fetch block by number via HTTP RPC
|
|
266
|
+
*/
|
|
267
|
+
async _fetchBlock(blockNumber) {
|
|
268
|
+
const hexBlock = '0x' + blockNumber.toString(16);
|
|
269
|
+
return this._httpRpc('jaelis_getBlockByNumber', [hexBlock, true]);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Send transaction to network
|
|
274
|
+
*/
|
|
275
|
+
async sendTransaction(signedTx) {
|
|
276
|
+
return this._httpRpc('jaelis_sendRawTransaction', [signedTx]);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Make HTTP RPC call
|
|
281
|
+
*/
|
|
282
|
+
async _httpRpc(method, params) {
|
|
283
|
+
return new Promise((resolve, reject) => {
|
|
284
|
+
const url = new URL(this.rpcEndpoint);
|
|
285
|
+
const isHttps = url.protocol === 'https:';
|
|
286
|
+
|
|
287
|
+
const body = JSON.stringify({
|
|
288
|
+
jsonrpc: '2.0',
|
|
289
|
+
id: this.requestId++,
|
|
290
|
+
method,
|
|
291
|
+
params
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const options = {
|
|
295
|
+
hostname: url.hostname,
|
|
296
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
297
|
+
path: url.pathname,
|
|
298
|
+
method: 'POST',
|
|
299
|
+
headers: {
|
|
300
|
+
'Content-Type': 'application/json',
|
|
301
|
+
'Content-Length': Buffer.byteLength(body)
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const client = isHttps ? https : http;
|
|
306
|
+
|
|
307
|
+
const req = client.request(options, (res) => {
|
|
308
|
+
let data = '';
|
|
309
|
+
res.on('data', chunk => data += chunk);
|
|
310
|
+
res.on('end', () => {
|
|
311
|
+
try {
|
|
312
|
+
const parsed = JSON.parse(data);
|
|
313
|
+
if (parsed.error) {
|
|
314
|
+
reject(new Error(parsed.error.message));
|
|
315
|
+
} else {
|
|
316
|
+
resolve(parsed.result);
|
|
317
|
+
}
|
|
318
|
+
} catch (e) {
|
|
319
|
+
reject(e);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
req.on('error', reject);
|
|
325
|
+
req.write(body);
|
|
326
|
+
req.end();
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Make WebSocket RPC call
|
|
332
|
+
*/
|
|
333
|
+
async _wsRpc(method, params) {
|
|
334
|
+
if (!this.isConnected) {
|
|
335
|
+
throw new Error('Not connected');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return new Promise((resolve, reject) => {
|
|
339
|
+
const id = this.requestId++;
|
|
340
|
+
const timeout = setTimeout(() => {
|
|
341
|
+
this.pendingRequests.delete(id);
|
|
342
|
+
reject(new Error('Request timeout'));
|
|
343
|
+
}, 30000);
|
|
344
|
+
|
|
345
|
+
this.pendingRequests.set(id, {
|
|
346
|
+
resolve: (result) => {
|
|
347
|
+
clearTimeout(timeout);
|
|
348
|
+
resolve(result);
|
|
349
|
+
},
|
|
350
|
+
reject: (error) => {
|
|
351
|
+
clearTimeout(timeout);
|
|
352
|
+
reject(error);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
this.ws.send(JSON.stringify({
|
|
357
|
+
jsonrpc: '2.0',
|
|
358
|
+
id,
|
|
359
|
+
method,
|
|
360
|
+
params
|
|
361
|
+
}));
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
module.exports = { SyncManager };
|
package/package.json
CHANGED
|
@@ -1,53 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jaelis-node",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Official JAELIS Blockchain Node -
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Official JAELIS Blockchain External Node - Connect to the JAELIS network, sync blocks, and expose local RPC for your dApps. Zero gas fees, multi-chain interop.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"jaelis-node": "./bin/jaelis-node.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"lib/",
|
|
11
|
+
"bin/",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
9
14
|
"scripts": {
|
|
10
|
-
"start": "node bin/jaelis-node.js
|
|
11
|
-
"start:testnet": "node bin/jaelis-node.js
|
|
12
|
-
"start:mainnet": "node bin/jaelis-node.js
|
|
13
|
-
"validator": "node bin/jaelis-node.js validator",
|
|
14
|
-
"bootstrap": "node bin/jaelis-node.js bootstrap",
|
|
15
|
-
"status": "node bin/jaelis-node.js status",
|
|
16
|
-
"test": "node test/node.test.js"
|
|
15
|
+
"start": "node bin/jaelis-node.js",
|
|
16
|
+
"start:testnet": "node bin/jaelis-node.js --network testnet",
|
|
17
|
+
"start:mainnet": "node bin/jaelis-node.js --network mainnet"
|
|
17
18
|
},
|
|
18
19
|
"keywords": [
|
|
19
20
|
"jaelis",
|
|
20
21
|
"blockchain",
|
|
21
22
|
"node",
|
|
22
|
-
"
|
|
23
|
-
"p2p",
|
|
23
|
+
"rpc",
|
|
24
24
|
"web3",
|
|
25
25
|
"ethereum",
|
|
26
|
+
"solana",
|
|
27
|
+
"multi-chain",
|
|
26
28
|
"zero-gas",
|
|
27
|
-
"zero-fee",
|
|
28
|
-
"proof-of-stake",
|
|
29
|
-
"poec",
|
|
30
|
-
"consensus",
|
|
31
|
-
"decentralized",
|
|
32
|
-
"crypto",
|
|
33
|
-
"cryptocurrency",
|
|
34
|
-
"ai-native",
|
|
35
|
-
"mcp",
|
|
36
|
-
"full-node",
|
|
37
|
-
"bootstrap-node",
|
|
38
|
-
"rpc-server",
|
|
39
|
-
"cross-chain",
|
|
40
|
-
"settlement",
|
|
41
|
-
"light-client",
|
|
42
29
|
"interoperability",
|
|
43
|
-
"
|
|
44
|
-
"solana",
|
|
45
|
-
"arbitrum",
|
|
46
|
-
"polygon",
|
|
47
|
-
"optimism"
|
|
30
|
+
"decentralized"
|
|
48
31
|
],
|
|
49
32
|
"author": "JAELIS Foundation",
|
|
50
33
|
"license": "MIT",
|
|
34
|
+
"homepage": "https://jaelis.io",
|
|
51
35
|
"repository": {
|
|
52
36
|
"type": "git",
|
|
53
37
|
"url": "https://github.com/jaelis-foundation/jaelis-node"
|
|
@@ -55,30 +39,12 @@
|
|
|
55
39
|
"bugs": {
|
|
56
40
|
"url": "https://github.com/jaelis-foundation/jaelis-node/issues"
|
|
57
41
|
},
|
|
58
|
-
"homepage": "https://jaelis.io",
|
|
59
42
|
"engines": {
|
|
60
43
|
"node": ">=18.0.0"
|
|
61
44
|
},
|
|
62
45
|
"dependencies": {
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
"@libp2p/tcp": "^9.1.6",
|
|
68
|
-
"@multiformats/multiaddr": "^13.0.1",
|
|
69
|
-
"chalk": "^4.1.2",
|
|
70
|
-
"commander": "^11.1.0",
|
|
71
|
-
"cors": "^2.8.5",
|
|
72
|
-
"express": "^4.18.2",
|
|
73
|
-
"level": "^8.0.0",
|
|
74
|
-
"libp2p": "^1.2.0",
|
|
75
|
-
"ora": "^5.4.1",
|
|
76
|
-
"ws": "^8.18.3"
|
|
77
|
-
},
|
|
78
|
-
"files": [
|
|
79
|
-
"bin/",
|
|
80
|
-
"lib/",
|
|
81
|
-
"config/",
|
|
82
|
-
"README.md"
|
|
83
|
-
]
|
|
46
|
+
"ws": "^8.18.0",
|
|
47
|
+
"level": "^8.0.1",
|
|
48
|
+
"commander": "^12.1.0"
|
|
49
|
+
}
|
|
84
50
|
}
|