@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,618 @@
1
+ const fetch = require('node-fetch'); // For HTTP requests (e.g., price lookups)
2
+ const db = require('./db.js')
3
+ const Litecoin = require('litecoin')
4
+ const util = require('util')
5
+ const Contracts = require('./contractRegistry.js')
6
+ const BigNumber = require('bignumber.js');
7
+
8
+ class VolumeIndex {
9
+ constructor(db) {
10
+ // Initialize data structures and database path
11
+ this.pairVolumes = {};
12
+ this.pairFees = {};
13
+ this.tokenPairCumulativeVolumes = 0;
14
+ this.ltcPairTotalVolume = 0;
15
+ this.contractCumulativeVolumes = 0;
16
+ this.cumulativeFees = 0;
17
+ this.dbPath = dbPath;
18
+ this.VWAPIndex = new Map()
19
+ }
20
+
21
+ static async saveVolumeDataById(id, rawVolume,ltcVolume, price,blockHeight, type) {
22
+ console.log('saving volume index data '+id, typeof id, rawVolume, ltcVolume, price, blockHeight, type)
23
+ const base = await db.getDatabase('volumeIndex')
24
+ await base.updateAsync(
25
+ { _id: id },
26
+ { _id: id, value: { blockHeight:blockHeight, rawVolume: rawVolume, ltcVolume: ltcVolume, price:price, type } },
27
+ { upsert: true }
28
+ );
29
+
30
+ // Update global cumulative volume variables
31
+ await VolumeIndex.updateCumulativeVolumes(ltcVolume, type,id,blockHeight);
32
+ return
33
+ }
34
+
35
+ static async getUTXOEquivalentVolume(volume, id, type,collateralId, notionalValue,inverse,price){
36
+ console.log('inside get getUTXOEquivalentVolume '+type+collateralId+notionalValue+inverse)
37
+ if(type === "contract"&&collateralId&&notionalValue&&inverse!==undefined){
38
+ const priceInLTC = await this.getTokenPriceInLTC(collateralId);
39
+ console.log('price in ltc for collateral '+collateralId+ ' '+priceInLTC+' trade price '+price+' volume '+volume)
40
+ const ltcPriceBN = new BigNumber(priceInLTC)
41
+ const volumeBN = new BigNumber(volume)
42
+ const tradePriceBN = new BigNumber(price)
43
+ const notionalBN = new BigNumber(notionalValue)
44
+ let volumeInLTC = volumeBN.times(ltcPriceBN).times(notionalBN)
45
+ if(inverse==false){
46
+ volumeInLTC = volumeInLTC.times(tradePriceBN)
47
+ }
48
+ console.log('result '+volumeInLTC.decimalPlaces(8).toNumber())
49
+ return volumeInLTC.decimalPlaces(8).toNumber()
50
+ }else if (type === "token") {
51
+ const [tokenId1, tokenId2] = id.split('-');
52
+ console.log('checking ids ' +tokenId1, tokenId2)
53
+ const priceInLTC1 = await this.getTokenPriceInLTC(tokenId1);
54
+ const priceInLTC2 = await this.getTokenPriceInLTC(tokenId2);
55
+ console.log('LTC prices of the tokens'+priceInLTC1, priceInLTC2)
56
+ const volumeInLTC = priceInLTC1*volume[0] + priceInLTC2*volume[1]
57
+ return volumeInLTC
58
+ }
59
+ }
60
+
61
+ static async updateCumulativeVolumes(volume, type, id, block) {
62
+ // load existing totals, guard nulls
63
+
64
+ const base = await db.getDatabase('volumeIndex');
65
+ const globalDoc = await base.findOneAsync({ _id: 'globalCumulativeVolume' }) || { value: { globalCumulativeVolume: 0 }};
66
+ const ltcDoc = await base.findOneAsync({ _id: 'ltcPairCumulativeVolume' }) || { value: { ltcPairTotalVolume: 0 }};
67
+
68
+ const globalCumulativeVolume = globalDoc.value.globalCumulativeVolume
69
+ const ltcPairTotalVolume = ltcDoc.value.ltcPairTotalVolume
70
+
71
+ console.log('inside updateCumulativeVolumes '+JSON.stringify(globalDoc)+' '+JSON.stringify(ltcDoc))
72
+ const BNGlobal = new BigNumber(globalCumulativeVolume || 0);
73
+ const BNltc = new BigNumber(ltcPairTotalVolume || 0);
74
+ const BNVol = new BigNumber(volume || 0);
75
+
76
+ // global always increments
77
+ const newGlobal = BNVol.plus(BNGlobal).decimalPlaces(8).toNumber();
78
+
79
+ // ltc pair increments only if type === "UTXO"
80
+ let newLtcPair = BNltc.toNumber();
81
+ if (type === "UTXO") {
82
+ newLtcPair = BNVol.plus(BNltc).decimalPlaces(8).toNumber();
83
+ }
84
+
85
+ await base.updateAsync(
86
+ { _id: 'ltcPairCumulativeVolume' },
87
+ { _id: 'ltcPairCumulativeVolume', value: { ltcPairTotalVolume: newLtcPair, block } },
88
+ { upsert: true }
89
+ );
90
+
91
+ await base.updateAsync(
92
+ { _id: 'globalCumulativeVolume' },
93
+ { _id: 'globalCumulativeVolume', value: { globalCumulativeVolume: newGlobal, block } },
94
+ { upsert: true }
95
+ );
96
+
97
+ return;
98
+ }
99
+
100
+
101
+ static async getTokenPriceInLTC(tokenId) {
102
+ // Attempt to fetch the VWAP price from the database
103
+ const base = await db.getDatabase('volumeIndex')
104
+ const vwapData = await base.findOneAsync({ _id: `0-${tokenId}` });
105
+ console.log('get token LTC price '+JSON.stringify(vwapData))
106
+ if (vwapData && vwapData.value && vwapData.value.price) {
107
+ return vwapData.value.price;
108
+ }
109
+
110
+ // If VWAP price is not available, return a default low value
111
+ return 0.001; // Minimum price
112
+ }
113
+
114
+ static async calculateVolIndex(lookbackBlocks = 14400) {
115
+ const base = await db.getDatabase('volumeIndex');
116
+ const docs = await base.findAsync({}).sort({ 'value.blockHeight': -1 }).limit(lookbackBlocks);
117
+
118
+ if (!docs || docs.length < 2) {
119
+ return 0;
120
+ }
121
+
122
+ // Collect log returns
123
+ let prices = docs.map(d => d.value.price).filter(p => p > 0);
124
+ let logReturns = [];
125
+ for (let i = 1; i < prices.length; i++) {
126
+ logReturns.push(Math.log(prices[i] / prices[i-1]));
127
+ }
128
+
129
+ // Standard deviation of log returns
130
+ const mean = logReturns.reduce((a,b) => a+b, 0) / logReturns.length;
131
+ const variance = logReturns.reduce((a,b) => a + Math.pow(b-mean,2), 0) / (logReturns.length-1);
132
+ const stdev = Math.sqrt(variance);
133
+
134
+ // Annualize (assuming 144 blocks ≈ 1 day)
135
+ const blocksPerYear = 144 * 365;
136
+ const volIndex = stdev * Math.sqrt(blocksPerYear);
137
+
138
+ // Save volIndex in db
139
+ await base.updateAsync(
140
+ { _id: 'volIndex' },
141
+ { _id: 'volIndex', value: { vol: volIndex, updatedAt: Date.now() } },
142
+ { upsert: true }
143
+ );
144
+
145
+ return volIndex;
146
+ }
147
+
148
+
149
+
150
+ /**
151
+ * Normalize ContractRegistry.getContractInfo(contractId) into a flat shape.
152
+ * Accepts either { data: {...} } or a flat object.
153
+ */
154
+ static async _normalizeContractInfo(contractId) {
155
+ const Contracts = require('./contractRegistry.js')
156
+ const raw = await Contracts.getContractInfo(contractId);
157
+ const d = (raw && raw.data) ? raw.data : (raw || {});
158
+
159
+ return {
160
+ contractId: d.id ?? raw?.id ?? contractId,
161
+ ticker: d.ticker,
162
+ native: !!d.native,
163
+ inverse: !!d.inverse,
164
+ // definitive fields from your sample
165
+ notionalPropertyId: d.notionalPropertyId ?? 0, // 0 => LTC
166
+ notionalValue: Number(d.notionalValue ?? 1),
167
+ collateralPropertyId: d.collateralPropertyId,
168
+ leverage: Number(d.leverage ?? 1) || 1,
169
+ onChainData: Array.isArray(d.onChainData) ? d.onChainData : [],
170
+ };
171
+ }
172
+
173
+ /**
174
+ * LTC value per 1 contract unit:
175
+ * ltcPerContract = (notionalValue * price(notionalPropertyId in LTC)) / leverage
176
+ * Handles inverse/native the same, since notional is explicit in (value, property).
177
+ */
178
+ static async getContractUnitLTCValue(contractId) {
179
+ try {
180
+ const c = await this._normalizeContractInfo(contractId);
181
+
182
+ // Price for the notional token in LTC
183
+ let tokenPriceInLTC = 1;
184
+ if (!(c.notionalPropertyId === 0 || c.notionalPropertyId === '0' || c.notionalPropertyId === 'LTC')) {
185
+ tokenPriceInLTC = await this.getTokenPriceInLTC(c.notionalPropertyId);
186
+ }
187
+
188
+ const notionalLTC = c.notionalValue * Number(tokenPriceInLTC || 0);
189
+ if (!Number.isFinite(notionalLTC) || notionalLTC <= 0) return 0;
190
+
191
+ const ltcPerContract = notionalLTC / (c.leverage || 1);
192
+ console.log('inside LTC contract value '+ltcPerContract.toFixed(8)+' '+notionalLTC+' '+c.leverage)
193
+ return Number(ltcPerContract.toFixed(8));
194
+ } catch (e) {
195
+ console.error('getContractUnitLTCValue error', e);
196
+ return 0;
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Debug/telemetry variant with all the inputs broken out.
202
+ */
203
+ static async getContractUnitLTCValueDetails(contractId) {
204
+ const c = await this._normalizeContractInfo(contractId);
205
+
206
+ let tokenPriceInLTC = 1;
207
+ if (!(c.notionalPropertyId === 0 || c.notionalPropertyId === '0' || c.notionalPropertyId === 'LTC')) {
208
+ tokenPriceInLTC = await this.getTokenPriceInLTC(c.notionalPropertyId);
209
+ }
210
+
211
+ const notionalLTC = c.notionalValue * Number(tokenPriceInLTC || 0);
212
+ console.log('inside get contract unit LTC Value '+notionalLTC+' '+JSON.stringify(c))
213
+ const ltcPerContract = Number.isFinite(notionalLTC) && c.leverage
214
+ ? Number((notionalLTC / c.leverage).toFixed(8))
215
+ : 0;
216
+
217
+ if(ltcPerContract==0){throw new Error()}
218
+ return ltcPerContract
219
+ }
220
+
221
+
222
+ /**
223
+ * Function to get the last price for a given token pair and block height.
224
+ * @param {string} tokenPair - The token pair in the format "X-Y".
225
+ * @param {number} blockHeight - The block height to compare against.
226
+ * @returns {Promise<number|null>} - The last price if found, otherwise null.
227
+ */
228
+ static async getLastPrice(tokenPair, blockHeight) {
229
+ try {
230
+ const base = await db.getDatabase('volumeIndex');
231
+ console.log('inside get last price ' + blockHeight);
232
+
233
+ // Try direct pair first
234
+ const direct = await base.findOneAsync({ _id: tokenPair });
235
+
236
+ if (direct && direct.value && direct.value.price) {
237
+ return direct.value.price;
238
+ }
239
+
240
+ // If not found, try the inverse pair
241
+ const [a, b] = tokenPair.split('-');
242
+ const inversePair = `${b}-${a}`;
243
+ const inverse = await base.findOneAsync({ _id: inversePair });
244
+
245
+ if (inverse && inverse.value && inverse.value.price) {
246
+ // invert the price for the obverse pair
247
+ const inverted = new BigNumber(1).div(inverse.value.price).toNumber();
248
+ console.log(
249
+ `Using inverse pair ${inversePair}, original tokenPair ${tokenPair}, inverted price=${inverted}`
250
+ );
251
+ return inverted;
252
+ }
253
+
254
+ console.error(
255
+ `No data found for token pair: ${tokenPair} or its inverse at or below block height ${blockHeight}`
256
+ );
257
+ return null;
258
+ } catch (error) {
259
+ console.error('Error fetching last price:', error);
260
+ return null;
261
+ }
262
+ }
263
+
264
+ static async getCumulativeVolumes(block) {
265
+ const base = await db.getDatabase('volumeIndex');
266
+
267
+ // Default values
268
+ let globalCumulativeVolume = 0;
269
+ let contractCumulativeVolume = 0;
270
+ let ltcPairTotalVolume = 0;
271
+
272
+ try {
273
+ const globalDocs = await base.findAsync({ _id: 'globalCumulativeVolume', 'value.block': { $lt: block } });
274
+ if (Array.isArray(globalDocs) && globalDocs.length) {
275
+ globalDocs.sort((a, b) => b.value.block - a.value.block);
276
+ globalCumulativeVolume = globalDocs[0].value.globalCumulativeVolume || 0;
277
+ }
278
+ } catch (err) {
279
+ console.error("Error fetching global cumulative volume:", err);
280
+ }
281
+
282
+ try {
283
+ const contractDocs = await base.findAsync({ _id: 'contractCumulativeVolume', 'value.block': { $lt: block } });
284
+ if (Array.isArray(contractDocs) && contractDocs.length) {
285
+ contractDocs.sort((a, b) => b.value.block - a.value.block);
286
+ contractCumulativeVolume = contractDocs[0].value.contractCumulativeVolume || 0;
287
+ }
288
+ } catch (err) {
289
+ console.error("Error fetching contract cumulative volume:", err);
290
+ }
291
+
292
+ try {
293
+ const ltcDocs = await base.findAsync({ _id: 'ltcPairCumulativeVolume', 'value.block': { $lt: block } });
294
+ if (Array.isArray(ltcDocs) && ltcDocs.length) {
295
+ ltcDocs.sort((a, b) => b.value.block - a.value.block);
296
+ ltcPairTotalVolume = ltcDocs[0].value.ltcPairTotalVolume || 0;
297
+ }
298
+ } catch (err) {
299
+ console.error("Error fetching LTC pair total volume:", err);
300
+ }
301
+
302
+ return {
303
+ globalCumulativeVolume,
304
+ ltcPairTotalVolume,
305
+ contractCumulativeVolume,
306
+ };
307
+ }
308
+
309
+
310
+ static async getBlockVolumes(blockHeight) {
311
+ try {
312
+ // Query the VolumeIndex.db for trades with the given blockHeight
313
+ const base = await db.getDatabase('volumeIndex')
314
+ const trades = await base.findAsync({
315
+ "value.blockHeight": blockHeight
316
+ });
317
+ // If no trades are found, return 0
318
+ if (!trades || trades.length === 0) {
319
+ return 0;
320
+ }
321
+
322
+ console.log('getting block volumes '+JSON.stringify(trades))
323
+ // Sum the total volume from the trades found
324
+ let totalLTCVolume = new BigNumber(0);
325
+ let totalVolume = new BigNumber(0)
326
+ trades.forEach(trade => {
327
+ const tradeVolume = new BigNumber(trade.value.ltcVolume);
328
+
329
+ if(trade._id.toString().includes('0')){
330
+ console.log(tradeVolume)
331
+ totalLTCVolume = totalLTCVolume.plus(tradeVolume);
332
+ }
333
+
334
+ totalVolume=totalVolume.plus(tradeVolume)
335
+
336
+ });
337
+ totalLTCVolume= totalLTCVolume.toNumber()
338
+ totalVolume= totalVolume.toNumber()
339
+ console.log(totalLTCVolume+' '+totalVolume)
340
+ // Return the total volume for the block
341
+ return {ltcPairs:totalLTCVolume,global:totalVolume};
342
+ } catch (error) {
343
+ return console.error(`Error fetching block volumes for block ${blockHeight}:`, error);
344
+ //throw new Error(`Failed to fetch block volumes for block ${blockHeight}`);
345
+ }
346
+ }
347
+
348
+ static async getVolumeDataById(id) {
349
+ return await db.getDatabase('volumeIndex').findOneAsync({ _id: id });
350
+ }
351
+
352
+ static async sampleVolumesByBlock(blockHeight) {
353
+ const volumeIndexData = await db.getDatabase('volumeIndex').findAsync({ blockHeight });
354
+ return volumeIndexData.map(entry => ({ id: entry._id, volume: entry.volume }));
355
+ }
356
+
357
+ static async sampleVolumesByBlockRange(startBlockHeight, endBlockHeight) {
358
+ const volumeIndexData = await db.getDatabase('volumeIndex').findAsync({
359
+ blockHeight: { $gte: startBlockHeight, $lte: endBlockHeight }
360
+ });
361
+ return volumeIndexData.map(entry => ({ id: entry._id, volume: entry.volume }));
362
+ }
363
+
364
+ static async calculateCumulativeVolume(id1, id2) {
365
+ const volumeIndexData = await db.getDatabase('volumeIndex').findAsync({ _id: { $regex: `^${id1}-${id2}-` } });
366
+ let cumulativeVolume = 0;
367
+ volumeIndexData.forEach(entry => cumulativeVolume += entry.volume);
368
+ return cumulativeVolume;
369
+ }
370
+
371
+ static async saveCumulativeVolume(id1, id2, cumulativeVolume) {
372
+ const id = `cumulative-${id1}-${id2}`;
373
+ await saveVolumeDataById(id, null, cumulativeVolume);
374
+ }
375
+
376
+ static async auditVWAP(blockHeight) {
377
+ const volumeData = await this.sampleVolumesByBlock(blockHeight);
378
+
379
+ // Calculate total volume and sum of (volume * price)
380
+ let totalVolume = 0;
381
+ let sumVolumeTimesPrice = 0;
382
+
383
+ for (const entry of volumeData) {
384
+ const price = await this.getTokenPriceInLTC(entry.id);
385
+ const volume = entry.volume;
386
+
387
+ totalVolume += volume;
388
+ sumVolumeTimesPrice += volume * price;
389
+ }
390
+
391
+ // Avoid division by zero
392
+ if (totalVolume === 0) {
393
+ return null;
394
+ }
395
+
396
+ // Calculate VWAP
397
+ const vwap = sumVolumeTimesPrice / totalVolume;
398
+ return vwap;
399
+ }
400
+
401
+ static calculateVWAP(data, contract = false) {
402
+ // Calculate total volume and sum of (volume * price)
403
+ let totalVolume = 0;
404
+ let sumVolumeTimesPrice = 0;
405
+
406
+ for (const entry of data) {
407
+ let volume;
408
+ let price;
409
+
410
+ if (entry.amount1 !== undefined && entry.amount2 !== undefined) {
411
+ volume = contract ? entry.amount2 : entry.amount1;
412
+ price = contract ? entry.amount1 : entry.amount2;
413
+ } else if (entry.amount !== undefined && entry.price !== undefined) {
414
+ volume = entry.amount;
415
+ price = entry.price;
416
+ } else {
417
+ throw new Error("Invalid data format. Each entry must contain either 'amount1' and 'amount2', or 'amount' and 'price'.");
418
+ }
419
+
420
+ totalVolume += volume;
421
+ sumVolumeTimesPrice += volume * price;
422
+ }
423
+
424
+ // Avoid division by zero
425
+ if (totalVolume === 0) {
426
+ return null;
427
+ }
428
+
429
+ // Calculate VWAP
430
+ const vwap = sumVolumeTimesPrice / totalVolume;
431
+ return vwap;
432
+ }
433
+
434
+ static async getVwapData(propertyId1, propertyId2, trailingBlocks) {
435
+ try {
436
+ // Fetch the N most recent VWAP entries for the specified property pair
437
+ const vwapData = await db.getDatabase('volumeIndex').findAsync({
438
+ _id: { $regex: `${propertyId1}-${propertyId2}-` }
439
+ }, {
440
+ sort: { blockHeight: -1 }, // Sort by blockHeight in descending order
441
+ limit: trailingBlocks // Limit to the N most recent entries
442
+ });
443
+
444
+ // Calculate total volume and sum of (volume * price)
445
+ let totalVolume = 0;
446
+ let sumVolumeTimesPrice = 0;
447
+
448
+ for (const entry of vwapData) {
449
+ const price = entry.value.price;
450
+ const volume = entry.value.volume;
451
+
452
+ totalVolume += volume;
453
+ sumVolumeTimesPrice += volume * price;
454
+ }
455
+
456
+ // Avoid division by zero
457
+ if (totalVolume === 0) {
458
+ return null;
459
+ }
460
+
461
+ // Calculate VWAP
462
+ const vwap = sumVolumeTimesPrice / totalVolume;
463
+ return vwap;
464
+ } catch (error) {
465
+ console.error('Error fetching VWAP data:', error);
466
+ throw new Error('Failed to fetch VWAP data.');
467
+ }
468
+ }
469
+
470
+ static async saveVWAP(id, blockHeight, vwap) {
471
+ console.log('saving VWAP'+ id, blockHeight, vwap)
472
+ const base = await db.getDatabase('volumeIndex')
473
+ await base.updateAsync(
474
+ { _id: 'vwap-'+id },
475
+ { value: { blockHeight:blockHeight, volume: volume, price:price } },
476
+ { upsert: true }
477
+ );
478
+ }
479
+
480
+ static async calculateLiquidityReward(tradeVolume, token) {
481
+
482
+ if (!this.globalCumulativeVolume || this.globalCumulativeVolume === 0) {
483
+ const blob = await getCumulativeVolumes; // Assuming this function fetches or initializes globalCumulativeVolume
484
+ this.globalCumulativeVolume=blob.globalCumulativeVolume
485
+ }
486
+
487
+ if(token!=0){
488
+ const tokenPriceInLTC = await this.getTokenPriceInLTC(token);
489
+ }
490
+
491
+ tradeVolume=tradeVolume*tokenPriceInLTC
492
+ const totalVolume = this.globalCumulativeVolume - tradeVolume;
493
+
494
+ // Calculate logarithmic value
495
+ const logVolume = Math.log10(totalVolume / 1e9); // Log base 10 with cap at 1 billion LTC
496
+
497
+ // Calculate liquidity reward based on log value
498
+ let liquidityReward = 0;
499
+ if (logVolume > 0) {
500
+ liquidityReward = logVolume * 3e6 / 3; // Adjust 3e6 for percentage calculation
501
+ }
502
+
503
+ return liquidityReward;
504
+ }
505
+ static async getVWAP(propertyId1, propertyId2, blockHeight, trailingBlocks) {
506
+ try {
507
+ const base = await db.getDatabase('volumeIndex');
508
+ const blockStart = blockHeight - trailingBlocks;
509
+
510
+ // Query volume index within the block range
511
+ const vwapData = await base.findAsync({
512
+ _id: { $in: [`${propertyId1}-${propertyId2}`, `${propertyId2}-${propertyId1}`] }, // Check both pair orders
513
+ "value.blockHeight": { $gte: blockStart, $lte: blockHeight }
514
+ });
515
+
516
+ if (!vwapData || vwapData.length === 0) {
517
+ //console.warn(`⚠️ No VWAP data for ${propertyId1}-${propertyId2} in blocks ${blockStart}-${blockHeight}`);
518
+ return null;
519
+ }
520
+
521
+ // Calculate VWAP
522
+ let totalVolume = new BigNumber(0);
523
+ let sumVolumeTimesPrice = new BigNumber(0);
524
+
525
+ for (const entry of vwapData) {
526
+ const price = new BigNumber(entry.value.price);
527
+ const volume = new BigNumber(entry.value.volume);
528
+
529
+ totalVolume = totalVolume.plus(volume);
530
+ sumVolumeTimesPrice = sumVolumeTimesPrice.plus(volume.times(price));
531
+ }
532
+
533
+ if (totalVolume.isZero()) return null;
534
+
535
+ return sumVolumeTimesPrice.dividedBy(totalVolume).decimalPlaces(8).toNumber();
536
+ } catch (error) {
537
+ console.error(`❌ Error fetching VWAP for ${propertyId1}-${propertyId2}:`, error);
538
+ return null;
539
+ }
540
+ }
541
+
542
+
543
+ static async baselineLiquidityReward(tradeVolume, fee, token) {
544
+ const totalVolume = this.globalCumulativeVolume - tradeVolume;
545
+ let tlPriceInLTC = 0.001
546
+ if(token!=0){
547
+
548
+ // Step 1: Get LTC price of the token in question
549
+ const tokenPriceInLTC = await this.getTokenPriceInLTC(token);
550
+
551
+ // Step 2: Get TL/LTC price (assuming TL is a specific token or currency)
552
+ tlPriceInLTC = await this.getTLPriceInLTC();
553
+
554
+ // Step 3: Calculate fee in TL
555
+ const feeInTL = fee * tokenPriceInLTC * tlPriceInLTC;
556
+ }else{
557
+ const feeInTL= fee * tlPriceInLTC
558
+ }
559
+
560
+
561
+ // Calculate logarithmic value
562
+ const logVolume = Math.log10(totalVolume);
563
+
564
+ // Calculate liquidity reward based on log value and fee
565
+ let liquidityReward = 0;
566
+ if (logVolume > 0) {
567
+ const feeAdjustment = 1/logVolume; // Reducing by 10% per log 10
568
+ liquidityReward = feeInTL * feeAdjustment;
569
+ }
570
+
571
+ return liquidityReward;
572
+ }
573
+
574
+ static async getTLPriceInLTC() {
575
+ // Attempt to fetch the VWAP price from the database
576
+ const base = await db.getDatabase('volumeIndex')
577
+ const vwapData = await base.findOneAsync({ _id: `vwap-1` });
578
+
579
+ if (vwapData && vwapData.value && vwapData.value.price) {
580
+ return vwapData.value.price;
581
+ }
582
+
583
+ // If VWAP price is not available, return a default low value
584
+ return 0.001; // Minimum price
585
+ }
586
+
587
+
588
+
589
+ static vestTokens(tradeVolume) {
590
+ // Calculate logarithmic value
591
+ const logVolume = Math.log10(this.globalCumulativeVolume / 1e9); // Log base 10 with cap at 100 billion LTC
592
+
593
+ // Tier 1 vesting tokens (1000 to 100,000,000 LTC)
594
+ let tier1Tokens = 0;
595
+ if (logVolume > 0) {
596
+ if (totalVolume >= 1000 && totalVolume <= 1e8) {
597
+ tier1Tokens = logVolume * 1e6; // Adjust 1e6 for tokens calculation
598
+ }
599
+ }
600
+
601
+ // Tier 2 vesting tokens (100,000,000 to 100 billion LTC)
602
+ let tier2Tokens = 0;
603
+ if (logVolume > 0) {
604
+ if (totalVolume > 1e8 && totalVolume <= 1e11) {
605
+ tier2Tokens = logVolume * 3e6; // Adjust 3e6 for tokens calculation
606
+ }
607
+ }
608
+
609
+ return {
610
+ tier1Tokens,
611
+ tier2Tokens
612
+ };
613
+ }
614
+
615
+
616
+ }
617
+
618
+ module.exports = VolumeIndex;