@dignetwork/dig-sdk 0.0.1-alpha.98 → 0.1.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.
Files changed (162) hide show
  1. package/LICENSE +21 -7
  2. package/README.md +267 -0
  3. package/dist/adapters.cjs +315 -0
  4. package/dist/adapters.cjs.map +1 -0
  5. package/dist/adapters.d.cts +20 -0
  6. package/dist/adapters.d.ts +20 -0
  7. package/dist/adapters.js +306 -0
  8. package/dist/adapters.js.map +1 -0
  9. package/dist/dev-shim-Bgw8X2E9.d.cts +118 -0
  10. package/dist/dev-shim-Bgw8X2E9.d.ts +118 -0
  11. package/dist/dig-client-entry-BIzuZ7Rs.d.cts +263 -0
  12. package/dist/dig-client-entry-BIzuZ7Rs.d.ts +263 -0
  13. package/dist/dig-client.cjs +330 -0
  14. package/dist/dig-client.cjs.map +1 -0
  15. package/dist/dig-client.d.cts +1 -0
  16. package/dist/dig-client.d.ts +1 -0
  17. package/dist/dig-client.js +319 -0
  18. package/dist/dig-client.js.map +1 -0
  19. package/dist/index.cjs +754 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.cts +192 -0
  22. package/dist/index.d.ts +192 -5
  23. package/dist/index.js +731 -19
  24. package/dist/index.js.map +1 -0
  25. package/dist/next.cjs +326 -0
  26. package/dist/next.cjs.map +1 -0
  27. package/dist/next.d.cts +23 -0
  28. package/dist/next.d.ts +23 -0
  29. package/dist/next.js +319 -0
  30. package/dist/next.js.map +1 -0
  31. package/dist/spend.cjs +14 -0
  32. package/dist/spend.cjs.map +1 -0
  33. package/dist/spend.d.cts +1 -0
  34. package/dist/spend.d.ts +1 -0
  35. package/dist/spend.js +3 -0
  36. package/dist/spend.js.map +1 -0
  37. package/dist/vite.cjs +338 -0
  38. package/dist/vite.cjs.map +1 -0
  39. package/dist/vite.d.cts +35 -0
  40. package/dist/vite.d.ts +35 -0
  41. package/dist/vite.js +332 -0
  42. package/dist/vite.js.map +1 -0
  43. package/package.json +87 -59
  44. package/vendor/PROVENANCE.md +102 -0
  45. package/vendor/dig_client.d.ts +150 -0
  46. package/vendor/dig_client.mjs +805 -0
  47. package/vendor/dig_client_bg.wasm +0 -0
  48. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +0 -163
  49. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +0 -1
  50. package/dist/DataIntegrityTree/DataIntegrityTree.js +0 -707
  51. package/dist/DataIntegrityTree/DataLayerError.d.ts +0 -6
  52. package/dist/DataIntegrityTree/DataLayerError.d.ts.map +0 -1
  53. package/dist/DataIntegrityTree/DataLayerError.js +0 -17
  54. package/dist/DataIntegrityTree/index.d.ts +0 -2
  55. package/dist/DataIntegrityTree/index.d.ts.map +0 -1
  56. package/dist/DataIntegrityTree/index.js +0 -17
  57. package/dist/DigNetwork/ContentServer.d.ts +0 -33
  58. package/dist/DigNetwork/ContentServer.d.ts.map +0 -1
  59. package/dist/DigNetwork/ContentServer.js +0 -308
  60. package/dist/DigNetwork/DigChallenge.d.ts +0 -82
  61. package/dist/DigNetwork/DigChallenge.d.ts.map +0 -1
  62. package/dist/DigNetwork/DigChallenge.js +0 -144
  63. package/dist/DigNetwork/DigNetwork.d.ts +0 -14
  64. package/dist/DigNetwork/DigNetwork.d.ts.map +0 -1
  65. package/dist/DigNetwork/DigNetwork.js +0 -169
  66. package/dist/DigNetwork/DigPeer.d.ts +0 -24
  67. package/dist/DigNetwork/DigPeer.d.ts.map +0 -1
  68. package/dist/DigNetwork/DigPeer.js +0 -118
  69. package/dist/DigNetwork/IncentiveServer.d.ts +0 -13
  70. package/dist/DigNetwork/IncentiveServer.d.ts.map +0 -1
  71. package/dist/DigNetwork/IncentiveServer.js +0 -76
  72. package/dist/DigNetwork/PropagationServer.d.ts +0 -75
  73. package/dist/DigNetwork/PropagationServer.d.ts.map +0 -1
  74. package/dist/DigNetwork/PropagationServer.js +0 -536
  75. package/dist/DigNetwork/index.d.ts +0 -4
  76. package/dist/DigNetwork/index.d.ts.map +0 -1
  77. package/dist/DigNetwork/index.js +0 -19
  78. package/dist/blockchain/DataStore.d.ts +0 -67
  79. package/dist/blockchain/DataStore.d.ts.map +0 -1
  80. package/dist/blockchain/DataStore.js +0 -413
  81. package/dist/blockchain/DataStoreSerializer.d.ts +0 -52
  82. package/dist/blockchain/DataStoreSerializer.d.ts.map +0 -1
  83. package/dist/blockchain/DataStoreSerializer.js +0 -109
  84. package/dist/blockchain/FullNodePeer.d.ts +0 -31
  85. package/dist/blockchain/FullNodePeer.d.ts.map +0 -1
  86. package/dist/blockchain/FullNodePeer.js +0 -295
  87. package/dist/blockchain/ServerCoin.d.ts +0 -29
  88. package/dist/blockchain/ServerCoin.d.ts.map +0 -1
  89. package/dist/blockchain/ServerCoin.js +0 -321
  90. package/dist/blockchain/Wallet.d.ts +0 -28
  91. package/dist/blockchain/Wallet.d.ts.map +0 -1
  92. package/dist/blockchain/Wallet.js +0 -253
  93. package/dist/blockchain/coins.d.ts +0 -6
  94. package/dist/blockchain/coins.d.ts.map +0 -1
  95. package/dist/blockchain/coins.js +0 -102
  96. package/dist/blockchain/index.d.ts +0 -8
  97. package/dist/blockchain/index.d.ts.map +0 -1
  98. package/dist/blockchain/index.js +0 -36
  99. package/dist/index.d.ts.map +0 -1
  100. package/dist/prompts.d.ts +0 -21
  101. package/dist/prompts.d.ts.map +0 -1
  102. package/dist/prompts.js +0 -149
  103. package/dist/types.d.ts +0 -64
  104. package/dist/types.d.ts.map +0 -1
  105. package/dist/types.js +0 -2
  106. package/dist/utils/ContentScanner.d.ts +0 -63
  107. package/dist/utils/ContentScanner.d.ts.map +0 -1
  108. package/dist/utils/ContentScanner.js +0 -175
  109. package/dist/utils/Environment.d.ts +0 -18
  110. package/dist/utils/Environment.d.ts.map +0 -1
  111. package/dist/utils/Environment.js +0 -85
  112. package/dist/utils/FileCache.d.ts +0 -11
  113. package/dist/utils/FileCache.d.ts.map +0 -1
  114. package/dist/utils/FileCache.js +0 -58
  115. package/dist/utils/FileTransfer.d.ts +0 -47
  116. package/dist/utils/FileTransfer.d.ts.map +0 -1
  117. package/dist/utils/FileTransfer.js +0 -209
  118. package/dist/utils/NconfManager.d.ts +0 -11
  119. package/dist/utils/NconfManager.d.ts.map +0 -1
  120. package/dist/utils/NconfManager.js +0 -56
  121. package/dist/utils/StoreArchiveManager.d.ts +0 -45
  122. package/dist/utils/StoreArchiveManager.d.ts.map +0 -1
  123. package/dist/utils/StoreArchiveManager.js +0 -153
  124. package/dist/utils/asyncPool.d.ts +0 -9
  125. package/dist/utils/asyncPool.d.ts.map +0 -1
  126. package/dist/utils/asyncPool.js +0 -23
  127. package/dist/utils/config.d.ts +0 -68
  128. package/dist/utils/config.d.ts.map +0 -1
  129. package/dist/utils/config.js +0 -223
  130. package/dist/utils/connectionUtils.d.ts +0 -10
  131. package/dist/utils/connectionUtils.d.ts.map +0 -1
  132. package/dist/utils/connectionUtils.js +0 -18
  133. package/dist/utils/credentialsUtils.d.ts +0 -8
  134. package/dist/utils/credentialsUtils.d.ts.map +0 -1
  135. package/dist/utils/credentialsUtils.js +0 -122
  136. package/dist/utils/directoryUtils.d.ts +0 -9
  137. package/dist/utils/directoryUtils.d.ts.map +0 -1
  138. package/dist/utils/directoryUtils.js +0 -110
  139. package/dist/utils/encryption.d.ts +0 -8
  140. package/dist/utils/encryption.d.ts.map +0 -1
  141. package/dist/utils/encryption.js +0 -55
  142. package/dist/utils/hashUtils.d.ts +0 -8
  143. package/dist/utils/hashUtils.d.ts.map +0 -1
  144. package/dist/utils/hashUtils.js +0 -44
  145. package/dist/utils/index.d.ts +0 -14
  146. package/dist/utils/index.d.ts.map +0 -1
  147. package/dist/utils/index.js +0 -29
  148. package/dist/utils/merkle.d.ts +0 -2
  149. package/dist/utils/merkle.d.ts.map +0 -1
  150. package/dist/utils/merkle.js +0 -28
  151. package/dist/utils/network.d.ts +0 -2
  152. package/dist/utils/network.d.ts.map +0 -1
  153. package/dist/utils/network.js +0 -54
  154. package/dist/utils/spinnerUtils.d.ts +0 -2
  155. package/dist/utils/spinnerUtils.d.ts.map +0 -1
  156. package/dist/utils/spinnerUtils.js +0 -47
  157. package/dist/utils/ssl.d.ts +0 -5
  158. package/dist/utils/ssl.d.ts.map +0 -1
  159. package/dist/utils/ssl.js +0 -50
  160. package/dist/utils/validationUtils.d.ts +0 -9
  161. package/dist/utils/validationUtils.d.ts.map +0 -1
  162. package/dist/utils/validationUtils.js +0 -55
@@ -1,295 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.FullNodePeer = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const os_1 = __importDefault(require("os"));
9
- const fs_1 = __importDefault(require("fs"));
10
- const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
11
- const chia_server_coin_1 = require("chia-server-coin");
12
- const promises_1 = require("dns/promises");
13
- const net_1 = __importDefault(require("net"));
14
- const lodash_1 = require("lodash");
15
- const nanospinner_1 = require("nanospinner");
16
- const config_1 = require("../utils/config");
17
- const Environment_1 = require("../utils/Environment");
18
- const FULLNODE_PORT = 8444;
19
- const LOCALHOST = "127.0.0.1";
20
- const CHIA_NODES_HOST = "chia-nodes";
21
- const DNS_HOSTS = [
22
- "dns-introducer.chia.net",
23
- "chia.ctrlaltdel.ch",
24
- "seeder.dexie.space",
25
- "chia.hoffmang.com",
26
- ];
27
- const CONNECTION_TIMEOUT = 2000;
28
- const CACHE_DURATION = 30000; // Cache duration in milliseconds
29
- class FullNodePeer {
30
- constructor(peer) {
31
- this.peer = peer;
32
- }
33
- /**
34
- * Connect to the best peer, optionally using custom certificate and key file paths.
35
- * @param {string} [certFilePath] - Optional custom certificate file path.
36
- * @param {string} [keyFilePath] - Optional custom key file path.
37
- * @returns {Promise<Peer>} The connected peer.
38
- */
39
- static async connect(certFilePath, keyFilePath) {
40
- const peer = await FullNodePeer.getBestPeer(certFilePath, keyFilePath);
41
- return new FullNodePeer(peer).peer;
42
- }
43
- static isPortReachable(host, port, timeout = CONNECTION_TIMEOUT) {
44
- return new Promise((resolve) => {
45
- const socket = new net_1.default.Socket()
46
- .setTimeout(timeout)
47
- .once("error", () => resolve(false))
48
- .once("timeout", () => resolve(false))
49
- .connect(port, host, () => {
50
- socket.end();
51
- resolve(true);
52
- });
53
- });
54
- }
55
- static isValidIpAddress(ip) {
56
- const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
57
- return ipv4Regex.test(ip);
58
- }
59
- /**
60
- * Retrieves the TRUSTED_FULLNODE IP from the environment
61
- * and verifies if it is a valid IP address.
62
- *
63
- * @returns {string | null} The valid IP address or null if invalid
64
- */
65
- static getTrustedFullNode() {
66
- const trustedNodeIp = Environment_1.Environment.TRUSTED_FULLNODE || null;
67
- if (trustedNodeIp && FullNodePeer.isValidIpAddress(trustedNodeIp)) {
68
- return trustedNodeIp;
69
- }
70
- return null;
71
- }
72
- static async fetchNewPeerIPs() {
73
- const trustedNodeIp = FullNodePeer.getTrustedFullNode();
74
- const priorityIps = [];
75
- // Prioritize trustedNodeIp unless it's deprioritized
76
- if (trustedNodeIp &&
77
- !FullNodePeer.deprioritizedIps.has(trustedNodeIp) &&
78
- (await FullNodePeer.isPortReachable(trustedNodeIp, FULLNODE_PORT))) {
79
- priorityIps.push(trustedNodeIp);
80
- }
81
- // Prioritize LOCALHOST unless it's deprioritized
82
- if (!FullNodePeer.deprioritizedIps.has(LOCALHOST) &&
83
- (await FullNodePeer.isPortReachable(LOCALHOST, FULLNODE_PORT))) {
84
- priorityIps.push(LOCALHOST);
85
- }
86
- // Prioritize CHIA_NODES_HOST unless it's deprioritized
87
- if (!FullNodePeer.deprioritizedIps.has(CHIA_NODES_HOST) &&
88
- (await FullNodePeer.isPortReachable(CHIA_NODES_HOST, FULLNODE_PORT))) {
89
- priorityIps.push(CHIA_NODES_HOST);
90
- }
91
- if (priorityIps.length > 0) {
92
- return priorityIps;
93
- }
94
- // Fetch peers from DNS introducers
95
- for (const DNS_HOST of DNS_HOSTS) {
96
- try {
97
- const ips = await (0, promises_1.resolve4)(DNS_HOST);
98
- if (ips && ips.length > 0) {
99
- const shuffledIps = ips.sort(() => 0.5 - Math.random());
100
- const reachableIps = [];
101
- for (const ip of shuffledIps) {
102
- if (await FullNodePeer.isPortReachable(ip, FULLNODE_PORT)) {
103
- reachableIps.push(ip);
104
- }
105
- if (reachableIps.length === 5)
106
- break;
107
- }
108
- if (reachableIps.length > 0) {
109
- return reachableIps;
110
- }
111
- }
112
- }
113
- catch (error) {
114
- console.error(`Failed to resolve IPs from ${DNS_HOST}: ${error.message}`);
115
- }
116
- }
117
- throw new Error("No reachable IPs found in any DNS records.");
118
- }
119
- static async getPeerIPs() {
120
- const ips = await FullNodePeer.memoizedFetchNewPeerIPs();
121
- const reachableIps = await Promise.all(ips.map(async (ip) => {
122
- if (ip && (await FullNodePeer.isPortReachable(ip, FULLNODE_PORT))) {
123
- return ip;
124
- }
125
- return null;
126
- })).then((results) => results.filter((ip) => ip !== null));
127
- if (reachableIps.length > 0) {
128
- return reachableIps;
129
- }
130
- // @ts-ignore
131
- if (FullNodePeer.memoizedFetchNewPeerIPs?.cache?.clear) {
132
- // Clear cache and reset deprioritized IPs when cache is cleared
133
- FullNodePeer.deprioritizedIps.clear();
134
- // @ts-ignore
135
- FullNodePeer.memoizedFetchNewPeerIPs.cache.clear();
136
- }
137
- return FullNodePeer.memoizedFetchNewPeerIPs();
138
- }
139
- static createPeerProxy(peer) {
140
- return new Proxy(peer, {
141
- get: (target, prop) => {
142
- const originalMethod = target[prop];
143
- if (typeof originalMethod === "function") {
144
- return async (...args) => {
145
- let timeoutId;
146
- // Start the timeout to forget the peer after 1 minute
147
- const timeoutPromise = new Promise((_, reject) => {
148
- timeoutId = setTimeout(() => {
149
- FullNodePeer.cachedPeer = null;
150
- reject(new Error("Operation timed out. Reconnecting to a new peer."));
151
- }, 60000); // 1 minute
152
- });
153
- try {
154
- // Run the original method and race it against the timeout
155
- const result = await Promise.race([
156
- originalMethod.apply(target, args),
157
- timeoutPromise,
158
- ]);
159
- // Clear the timeout if the operation succeeded
160
- if (timeoutId) {
161
- clearTimeout(timeoutId);
162
- }
163
- return result;
164
- }
165
- catch (error) {
166
- // If the error is WebSocket-related or timeout, reset the peer
167
- if (error.message.includes("WebSocket") ||
168
- error.message.includes("Operation timed out")) {
169
- FullNodePeer.cachedPeer = null;
170
- // @ts-ignore
171
- FullNodePeer.memoizedFetchNewPeerIPs.cache.clear();
172
- FullNodePeer.deprioritizedIps.clear();
173
- console.info(`Fullnode Peer error, reconnecting to a new peer...`);
174
- const newPeer = await FullNodePeer.getBestPeer();
175
- return newPeer[prop](...args);
176
- }
177
- throw error;
178
- }
179
- };
180
- }
181
- return originalMethod;
182
- },
183
- });
184
- }
185
- static async getBestPeer(certFilePath, keyFilePath) {
186
- const now = Date.now();
187
- if (FullNodePeer.cachedPeer &&
188
- now - FullNodePeer.cachedPeer.timestamp < CACHE_DURATION) {
189
- return FullNodePeer.cachedPeer.peer;
190
- }
191
- let certFile;
192
- let keyFile;
193
- // If certFilePath or keyFilePath is provided, ensure both are provided
194
- if (certFilePath && keyFilePath) {
195
- certFile = certFilePath;
196
- keyFile = keyFilePath;
197
- if (!fs_1.default.existsSync(certFile)) {
198
- throw new Error(`Certificate file not found: ${certFile}`);
199
- }
200
- if (!fs_1.default.existsSync(keyFile)) {
201
- throw new Error(`Key file not found: ${keyFile}`);
202
- }
203
- }
204
- else {
205
- // Use default paths if no custom paths are provided
206
- const sslFolder = path_1.default.resolve(os_1.default.homedir(), ".dig", "ssl");
207
- certFile = path_1.default.join(sslFolder, "public_dig.crt");
208
- keyFile = path_1.default.join(sslFolder, "public_dig.key");
209
- if (!fs_1.default.existsSync(sslFolder)) {
210
- throw new Error(`SSL folder not found: ${sslFolder}`);
211
- }
212
- }
213
- new chia_server_coin_1.Tls(certFile, keyFile);
214
- const peerIPs = await FullNodePeer.getPeerIPs();
215
- const trustedNodeIp = Environment_1.Environment.TRUSTED_FULLNODE || null;
216
- const peers = await Promise.all(peerIPs.map(async (ip) => {
217
- if (ip) {
218
- // Allow override of the trusted fullnode port if the override exists
219
- let port = FULLNODE_PORT;
220
- if (trustedNodeIp && ip === trustedNodeIp) {
221
- const trustedFullNodePort = Environment_1.Environment.TRUSTED_FULLNODE_PORT;
222
- if (trustedFullNodePort) {
223
- port = trustedFullNodePort;
224
- }
225
- }
226
- try {
227
- const peer = await datalayer_driver_1.Peer.new(`${ip}:${port}`, false, certFile, keyFile);
228
- return FullNodePeer.createPeerProxy(peer);
229
- }
230
- catch (error) {
231
- console.error(`Failed to create peer for IP ${ip}: ${error.message}`);
232
- return null;
233
- }
234
- }
235
- return null;
236
- })).then((results) => results.filter((peer) => peer !== null));
237
- if (peers.length === 0) {
238
- throw new Error("No peers available, please try again.");
239
- }
240
- await new Promise((resolve) => setTimeout(resolve, 1000));
241
- const peakHeights = await Promise.all(peers.map((peer) => peer
242
- .getPeak()
243
- .then((height) => height)
244
- .catch((error) => {
245
- console.error(`Failed to get peak for peer: ${error.message}`);
246
- return null;
247
- })));
248
- const validHeights = peakHeights.filter((height) => height !== null);
249
- if (validHeights.length === 0) {
250
- throw new Error("No valid peak heights obtained from any peer.");
251
- }
252
- const highestPeak = Math.max(...validHeights);
253
- // Prioritize LOCALHOST, TRUSTED_NODE_IP, and CHIA_NODES_HOST if they have the highest peak height
254
- let bestPeerIndex = validHeights.findIndex((height, index) => height === highestPeak &&
255
- !FullNodePeer.deprioritizedIps.has(peerIPs[index]) && // Exclude deprioritized IPs
256
- (peerIPs[index] === LOCALHOST ||
257
- peerIPs[index] === trustedNodeIp ||
258
- peerIPs[index] === CHIA_NODES_HOST));
259
- // If LOCALHOST, TRUSTED_NODE_IP, or CHIA_NODES_HOST don't have the highest peak, select any peer with the highest peak
260
- if (bestPeerIndex === -1) {
261
- bestPeerIndex = validHeights.findIndex((height) => height === highestPeak);
262
- }
263
- const bestPeer = peers[bestPeerIndex];
264
- FullNodePeer.cachedPeer = { peer: bestPeer, timestamp: now };
265
- console.log(`Using Fullnode Peer: ${peerIPs[bestPeerIndex]}`);
266
- return bestPeer;
267
- }
268
- getPeer() {
269
- return this.peer;
270
- }
271
- static async waitForConfirmation(parentCoinInfo) {
272
- const spinner = (0, nanospinner_1.createSpinner)("Waiting for confirmation...").start();
273
- const peer = await FullNodePeer.connect();
274
- try {
275
- while (true) {
276
- const confirmed = await peer.isCoinSpent(parentCoinInfo, config_1.MIN_HEIGHT, Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex"));
277
- if (confirmed) {
278
- spinner.success({ text: "Coin confirmed!" });
279
- return true;
280
- }
281
- await new Promise((resolve) => setTimeout(resolve, 5000));
282
- }
283
- }
284
- catch (error) {
285
- spinner.error({ text: "Error while waiting for confirmation." });
286
- throw error;
287
- }
288
- }
289
- }
290
- exports.FullNodePeer = FullNodePeer;
291
- FullNodePeer.cachedPeer = null;
292
- FullNodePeer.deprioritizedIps = new Set(); // New set for deprioritized IPs
293
- (() => {
294
- FullNodePeer.memoizedFetchNewPeerIPs = (0, lodash_1.memoize)(FullNodePeer.fetchNewPeerIPs);
295
- })();
@@ -1,29 +0,0 @@
1
- import { ServerCoin as ServerCoinDriver } from "@dignetwork/datalayer-driver";
2
- import { NconfManager } from "../utils/NconfManager";
3
- export declare class ServerCoin {
4
- private storeId;
5
- static readonly serverCoinManager: NconfManager;
6
- constructor(storeId: string);
7
- createForEpoch(peerIp: string, rootHash: string): Promise<ServerCoinDriver>;
8
- saveServerCoinData(serverCoin: ServerCoinDriver, epoch: number, peerIp: string, rootHash: string): Promise<void>;
9
- melt(epoch: number, peerIp: string): Promise<void>;
10
- private removeServerCoinData;
11
- getAllEpochPeers(epoch: number, blacklist?: string[]): Promise<string[]>;
12
- getActiveEpochPeers(blacklist?: string[]): Promise<string[]>;
13
- sampleCurrentEpoch(sampleSize?: number, blacklist?: string[]): Promise<string[]>;
14
- sampleServerCoinsByEpoch(epoch: number, sampleSize?: number, blacklist?: string[]): Promise<string[]>;
15
- static getCurrentEpoch(): {
16
- epoch: number;
17
- round: number;
18
- };
19
- ensureServerCoinExists(peerIp: string): Promise<void>;
20
- meltOutdatedEpochs(peerIp: string): Promise<void>;
21
- static meltUntrackedStoreCoins(): Promise<void>;
22
- private getServerCoinsForStore;
23
- hasEpochCoinBeenCreated(currentEpoch: number, peerIp: string): Promise<boolean>;
24
- static calculateEpochAndRound(currentTimestampUTC: Date): {
25
- epoch: number;
26
- round: number;
27
- };
28
- }
29
- //# sourceMappingURL=ServerCoin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServerCoin.d.ts","sourceRoot":"","sources":["../../src/blockchain/ServerCoin.ts"],"names":[],"mappings":"AACA,OAAO,EAML,UAAU,IAAI,gBAAgB,EAE/B,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAYrD,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,gBAAuB,iBAAiB,eAEtC;gBAEU,OAAO,EAAE,MAAM;IAKd,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4D3E,kBAAkB,CAC7B,UAAU,EAAE,gBAAgB,EAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAsBH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAoDjD,oBAAoB;IAerB,gBAAgB,CAC3B,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC;IAgDP,mBAAmB,CAC9B,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC;IAMP,kBAAkB,CAC7B,UAAU,GAAE,MAAU,EACtB,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC;IAMP,wBAAwB,CACnC,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAU,EACtB,SAAS,GAAE,MAAM,EAAO,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC;WAeN,eAAe,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAKpD,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiFrD,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WA+B1C,uBAAuB;YAkE7B,sBAAsB;IAWvB,uBAAuB,CAClC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC;WAuBL,sBAAsB,CAAC,mBAAmB,EAAE,IAAI,GAAG;QAC/D,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACf;CA2BF"}
@@ -1,321 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ServerCoin = void 0;
7
- const lodash_1 = __importDefault(require("lodash"));
8
- const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
9
- const FullNodePeer_1 = require("./FullNodePeer");
10
- const coins_1 = require("./coins");
11
- const Wallet_1 = require("./Wallet");
12
- const NconfManager_1 = require("../utils/NconfManager");
13
- const DataStore_1 = require("./DataStore");
14
- const node_cache_1 = __importDefault(require("node-cache"));
15
- const network_1 = require("../utils/network");
16
- const Environment_1 = require("../utils/Environment");
17
- const serverCoinCollateral = 300000000;
18
- // Initialize the cache with a TTL of 300 seconds (5 minutes)
19
- const serverCoinPeersCache = new node_cache_1.default({ stdTTL: 300 });
20
- class ServerCoin {
21
- constructor(storeId) {
22
- this.storeId = storeId;
23
- }
24
- // Create a new server coin for the current epoch
25
- async createForEpoch(peerIp, rootHash) {
26
- try {
27
- const peer = await FullNodePeer_1.FullNodePeer.connect();
28
- const wallet = await Wallet_1.Wallet.load("default");
29
- const publicSyntheticKey = await wallet.getPublicSyntheticKey();
30
- const serverCoinCreationCoins = await (0, coins_1.selectUnspentCoins)(peer, BigInt(serverCoinCollateral), BigInt(1000000));
31
- const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
32
- const epochBasedHint = (0, datalayer_driver_1.morphLauncherId)(Buffer.from(this.storeId, "hex"), BigInt(currentEpoch));
33
- const newServerCoin = (0, datalayer_driver_1.createServerCoin)(publicSyntheticKey, serverCoinCreationCoins, epochBasedHint, [peerIp], BigInt(serverCoinCollateral), BigInt(1000000));
34
- const combinedCoinSpends = [...newServerCoin.coinSpends];
35
- const sig = (0, datalayer_driver_1.signCoinSpends)(combinedCoinSpends, [await wallet.getPrivateSyntheticKey()], false);
36
- const err = await peer.broadcastSpend(combinedCoinSpends, [sig]);
37
- if (err) {
38
- if (err.includes("no spendable coins")) {
39
- console.log("No coins available. Will try again in 5 seconds...");
40
- await new Promise((resolve) => setTimeout(resolve, 5000));
41
- return this.createForEpoch(peerIp, rootHash);
42
- }
43
- throw new Error(err);
44
- }
45
- // Cache the new server coin in the NconfManager
46
- await this.saveServerCoinData(newServerCoin.serverCoin, currentEpoch, peerIp, rootHash);
47
- return newServerCoin.serverCoin;
48
- }
49
- catch (error) {
50
- throw new Error("Failed to create server coin: " + error.message);
51
- }
52
- }
53
- // Save the server coin data to NconfManager
54
- async saveServerCoinData(serverCoin, epoch, peerIp, rootHash) {
55
- const newServerCoinData = {
56
- coin: {
57
- amount: serverCoin.coin.amount.toString(),
58
- puzzleHash: serverCoin.coin.puzzleHash.toString("hex"),
59
- parentCoinInfo: serverCoin.coin.parentCoinInfo.toString("hex"),
60
- },
61
- createdAt: new Date().toISOString(),
62
- epoch,
63
- rootHash,
64
- };
65
- const serverCoins = await this.getServerCoinsForStore(peerIp);
66
- serverCoins.push(newServerCoinData);
67
- await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
68
- }
69
- // Melt server coin by epoch
70
- async melt(epoch, peerIp) {
71
- const peer = await FullNodePeer_1.FullNodePeer.connect();
72
- const wallet = await Wallet_1.Wallet.load("default");
73
- const publicSyntheticKey = await wallet.getPublicSyntheticKey();
74
- const serverCoins = await this.getServerCoinsForStore(peerIp);
75
- const serverCoin = serverCoins.find((coin) => coin.epoch === epoch);
76
- if (!serverCoin) {
77
- throw new Error(`No server coin found for epoch ${epoch} in store ${this.storeId}.`);
78
- }
79
- const feeCoins = await (0, coins_1.selectUnspentCoins)(peer, BigInt(0), BigInt(1000000));
80
- const coin = {
81
- amount: BigInt(serverCoin.coin.amount),
82
- puzzleHash: Buffer.from(serverCoin.coin.puzzleHash, "hex"),
83
- parentCoinInfo: Buffer.from(serverCoin.coin.parentCoinInfo, "hex"),
84
- };
85
- const serverCoinId = (0, datalayer_driver_1.getCoinId)(coin);
86
- console.log("Melt Coin ID: ", serverCoinId.toString("hex"));
87
- const spendBundle = await peer.lookupAndSpendServerCoins(publicSyntheticKey, [coin, ...feeCoins], BigInt(1000000), false);
88
- const sig = (0, datalayer_driver_1.signCoinSpends)(spendBundle, [await wallet.getPrivateSyntheticKey()], false);
89
- const err = await peer.broadcastSpend(spendBundle, [sig]);
90
- if (err) {
91
- throw new Error(err);
92
- }
93
- await FullNodePeer_1.FullNodePeer.waitForConfirmation(serverCoinId);
94
- // Remove the melted coin from the NconfManager
95
- await this.removeServerCoinData(serverCoin.coin, peerIp);
96
- }
97
- // Remove the melted server coin from NconfManager
98
- async removeServerCoinData(serverCoin, peerIp) {
99
- let serverCoins = await this.getServerCoinsForStore(peerIp);
100
- serverCoins = serverCoins.filter((coin) => coin.coin.parentCoinInfo !== serverCoin.parentCoinInfo);
101
- await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
102
- }
103
- async getAllEpochPeers(epoch, blacklist = []) {
104
- const cacheKey = `serverCoinPeers-${this.storeId}-${epoch}`;
105
- // Check if the result is already cached
106
- const cachedPeers = serverCoinPeersCache.get(cacheKey);
107
- if (cachedPeers) {
108
- return cachedPeers;
109
- }
110
- const epochBasedHint = (0, datalayer_driver_1.morphLauncherId)(Buffer.from(this.storeId, "hex"), BigInt(epoch));
111
- const peer = await FullNodePeer_1.FullNodePeer.connect();
112
- const maxClvmCost = BigInt(11000000000);
113
- const hintedCoinStates = await peer.getHintedCoinStates(epochBasedHint, false);
114
- const filteredCoinStates = hintedCoinStates.filter((coinState) => coinState.coin.amount >= serverCoinCollateral);
115
- // Use a Set to ensure uniqueness
116
- const serverCoinPeers = new Set();
117
- for (const coinState of filteredCoinStates) {
118
- const serverCoin = await peer.fetchServerCoin(coinState, maxClvmCost);
119
- const peerUrl = serverCoin.memoUrls[0];
120
- if (!blacklist.includes(peerUrl)) {
121
- serverCoinPeers.add(peerUrl);
122
- }
123
- }
124
- if (Environment_1.Environment.DEBUG) {
125
- console.log("Server Coin Peers: ", serverCoinPeers);
126
- }
127
- const peerList = Array.from(serverCoinPeers);
128
- // Cache the result
129
- serverCoinPeersCache.set(cacheKey, peerList);
130
- return peerList;
131
- }
132
- async getActiveEpochPeers(blacklist = []) {
133
- const { epoch } = ServerCoin.getCurrentEpoch();
134
- return this.getAllEpochPeers(epoch, blacklist);
135
- }
136
- // Sample server coins for the current epoch
137
- async sampleCurrentEpoch(sampleSize = 5, blacklist = []) {
138
- const { epoch } = ServerCoin.getCurrentEpoch();
139
- return this.sampleServerCoinsByEpoch(epoch, sampleSize, blacklist);
140
- }
141
- // Sample server coins by epoch
142
- async sampleServerCoinsByEpoch(epoch, sampleSize = 5, blacklist = []) {
143
- // We dont want our own IP to be included
144
- const myIp = await (0, network_1.getPublicIpAddress)();
145
- if (myIp) {
146
- blacklist.push(myIp);
147
- }
148
- const serverCoinPeers = await this.getAllEpochPeers(epoch, blacklist);
149
- if (Environment_1.Environment.DEBUG) {
150
- console.log("Server Coin Peers: ", serverCoinPeers);
151
- }
152
- return lodash_1.default.sampleSize(serverCoinPeers, sampleSize);
153
- }
154
- // Get the current epoch based on the current timestamp
155
- static getCurrentEpoch() {
156
- return ServerCoin.calculateEpochAndRound(new Date());
157
- }
158
- // Ensure server coin exists for the current epoch
159
- async ensureServerCoinExists(peerIp) {
160
- try {
161
- console.log(`Ensuring server coin exists for store ${this.storeId}...`);
162
- const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
163
- const serverCoins = await this.getServerCoinsForStore(peerIp);
164
- // Check if a server coin already exists for the current epoch
165
- const existingCoin = serverCoins.find((coin) => coin.epoch === currentEpoch);
166
- const dataStore = DataStore_1.DataStore.from(this.storeId);
167
- const rootHistory = await dataStore.getRootHistory(true);
168
- const lastRoot = lodash_1.default.last(rootHistory);
169
- if (!lastRoot) {
170
- throw new Error('Cant get the last root on chain, something is wrong.');
171
- }
172
- if (existingCoin) {
173
- // nothing to do
174
- if (lastRoot?.synced && lastRoot?.root_hash === existingCoin.rootHash) {
175
- return;
176
- }
177
- // everything is fine, lets just update the roothash for tracking
178
- if (lastRoot?.synced && lastRoot?.root_hash !== existingCoin.rootHash) {
179
- existingCoin.rootHash = lastRoot.root_hash;
180
- // Update the conf with the modified server coin
181
- await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
182
- return;
183
- }
184
- // If not synced, melt the coin, a new one will be created when synced up
185
- // this helps prevent penalties for not having a valid peer registered
186
- await this.melt(currentEpoch, peerIp);
187
- }
188
- // Don't create a server coin until you're synced up
189
- if (!lodash_1.default.last(rootHistory)?.synced) {
190
- return;
191
- }
192
- console.log(`No server coin found for epoch ${currentEpoch}. Creating new server coin...`);
193
- const serverCoin = await this.createForEpoch(peerIp, lastRoot?.root_hash);
194
- const newServerCoinData = {
195
- coin: {
196
- amount: serverCoin.coin.amount.toString(),
197
- puzzleHash: serverCoin.coin.puzzleHash.toString("hex"),
198
- parentCoinInfo: serverCoin.coin.parentCoinInfo.toString("hex"),
199
- },
200
- createdAt: new Date().toISOString(),
201
- epoch: currentEpoch,
202
- rootHash: lodash_1.default.last(rootHistory)?.root_hash || "",
203
- };
204
- await FullNodePeer_1.FullNodePeer.waitForConfirmation(serverCoin.coin.parentCoinInfo);
205
- serverCoins.push(newServerCoinData);
206
- await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
207
- console.log(`Server coin created and saved for store ${this.storeId}. Epoch: ${currentEpoch}`);
208
- }
209
- catch (error) {
210
- console.error(`Error ensuring server coin: ${error.message}`);
211
- throw error;
212
- }
213
- }
214
- // Melt outdated server coins
215
- async meltOutdatedEpochs(peerIp) {
216
- try {
217
- const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
218
- let serverCoins = await this.getServerCoinsForStore(peerIp);
219
- // Filter out coins that are not in the current epoch
220
- const outdatedCoins = serverCoins.filter((coin) => coin.epoch < currentEpoch);
221
- for (const serverCoin of outdatedCoins) {
222
- await this.melt(serverCoin.epoch, peerIp);
223
- // Remove the processed coin from the serverCoins array
224
- serverCoins = serverCoins.filter((coin) => coin.epoch !== serverCoin.epoch);
225
- // Update the nconf file with the updated array
226
- await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
227
- }
228
- }
229
- catch (error) {
230
- console.error(`Error processing outdated epochs: ${error.message}`);
231
- throw error;
232
- }
233
- }
234
- // If a store is unsubscribed this will melt all of its untracked coins and recover the locked amount
235
- static async meltUntrackedStoreCoins() {
236
- // Get all the store coins from the server config
237
- const allServerCoins = await ServerCoin.serverCoinManager.getFullConfig();
238
- // Get all the store ids from the server config
239
- const storeIdsWithCoins = Object.keys(allServerCoins);
240
- // Get all the subscribed stores and map them to their StoreId
241
- const allSubscribedStores = DataStore_1.DataStore.getAllStores();
242
- const allSubscribedStoreIds = allSubscribedStores.map((store) => store.StoreId);
243
- // Iterate over each store in the server coins
244
- for (const storeCoin of storeIdsWithCoins) {
245
- const serverCoin = new ServerCoin(storeCoin);
246
- // If the store is no longer subscribed
247
- if (!allSubscribedStoreIds.includes(storeCoin)) {
248
- // Get all the IPs that have coins for this untracked store
249
- const ips = Object.keys(allServerCoins[storeCoin]);
250
- // Iterate over each IP (e.g., "71.121.246.129")
251
- for (const ip of ips) {
252
- // Get the array of coins for that IP
253
- let coins = allServerCoins[storeCoin][ip];
254
- // Iterate over each coin and melt it
255
- for (const coinInfo of coins) {
256
- const { epoch, coin } = coinInfo;
257
- // Melt the coin
258
- await serverCoin.melt(epoch, ip);
259
- // Remove the melted coin from the array
260
- coins = coins.filter((c) => c !== coinInfo);
261
- // Update the config to reflect the remaining coins for this IP
262
- await ServerCoin.serverCoinManager.setConfigValue(`${storeCoin}:${ip}`, coins);
263
- }
264
- // If no coins are left for this IP, optionally remove the entire IP entry
265
- if (coins.length === 0) {
266
- delete allServerCoins[storeCoin][ip];
267
- await ServerCoin.serverCoinManager.setConfigValue(`${storeCoin}:${ip}`, undefined);
268
- }
269
- }
270
- // If no IPs are left for this store, optionally remove the store entry
271
- if (Object.keys(allServerCoins[storeCoin]).length === 0) {
272
- delete allServerCoins[storeCoin];
273
- await ServerCoin.serverCoinManager.setConfigValue(storeCoin, undefined);
274
- }
275
- }
276
- }
277
- }
278
- // Retrieve server coins from the store
279
- async getServerCoinsForStore(peerIp) {
280
- const serverCoins = (await ServerCoin.serverCoinManager.getConfigValue(`${this.storeId}:${peerIp}`)) || [];
281
- return serverCoins;
282
- }
283
- // Check if the server coin has been created for the current epoch
284
- async hasEpochCoinBeenCreated(currentEpoch, peerIp) {
285
- try {
286
- const serverCoins = await this.getServerCoinsForStore(peerIp);
287
- const existingCoin = serverCoins.find((coin) => coin.epoch === currentEpoch);
288
- if (!existingCoin) {
289
- console.log(`No server coin found for epoch ${currentEpoch}.`);
290
- return false;
291
- }
292
- console.log(`Server coin found for epoch ${currentEpoch}.`);
293
- return true;
294
- }
295
- catch (error) {
296
- console.error(`Error checking for existing server coin: ${error.message}`);
297
- return false;
298
- }
299
- }
300
- // Static method to calculate the current epoch
301
- static calculateEpochAndRound(currentTimestampUTC) {
302
- const firstEpochStart = new Date(Date.UTC(2024, 8, 3, 0, 0)); // Sept 3, 2024, 00:00 UTC
303
- // Convert the current timestamp to milliseconds
304
- const currentTimestampMillis = currentTimestampUTC.getTime();
305
- // Calculate the number of milliseconds in one epoch (7 days)
306
- const millisecondsInEpoch = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds
307
- // Calculate the difference in milliseconds between the current timestamp and the first epoch start
308
- const differenceMillis = currentTimestampMillis - firstEpochStart.getTime();
309
- // Calculate the current epoch number
310
- const epochNumber = Math.floor(differenceMillis / millisecondsInEpoch) + 1;
311
- // Calculate the milliseconds elapsed since the start of the current epoch
312
- const elapsedMillisInCurrentEpoch = differenceMillis % millisecondsInEpoch;
313
- // Calculate the number of milliseconds in a round (10 minutes)
314
- const millisecondsInRound = 10 * 60 * 1000; // 10 minutes in milliseconds
315
- // Calculate the current round number
316
- const roundNumber = Math.floor(elapsedMillisInCurrentEpoch / millisecondsInRound) + 1;
317
- return { epoch: epochNumber, round: roundNumber };
318
- }
319
- }
320
- exports.ServerCoin = ServerCoin;
321
- ServerCoin.serverCoinManager = new NconfManager_1.NconfManager("server_coin.json");