jaelis-node 1.7.0 → 1.8.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 CHANGED
@@ -440,6 +440,22 @@ JAELIS implements three patent-pending systems:
440
440
  - Address poisoning detection
441
441
  - No trusted setup for privacy features
442
442
 
443
+ ## AI Integration (MCP)
444
+
445
+ JAELIS is AI-native. Claude Desktop users can interact with the blockchain through MCP (Model Context Protocol):
446
+
447
+ ```json
448
+ {
449
+ "mcpServers": {
450
+ "jaelis": {
451
+ "url": "https://mcp.jaelis.io/sse"
452
+ }
453
+ }
454
+ }
455
+ ```
456
+
457
+ Add this to your Claude Desktop config and get 274+ JAELIS tools automatically - create wallets, send transactions, deploy contracts, query balances, and more.
458
+
443
459
  ## Links
444
460
 
445
461
  - SDK: [npmjs.com/package/jaelis.js](https://www.npmjs.com/package/jaelis.js)
@@ -42,10 +42,10 @@ const NETWORKS = {
42
42
  name: 'JAELIS Testnet',
43
43
  symbol: 'tJAELIS',
44
44
  rpcUrl: 'https://rpc.jaelis.io',
45
+ // Bootstrap via DNS - rpc.jaelis.io resolves to 73.116.51.60
46
+ // No peer ID needed - learned during libp2p handshake
45
47
  bootstrapNodes: [
46
- '/dns4/rpc.jaelis.io/tcp/30305/p2p/QmBootstrap1',
47
- '/dns4/rpc.jaelis.io/tcp/30306/p2p/QmBootstrap2',
48
- '/dns4/rpc.jaelis.io/tcp/30307/p2p/QmBootstrap3'
48
+ '/dns4/rpc.jaelis.io/tcp/30303'
49
49
  ]
50
50
  },
51
51
  mainnet: {
@@ -8,9 +8,7 @@
8
8
  "name": "testnet",
9
9
  "chainId": 4545,
10
10
  "bootstrapNodes": [
11
- "/dns4/rpc.jaelis.io/tcp/30305/p2p/QmBootstrap1",
12
- "/dns4/rpc.jaelis.io/tcp/30306/p2p/QmBootstrap2",
13
- "/dns4/rpc.jaelis.io/tcp/30307/p2p/QmBootstrap3"
11
+ "/dns4/rpc.jaelis.io/tcp/30303"
14
12
  ]
15
13
  },
16
14
  "rpc": {
@@ -8,9 +8,7 @@
8
8
  "https://rpc.jaelis.io"
9
9
  ],
10
10
  "bootstrapNodes": [
11
- "/dns4/rpc.jaelis.io/tcp/30305/p2p/QmBootstrap1",
12
- "/dns4/rpc.jaelis.io/tcp/30306/p2p/QmBootstrap2",
13
- "/dns4/rpc.jaelis.io/tcp/30307/p2p/QmBootstrap3"
11
+ "/dns4/rpc.jaelis.io/tcp/30303"
14
12
  ],
15
13
  "genesis": {
16
14
  "timestamp": 1731398400000,
package/lib/index.js CHANGED
@@ -762,7 +762,8 @@ class JaelisNode extends EventEmitter {
762
762
  method: 'POST',
763
763
  headers: {
764
764
  'Content-Type': 'application/json',
765
- 'Content-Length': Buffer.byteLength(data)
765
+ 'Content-Length': Buffer.byteLength(data),
766
+ 'User-Agent': 'JAELIS-Node/1.7.0' // Identifies us as a node - gets priority treatment
766
767
  }
767
768
  };
768
769
 
@@ -825,7 +826,8 @@ class JaelisNode extends EventEmitter {
825
826
  method: 'POST',
826
827
  headers: {
827
828
  'Content-Type': 'application/json',
828
- 'Content-Length': Buffer.byteLength(data)
829
+ 'Content-Length': Buffer.byteLength(data),
830
+ 'User-Agent': 'JAELIS-Node/1.7.0' // Identifies us as a node - gets priority treatment
829
831
  }
830
832
  };
831
833
 
@@ -1102,23 +1104,46 @@ class EmbeddedBlockchain {
1102
1104
  * Validates the block before adding to chain
1103
1105
  */
1104
1106
  async addBlock(block) {
1105
- if (!block || !block.number) {
1107
+ if (!block || block.number === undefined) {
1106
1108
  throw new Error('Invalid block');
1107
1109
  }
1108
1110
 
1111
+ // Normalize block number - could be hex string (0x1) or decimal
1112
+ let blockNumber = block.number;
1113
+ if (typeof blockNumber === 'string') {
1114
+ if (blockNumber.startsWith('0x')) {
1115
+ blockNumber = parseInt(blockNumber, 16);
1116
+ } else {
1117
+ blockNumber = parseInt(blockNumber, 10);
1118
+ }
1119
+ }
1120
+
1109
1121
  const expectedNumber = this.chain.length;
1110
- if (block.number !== expectedNumber) {
1122
+ if (blockNumber !== expectedNumber) {
1111
1123
  // Skip if we already have this block or it's out of order
1112
- if (block.number < expectedNumber) {
1124
+ if (blockNumber < expectedNumber) {
1113
1125
  return { status: 'skipped', reason: 'already_have' };
1114
1126
  }
1115
- throw new Error(`Block out of order: expected ${expectedNumber}, got ${block.number}`);
1127
+ throw new Error(`Block out of order: expected ${expectedNumber}, got ${blockNumber}`);
1116
1128
  }
1117
1129
 
1118
- // Validate parent hash
1130
+ // Store normalized block number for consistency
1131
+ block.number = blockNumber;
1132
+
1133
+ // Validate parent hash (skip for first sync - genesis hash may differ)
1134
+ // Like Ethereum "fast sync" - we trust the RPC source initially
1119
1135
  const parentBlock = this.getLatestBlock();
1120
- if (block.parentHash && parentBlock.hash && block.parentHash !== parentBlock.hash) {
1121
- throw new Error('Invalid parent hash - possible chain reorg');
1136
+ if (blockNumber > 1 && block.parentHash && parentBlock.hash) {
1137
+ // Only validate parent hash for blocks after genesis
1138
+ // During initial sync, parent hashes are validated by the remote node
1139
+ if (block.parentHash !== parentBlock.hash) {
1140
+ // Check if this is initial sync (chain is mostly empty)
1141
+ if (this.chain.length > 10) {
1142
+ throw new Error('Invalid parent hash - possible chain reorg');
1143
+ }
1144
+ // During initial sync, log but continue
1145
+ console.log(`[SYNC] Accepting block ${blockNumber} (trusting remote during initial sync)`);
1146
+ }
1122
1147
  }
1123
1148
 
1124
1149
  // Add block to chain
@@ -1215,9 +1240,10 @@ class EmbeddedNetwork {
1215
1240
  const { tcp } = await import('@libp2p/tcp');
1216
1241
  const { noise } = await import('@chainsafe/libp2p-noise');
1217
1242
  const { yamux } = await import('@chainsafe/libp2p-yamux');
1218
- const { bootstrap } = await import('@libp2p/bootstrap');
1219
1243
  const { identify } = await import('@libp2p/identify');
1220
1244
 
1245
+ // Create libp2p node - JAELIS user node
1246
+ // Like Ethereum: start listening, bootstrap nodes come later via DHT
1221
1247
  const config = {
1222
1248
  addresses: {
1223
1249
  listen: [`/ip4/${this.host}/tcp/${this.port}`]
@@ -1230,17 +1256,11 @@ class EmbeddedNetwork {
1230
1256
  }
1231
1257
  };
1232
1258
 
1233
- // Add bootstrap if we have nodes
1234
- if (this.bootstrapNodes.length > 0) {
1235
- const validBootstrap = this.bootstrapNodes.filter(n => n.includes('/p2p/'));
1236
- if (validBootstrap.length > 0) {
1237
- config.peerDiscovery = [bootstrap({ list: validBootstrap })];
1238
- }
1239
- }
1240
-
1241
1259
  this.libp2p = await createLibp2p(config);
1242
1260
  await this.libp2p.start();
1243
1261
 
1262
+ console.log(`[P2P] Node started with ID: ${this.libp2p.peerId.toString().slice(0, 16)}...`);
1263
+
1244
1264
  // Track peers
1245
1265
  this.libp2p.addEventListener('peer:connect', (evt) => {
1246
1266
  const peerId = evt.detail.toString();
@@ -1253,6 +1273,20 @@ class EmbeddedNetwork {
1253
1273
  this.peers.delete(peerId);
1254
1274
  console.log(`[P2P] Peer disconnected (${this.peers.size} remaining)`);
1255
1275
  });
1276
+
1277
+ // Try to dial bootstrap nodes directly (without peer ID)
1278
+ // Like Ethereum: we connect via TCP, then learn peer ID during handshake
1279
+ for (const addr of this.bootstrapNodes) {
1280
+ try {
1281
+ const { multiaddr } = await import('@multiformats/multiaddr');
1282
+ const ma = multiaddr(addr);
1283
+ await this.libp2p.dial(ma);
1284
+ console.log(`[P2P] Connected to bootstrap: ${addr}`);
1285
+ } catch (err) {
1286
+ // Bootstrap unavailable - this is OK, we'll use RPC fallback
1287
+ console.log(`[P2P] Bootstrap ${addr.slice(0, 30)}... unavailable`);
1288
+ }
1289
+ }
1256
1290
  }
1257
1291
 
1258
1292
  async _startRPCFallback() {
@@ -1287,7 +1321,8 @@ class EmbeddedNetwork {
1287
1321
  method: 'POST',
1288
1322
  headers: {
1289
1323
  'Content-Type': 'application/json',
1290
- 'Content-Length': Buffer.byteLength(data)
1324
+ 'Content-Length': Buffer.byteLength(data),
1325
+ 'User-Agent': 'JAELIS-Node/1.7.0' // Node sync traffic - exempt from rate limits
1291
1326
  }
1292
1327
  }, (res) => {
1293
1328
  let body = '';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jaelis-node",
3
- "version": "1.7.0",
4
- "description": "Official JAELIS Blockchain Node - Universal VM (6 languages), LevelDB state persistence, native jaelis_* RPC, multi-ecosystem compatibility (eth/solana/move/ton/btc/wasm/starknet), Cross-Chain Settlement (30+ chains!)",
3
+ "version": "1.8.0",
4
+ "description": "Official JAELIS Blockchain Node - Universal VM (6 languages), LevelDB state persistence, native jaelis_* RPC, multi-ecosystem compatibility (eth/solana/move/ton/btc/wasm/starknet), Cross-Chain Settlement (30+ chains!), AI-native MCP integration",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
7
7
  "jaelis-node": "./bin/jaelis-node.js"
@@ -60,17 +60,18 @@
60
60
  "node": ">=18.0.0"
61
61
  },
62
62
  "dependencies": {
63
+ "@chainsafe/libp2p-noise": "^15.1.2",
64
+ "@chainsafe/libp2p-yamux": "^6.0.2",
65
+ "@libp2p/bootstrap": "^10.1.5",
66
+ "@libp2p/identify": "^1.0.21",
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",
63
73
  "level": "^8.0.0",
64
74
  "libp2p": "^1.2.0",
65
- "@libp2p/tcp": "^9.0.0",
66
- "@libp2p/bootstrap": "^10.0.0",
67
- "@libp2p/identify": "^1.0.0",
68
- "@chainsafe/libp2p-noise": "^15.0.0",
69
- "@chainsafe/libp2p-yamux": "^6.0.0",
70
- "express": "^4.18.2",
71
- "cors": "^2.8.5",
72
- "commander": "^11.1.0",
73
- "chalk": "^4.1.2",
74
75
  "ora": "^5.4.1"
75
76
  },
76
77
  "files": [