@tradelayerprotocol/tradelayer 1.9.1

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 (249) hide show
  1. package/.claude/settings.local.json +13 -0
  2. package/.claude/skills/tl-algo/SKILL.md +255 -0
  3. package/.gitattributes +2 -0
  4. package/.github/workflows/publish.yaml +26 -0
  5. package/4mm.js +163 -0
  6. package/LICENSE +21 -0
  7. package/NPMSwapRefactor.zip +0 -0
  8. package/README.md +217 -0
  9. package/address.sh +26 -0
  10. package/algoAPI.js +581 -0
  11. package/analyzepsbt.js +92 -0
  12. package/apiEx.js +99 -0
  13. package/bb_hyperscalper.js +290 -0
  14. package/bbo_demo.js +111 -0
  15. package/buyer.js +622 -0
  16. package/client.js +50 -0
  17. package/createTxTest.js +26 -0
  18. package/createWallet.js +75 -0
  19. package/daytrader.js +531 -0
  20. package/decodeTest.js +69 -0
  21. package/fundingManager.js +144 -0
  22. package/index.js +4 -0
  23. package/listener.js +27 -0
  24. package/litecoreTxBuilder.js +1128 -0
  25. package/mmEx.js +356 -0
  26. package/networks.js +51 -0
  27. package/orderbook.js +200 -0
  28. package/package.json +34 -0
  29. package/perTradeQueue.js +36 -0
  30. package/projectsTLNPMTLNPM/package-lock.json +162 -0
  31. package/projectsTLNPMTLNPM/package.json +5 -0
  32. package/quick.js +32 -0
  33. package/quickFut.js +37 -0
  34. package/quickSell.js +37 -0
  35. package/relayerClient.js +117 -0
  36. package/run4mm.js +80 -0
  37. package/run_bbo_tracker.js +241 -0
  38. package/seller.js +443 -0
  39. package/session.js +45 -0
  40. package/setup-lin-ltc.sh +139 -0
  41. package/setup-lin.sh +203 -0
  42. package/setup-win-ltc.bat +108 -0
  43. package/setup-win.bat +167 -0
  44. package/spam_screamer_futures.js +222 -0
  45. package/tradelayer.js/.gitattributes +2 -0
  46. package/tradelayer.js/README.md +2 -0
  47. package/tradelayer.js/oldTests/activationTest.js +6 -0
  48. package/tradelayer.js/oldTests/base58.test.js +23 -0
  49. package/tradelayer.js/oldTests/base64Decode.test.js +16 -0
  50. package/tradelayer.js/oldTests/blocksRefactor.js +140 -0
  51. package/tradelayer.js/oldTests/checkVestBalance.js +25 -0
  52. package/tradelayer.js/oldTests/consensusHashProto.js +151 -0
  53. package/tradelayer.js/oldTests/contractOrderbook.js +243 -0
  54. package/tradelayer.js/oldTests/createPayload.js +0 -0
  55. package/tradelayer.js/oldTests/createTestnetAddr.js +43 -0
  56. package/tradelayer.js/oldTests/decode.js +205 -0
  57. package/tradelayer.js/oldTests/decodeTest.js +50 -0
  58. package/tradelayer.js/oldTests/displayTallyMap.js +19 -0
  59. package/tradelayer.js/oldTests/encodeDecode.js +340 -0
  60. package/tradelayer.js/oldTests/expressTest.js +29 -0
  61. package/tradelayer.js/oldTests/extractBlocksVanilla.js +214 -0
  62. package/tradelayer.js/oldTests/extractBlocksVanillaa.js +179 -0
  63. package/tradelayer.js/oldTests/extractPubkeyTest.js +60 -0
  64. package/tradelayer.js/oldTests/fillInputCacheProto.js +111 -0
  65. package/tradelayer.js/oldTests/getRawTxTest.js +22 -0
  66. package/tradelayer.js/oldTests/indexTest.js +26 -0
  67. package/tradelayer.js/oldTests/initTokensTest.js +32 -0
  68. package/tradelayer.js/oldTests/interfaceChild.js +129 -0
  69. package/tradelayer.js/oldTests/listenerChild.js +112 -0
  70. package/tradelayer.js/oldTests/opdecode.js +26 -0
  71. package/tradelayer.js/oldTests/options.js +79 -0
  72. package/tradelayer.js/oldTests/optxtest.js +116 -0
  73. package/tradelayer.js/oldTests/optxtest1.js +64 -0
  74. package/tradelayer.js/oldTests/oracle.test.js +32 -0
  75. package/tradelayer.js/oldTests/orderbook.test.js +36 -0
  76. package/tradelayer.js/oldTests/parsing.js +93 -0
  77. package/tradelayer.js/oldTests/payload.js +13 -0
  78. package/tradelayer.js/oldTests/persistenceUnitTest.js +23 -0
  79. package/tradelayer.js/oldTests/property.test.js +53 -0
  80. package/tradelayer.js/oldTests/propertyLevel.js +75 -0
  81. package/tradelayer.js/oldTests/propertyTest.js +32 -0
  82. package/tradelayer.js/oldTests/queryAddressTest.js +17 -0
  83. package/tradelayer.js/oldTests/salter.js +14 -0
  84. package/tradelayer.js/oldTests/tally.js +81 -0
  85. package/tradelayer.js/oldTests/tally.test.js +48 -0
  86. package/tradelayer.js/oldTests/tally2.js +124 -0
  87. package/tradelayer.js/oldTests/tally3.js +142 -0
  88. package/tradelayer.js/oldTests/tallyDiag.js +38 -0
  89. package/tradelayer.js/oldTests/testGetRaw.js +40 -0
  90. package/tradelayer.js/oldTests/testHexConvert.js +47 -0
  91. package/tradelayer.js/oldTests/testNewEncoding.js +96 -0
  92. package/tradelayer.js/oldTests/testNewEncoding2.js +113 -0
  93. package/tradelayer.js/oldTests/testNewEncoding3 +112 -0
  94. package/tradelayer.js/oldTests/testNewEncoding3.js +168 -0
  95. package/tradelayer.js/oldTests/testOPReturn.js +102 -0
  96. package/tradelayer.js/oldTests/testPayload.js +23 -0
  97. package/tradelayer.js/oldTests/testRaw.js +50 -0
  98. package/tradelayer.js/oldTests/testSendTooMuch.js +20 -0
  99. package/tradelayer.js/oldTests/testTxBuild +28 -0
  100. package/tradelayer.js/oldTests/testTxBuild.js +42 -0
  101. package/tradelayer.js/oldTests/tokenOrderbook.js +243 -0
  102. package/tradelayer.js/oldTests/txUtilsA.js +515 -0
  103. package/tradelayer.js/oldTests/validityUnitTest.js +53 -0
  104. package/tradelayer.js/oldTests/vaults.js +72 -0
  105. package/tradelayer.js/oldTests/volumeIndex.js +117 -0
  106. package/tradelayer.js/oldTests/volumeIndex2.js +88 -0
  107. package/tradelayer.js/output_base64.txt +1 -0
  108. package/tradelayer.js/package-lock.json +9967 -0
  109. package/tradelayer.js/package.json +61 -0
  110. package/tradelayer.js/server/index.js +88 -0
  111. package/tradelayer.js/server/litecoind.exe +0 -0
  112. package/tradelayer.js/src/activation.js +303 -0
  113. package/tradelayer.js/src/adjuster.js +77 -0
  114. package/tradelayer.js/src/amm.js +400 -0
  115. package/tradelayer.js/src/base256.js +55 -0
  116. package/tradelayer.js/src/base94.js +79 -0
  117. package/tradelayer.js/src/channels.js +1163 -0
  118. package/tradelayer.js/src/clearing.js +3109 -0
  119. package/tradelayer.js/src/clearlist.js +364 -0
  120. package/tradelayer.js/src/client.js +295 -0
  121. package/tradelayer.js/src/consensus.js +613 -0
  122. package/tradelayer.js/src/contractRegistry.js +964 -0
  123. package/tradelayer.js/src/db.js +89 -0
  124. package/tradelayer.js/src/init.js +24 -0
  125. package/tradelayer.js/src/insurance.js +347 -0
  126. package/tradelayer.js/src/interface.js +218 -0
  127. package/tradelayer.js/src/interfaceExpress.js +178 -0
  128. package/tradelayer.js/src/iou.js +509 -0
  129. package/tradelayer.js/src/listener.js +226 -0
  130. package/tradelayer.js/src/logic.js +1702 -0
  131. package/tradelayer.js/src/main.js +927 -0
  132. package/tradelayer.js/src/marginMap.js +2165 -0
  133. package/tradelayer.js/src/options.js +126 -0
  134. package/tradelayer.js/src/oracle.js +394 -0
  135. package/tradelayer.js/src/orderbook.js +4123 -0
  136. package/tradelayer.js/src/persistence.js +554 -0
  137. package/tradelayer.js/src/property.js +411 -0
  138. package/tradelayer.js/src/reOrg.js +41 -0
  139. package/tradelayer.js/src/scaling.js +145 -0
  140. package/tradelayer.js/src/tally.js +1275 -0
  141. package/tradelayer.js/src/tradeHistoryManager.js +552 -0
  142. package/tradelayer.js/src/txDecoder.js +584 -0
  143. package/tradelayer.js/src/txEncoder.js +610 -0
  144. package/tradelayer.js/src/txIndex.js +502 -0
  145. package/tradelayer.js/src/txUtils.js +1392 -0
  146. package/tradelayer.js/src/types.js +429 -0
  147. package/tradelayer.js/src/validity.js +3077 -0
  148. package/tradelayer.js/src/vaults.js +430 -0
  149. package/tradelayer.js/src/vesting.js +491 -0
  150. package/tradelayer.js/src/volumeIndex.js +618 -0
  151. package/tradelayer.js/src/walletInterface.js +220 -0
  152. package/tradelayer.js/src/walletListener.js +665 -0
  153. package/tradelayer.js/tests/256decode.js +82 -0
  154. package/tradelayer.js/tests/UTXOracle.js +205 -0
  155. package/tradelayer.js/tests/base94test.js +23 -0
  156. package/tradelayer.js/tests/cancelTxTest.js +62 -0
  157. package/tradelayer.js/tests/contractInterfaceTest.js +48 -0
  158. package/tradelayer.js/tests/decimalTest.js +65 -0
  159. package/tradelayer.js/tests/decoderTest.js +100 -0
  160. package/tradelayer.js/tests/deltaCount.js +47 -0
  161. package/tradelayer.js/tests/deltaCount2.js +60 -0
  162. package/tradelayer.js/tests/interfaceTest.js +37 -0
  163. package/tradelayer.js/tests/mainTest.js +53 -0
  164. package/tradelayer.js/tests/makeActivationTest.js +24 -0
  165. package/tradelayer.js/tests/maxHeightTest.js +49 -0
  166. package/tradelayer.js/tests/reverseHash.js +72 -0
  167. package/tradelayer.js/tests/sensitiveConsoleOutput.txt +267 -0
  168. package/tradelayer.js/tests/tallyTest.js +40 -0
  169. package/tradelayer.js/tests/testBuybacks.js +46 -0
  170. package/tradelayer.js/tests/testCodeHash.js +49 -0
  171. package/tradelayer.js/tests/testConsensusHash.js +91 -0
  172. package/tradelayer.js/tests/testDecode.js +30 -0
  173. package/tradelayer.js/tests/testEncodingLengths.js +129 -0
  174. package/tradelayer.js/tests/testGetTx +32 -0
  175. package/tradelayer.js/tests/testGetTx.js +32 -0
  176. package/tradelayer.js/tests/testHexHash.js +32 -0
  177. package/tradelayer.js/tests/testIndexHash.js +35 -0
  178. package/tradelayer.js/tests/testInitContracts.js +38 -0
  179. package/tradelayer.js/tests/testMaxConsensus.js +12 -0
  180. package/tradelayer.js/tests/testMaxSynth.js +44 -0
  181. package/tradelayer.js/tests/testMint.js +21 -0
  182. package/tradelayer.js/tests/testNetwork.js +33 -0
  183. package/tradelayer.js/tests/testOrderbookLoad.js +62 -0
  184. package/tradelayer.js/tests/testRebates.js +32 -0
  185. package/tradelayer.js/tests/testRedeem.js +22 -0
  186. package/tradelayer.js/tests/testTokenTrade.js +39 -0
  187. package/tradelayer.js/tests/testTxBuild.js +42 -0
  188. package/tradelayer.js/tests/testUTXOTrade.js +27 -0
  189. package/tradelayer.js/tests/tokenTradeHistory.js +27 -0
  190. package/tradelayer.js/tests/tradeFutures.js +40 -0
  191. package/tradelayer.js/tests/tradeHistoryExample.js +35 -0
  192. package/tradelayer.js/tests/tradeHistoryLoad.js +15 -0
  193. package/tradelayer.js/tests/txScanTest.js +134 -0
  194. package/tradelayer.js/tests/validateTest.js +136 -0
  195. package/tradelayer.js/tests/vestingTest.js +37 -0
  196. package/tradelayer.js/utils/activateMainnet.js +59 -0
  197. package/tradelayer.js/utils/activateMainnetDoge.js +63 -0
  198. package/tradelayer.js/utils/autocompactdb.js +23 -0
  199. package/tradelayer.js/utils/base64toHex.js +32 -0
  200. package/tradelayer.js/utils/broadcastDoge.js +38 -0
  201. package/tradelayer.js/utils/calcRedeem.js +19 -0
  202. package/tradelayer.js/utils/checkNetwork.js +27 -0
  203. package/tradelayer.js/utils/createAddress.js +48 -0
  204. package/tradelayer.js/utils/createAttestation.js +133 -0
  205. package/tradelayer.js/utils/createContract.js +118 -0
  206. package/tradelayer.js/utils/createOracle.js +94 -0
  207. package/tradelayer.js/utils/createwallet.js +20 -0
  208. package/tradelayer.js/utils/crossFuturesTrades.js +57 -0
  209. package/tradelayer.js/utils/crossTokenTrades.js +62 -0
  210. package/tradelayer.js/utils/dumpPriv.js +29 -0
  211. package/tradelayer.js/utils/generateChannel.js +34 -0
  212. package/tradelayer.js/utils/getInfo.js +21 -0
  213. package/tradelayer.js/utils/hardWipe.js +20 -0
  214. package/tradelayer.js/utils/hexTo64.js +16 -0
  215. package/tradelayer.js/utils/importAddress.js +28 -0
  216. package/tradelayer.js/utils/importpriv.js +20 -0
  217. package/tradelayer.js/utils/issueOracleContract.js +67 -0
  218. package/tradelayer.js/utils/issueTokens.js +41 -0
  219. package/tradelayer.js/utils/listunspent.js +66 -0
  220. package/tradelayer.js/utils/litecoinClient.js +30 -0
  221. package/tradelayer.js/utils/loadwallet.js +20 -0
  222. package/tradelayer.js/utils/publishOracle.js +113 -0
  223. package/tradelayer.js/utils/sendActivation.js +21 -0
  224. package/tradelayer.js/utils/sendChannelContractTrade.js +34 -0
  225. package/tradelayer.js/utils/sendChannelTokenTrade.js +34 -0
  226. package/tradelayer.js/utils/sendCommit.js +24 -0
  227. package/tradelayer.js/utils/sendDoge.js +62 -0
  228. package/tradelayer.js/utils/sendDogeMain.js +67 -0
  229. package/tradelayer.js/utils/sendDogeTx.js +46 -0
  230. package/tradelayer.js/utils/sendLTC.js +63 -0
  231. package/tradelayer.js/utils/sendMainnet.js +62 -0
  232. package/tradelayer.js/utils/sendTransfer.js +19 -0
  233. package/tradelayer.js/utils/sendVestTest.js +88 -0
  234. package/tradelayer.js/utils/sendWithdrawal.js +26 -0
  235. package/tradelayer.js/utils/simpleStart.js +8 -0
  236. package/tradelayer.js/utils/startStop.js +27 -0
  237. package/tradelayer.js/utils/structuredTrades.js +136 -0
  238. package/tradelayer.js/utils/verifySignature.js +90 -0
  239. package/tradelayer.js/utils/verifyWitnessAndScriptPubkey.js +41 -0
  240. package/tradelayer.js/utils/walletCache.js +172 -0
  241. package/tradelayer.js/utils/walletContractInterface.js +48 -0
  242. package/tradelayer.js/utils/walletFetchTxs.js +66 -0
  243. package/tradelayer.js/utils/walletUtils.js +97 -0
  244. package/tradelayer.js/utils/wipeDB.js +55 -0
  245. package/tradelayer.js/utils/wipeDBNotTx.js +50 -0
  246. package/txEncoder.js +529 -0
  247. package/utility.js +28 -0
  248. package/verifymessage.js +38 -0
  249. package/ws-transport.js +311 -0
@@ -0,0 +1,364 @@
1
+ const dbInstance = require('./db.js');
2
+
3
+ class clearlistManager {
4
+ static clearlists = new Map();
5
+ static banlist = ["US", "KP", "SY", "RU", "IR", "CU"];
6
+ static xpubCache = new Map(); // xpub -> derived addresses array
7
+
8
+ static async createClearlist(adminAddress, name, url, description, backupAddress,id) {
9
+
10
+ if(!id){
11
+ id = await this.getNextId();
12
+ }
13
+
14
+ const clearlistData = {
15
+ id: id,
16
+ admin: adminAddress,
17
+ name: name,
18
+ description: description,
19
+ backup: backupAddress
20
+ };
21
+
22
+ const base = await dbInstance.getDatabase('clearlists')
23
+ await base.updateAsync(
24
+ { _id: id },
25
+ { $set: { data: clearlistData } },
26
+ { upsert: true }
27
+ );
28
+
29
+ return clearlistData;
30
+ }
31
+
32
+ static async loadClearlists() {
33
+ try {
34
+ const base = await dbInstance.getDatabase('clearlists')
35
+ const clearLists = await base.findAsync({});
36
+ clearLists.forEach(({ _id, data }) => {
37
+ this.clearlists.set(_id, data);
38
+ });
39
+
40
+ return clearLists
41
+ } catch (error) {
42
+ console.error('Error loading clearlists from the database:', error);
43
+ }
44
+ }
45
+
46
+ static async getClearlistById(clearlistId) {
47
+ try {
48
+ // Load all clearlists into memory
49
+ await this.loadClearlists();
50
+
51
+ // Check if the clearlistId exists in the Map
52
+ if (this.clearlists.has(clearlistId)) {
53
+ const clearlistData = this.clearlists.get(clearlistId);
54
+ console.log(`Clearlist found: ID ${clearlistId}`, clearlistData);
55
+ return clearlistData;
56
+ }
57
+
58
+ console.log(`Clearlist ID ${clearlistId} not found.`);
59
+ return false; // Return false if the clearlistId doesn't exist
60
+ } catch (error) {
61
+ console.error(`Error finding clearlist with ID ${clearlistId}:`, error.message);
62
+ throw error;
63
+ }
64
+ }
65
+
66
+
67
+ static async getList(id) {
68
+ try {
69
+ const base = await dbInstance.getDatabase('attestations')
70
+ const clearlist = await base.findOneAsync({ _id: id });
71
+ if (clearlist) {
72
+ return clearlist.data;
73
+ } else {
74
+ console.log(`No clearlist found for ID: ${id}`);
75
+ return null;
76
+ }
77
+ } catch (error) {
78
+ console.error(`Error loading clearlist with ID ${id}:`, error);
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ static async verifyAdmin(clearlistId, adminAddress) {
84
+ const clearlist = this.clearlists.get(clearlistId);
85
+
86
+ if (!clearlist) {
87
+ throw new Error('Clearlist not found');
88
+ }
89
+
90
+ return clearlist.adminAddress === adminAddress;
91
+ }
92
+
93
+ static async updateAdmin(clearlistId, newAdminAddress, backup) {
94
+ const clearlistKey = `${clearlistId}`;
95
+ const clearlist = this.clearlists.get(clearlistId);
96
+
97
+ if (!clearlist) {
98
+ throw new Error('Clearlist not found');
99
+ }
100
+
101
+ if (backup) {
102
+ clearlist.backupAddress = newAdminAddress;
103
+ } else {
104
+ clearlist.adminAddress = newAdminAddress;
105
+ }
106
+ await this.db.updateAsync({ _id: clearlistKey }, { $set: { data: clearlist } });
107
+ this.clearlists.set(clearlistId, clearlist);
108
+
109
+ console.log(`Clearlist ID ${clearlistId} admin updated to ${newAdminAddress}`);
110
+ }
111
+
112
+ static async getNextId() {
113
+ let maxId = 0;
114
+ await this.loadClearlists();
115
+ for (const key of this.clearlists.keys()) {
116
+ const currentId = parseInt(key);
117
+ if (currentId > maxId) {
118
+ maxId = currentId;
119
+ }
120
+ }
121
+ return maxId + 1;
122
+ }
123
+
124
+ static async addAttestation(clearlistId, address, metaData, block) {
125
+ const attestationId = address;
126
+
127
+ // Detect xpub prefix in metaData
128
+ let xpub = null;
129
+ if (typeof metaData === 'string' && metaData.startsWith('xpub:')) {
130
+ xpub = metaData.slice(5); // strip 'xpub:' prefix
131
+ }
132
+
133
+ const attestationData = {
134
+ listId: clearlistId,
135
+ address: address,
136
+ status: 'active',
137
+ data: metaData,
138
+ xpub: xpub,
139
+ timestamp: block
140
+ };
141
+
142
+ const base = await dbInstance.getDatabase('attestations');
143
+ await base.updateAsync(
144
+ { _id: attestationId },
145
+ { $set: { data: attestationData } },
146
+ { upsert: true }
147
+ );
148
+
149
+ return attestationId;
150
+ }
151
+
152
+ static async addAttestationWithXpub(clearlistId, address, metaData, xpub, block) {
153
+ const attestationId = address;
154
+ const attestationData = {
155
+ listId: clearlistId,
156
+ address: address,
157
+ status: 'active',
158
+ data: metaData,
159
+ xpub: xpub || null,
160
+ timestamp: block
161
+ };
162
+
163
+ const base = await dbInstance.getDatabase('attestations');
164
+ await base.updateAsync(
165
+ { _id: attestationId },
166
+ { $set: { data: attestationData } },
167
+ { upsert: true }
168
+ );
169
+
170
+ return attestationId;
171
+ }
172
+
173
+ /**
174
+ * Derive first N addresses from an xpub (receive chain m/0/0..m/0/19 and change chain m/1/0..m/1/19).
175
+ * Uses bitcore-lib-ltc HDPublicKey. Results are cached per xpub.
176
+ */
177
+ static deriveAddressesFromXpub(xpub, network) {
178
+ if (this.xpubCache.has(xpub)) {
179
+ return this.xpubCache.get(xpub);
180
+ }
181
+
182
+ const addresses = [];
183
+ const GAP_LIMIT = 20;
184
+
185
+ try {
186
+ // Try bitcore-lib-ltc first (LTC network)
187
+ let HDPublicKey, Networks;
188
+ try {
189
+ const litecore = require('bitcore-lib-ltc');
190
+ HDPublicKey = litecore.HDPublicKey;
191
+ Networks = litecore.Networks;
192
+ } catch (e) {
193
+ const bitcore = require('bitcore-lib');
194
+ HDPublicKey = bitcore.HDPublicKey;
195
+ Networks = bitcore.Networks;
196
+ }
197
+
198
+ const hdPubKey = new HDPublicKey(xpub);
199
+
200
+ // Derive receive chain (m/0/i) and change chain (m/1/i)
201
+ for (const chain of [0, 1]) {
202
+ const chainKey = hdPubKey.deriveChild(chain);
203
+ for (let i = 0; i < GAP_LIMIT; i++) {
204
+ const derived = chainKey.deriveChild(i);
205
+ const addr = derived.publicKey.toAddress().toString();
206
+ addresses.push(addr);
207
+ }
208
+ }
209
+ } catch (e) {
210
+ console.error('Error deriving addresses from xpub:', e.message);
211
+ return [];
212
+ }
213
+
214
+ this.xpubCache.set(xpub, addresses);
215
+ return addresses;
216
+ }
217
+
218
+ /**
219
+ * Check if an address is in a clearlist either directly or via xpub derivation.
220
+ */
221
+ static async isAddressInClearlistOrDerived(clearlistId, address) {
222
+ // First check direct attestation
223
+ const direct = await this.isAddressInClearlist(clearlistId, address);
224
+ if (direct) return true;
225
+
226
+ // Check xpub-bearing attestations in this clearlist
227
+ const base = await dbInstance.getDatabase('attestations');
228
+ const xpubAttestations = await base.findAsync({
229
+ 'data.listId': clearlistId,
230
+ 'data.status': 'active',
231
+ 'data.xpub': { $exists: true, $ne: null }
232
+ });
233
+
234
+ for (const att of xpubAttestations) {
235
+ const xpub = att.data.xpub;
236
+ if (!xpub) continue;
237
+ const derivedAddresses = this.deriveAddressesFromXpub(xpub);
238
+ if (derivedAddresses.includes(address)) {
239
+ return true;
240
+ }
241
+ }
242
+
243
+ return false;
244
+ }
245
+
246
+ static async revokeAttestation(attestationId, targetAddress, revokeReason,block) {
247
+ const attestationKey = `attestation:${targetAddress}`;
248
+ const base= await dbInstance.getDatabase('attestations')
249
+ const attestation = await base.findOneAsync({ _id: attestationKey });
250
+
251
+ if (!attestation) {
252
+ throw new Error('Attestation not found');
253
+ }
254
+
255
+ attestation.data.status = 'revoked';
256
+ attestation.data.id = attestationId;
257
+ attestation.data.revokeReason = revokeReason;
258
+ attestation.data.timestamp = block
259
+
260
+ await this.attestationsDb.updateAsync(
261
+ { _id: attestationKey },
262
+ { $set: { data: attestation.data } }
263
+ );
264
+
265
+ return attestationId;
266
+ }
267
+
268
+ static async getCountryCodeByAddress(address) {
269
+ try {
270
+ const base = await dbInstance.getDatabase('attestations');
271
+
272
+ // Fetch all attestations for the given address
273
+ const attestations = await base.findAsync({ 'data.address': address });
274
+
275
+ if (!attestations || attestations.length === 0) {
276
+ console.log(`No attestations found for address: ${address}`);
277
+ return null; // No attestations for this address
278
+ }
279
+
280
+ // Loop through attestations to find one with clearListId: 0 and a valid countryCode
281
+ for (const attestation of attestations) {
282
+ const { listId, data} = attestation.data;
283
+
284
+ if (listId === 0 && data) {
285
+ return {
286
+ address,
287
+ countryCode: data,
288
+ blockHeight: attestation.data.blockHeight || null, // Optional blockHeight in metadata
289
+ };
290
+ }
291
+ }
292
+
293
+ // If no valid attestation with clearListId: 0 and countryCode is found
294
+ console.log(`No valid attestation with clearListId 0 and country code found for address: ${address}`);
295
+ return null;
296
+ } catch (error) {
297
+ console.error(`Error fetching country code for address ${address}:`, error);
298
+ return null; // Gracefully return null on error
299
+ }
300
+ }
301
+
302
+ static async setBanlist(banlistArray,block) {
303
+ try {
304
+ const base = await dbInstance.getDatabase('clearlists');
305
+ await base.updateAsync(
306
+ { _id: 'globalBanlist' }, // Fixed ID for the banlist entity
307
+ { $set: { data: banlistArray, timestamp: block } },
308
+ { upsert: true }
309
+ );
310
+ console.log('Banlist updated successfully.');
311
+ } catch (error) {
312
+ console.error('Error updating Banlist in database:', error);
313
+ throw error;
314
+ }
315
+ this.banlist= banlistArray
316
+ }
317
+
318
+ static async getBanlist() {
319
+ try {
320
+ const base = await dbInstance.getDatabase('clearlists');
321
+ const banlist = await base.findAsync({ _id: 'globalBanlist' });
322
+ if (banlist) {
323
+ return banlist.data; // Return the banlist array
324
+ } else {
325
+ console.log('No Banlist found in the database.');
326
+ return null; // Return null if no Banlist exists
327
+ }
328
+ } catch (error) {
329
+ console.error('Error fetching Banlist from database:', error);
330
+ throw error;
331
+ }
332
+ }
333
+
334
+ static async getAttestations(clearlistId) {
335
+ const base = await dbInstance.getDatabase('attestations')
336
+ return await base.findAsync({ 'data.clearlistId': clearlistId });
337
+ }
338
+
339
+ static async getAttestationHistory(address, clearlistId) {
340
+ const base = await dbInstance.getDatabase('attestations');
341
+
342
+ // Fetch all matching records for the address and listId
343
+ const records = await base.findAsync({ 'data.address': address, 'data.listId': clearlistId });
344
+
345
+ // Sort by timestamp (descending)
346
+ const sortedRecords = records.sort((a, b) => b.data.timestamp - a.data.timestamp);
347
+
348
+ return sortedRecords; // Return sorted array
349
+ }
350
+
351
+
352
+ static async isAddressInClearlist(clearlistId, address) {
353
+
354
+ const base = await dbInstance.getDatabase('attestations')
355
+ const attestations = await base.findAsync({
356
+ 'data.clearlistId': clearlistId,
357
+ 'data.address': address,
358
+ 'data.status': 'active'
359
+ });
360
+ return attestations.length > 0;
361
+ }
362
+ }
363
+
364
+ module.exports = clearlistManager;
@@ -0,0 +1,295 @@
1
+ const util = require('util');
2
+ const Litecoin = require('litecoin');
3
+ const Bitcoin = require('bitcoin');
4
+ const Doge = require('dogecoind-rpc');
5
+
6
+ // --- ENV bootstrap helpers (safe if .env is missing) ---
7
+ const path = require('path');
8
+
9
+ function loadDotenvFromKnownLocations() {
10
+ // lazy-load to avoid hard dependency if dotenv isn't installed yet
11
+ let dotenv;
12
+ try { dotenv = require('dotenv'); } catch { return; }
13
+
14
+ // 1) repo-style: one level up relative to this file (…/ .env)
15
+ const repoEnv = path.join(__dirname, '..', '.env');
16
+ dotenv.config({ path: repoEnv, override: false });
17
+
18
+ // 2) fallback: current working directory (.env)
19
+ dotenv.config({ override: false });
20
+ }
21
+
22
+ function getRpcBootstrapFromEnv(defaultChain = 'LTC') {
23
+ loadDotenvFromKnownLocations();
24
+
25
+ const env = process.env;
26
+ const ENV_CHAIN = (env.CHAIN || '').toUpperCase();
27
+ const AUTODETECT = (env.AUTODETECT || '1') !== '0'; // AUTODETECT=0 → lock env, skip discovery
28
+
29
+ const DEFAULT_PORT = { BTC: 8332, BTCTEST: 18332, LTC: 9332, LTCTEST: 19332, DOGE: 22555, DOGETEST:44555 };
30
+ const chain = ['BTC', 'LTC', 'DOGE'].includes(ENV_CHAIN) ? ENV_CHAIN : defaultChain;
31
+
32
+ const host = env.RPC_HOST || '127.0.0.1';
33
+ const user = env.RPC_USER || 'user';
34
+ const pass = env.RPC_PASS || 'pass';
35
+ const port = Number(env.RPC_PORT || DEFAULT_PORT[chain]);
36
+ const timeout = Number(env.TIMEOUT_MS || 60000);
37
+
38
+ // If any of CHAIN / RPC_PORT is provided OR AUTODETECT=0, we consider this a "locked" bootstrap.
39
+ const locked = (!AUTODETECT) || !!env.CHAIN || !!env.RPC_PORT;
40
+
41
+ return {
42
+ // normalized values
43
+ chain, host, port, user, pass, timeout,
44
+ // whether the caller should skip autodetect and return immediately
45
+ locked,
46
+ };
47
+ }
48
+
49
+
50
+ let clientInstance = null;
51
+
52
+ class ClientWrapper {
53
+ constructor() {
54
+ if (clientInstance) {
55
+ return clientInstance;
56
+ }
57
+ this.chain = null;
58
+ this.client = null;
59
+ this.initializing = false
60
+ clientInstance = this; // Assign the instance to the singleton variable
61
+ }
62
+
63
+ async init() {
64
+
65
+ // If already initializing, wait for the process to finish
66
+ if (this.isInitializing) {
67
+ console.log('Client initialization already in progress. Waiting...');
68
+ return this.waitForInitialization(); // Wait for ongoing initialization to complete
69
+ }
70
+
71
+ this.isInitializing = true; // Set flag to indicate initialization is in progress
72
+
73
+ if(!this.client){
74
+ const boot = this.getEnvBootstrap('LTCTEST'); // default LTC; change to 'BTC' if you prefer
75
+
76
+ this.config = {
77
+ host: boot.host,
78
+ port: boot.port,
79
+ user: boot.user,
80
+ pass: boot.pass,
81
+ timeout: boot.timeout,
82
+ };
83
+
84
+ // Build a client immediately using the env-chosen CHAIN (or default)
85
+ this.chain = boot.chain;
86
+ this.client = this._createClientByChain(this.chain);
87
+
88
+ // If .env told us to lock (AUTODETECT=0 or CHAIN/RPC_PORT provided), stop here.
89
+ // (No probing needed; this lets desktop/server scripts fully control startup.)
90
+ if (boot.locked) {
91
+ return this.chain;
92
+ }
93
+
94
+ // Wait for the blockchain to finish initial block download and indexing
95
+ let isTest = true
96
+ try {
97
+ const blockchainInfo = await this.getBlockchainInfo();
98
+ isTest = blockchainInfo.chain === 'test';
99
+ console.log('is test '+isTest)
100
+ }catch (error) {
101
+ if (error.code === -28) {
102
+ console.log('Getting the err on the second call.');
103
+ }
104
+ }
105
+
106
+ const networkInfo = await this.getNetworkInfo();
107
+ console.log('determining chain in init '+JSON.stringify(networkInfo))
108
+ this.chain = this.determineChainFromSubversion(networkInfo.subversion);
109
+
110
+ if (!this.chain) throw new Error('Unable to determine blockchain chain.');
111
+
112
+ this.config.port = isTest
113
+ ? (this.chain === 'BTC' ? 18332 : this.chain === 'DOGE' ? 44556 : 19332)
114
+ : (this.chain === 'BTC' ? 8332 : this.chain === 'DOGE' ? 22555 : 9332);
115
+
116
+ this.client = this._createClientByChain(this.chain);
117
+ }
118
+ return this.chain
119
+ }
120
+
121
+ async waitForInitialization() {
122
+ while (this.isInitializing) {
123
+ console.log('waiting for initialization')
124
+ await new Promise(resolve => setTimeout(resolve, 100)); // Wait 100ms between checks
125
+ }
126
+ return this.chain; // Return the chain after initialization completes
127
+ }
128
+
129
+ // inside your existing class (e.g., RpcClient / whatever it’s named)
130
+ getEnvBootstrap(defaultChain = 'LTC') {
131
+ return getRpcBootstrapFromEnv(defaultChain);
132
+ }
133
+
134
+
135
+
136
+ _createClientByChain(chain) {
137
+ switch (chain) {
138
+ case 'BTC':
139
+ return new Bitcoin.Client(this.config);
140
+ case 'DOGE':
141
+ return new Doge.Client(this.config);
142
+ default:
143
+ return new Litecoin.Client(this.config);
144
+ }
145
+ }
146
+
147
+ static async getInstance(txIndex) {
148
+ if (!clientInstance) {
149
+ if(txIndex){console.log('initializing client by way of txIndex')}
150
+ if(this.isInitializing){await this.waitForInitialization()}
151
+ const clientWrapper = new ClientWrapper();
152
+ console.log('constructed client wrapper now init')
153
+ await clientWrapper.init();
154
+ }
155
+ return clientInstance;
156
+ }
157
+
158
+ determineChainFromSubversion(subversion, flag) {
159
+ console.log('chain subversion '+subversion+' '+flag )
160
+ subversion = subversion.toLowerCase();
161
+ if (subversion.includes('litecoin')) return 'LTC';
162
+ if (subversion.includes('bitcoin')) return 'BTC';
163
+ if (subversion.includes('dogecoin')) return 'DOGE';
164
+ throw new Error(`Unknown chain in subversion: ${subversion}`);
165
+ }
166
+
167
+ getBlockchainInfo() {
168
+ return util.promisify(this.client.cmd.bind(this.client, 'getblockchaininfo'))();
169
+ }
170
+
171
+ getRawTransaction(txId, verbose = true, blockHash) {
172
+ return util.promisify(this.client.cmd.bind(this.client, 'getrawtransaction'))(txId, verbose);
173
+ }
174
+
175
+ getnewaddress() {
176
+ return util.promisify(this.client.cmd.bind(this.client, 'getnewaddress'))();
177
+ }
178
+
179
+ sendtoaddress(addr,amt){
180
+ return util.promisify(this.client.cmd.bind(this.client, 'sendtoaddress'))(addr,amt)
181
+ }
182
+
183
+ getNetworkInfo(){
184
+ return util.promisify(this.client.cmd.bind(this.client, 'getnetworkinfo'))()
185
+ }
186
+
187
+ getTransaction(txId) {
188
+ return util.promisify(this.client.cmd.bind(this.client, 'gettransaction'))(txId);
189
+ }
190
+
191
+ getBlock(blockHash) {
192
+ return util.promisify(this.client.cmd.bind(this.client, 'getblock'))(blockHash);
193
+ }
194
+
195
+ getBlockHash(height) {
196
+ return util.promisify(this.client.cmd.bind(this.client, 'getblockhash'))(height);
197
+ }
198
+
199
+ createRawTransaction(...params) {
200
+ return util.promisify(this.client.cmd.bind(this.client, 'createrawtransaction'))(...params);
201
+ }
202
+
203
+ listUnspent(...params) {
204
+ return util.promisify(this.client.cmd.bind(this.client, 'listunspent'))(...params);
205
+ }
206
+
207
+ decoderawtransaction(...params) {
208
+ return util.promisify(this.client.cmd.bind(this.client, 'decoderawtransaction'))(...params);
209
+ }
210
+
211
+ signrawtransactionwithwallet(...params) {
212
+ return util.promisify(this.client.cmd.bind(this.client, 'signrawtransactionwithwallet'))(...params);
213
+ }
214
+
215
+ dumpprivkey(...params) {
216
+ return util.promisify(this.client.cmd.bind(this.client, 'dumpprivkey'))(...params);
217
+ }
218
+
219
+ sendrawtransaction(...params) {
220
+ return util.promisify(this.client.cmd.bind(this.client, 'sendrawtransaction'))(...params);
221
+ }
222
+
223
+ validateAddress(...params) {
224
+ return util.promisify(this.client.cmd.bind(this.client, 'validateaddress'))(...params);
225
+ }
226
+
227
+ getBlockCount() {
228
+ return util.promisify(this.client.cmd.bind(this.client, 'getblockcount'))();
229
+ }
230
+
231
+ loadWallet(...params) {
232
+ return util.promisify(this.client.cmd.bind(this.client, 'loadwallet'))(...params);
233
+ }
234
+
235
+ listlabels(...params) {
236
+ return util.promisify(this.client.cmd.bind(this.client, 'listlabels'))(...params);
237
+ }
238
+
239
+ getaddressesbylabel(label) {
240
+ return util.promisify(this.client.cmd.bind(this.client, 'getaddressesbylabel'))(label);
241
+ }
242
+
243
+ getwalletinfo() {
244
+ return util.promisify(this.client.cmd.bind(this.client, 'getwalletinfo'))();
245
+ }
246
+
247
+ listunspent() {
248
+ return util.promisify(this.client.cmd.bind(this.client, 'listunspent'))();
249
+ }
250
+
251
+
252
+ // Add this method to the ClientWrapper class
253
+ async verifyClientChain() {
254
+ try {
255
+ const networkInfo = await clientInstance.getNetworkInfo();
256
+ const subversion = networkInfo.subversion.toLowerCase();
257
+ let match;
258
+ if (subversion.includes('litecoin')) {
259
+ match = 'LTC';
260
+ } else if (subversion.includes('bitcoin')) {
261
+ match = 'BTC';
262
+ } else if (subversion.includes('dogecoin')) {
263
+ match = 'DOGE';
264
+ }
265
+
266
+ if (match && match !== this.chain) {
267
+ console.warn(`Mismatch: Configured chain is ${this.chain}, but detected ${match}.`);
268
+ this.chain = match;
269
+ } else {
270
+ console.log(`Verified chain: ${this.chain}`);
271
+ }
272
+ } catch (error) {
273
+ console.error('Error verifying chain:', error);
274
+ }
275
+ }
276
+
277
+ async getChain() {
278
+ const bleh= await this.getNetworkInfo(); // Double-check chain type
279
+ console.log('determining chain in get chain')
280
+ return this.determineChainFromSubversion(bleh.subversion, true);
281
+ }
282
+
283
+ async getTest(){
284
+ const blockchainInfo = await this.getBlockchainInfo();
285
+ return blockchainInfo.chain === 'test';
286
+ }
287
+
288
+ clientInstance = this;
289
+
290
+
291
+ // Additional RPC methods as needed...
292
+ }
293
+
294
+ // Export singleton instance
295
+ module.exports = ClientWrapper;