@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,502 @@
1
+
2
+ const json = require('big-json');
3
+ const util = require('util');
4
+ const TxUtils = require('./txUtils');
5
+ //const Types = require('./types.js');
6
+ const db = require('./db.js');
7
+ const ClientWrapper = require('./client.js'); // Wait for client to initialize//console.log('this.client in TxId'+this.client)
8
+ const transparentIndex = [];
9
+
10
+ class TxIndex {
11
+ static instance=null;
12
+
13
+ constructor() {
14
+ if (TxIndex.instance) {
15
+ return TxIndex.instance;
16
+ }
17
+ this.client=null
18
+ TxIndex.instance = this;
19
+ this.parseBlock = 0
20
+ }
21
+
22
+ static async init() {
23
+ this.client = await ClientWrapper.getInstance(true);
24
+ console.log('this.client '+this.client.chain)
25
+ //await db.init(this.client.chain)
26
+ // Use this.this.client for this.client-related actions within TxIndex methods
27
+ return this
28
+ }
29
+
30
+ static async getInstance(test) {
31
+ if (!TxIndex.instance) {
32
+ TxIndex.instance = new TxIndex(test);
33
+ }
34
+ console.log('calling init in txindex')
35
+ await this.init()
36
+ return TxIndex.instance;
37
+ }
38
+
39
+ static async initializeIndex(genesisBlock) {
40
+ try {
41
+ const base = await db.getDatabase('txIndex')
42
+ const existingGenesisBlock = await base.findOneAsync({ _id: 'genesisBlock' });
43
+ if (existingGenesisBlock) {
44
+ console.log('Genesis block is already initialized:', existingGenesisBlock.value);
45
+ return;
46
+ }
47
+ } catch (error) {
48
+ // Handle any errors that occur during database access
49
+ console.error('Error checking for existing genesis block:', error);
50
+ throw error;
51
+ }
52
+
53
+ // If the "genesisBlock" key does not exist, initialize it
54
+ try {
55
+ await base.insertAsync({ _id: 'genesisBlock', value: genesisBlock });
56
+ console.log('Genesis block initialized:', genesisBlock);
57
+ } catch (error) {
58
+ // Handle any errors that occur during insertion
59
+ console.error('Error initializing genesis block:', error);
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ static async extractBlockData(startHeight) {
65
+ let chainTip = await this.fetchChainTip();
66
+ const forwardOnly = process.env.TL_FORWARD_INDEX === '1' || process.env.TL_FORWARD_INDEX === 'true';
67
+
68
+ let effectiveStart = startHeight;
69
+
70
+ if (forwardOnly) {
71
+ try {
72
+ const maxIndexed = await TxIndex.findMaxIndexedBlock();
73
+ if (maxIndexed !== null && maxIndexed !== undefined) {
74
+ // Resume from the last indexed height + 1
75
+ effectiveStart = maxIndexed + 1;
76
+ } else {
77
+ // No existing index: in forward-only mode, start at current tip
78
+ // to avoid deep rescans on pruned nodes.
79
+ effectiveStart = chainTip;
80
+ }
81
+ } catch (err) {
82
+ console.error('Error determining forward index start height:', err);
83
+ }
84
+ }
85
+
86
+ if (effectiveStart === undefined || effectiveStart === null) {
87
+ effectiveStart = 0;
88
+ }
89
+
90
+ if (effectiveStart > chainTip) {
91
+ console.log('extractBlockData: nothing to index, effectiveStart > chainTip');
92
+ return;
93
+ }
94
+
95
+ console.log('building index until' + chainTip + ' from ' + effectiveStart);
96
+ for (let height = effectiveStart; height <= chainTip; height++) {
97
+ this.parseBlock = height
98
+ if (height % 100 == 1) { console.log('indexed to ' + height) };
99
+ let blockData = await this.fetchBlockData(height);
100
+ //console.log(blockData)
101
+ await this.processBlockData(blockData, height);
102
+ //chainTip = await this.fetchChainTip();
103
+ }
104
+ console.log('indexed to chaintip');
105
+ this.saveMaxHeight(chainTip)
106
+ console.log('built index');
107
+ }
108
+
109
+ static async saveMaxHeight(chainTip){
110
+ // Use the correct NeDB method to insert or update the 'indexExists' document
111
+ // After processing the block, update 'MaxHeight'
112
+ //console.log('saving MaxHeight '+chainTip)
113
+ if(chainTip==undefined||chainTip==null){
114
+ //console.log('no value to save, returning from saveMaxHeight ')
115
+ return
116
+ }
117
+
118
+ const base = await db.getDatabase('txIndex')
119
+ await base.updateAsync(
120
+ { _id: 'MaxHeight' }, // Query
121
+ { $set: { value: chainTip } }, // Update
122
+ { upsert: true } // Options
123
+ );
124
+
125
+ try {
126
+ await base.updateAsync(
127
+ { _id: 'indexExists' },
128
+ { _id: 'indexExists', value: true },
129
+ { upsert: true } // This option ensures that the document is inserted if it doesn't exist or updated if it does.
130
+ );
131
+ //console.log('Index flag set successfully.');
132
+ } catch (error) {
133
+ console.error('Error setting the index flag:', error);
134
+ throw error;
135
+ }
136
+ }
137
+
138
+ static async fetchChainTip() {
139
+ try {
140
+ const chainTip = await this.client.getBlockCount();
141
+ return chainTip;
142
+ } catch (error) {
143
+ throw new Error(`Error fetching chain tip: ${error}`);
144
+ }
145
+ }
146
+
147
+
148
+ static async fetchBlockData(height) {
149
+ try {
150
+ // Fetch the block hash for the given height
151
+ const blockHash = await this.client.getBlockHash(height);
152
+ // Fetch the block data using the retrieved block hash
153
+ const block = await this.client.getBlock(blockHash);
154
+ return block;
155
+ } catch (error) {
156
+ console.error(`Error fetching block data for height ${height}:`, error);
157
+ throw error;
158
+ }
159
+ }
160
+
161
+ static async processBlockData(blockData, blockHeight) {
162
+ const txIndexDB = await db.getDatabase('txIndex');
163
+
164
+ let txDetails = [];
165
+
166
+ for (const txId of blockData.tx) {
167
+
168
+ const txHex = await TxIndex.fetchTransactionData(txId, false, blockData.hash);
169
+ const txData = await TxIndex.DecodeRawTransaction(txHex);
170
+
171
+ if (txData != null && txData != undefined && txData.marker === 'tl') {
172
+
173
+ const payload = txData.payload;
174
+ const thisTx = await TxIndex.processTransaction(payload, txId, txData.marker);
175
+
176
+ txDetails.push(thisTx);
177
+
178
+ console.log('payload ' + payload + JSON.stringify(thisTx));
179
+
180
+ // 🔥 FIX: store **one tx per document** instead of the whole txDetails array
181
+ try {
182
+ await txIndexDB.updateAsync(
183
+ { _id: `tx-${blockHeight}-${txId}` },
184
+ { _id: `tx-${blockHeight}-${txId}`, value: thisTx },
185
+ { upsert: true }
186
+ );
187
+ } catch (dbError) {
188
+ console.error(`Error inserting transaction data for txId ${txId} at blockHeight ${blockHeight}:`, dbError);
189
+ }
190
+
191
+ await this.saveMaxHeight(blockHeight);
192
+ }
193
+ }
194
+
195
+ return txDetails;
196
+ }
197
+
198
+
199
+ static async fetchTransactionData(txId, verbose, blockHash) {
200
+ try {
201
+ const transaction = await this.client.getRawTransaction(txId,verbose,blockHash);
202
+ return transaction;
203
+ } catch (error) {
204
+ console.error('Error fetching transaction:', error);
205
+ throw error;
206
+ }
207
+ }
208
+
209
+
210
+ /*static async DecodeRawTransaction(rawTx) {
211
+ try {
212
+ const decodedTx = await this.client.decoderawtransaction(rawTx);
213
+ const opReturnOutput = decodedTx.vout.find(output => output.scriptPubKey.type === 'nulldata');
214
+
215
+ if (opReturnOutput) {
216
+ const opReturnData = opReturnOutput.scriptPubKey.hex;
217
+ // Decode the entire hex string
218
+ const decodedData = Buffer.from(opReturnData, 'hex').toString();
219
+
220
+ // Search for "tl" in the decoded string
221
+ const markerIndex = decodedData.indexOf('tl');
222
+ if (markerIndex !== -1) {
223
+ console.log('decoded total payload '+decodedData)
224
+ // Extract everything after "tl" as the payload
225
+ const payload = decodedData.substring(markerIndex + 2);
226
+ console.log('Decoded Payload:', payload);
227
+ return { marker: 'tl', payload, decodedTx };
228
+ } else {
229
+ //console.error('No "tl" marker found.');
230
+ return null;
231
+ }
232
+ } else {
233
+ //console.error('No OP_RETURN output found.');
234
+ return null;
235
+ }
236
+ } catch (error) {
237
+ console.error('Error decoding raw transaction:', error);
238
+ }
239
+ }*/
240
+
241
+ static async DecodeRawTransaction(rawTx) {
242
+ try {
243
+ const decodedTx = await this.client.decoderawtransaction(rawTx);
244
+
245
+ const opReturnOutput = decodedTx.vout.find(output => output.scriptPubKey.type === 'nulldata');
246
+
247
+ if (opReturnOutput) {
248
+ //console.log(opReturnOutput)
249
+ const opReturnData = opReturnOutput.scriptPubKey.hex;
250
+ //console.log('OP_RETURN Data:', opReturnData)
251
+ // Extract and log the "tl" marker
252
+
253
+ // Check if the hex contains the marker "746c" (which corresponds to "tl")
254
+ let markerHex = "746c"; // Hex for "tl"
255
+ let payloadStart =8
256
+ let markerPosition = opReturnData.indexOf(markerHex);
257
+ if (markerPosition === -1||markerPosition>6) {
258
+ //console.error('Marker "tl" not found in OP_RETURN data');
259
+ return null;
260
+ }else if(markerHex = opReturnData.substring(4, 8)){
261
+ payloadStart= 8
262
+ }else if(markerHex==opReturnData.substring(5, 9)){
263
+ payloadStart= 9
264
+ }else if(markerHex==opReturnData.substring(6,10)){
265
+ payloadStart=10
266
+ }; // '746c' for 'tl'
267
+ let marker = Buffer.from(markerHex, 'hex').toString(); // Extract and log the actual payload
268
+ const payloadHex = opReturnData.substring(payloadStart);
269
+ const payloadBuff = Buffer.from(payloadHex, 'hex')
270
+ console.log(marker + ' ' +payloadBuff)
271
+ if (!this.isPrintableASCII(payloadBuff)) {
272
+ console.log('boop')
273
+ return null;
274
+ }
275
+ const payload = payloadBuff.toString();
276
+ console.log('market data ' +markerHex+' '+marker+' '+payload)
277
+ if(marker=='tl'){console.log('Pre-decoded and Decoded Payload:', opReturnData + ' ' + payload+ ' decoding the whole thing '+Buffer.from(opReturnData, 'hex').toString())};
278
+ return { marker, payload , decodedTx};
279
+ } else {
280
+ //console.log('No OP_RETURN output found.');
281
+ return null;
282
+ }
283
+ // Process decoded transaction logic here...
284
+ return decodedTx;
285
+ } catch (error) {
286
+ //console.error('Error decoding raw transaction:', error);
287
+ }
288
+ }
289
+
290
+
291
+ static isPrintableASCII(buf) {
292
+ // Byte-preserving check; no UTF-8 decoding side effects
293
+ const s = buf.toString('latin1');
294
+ console.log(s+Boolean(/^[\x20-\x7E]*$/.test(s)))
295
+ return /^[\x20-\x7E]*$/.test(s); // space..~ only
296
+ }
297
+
298
+ static async processTransaction(payload, txId, marker) {
299
+ const Types = require('./types.js'); // Lazy load Types
300
+ // Process the transaction...
301
+ const sender = await TxUtils.getSender(txId);
302
+ const outputs = await TxUtils.getTransactionOutputs(txId);
303
+ const reference = outputs
304
+ .filter(o => o.vout === 0 || o.vout === 1)
305
+ .map(o => ({
306
+ address: o.address,
307
+ satoshis: o.satoshis
308
+ }));
309
+ const decodedParams = Types.decodePayload(txId, marker, payload);
310
+ console.log('sender, ref, payload, decode, market, txid '+JSON.stringify({ sender, reference, payload, decodedParams, marker, txId}))
311
+ return { sender, reference, payload, decodedParams, marker, txId};
312
+ }
313
+
314
+ async saveTransactionData(txId, txData, payload, blockHeight, txDetails) {
315
+ const indexKey = `tx-${blockHeight}-${txId}`;
316
+ const document = {
317
+ _id: indexKey,
318
+ txData: txDetails
319
+ };
320
+
321
+ console.log(document);
322
+
323
+ try {
324
+ // Check if the document already exists
325
+ const base = await db.getDatabase('txIndex')
326
+ const existingDocument = await base.findOneAsync({ _id: indexKey });
327
+
328
+ if (existingDocument) {
329
+ // Document exists, perform an update
330
+ const update = { $set: { txData, payload } };
331
+ await base.updateAsync({ _id: indexKey }, update);
332
+ //console.log(`Transaction data updated for ${indexKey}`);
333
+ } else {
334
+ // Document does not exist, perform an insert
335
+ await base.insertAsync(document);
336
+ //console.log(`Transaction data inserted for ${indexKey}`);
337
+ }
338
+ } catch (error) {
339
+ // Handle any errors
340
+ console.error(`Error saving transaction data for ${indexKey}: ${error}`);
341
+ }
342
+ }
343
+
344
+
345
+
346
+ async loadIndex() {
347
+ try {
348
+ const data = {};
349
+ const base = await db.getDatabase('txIndex')
350
+ const entries = await base.findAsync({});
351
+
352
+ entries.forEach(entry => {
353
+ data[entry._id] = entry.value;
354
+ });
355
+
356
+ return data;
357
+ } catch (err) {
358
+ console.error('Error loading index:', err);
359
+ throw err;
360
+ }
361
+ }
362
+
363
+ static async upsertTxValidityAndReason(txId, type, isValid, reason) {
364
+
365
+ // Fetch all entries with _id starting with "tx"
366
+ const base = await db.getDatabase('txIndex')
367
+ const allTxData = await base.findAsync({ _id: { $regex: /^tx/ } });
368
+
369
+ // Filter for the entry ending with the specified txId
370
+ const txData = allTxData.find(txData => txData._id.endsWith(`-${txId}`));
371
+
372
+ // If the entry is found, update it; otherwise, create a new one
373
+ if (txData) {
374
+ await base.updateAsync(
375
+ { _id: txData._id },
376
+ { $set: { type: type, valid: isValid, reason: reason } },
377
+ { upsert: true }
378
+ );
379
+ //console.log(`Transaction ${txData._id} validity updated in txIndex.`);
380
+ } else {
381
+ console.error(`No entry found for transaction ${txId} in txIndex.`);
382
+ }
383
+ }
384
+
385
+
386
+ static async clearTxIndex() {
387
+ return new Promise(async (resolve, reject) => {
388
+ try {
389
+ // Initialize your NeDB database
390
+ const db = new Datastore({ filename: 'your_nedb_database.db', autoload: true });
391
+
392
+ // Remove all documents from the txIndex collection
393
+ await db.remove({}, { multi: true });
394
+
395
+ console.log('Cleared all entries from txIndexDB.');
396
+ resolve();
397
+ } catch (error) {
398
+ console.error('Error in clearing txIndexDB:', error);
399
+ reject(error);
400
+ }
401
+ });
402
+ }
403
+
404
+ async initializeOrLoadDB(genesisBlock) {
405
+ return new Promise(async (resolve, reject) => {
406
+ try {
407
+ // Access the txIndex database using dbInstance
408
+ const txIndexDB = await db.getDatabase('txIndex');
409
+
410
+ // Attempt to find the 'genesisBlock' key
411
+ await txIndexDB.findOneAsync({ _id: 'genesisBlock' })
412
+ .then(doc => {
413
+ if (!doc) {
414
+ // If 'genesisBlock' key does not exist, initialize it
415
+ console.log('Initializing database with genesis block:', genesisBlock);
416
+ return txIndexDB.insertAsync({ _id: 'genesisBlock', value: genesisBlock });
417
+ } else {
418
+ //console.log('Database already initialized. Genesis block:', doc.value);
419
+ // Database already exists, resolve the promise
420
+ return Promise.resolve();
421
+ }
422
+ })
423
+ .then(() => resolve())
424
+ .catch(error => {
425
+ console.error('Error accessing database:', error);
426
+ reject(error);
427
+ });
428
+ } catch (error) {
429
+ console.error('Error accessing database:', error);
430
+ reject(error);
431
+ }
432
+ });
433
+ }
434
+
435
+ static async resetIndexFlag() {
436
+ await txIndexDB.del('indexExists');
437
+ await txIndexDB.del('genesisBlock');
438
+ console.log('Index flags reset successfully.');
439
+ }
440
+
441
+ static async findMaxIndexedBlock() {
442
+ try {
443
+ const txIndexDB = await db.getDatabase('txIndex')
444
+ const maxHeightDoc = await txIndexDB.findOneAsync({ _id: 'MaxHeight' });
445
+
446
+ if (maxHeightDoc) {
447
+ return maxHeightDoc.value;
448
+ } else {
449
+ // Handle the case where MaxHeight hasn't been set yet
450
+ //console.log('MaxHeight not found in txIndexDB.');
451
+ return null; // or an appropriate default/fallback value
452
+ }
453
+ } catch (err) {
454
+ console.error('Error finding MaxIndexedBlock:', err);
455
+ throw err;
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Retrieves and deserializes data for a given transaction ID from the txIndex database.
461
+ * @param {string} txId The transaction ID to query.
462
+ * @returns {Promise<object|null>} The deserialized transaction data or null if not found.
463
+ */
464
+ static async getTransactionData(txId) {
465
+ try {
466
+ const blockHeight = await TxIndex.fetchChainTip()
467
+ const txData = await db.getDatabase('txIndex').findOneAsync({ _id: indexKey });
468
+
469
+ if (txData) {
470
+ console.log(`Transaction data found for ${txId}:`, txData);
471
+ return txData.value; // Return the value part of the transaction data
472
+ } else {
473
+ console.log(`No transaction data found for ${txId}.`);
474
+ return null;
475
+ }
476
+ } catch (error) {
477
+ console.error(`Error retrieving transaction data for ${txId}:`, error);
478
+ reject(error);
479
+ }
480
+ }
481
+
482
+ static async checkForIndex() {
483
+ try {
484
+ const txIndexDB = await db.getDatabase('txIndex');
485
+ const indexExistsValue = await txIndexDB.findOneAsync({ _id: 'indexExists' });
486
+
487
+ if (indexExistsValue) {
488
+ console.log(`'indexExists' key found with value: ${indexExistsValue.value}`);
489
+ return true; // The index exists
490
+ } else {
491
+ console.log("'indexExists' key not found.");
492
+ return false; // The index does not exist
493
+ }
494
+ } catch (error) {
495
+ console.error('Error checking for index:', error);
496
+ }
497
+ }
498
+
499
+
500
+ }
501
+
502
+ module.exports = TxIndex;