@dignetwork/dig-sdk 0.0.1-alpha.10 → 0.0.1-alpha.100

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 (68) hide show
  1. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +5 -2
  2. package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
  3. package/dist/DataIntegrityTree/DataIntegrityTree.js +93 -34
  4. package/dist/DigNetwork/ContentServer.d.ts +13 -10
  5. package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
  6. package/dist/DigNetwork/ContentServer.js +108 -175
  7. package/dist/DigNetwork/DigNetwork.d.ts +3 -9
  8. package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
  9. package/dist/DigNetwork/DigNetwork.js +98 -189
  10. package/dist/DigNetwork/DigPeer.d.ts +8 -3
  11. package/dist/DigNetwork/DigPeer.d.ts.map +1 -1
  12. package/dist/DigNetwork/DigPeer.js +68 -114
  13. package/dist/DigNetwork/PropagationServer.d.ts +73 -33
  14. package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
  15. package/dist/DigNetwork/PropagationServer.js +508 -360
  16. package/dist/blockchain/DataStore.d.ts +18 -7
  17. package/dist/blockchain/DataStore.d.ts.map +1 -1
  18. package/dist/blockchain/DataStore.js +78 -98
  19. package/dist/blockchain/DataStoreSerializer.d.ts +1 -1
  20. package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -1
  21. package/dist/blockchain/FullNodePeer.d.ts +2 -1
  22. package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
  23. package/dist/blockchain/FullNodePeer.js +34 -11
  24. package/dist/blockchain/ServerCoin.d.ts +13 -5
  25. package/dist/blockchain/ServerCoin.d.ts.map +1 -1
  26. package/dist/blockchain/ServerCoin.js +88 -25
  27. package/dist/blockchain/Wallet.d.ts +2 -2
  28. package/dist/blockchain/Wallet.d.ts.map +1 -1
  29. package/dist/blockchain/Wallet.js +51 -18
  30. package/dist/blockchain/coins.d.ts +1 -1
  31. package/dist/blockchain/coins.d.ts.map +1 -1
  32. package/dist/blockchain/coins.js +5 -4
  33. package/dist/types.d.ts +2 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/utils/ContentScanner.d.ts +63 -0
  36. package/dist/utils/ContentScanner.d.ts.map +1 -0
  37. package/dist/utils/ContentScanner.js +175 -0
  38. package/dist/utils/Environment.d.ts +18 -0
  39. package/dist/utils/Environment.d.ts.map +1 -0
  40. package/dist/utils/Environment.js +85 -0
  41. package/dist/utils/FileTransfer.d.ts +47 -0
  42. package/dist/utils/FileTransfer.d.ts.map +1 -0
  43. package/dist/utils/FileTransfer.js +209 -0
  44. package/dist/utils/NconfManager.js +2 -1
  45. package/dist/utils/StoreArchiveManager.d.ts +45 -0
  46. package/dist/utils/StoreArchiveManager.d.ts.map +1 -0
  47. package/dist/utils/StoreArchiveManager.js +153 -0
  48. package/dist/utils/asyncPool.d.ts +9 -0
  49. package/dist/utils/asyncPool.d.ts.map +1 -0
  50. package/dist/utils/asyncPool.js +23 -0
  51. package/dist/utils/config.d.ts +4 -3
  52. package/dist/utils/config.d.ts.map +1 -1
  53. package/dist/utils/config.js +12 -7
  54. package/dist/utils/directoryUtils.d.ts +0 -6
  55. package/dist/utils/directoryUtils.d.ts.map +1 -1
  56. package/dist/utils/directoryUtils.js +30 -11
  57. package/dist/utils/index.d.ts +1 -1
  58. package/dist/utils/index.d.ts.map +1 -1
  59. package/dist/utils/index.js +1 -1
  60. package/dist/utils/merkle.d.ts +2 -0
  61. package/dist/utils/merkle.d.ts.map +1 -0
  62. package/dist/utils/merkle.js +28 -0
  63. package/dist/utils/network.d.ts.map +1 -1
  64. package/dist/utils/network.js +26 -10
  65. package/package.json +13 -3
  66. package/dist/utils/deltaUtils.d.ts +0 -2
  67. package/dist/utils/deltaUtils.d.ts.map +0 -1
  68. package/dist/utils/deltaUtils.js +0 -83
@@ -5,27 +5,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ServerCoin = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
- const datalayer_driver_1 = require("datalayer-driver");
8
+ const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
9
9
  const FullNodePeer_1 = require("./FullNodePeer");
10
10
  const coins_1 = require("./coins");
11
11
  const Wallet_1 = require("./Wallet");
12
12
  const NconfManager_1 = require("../utils/NconfManager");
13
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");
14
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 });
15
20
  class ServerCoin {
16
21
  constructor(storeId) {
17
22
  this.storeId = storeId;
18
23
  }
19
24
  // Create a new server coin for the current epoch
20
- async createForEpoch(peerIp) {
25
+ async createForEpoch(peerIp, rootHash) {
21
26
  try {
22
27
  const peer = await FullNodePeer_1.FullNodePeer.connect();
23
28
  const wallet = await Wallet_1.Wallet.load("default");
24
29
  const publicSyntheticKey = await wallet.getPublicSyntheticKey();
25
30
  const serverCoinCreationCoins = await (0, coins_1.selectUnspentCoins)(peer, BigInt(serverCoinCollateral), BigInt(1000000));
26
- const currentEpoch = ServerCoin.getCurrentEpoch();
31
+ const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
27
32
  const epochBasedHint = (0, datalayer_driver_1.morphLauncherId)(Buffer.from(this.storeId, "hex"), BigInt(currentEpoch));
28
- const newServerCoin = (0, datalayer_driver_1.createServerCoin)(publicSyntheticKey, serverCoinCreationCoins, epochBasedHint, [peerIp], BigInt(serverCoinCollateral), BigInt(1000000));
33
+ const newServerCoin = (0, datalayer_driver_1.createServerCoin)(publicSyntheticKey, serverCoinCreationCoins, epochBasedHint, [peerIp, publicSyntheticKey.toString("hex")], BigInt(serverCoinCollateral), BigInt(1000000));
29
34
  const combinedCoinSpends = [...newServerCoin.coinSpends];
30
35
  const sig = (0, datalayer_driver_1.signCoinSpends)(combinedCoinSpends, [await wallet.getPrivateSyntheticKey()], false);
31
36
  const err = await peer.broadcastSpend(combinedCoinSpends, [sig]);
@@ -33,12 +38,12 @@ class ServerCoin {
33
38
  if (err.includes("no spendable coins")) {
34
39
  console.log("No coins available. Will try again in 5 seconds...");
35
40
  await new Promise((resolve) => setTimeout(resolve, 5000));
36
- return this.createForEpoch(peerIp);
41
+ return this.createForEpoch(peerIp, rootHash);
37
42
  }
38
43
  throw new Error(err);
39
44
  }
40
45
  // Cache the new server coin in the NconfManager
41
- await this.saveServerCoinData(newServerCoin.serverCoin, currentEpoch, peerIp);
46
+ await this.saveServerCoinData(newServerCoin.serverCoin, currentEpoch, peerIp, rootHash);
42
47
  return newServerCoin.serverCoin;
43
48
  }
44
49
  catch (error) {
@@ -46,7 +51,7 @@ class ServerCoin {
46
51
  }
47
52
  }
48
53
  // Save the server coin data to NconfManager
49
- async saveServerCoinData(serverCoin, epoch, peerIp) {
54
+ async saveServerCoinData(serverCoin, epoch, peerIp, rootHash) {
50
55
  const newServerCoinData = {
51
56
  coin: {
52
57
  amount: serverCoin.coin.amount.toString(),
@@ -54,7 +59,8 @@ class ServerCoin {
54
59
  parentCoinInfo: serverCoin.coin.parentCoinInfo.toString("hex"),
55
60
  },
56
61
  createdAt: new Date().toISOString(),
57
- epoch: epoch,
62
+ epoch,
63
+ rootHash,
58
64
  };
59
65
  const serverCoins = await this.getServerCoinsForStore(peerIp);
60
66
  serverCoins.push(newServerCoinData);
@@ -94,13 +100,13 @@ class ServerCoin {
94
100
  serverCoins = serverCoins.filter((coin) => coin.coin.parentCoinInfo !== serverCoin.parentCoinInfo);
95
101
  await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
96
102
  }
97
- // Sample server coins for the current epoch
98
- async sampleCurrentEpoch(sampleSize = 5, blacklist = []) {
99
- const epoch = ServerCoin.getCurrentEpoch();
100
- return this.sampleServerCoinsByEpoch(epoch, sampleSize, blacklist);
101
- }
102
- // Sample server coins by epoch
103
- async sampleServerCoinsByEpoch(epoch, sampleSize = 5, blacklist = []) {
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
+ }
104
110
  const epochBasedHint = (0, datalayer_driver_1.morphLauncherId)(Buffer.from(this.storeId, "hex"), BigInt(epoch));
105
111
  const peer = await FullNodePeer_1.FullNodePeer.connect();
106
112
  const maxClvmCost = BigInt(11000000000);
@@ -111,33 +117,83 @@ class ServerCoin {
111
117
  for (const coinState of filteredCoinStates) {
112
118
  const serverCoin = await peer.fetchServerCoin(coinState, maxClvmCost);
113
119
  const peerUrl = serverCoin.memoUrls[0];
120
+ // The second memo URL is the public key
121
+ // We will utilize this for future features
122
+ const publicKey = serverCoin.memoUrls[1];
114
123
  if (!blacklist.includes(peerUrl)) {
115
124
  serverCoinPeers.add(peerUrl);
116
125
  }
117
126
  }
118
- if (process.env.DIG_DEBUG === "1") {
127
+ if (Environment_1.Environment.DEBUG) {
128
+ console.log("Server Coin Peers: ", serverCoinPeers);
129
+ }
130
+ const peerList = Array.from(serverCoinPeers);
131
+ // Cache the result
132
+ serverCoinPeersCache.set(cacheKey, peerList);
133
+ return peerList;
134
+ }
135
+ async getActiveEpochPeers(blacklist = []) {
136
+ const { epoch } = ServerCoin.getCurrentEpoch();
137
+ return this.getAllEpochPeers(epoch, blacklist);
138
+ }
139
+ // Sample server coins for the current epoch
140
+ async sampleCurrentEpoch(sampleSize = 5, blacklist = []) {
141
+ const { epoch } = ServerCoin.getCurrentEpoch();
142
+ return this.sampleServerCoinsByEpoch(epoch, sampleSize, blacklist);
143
+ }
144
+ // Sample server coins by epoch
145
+ async sampleServerCoinsByEpoch(epoch, sampleSize = 5, blacklist = []) {
146
+ // We dont want our own IP to be included
147
+ const myIp = await (0, network_1.getPublicIpAddress)();
148
+ if (myIp) {
149
+ blacklist.push(myIp);
150
+ }
151
+ const serverCoinPeers = await this.getAllEpochPeers(epoch, blacklist);
152
+ if (Environment_1.Environment.DEBUG) {
119
153
  console.log("Server Coin Peers: ", serverCoinPeers);
120
154
  }
121
- // Convert the Set back to an array if needed
122
- return lodash_1.default.sampleSize(Array.from(serverCoinPeers), sampleSize);
155
+ return lodash_1.default.sampleSize(serverCoinPeers, sampleSize);
123
156
  }
124
157
  // Get the current epoch based on the current timestamp
125
158
  static getCurrentEpoch() {
126
- return ServerCoin.calculateEpoch(new Date());
159
+ return ServerCoin.calculateEpochAndRound(new Date());
127
160
  }
128
161
  // Ensure server coin exists for the current epoch
129
162
  async ensureServerCoinExists(peerIp) {
130
163
  try {
131
164
  console.log(`Ensuring server coin exists for store ${this.storeId}...`);
132
- const currentEpoch = ServerCoin.getCurrentEpoch();
165
+ const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
133
166
  const serverCoins = await this.getServerCoinsForStore(peerIp);
134
167
  // Check if a server coin already exists for the current epoch
135
168
  const existingCoin = serverCoins.find((coin) => coin.epoch === currentEpoch);
169
+ const dataStore = DataStore_1.DataStore.from(this.storeId);
170
+ const rootHistory = await dataStore.getRootHistory(true);
171
+ const lastRoot = lodash_1.default.last(rootHistory);
172
+ if (!lastRoot) {
173
+ throw new Error('Cant get the last root on chain, something is wrong.');
174
+ }
136
175
  if (existingCoin) {
176
+ // nothing to do
177
+ if (lastRoot?.synced && lastRoot?.root_hash === existingCoin.rootHash) {
178
+ return;
179
+ }
180
+ // everything is fine, lets just update the roothash for tracking
181
+ if (lastRoot?.synced && lastRoot?.root_hash !== existingCoin.rootHash) {
182
+ existingCoin.rootHash = lastRoot.root_hash;
183
+ // Update the conf with the modified server coin
184
+ await ServerCoin.serverCoinManager.setConfigValue(`${this.storeId}:${peerIp}`, serverCoins);
185
+ return;
186
+ }
187
+ // If not synced, melt the coin, a new one will be created when synced up
188
+ // this helps prevent penalties for not having a valid peer registered
189
+ await this.melt(currentEpoch, peerIp);
190
+ }
191
+ // Don't create a server coin until you're synced up
192
+ if (!lodash_1.default.last(rootHistory)?.synced) {
137
193
  return;
138
194
  }
139
195
  console.log(`No server coin found for epoch ${currentEpoch}. Creating new server coin...`);
140
- const serverCoin = await this.createForEpoch(peerIp);
196
+ const serverCoin = await this.createForEpoch(peerIp, lastRoot?.root_hash);
141
197
  const newServerCoinData = {
142
198
  coin: {
143
199
  amount: serverCoin.coin.amount.toString(),
@@ -146,6 +202,7 @@ class ServerCoin {
146
202
  },
147
203
  createdAt: new Date().toISOString(),
148
204
  epoch: currentEpoch,
205
+ rootHash: lodash_1.default.last(rootHistory)?.root_hash || "",
149
206
  };
150
207
  await FullNodePeer_1.FullNodePeer.waitForConfirmation(serverCoin.coin.parentCoinInfo);
151
208
  serverCoins.push(newServerCoinData);
@@ -160,7 +217,7 @@ class ServerCoin {
160
217
  // Melt outdated server coins
161
218
  async meltOutdatedEpochs(peerIp) {
162
219
  try {
163
- const currentEpoch = ServerCoin.getCurrentEpoch();
220
+ const { epoch: currentEpoch } = ServerCoin.getCurrentEpoch();
164
221
  let serverCoins = await this.getServerCoinsForStore(peerIp);
165
222
  // Filter out coins that are not in the current epoch
166
223
  const outdatedCoins = serverCoins.filter((coin) => coin.epoch < currentEpoch);
@@ -244,17 +301,23 @@ class ServerCoin {
244
301
  }
245
302
  }
246
303
  // Static method to calculate the current epoch
247
- static calculateEpoch(currentTimestampUTC) {
304
+ static calculateEpochAndRound(currentTimestampUTC) {
248
305
  const firstEpochStart = new Date(Date.UTC(2024, 8, 3, 0, 0)); // Sept 3, 2024, 00:00 UTC
249
306
  // Convert the current timestamp to milliseconds
250
307
  const currentTimestampMillis = currentTimestampUTC.getTime();
251
308
  // Calculate the number of milliseconds in one epoch (7 days)
252
- const millisecondsInEpoch = 7 * 24 * 60 * 60 * 1000;
309
+ const millisecondsInEpoch = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds
253
310
  // Calculate the difference in milliseconds between the current timestamp and the first epoch start
254
311
  const differenceMillis = currentTimestampMillis - firstEpochStart.getTime();
255
312
  // Calculate the current epoch number
256
313
  const epochNumber = Math.floor(differenceMillis / millisecondsInEpoch) + 1;
257
- return epochNumber;
314
+ // Calculate the milliseconds elapsed since the start of the current epoch
315
+ const elapsedMillisInCurrentEpoch = differenceMillis % millisecondsInEpoch;
316
+ // Calculate the number of milliseconds in a round (10 minutes)
317
+ const millisecondsInRound = 10 * 60 * 1000; // 10 minutes in milliseconds
318
+ // Calculate the current round number
319
+ const roundNumber = Math.floor(elapsedMillisInCurrentEpoch / millisecondsInRound) + 1;
320
+ return { epoch: epochNumber, round: roundNumber };
258
321
  }
259
322
  }
260
323
  exports.ServerCoin = ServerCoin;
@@ -1,5 +1,5 @@
1
1
  import { Buffer } from "buffer";
2
- import { Peer, Coin, CoinSpend } from "datalayer-driver";
2
+ import { Peer, Coin, CoinSpend } from "@dignetwork/datalayer-driver";
3
3
  export declare const DEFAULT_FEE_COIN_COST = 64000000;
4
4
  export declare class Wallet {
5
5
  private mnemonic;
@@ -20,7 +20,7 @@ export declare class Wallet {
20
20
  private static getWalletFromKeyring;
21
21
  private static saveWalletToKeyring;
22
22
  createKeyOwnershipSignature(nonce: string): Promise<string>;
23
- verifyKeyOwnershipSignature(nonce: string, signature: string, publicKey: string): Promise<boolean>;
23
+ static verifyKeyOwnershipSignature(nonce: string, signature: string, publicKey: string): Promise<boolean>;
24
24
  selectUnspentCoins(peer: Peer, coinAmount: bigint, feeBigInt: bigint, omitCoins?: Coin[]): Promise<Coin[]>;
25
25
  static calculateFeeForCoinSpends(peer: Peer, coinSpends: CoinSpend[] | null): Promise<bigint>;
26
26
  static isCoinSpendable(peer: Peer, coinId: Buffer): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"Wallet.d.ts","sourceRoot":"","sources":["../../src/blockchain/Wallet.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EASL,IAAI,EACJ,IAAI,EAEJ,SAAS,EAEV,MAAM,kBAAkB,CAAC;AAM1B,eAAO,MAAM,qBAAqB,WAAa,CAAC;AAOhD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO;WAKa,IAAI,CACtB,UAAU,GAAE,MAAkB,EAC9B,iBAAiB,GAAE,OAAc,GAChC,OAAO,CAAC,MAAM,CAAC;IAsBX,WAAW,IAAI,MAAM;WAOR,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAMpD,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAShE,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6BhE,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKrC,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC;IAMxC,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKzC,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAMrC,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;WAK7B,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WASlD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;mBAU/B,oBAAoB;mBAWpB,mBAAmB;IAM3B,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO3D,2BAA2B,CACtC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IASN,kBAAkB,CAC7B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,IAAI,EAAO,GACrB,OAAO,CAAC,IAAI,EAAE,CAAC;WAwCE,yBAAyB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;WAItF,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAOlF"}
1
+ {"version":3,"file":"Wallet.d.ts","sourceRoot":"","sources":["../../src/blockchain/Wallet.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EASL,IAAI,EACJ,IAAI,EAEJ,SAAS,EAEV,MAAM,8BAA8B,CAAC;AAQtC,eAAO,MAAM,qBAAqB,WAAa,CAAC;AAOhD,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO;WAKa,IAAI,CACtB,UAAU,GAAE,MAAkB,EAC9B,iBAAiB,GAAE,OAAc,GAChC,OAAO,CAAC,MAAM,CAAC;IAsBX,WAAW,IAAI,MAAM;WAOR,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAMpD,YAAY,CAC9B,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC;WASE,oBAAoB,CACtC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;IA6BL,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKrC,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC;IAMxC,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKzC,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAMrC,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;WAK7B,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;WASlD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;mBAU/B,oBAAoB;mBAcpB,mBAAmB;IAS3B,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAUpD,2BAA2B,CAC7C,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IASN,kBAAkB,CAC7B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,IAAI,EAAO,GACrB,OAAO,CAAC,IAAI,EAAE,CAAC;WA+EE,yBAAyB,CAC3C,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,GAC7B,OAAO,CAAC,MAAM,CAAC;WAIE,eAAe,CACjC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC;CAWpB"}
@@ -38,9 +38,11 @@ const chia_root_resolver_1 = require("chia-root-resolver");
38
38
  const chia_config_loader_1 = require("chia-config-loader");
39
39
  const encryption_1 = require("../utils/encryption");
40
40
  const buffer_1 = require("buffer");
41
- const datalayer_driver_1 = require("datalayer-driver");
41
+ const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
42
42
  const config_1 = require("../utils/config");
43
43
  const FileCache_1 = require("../utils/FileCache");
44
+ const config_2 = require("../utils/config");
45
+ const path_1 = __importDefault(require("path"));
44
46
  const KEYRING_FILE = "keyring.json";
45
47
  const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
46
48
  exports.DEFAULT_FEE_COIN_COST = 64000000;
@@ -174,31 +176,62 @@ class Wallet {
174
176
  const signature = (0, datalayer_driver_1.signMessage)(buffer_1.Buffer.from(message, "utf-8"), privateSyntheticKey);
175
177
  return signature.toString("hex");
176
178
  }
177
- async verifyKeyOwnershipSignature(nonce, signature, publicKey) {
179
+ static async verifyKeyOwnershipSignature(nonce, signature, publicKey) {
178
180
  const message = `Signing this message to prove ownership of key.\n\nNonce: ${nonce}`;
179
181
  return (0, datalayer_driver_1.verifySignedMessage)(buffer_1.Buffer.from(signature, "hex"), buffer_1.Buffer.from(publicKey, "hex"), buffer_1.Buffer.from(message, "utf-8"));
180
182
  }
181
183
  async selectUnspentCoins(peer, coinAmount, feeBigInt, omitCoins = []) {
182
- const cache = new FileCache_1.FileCache("reserved_coins");
183
- const cachedReservedCoins = cache.getCachedKeys();
184
- const now = Date.now();
185
- const omitCoinIds = omitCoins.map((coin) => (0, datalayer_driver_1.getCoinId)(coin).toString("hex"));
186
- cachedReservedCoins.forEach((coinId) => {
187
- const reservation = cache.get(coinId);
188
- if (reservation && reservation.expiry > now) {
189
- omitCoinIds.push(coinId);
184
+ const cache = new FileCache_1.FileCache(path_1.default.join(config_2.USER_DIR_PATH, "reserved_coins"));
185
+ const ownerPuzzleHash = await this.getOwnerPuzzleHash();
186
+ // Define a function to attempt selecting unspent coins
187
+ const trySelectCoins = async () => {
188
+ const now = Date.now();
189
+ const omitCoinIds = omitCoins.map((coin) => (0, datalayer_driver_1.getCoinId)(coin).toString("hex"));
190
+ // Update omitCoinIds with currently valid reserved coins
191
+ const cachedReservedCoins = cache.getCachedKeys();
192
+ cachedReservedCoins.forEach((coinId) => {
193
+ const reservation = cache.get(coinId);
194
+ if (reservation && reservation.expiry > now) {
195
+ if (!omitCoinIds.includes(coinId)) {
196
+ omitCoinIds.push(coinId);
197
+ }
198
+ }
199
+ else {
200
+ cache.delete(coinId);
201
+ }
202
+ });
203
+ const coinsResp = await peer.getAllUnspentCoins(ownerPuzzleHash, config_1.MIN_HEIGHT, buffer_1.Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex"));
204
+ const unspentCoins = coinsResp.coins.filter((coin) => !omitCoinIds.includes((0, datalayer_driver_1.getCoinId)(coin).toString("hex")));
205
+ const selectedCoins = (0, datalayer_driver_1.selectCoins)(unspentCoins, feeBigInt + coinAmount);
206
+ return selectedCoins;
207
+ };
208
+ let selectedCoins = [];
209
+ let retry = true;
210
+ while (retry) {
211
+ selectedCoins = await trySelectCoins();
212
+ if (selectedCoins.length > 0) {
213
+ // Coins have been successfully selected
214
+ retry = false;
190
215
  }
191
216
  else {
192
- cache.delete(coinId);
217
+ const now = Date.now();
218
+ // Check if there are any valid cached reserved coins left
219
+ const cachedReservedCoins = cache.getCachedKeys().filter((coinId) => {
220
+ const reservation = cache.get(coinId);
221
+ return reservation && reservation.expiry > now;
222
+ });
223
+ if (cachedReservedCoins.length > 0) {
224
+ // Wait 10 seconds and try again
225
+ console.log("No unspent coins available. Waiting 10 seconds...");
226
+ await new Promise((resolve) => setTimeout(resolve, 10000));
227
+ }
228
+ else {
229
+ // No unspent coins and no reserved coins
230
+ throw new Error("No unspent coins available.");
231
+ }
193
232
  }
194
- });
195
- const ownerPuzzleHash = await this.getOwnerPuzzleHash();
196
- const coinsResp = await peer.getAllUnspentCoins(ownerPuzzleHash, config_1.MIN_HEIGHT, buffer_1.Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex"));
197
- const unspentCoins = coinsResp.coins.filter((coin) => !omitCoinIds.includes((0, datalayer_driver_1.getCoinId)(coin).toString("hex")));
198
- const selectedCoins = (0, datalayer_driver_1.selectCoins)(unspentCoins, feeBigInt + coinAmount);
199
- if (selectedCoins.length === 0) {
200
- throw new Error("No unspent coins available.");
201
233
  }
234
+ // Reserve the selected coins
202
235
  selectedCoins.forEach((coin) => {
203
236
  const coinId = (0, datalayer_driver_1.getCoinId)(coin).toString("hex");
204
237
  cache.set(coinId, { coinId, expiry: Date.now() + CACHE_DURATION });
@@ -1,4 +1,4 @@
1
- import { Peer, Coin, CoinSpend } from "datalayer-driver";
1
+ import { Peer, Coin, CoinSpend } from "@dignetwork/datalayer-driver";
2
2
  export declare const DEFAULT_FEE_COIN_COST = 64000000;
3
3
  export declare const calculateFeeForCoinSpends: (peer: Peer, coinSpends: CoinSpend[] | null) => Promise<bigint>;
4
4
  export declare const selectUnspentCoins: (peer: Peer, coinAmount: bigint, feeBigInt: bigint, omitCoins?: Coin[], walletName?: string) => Promise<Coin[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"coins.d.ts","sourceRoot":"","sources":["../../src/blockchain/coins.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,IAAI,EACJ,IAAI,EAEJ,SAAS,EAEV,MAAM,kBAAkB,CAAC;AAK1B,eAAO,MAAM,qBAAqB,WAAa,CAAC;AAWhD,eAAO,MAAM,yBAAyB,SAC9B,IAAI,cACE,SAAS,EAAE,GAAG,IAAI,KAC7B,OAAO,CAAC,MAAM,CA4BhB,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACvB,IAAI,cACE,MAAM,aACP,MAAM,cACN,IAAI,EAAE,eACL,MAAM,KACjB,OAAO,CAAC,IAAI,EAAE,CAoEhB,CAAC;AAGF,eAAO,MAAM,eAAe,SACpB,IAAI,UACF,MAAM,KACb,OAAO,CAAC,OAAO,CAWjB,CAAC"}
1
+ {"version":3,"file":"coins.d.ts","sourceRoot":"","sources":["../../src/blockchain/coins.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,IAAI,EACJ,IAAI,EAEJ,SAAS,EAEV,MAAM,8BAA8B,CAAC;AAMtC,eAAO,MAAM,qBAAqB,WAAa,CAAC;AAWhD,eAAO,MAAM,yBAAyB,SAC9B,IAAI,cACE,SAAS,EAAE,GAAG,IAAI,KAC7B,OAAO,CAAC,MAAM,CA4BhB,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACvB,IAAI,cACE,MAAM,aACP,MAAM,cACN,IAAI,EAAE,eACL,MAAM,KACjB,OAAO,CAAC,IAAI,EAAE,CAoEhB,CAAC;AAGF,eAAO,MAAM,eAAe,SACpB,IAAI,UACF,MAAM,KACb,OAAO,CAAC,OAAO,CAWjB,CAAC"}
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isCoinSpendable = exports.selectUnspentCoins = exports.calculateFeeForCoinSpends = exports.DEFAULT_FEE_COIN_COST = void 0;
4
- const datalayer_driver_1 = require("datalayer-driver");
4
+ const datalayer_driver_1 = require("@dignetwork/datalayer-driver");
5
5
  const Wallet_1 = require("./Wallet");
6
6
  const config_1 = require("../utils/config");
7
7
  const FileCache_1 = require("../utils/FileCache");
8
+ const Environment_1 = require("../utils/Environment");
8
9
  exports.DEFAULT_FEE_COIN_COST = 64000000;
9
10
  // Set cache expiration time (5 minutes)
10
11
  const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds
@@ -63,18 +64,18 @@ const selectUnspentCoins = async (peer, coinAmount, feeBigInt, omitCoins = [], w
63
64
  const wallet = await Wallet_1.Wallet.load(walletName);
64
65
  const ownerPuzzleHash = await wallet.getOwnerPuzzleHash();
65
66
  const coinsResp = await peer.getAllUnspentCoins(ownerPuzzleHash, config_1.MIN_HEIGHT, Buffer.from(config_1.MIN_HEIGHT_HEADER_HASH, "hex"));
66
- if (process.env.DIG_DEBUG === "1") {
67
+ if (Environment_1.Environment.DEBUG) {
67
68
  console.log("Unspent Coins:", coinsResp); // Debugging
68
69
  }
69
70
  const unspentCoins = coinsResp.coins;
70
71
  // Filter out the omitted coins
71
72
  const filteredUnspentCoins = unspentCoins.filter((coin) => !omitCoinIds.includes((0, datalayer_driver_1.getCoinId)(coin).toString("hex")));
72
- if (process.env.DIG_DEBUG === "1") {
73
+ if (Environment_1.Environment.DEBUG) {
73
74
  console.log("Unspent Coins after filtering:", filteredUnspentCoins); // Debugging
74
75
  }
75
76
  // Select coins needed for the transaction
76
77
  const selectedCoins = (0, datalayer_driver_1.selectCoins)(filteredUnspentCoins, feeBigInt + coinAmount);
77
- if (process.env.DIG_DEBUG === "1") {
78
+ if (Environment_1.Environment.DEBUG) {
78
79
  console.log("Selected Coins:", selectedCoins); // Debugging
79
80
  }
80
81
  // If no coins are selected, throw an error
package/dist/types.d.ts CHANGED
@@ -23,6 +23,7 @@ export interface DigConfig {
23
23
  export interface RootHistoryItem {
24
24
  root_hash: string;
25
25
  timestamp: Number | undefined;
26
+ synced: boolean;
26
27
  }
27
28
  export interface DatFile {
28
29
  root: string;
@@ -47,6 +48,7 @@ export interface ServerCoinData {
47
48
  coin: CoinData;
48
49
  createdAt: string;
49
50
  epoch: number;
51
+ rootHash: string;
50
52
  }
51
53
  export interface IncentiveProgramData {
52
54
  storeId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE;QACL,CAAC,GAAG,EAAE,MAAM,GAAG;YACb,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,cAAc,CAAC;CAC9B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE;QACL,CAAC,GAAG,EAAE,MAAM,GAAG;YACb,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,cAAc,CAAC;CAC9B"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @class IllegalContentScanner
3
+ * Scans files for illegal content using ClamAV running in a Docker container and deletes files if flagged.
4
+ */
5
+ export declare class IllegalContentScanner {
6
+ private clamAVContainerName;
7
+ private virusTotalApiKey?;
8
+ private openAiApiKey?;
9
+ /**
10
+ * @constructor
11
+ * @param clamAVContainerName The name of the Docker container running ClamAV (default: 'clamav').
12
+ */
13
+ constructor(clamAVContainerName?: string);
14
+ /**
15
+ * Scans a file for illegal content using ClamAV, VirusTotal, and OpenAI Moderation API.
16
+ * If a service is missing its API key, the scan for that service is skipped.
17
+ * @param filePath The path of the file to scan.
18
+ * @returns {Promise<void>} A promise that resolves after the scan and potential deletion.
19
+ */
20
+ scanFile(filePath: string): Promise<void>;
21
+ /**
22
+ * Scans a file using ClamAV running in Docker.
23
+ * @param filePath The path of the file to scan.
24
+ * @returns {Promise<string>} The result of the ClamAV scan.
25
+ */
26
+ private scanWithClamAV;
27
+ /**
28
+ * Submits a file to VirusTotal for scanning.
29
+ * @param filePath The path of the file to scan.
30
+ * @returns {Promise<any>} The result from VirusTotal.
31
+ */
32
+ private scanWithVirusTotal;
33
+ /**
34
+ * Scans file content (text) using OpenAI's Moderation API.
35
+ * @param content The text content to scan.
36
+ * @returns {Promise<any>} The result from OpenAI's Moderation API.
37
+ */
38
+ private scanWithOpenAI;
39
+ /**
40
+ * Checks if the ClamAV scan result indicates a malicious file.
41
+ * @param result The ClamAV scan output.
42
+ * @returns {boolean} True if the file is flagged, false otherwise.
43
+ */
44
+ private isClamAVResultMalicious;
45
+ /**
46
+ * Checks if the VirusTotal result indicates a malicious file.
47
+ * @param result The VirusTotal scan result.
48
+ * @returns {boolean} True if the file is flagged, false otherwise.
49
+ */
50
+ private isVirusTotalResultMalicious;
51
+ /**
52
+ * Checks if the OpenAI Moderation result indicates harmful content.
53
+ * @param result The OpenAI Moderation result.
54
+ * @returns {boolean} True if harmful content is detected, false otherwise.
55
+ */
56
+ private isOpenAiResultMalicious;
57
+ /**
58
+ * Deletes a file from the filesystem.
59
+ * @param filePath The file to delete.
60
+ */
61
+ private deleteFile;
62
+ }
63
+ //# sourceMappingURL=ContentScanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentScanner.d.ts","sourceRoot":"","sources":["../../src/utils/ContentScanner.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,qBAAa,qBAAqB;IAC9B,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B;;;OAGG;gBACS,mBAAmB,GAAE,MAAiB;IAMlD;;;;;OAKG;IACU,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqDtD;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;OAIG;YACW,kBAAkB;IAgBhC;;;;OAIG;YACW,cAAc;IAa5B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAKnC;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;;OAGG;IACH,OAAO,CAAC,UAAU;CASrB"}