@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,178 @@
1
+ const axios = require('axios');
2
+ const serverUrl = 'http://localhost:3000'; // Adjust the server URL as needed
3
+
4
+ const expressInterface = {
5
+ async initMain(test) {
6
+ try {
7
+ console.log('about to init')
8
+ const response = await axios.post(`${serverUrl}/initMain`, { test: test });
9
+ console.log(response.data);
10
+ } catch (error) {
11
+ console.error('Error in init:', error.response ? error.response.data : error.message);
12
+ }
13
+ },
14
+
15
+ async listProperties() {
16
+ try {
17
+ const response = await axios.post(`${serverUrl}/listProperties`);
18
+ return response.data;
19
+ } catch (error) {
20
+ //console.error('Error in listProperties:', error.response ? error.response.data : error.message);
21
+ throw error;
22
+ }
23
+ },
24
+
25
+ async getAllBalancesForAddress(address) {
26
+ try {
27
+ const response = await axios.post(`${serverUrl}/getAllBalancesForAddress`, { address });
28
+ return response.data;
29
+ } catch (error) {
30
+ console.error('Error in getAllBalancesForAddress:', error.response ? error.response.data : error.message);
31
+ throw error;
32
+ }
33
+ },
34
+
35
+ async getActivations() {
36
+ try {
37
+ const response = await axios.post(`${serverUrl}/getActivations`);
38
+ return response.data;
39
+ } catch (error) {
40
+ console.error('Error in getActivations:', error.response ? error.response.data : error.message);
41
+ throw error;
42
+ }
43
+ },
44
+
45
+ async getOrderBook(propertyId1, propertyId2) {
46
+ try {
47
+ const response = await axios.post(`${serverUrl}/getOrderBook`, { propertyId1, propertyId2 });
48
+ return response.data;
49
+ } catch (error) {
50
+ console.error('Error in getOrderBook:', error.response ? error.response.data : error.message);
51
+ throw error;
52
+ }
53
+ },
54
+
55
+ async getContractOrderBook(contractId) {
56
+ try {
57
+ const response = await axios.post(`${serverUrl}/getContractOrderBook`, { contractId });
58
+ return response.data;
59
+ } catch (error) {
60
+ console.error('Error in getOrderBook:', error.response ? error.response.data : error.message);
61
+ throw error;
62
+ }
63
+ },
64
+
65
+ async listContractSeries() {
66
+ try {
67
+ const response = await axios.post(`${serverUrl}/listContractSeries`);
68
+ return response.data;
69
+ } catch (error) {
70
+ console.error('Error in listContractSeries:', error.response ? error.response.data : error.message);
71
+ throw error;
72
+ }
73
+ },
74
+
75
+ async listOracles() {
76
+ try {
77
+ const response = await axios.post(`${serverUrl}/listOracles`);
78
+ return response.data;
79
+ } catch (error) {
80
+ console.error('Error in listOracles:', error.response ? error.response.data : error.message);
81
+ throw error;
82
+ }
83
+ },
84
+
85
+ async getContractPositionForAddressAndContractId(address, contractId) {
86
+ try {
87
+ const response = await axios.get(`${serverUrl}/contractPosition/${address}/${contractId}`);
88
+ return response.data;
89
+ } catch (error) {
90
+ console.error('Error in getContractPositionForAddressAndContractId:', error.response ? error.response.data : error.message);
91
+ throw error;
92
+ }
93
+ },
94
+
95
+ async getTradeHistory(propertyId1, propertyId2) {
96
+ try {
97
+ const response = await axios.get(`${serverUrl}/tradeHistory/${propertyId1}/${propertyId2}`);
98
+ return response.data;
99
+ } catch (error) {
100
+ console.error('Error in getTradeHistory:', error.response ? error.response.data : error.message);
101
+ throw error;
102
+ }
103
+ },
104
+
105
+ async getContractTradeHistory(contractId) {
106
+ try {
107
+ const response = await axios.get(`${serverUrl}/contractTradeHistory/${contractId}`);
108
+ return response.data;
109
+ } catch (error) {
110
+ console.error('Error in getContractTradeHistory:', error.response ? error.response.data : error.message);
111
+ throw error;
112
+ }
113
+ },
114
+
115
+ async getFundingHistory(contractId) {
116
+ try {
117
+ const response = await axios.get(`${serverUrl}/fundingHistory/${contractId}`);
118
+ return response.data;
119
+ } catch (error) {
120
+ console.error('Error in getFundingHistory:', error.response ? error.response.data : error.message);
121
+ throw error;
122
+ }
123
+ },
124
+
125
+ async getOracleHistory(oracleId) {
126
+ try {
127
+ const response = await axios.get(`${serverUrl}/oracleHistory/${oracleId}`);
128
+ return response.data;
129
+ } catch (error) {
130
+ console.error('Error in getOracleHistory:', error.response ? error.response.data : error.message);
131
+ throw error;
132
+ }
133
+ },
134
+
135
+ async getClearingHistory(contractId) {
136
+ try {
137
+ const response = await axios.get(`${serverUrl}/clearingHistory/${contractId}`);
138
+ return response.data;
139
+ } catch (error) {
140
+ console.error('Error in getClearingHistory:', error.response ? error.response.data : error.message);
141
+ throw error;
142
+ }
143
+ },
144
+
145
+ async getWalletPositions() {
146
+ try {
147
+ const response = await axios.get(`${serverUrl}/walletPositions`);
148
+ return response.data;
149
+ } catch (error) {
150
+ console.error('Error in getWalletPositions:', error.response ? error.response.data : error.message);
151
+ throw error;
152
+ }
153
+ },
154
+
155
+ async getAddressesWithProperty(propertyId) {
156
+ try {
157
+ const response = await axios.get(`${serverUrl}/addressesWithProperty/${propertyId}`);
158
+ return response.data;
159
+ } catch (error) {
160
+ console.error('Error in getAddressesWithProperty:', error.response ? error.response.data : error.message);
161
+ throw error;
162
+ }
163
+ },
164
+
165
+ async getContractPositionForAddressAndContractId(address, contractId) {
166
+ try {
167
+ const response = await axios.get(`${serverUrl}/contractPosition/${address}/${contractId}`);
168
+ return response.data;
169
+ } catch (error) {
170
+ console.error('Error in getContractPositionForAddressAndContractId:', error.response ? error.response.data : error.message);
171
+ throw error;
172
+ }
173
+ }
174
+
175
+
176
+ };
177
+
178
+ module.exports = expressInterface;
@@ -0,0 +1,509 @@
1
+ // pnlIou.js
2
+ //
3
+ // STATIC IOU BUCKET
4
+ // Records PnL mismatch or loss shortfalls per (contractId, propertyId).
5
+ // No instance state. No RAM caching.
6
+ // Compatible with NeDB or Mongo via your db.js wrapper.
7
+ //
8
+ // KEY CHANGE: Track blockLosses and blockProfits separately.
9
+ // - blockLosses: real tokens debited from losers (available to pay IOU holders)
10
+ // - blockProfits: unfunded gains that become IOU claims
11
+ // - blockDelta: kept for backward compat (= blockLosses - blockProfits from bucket perspective)
12
+
13
+ const BigNumber = require('bignumber.js');
14
+ const dbInstance = require('./db.js');
15
+
16
+ class PnlIou {
17
+ // -----------------------
18
+ // Helpers
19
+ // -----------------------
20
+ static key(contractId, propertyId) {
21
+ return `${contractId}:${propertyId}`;
22
+ }
23
+
24
+ static async _db() {
25
+ return await dbInstance.getDatabase('iou');
26
+ }
27
+
28
+ // -----------------------
29
+ // Audit helper (same DB)
30
+ // -----------------------
31
+ static async audit(event) {
32
+ const db = await PnlIou._db();
33
+
34
+ const doc = {
35
+ _id: `audit:${event.block}:${event.contractId}:${event.propertyId}:${Date.now()}:${Math.random()}`,
36
+ type: 'audit',
37
+ ts: Date.now(),
38
+ ...event
39
+ };
40
+
41
+ try {
42
+ await db.insertAsync(doc);
43
+ } catch (e) {
44
+ // audit must never break consensus
45
+ console.warn('IOU audit insert failed:', e.message);
46
+ }
47
+ }
48
+
49
+ static claimKey(contractId, propertyId) {
50
+ return `claims:${Number(contractId)}:${Number(propertyId)}`;
51
+ }
52
+
53
+ static async getClaimMap(contractId, propertyId) {
54
+ const db = await dbInstance.getDatabase('iou');
55
+ return await db.findOneAsync({
56
+ _id: PnlIou.claimKey(contractId, propertyId)
57
+ });
58
+ }
59
+
60
+ static async saveClaimMap(doc) {
61
+ const db = await dbInstance.getDatabase('iou');
62
+ await db.updateAsync(
63
+ { _id: doc._id },
64
+ doc,
65
+ { upsert: true }
66
+ );
67
+ }
68
+
69
+ static async getBucket(contractId, propertyId) {
70
+ const key = PnlIou.key(contractId, propertyId);
71
+ const db = await PnlIou._db();
72
+
73
+ let doc = null;
74
+ try {
75
+ doc = await db.findOneAsync({ _id: key });
76
+ } catch (e) {
77
+ return null;
78
+ }
79
+
80
+ if (!doc) return null;
81
+
82
+ return {
83
+ ...doc,
84
+ amount: new BigNumber(doc.amount || 0),
85
+ blockStartAmount: new BigNumber(doc.blockStartAmount || 0),
86
+ blockDelta: new BigNumber(doc.blockDelta || 0),
87
+ blockLosses: new BigNumber(doc.blockLosses || 0),
88
+ blockProfits: new BigNumber(doc.blockProfits || 0)
89
+ };
90
+ }
91
+
92
+ static async addIouClaims(
93
+ contractId,
94
+ propertyId,
95
+ block,
96
+ buyerAddr,
97
+ sellerAddr,
98
+ buyerPnl,
99
+ sellerPnl,
100
+ delta
101
+ ) {
102
+ const d = new BigNumber(delta || 0);
103
+ if (d.lte(0)) return null;
104
+
105
+ const bP = new BigNumber(buyerPnl || 0);
106
+ const sP = new BigNumber(sellerPnl || 0);
107
+
108
+ const posBuyer = BigNumber.max(bP, 0);
109
+ const posSeller = BigNumber.max(sP, 0);
110
+ const sumPos = posBuyer.plus(posSeller);
111
+ if (sumPos.lte(0)) return null;
112
+
113
+ const buyerShare = posBuyer.gt(0) ? d.times(posBuyer.div(sumPos)) : new BigNumber(0);
114
+ const sellerShare = posSeller.gt(0) ? d.times(posSeller.div(sumPos)) : new BigNumber(0);
115
+
116
+ let doc = await PnlIou.getClaimMap(contractId, propertyId);
117
+
118
+ if (!doc) {
119
+ doc = {
120
+ _id: PnlIou.claimKey(contractId, propertyId),
121
+ contractId: Number(contractId),
122
+ propertyId: Number(propertyId),
123
+ claims: {},
124
+ lastBlock: block
125
+ };
126
+ }
127
+
128
+ if (buyerShare.gt(0)) {
129
+ doc.claims[buyerAddr] = new BigNumber(doc.claims[buyerAddr] || 0)
130
+ .plus(buyerShare)
131
+ .toString(10);
132
+ }
133
+
134
+ if (sellerShare.gt(0)) {
135
+ doc.claims[sellerAddr] = new BigNumber(doc.claims[sellerAddr] || 0)
136
+ .plus(sellerShare)
137
+ .toString(10);
138
+ }
139
+
140
+ doc.lastBlock = block;
141
+ await PnlIou.saveClaimMap(doc);
142
+
143
+ // optional but recommended for traceability
144
+ await PnlIou.audit({
145
+ event: 'claim_accrual',
146
+ block,
147
+ contractId: Number(contractId),
148
+ propertyId: Number(propertyId),
149
+ delta: d.toString(10),
150
+ buyerAddr,
151
+ sellerAddr,
152
+ buyerShare: buyerShare.toString(10),
153
+ sellerShare: sellerShare.toString(10)
154
+ });
155
+
156
+ return doc;
157
+ }
158
+
159
+ // -----------------------
160
+ // Add a LOSS to the bucket (positive amount = real tokens debited from loser)
161
+ // These tokens are available to pay out to IOU claimants
162
+ // -----------------------
163
+ static async addLoss(contractId, propertyId, lossAmount, block) {
164
+ const loss = new BigNumber(lossAmount || 0);
165
+ if (loss.lte(0)) return null;
166
+
167
+ const key = PnlIou.key(contractId, propertyId);
168
+ const db = await dbInstance.getDatabase('iou');
169
+
170
+ let existing = null;
171
+ try { existing = await db.findOneAsync({ _id: key }); } catch (e) {}
172
+
173
+ const current = new BigNumber((existing && existing.amount) || 0);
174
+ const isNewBlock = !(existing && Number(existing.lastBlock) === Number(block));
175
+
176
+ const blockStart = isNewBlock
177
+ ? current
178
+ : new BigNumber((existing && existing.blockStartAmount) || current);
179
+
180
+ const prevBlockDelta = isNewBlock
181
+ ? new BigNumber(0)
182
+ : new BigNumber((existing && existing.blockDelta) || 0);
183
+
184
+ const prevBlockLosses = isNewBlock
185
+ ? new BigNumber(0)
186
+ : new BigNumber((existing && existing.blockLosses) || 0);
187
+
188
+ const prevBlockProfits = isNewBlock
189
+ ? new BigNumber(0)
190
+ : new BigNumber((existing && existing.blockProfits) || 0);
191
+
192
+ // Loss adds to bucket (positive delta from bucket's perspective - tokens flowed in)
193
+ const nextBlockDelta = prevBlockDelta.plus(loss);
194
+ const nextBlockLosses = prevBlockLosses.plus(loss);
195
+ const updated = current.plus(loss);
196
+
197
+ const doc = {
198
+ _id: key,
199
+ contractId: Number(contractId),
200
+ propertyId: Number(propertyId),
201
+ amount: updated.toString(10),
202
+ lastBlock: block,
203
+ blockStartAmount: blockStart.toString(10),
204
+ blockDelta: nextBlockDelta.toString(10),
205
+ blockLosses: nextBlockLosses.toString(10),
206
+ blockProfits: prevBlockProfits.toString(10)
207
+ };
208
+
209
+ await db.updateAsync({ _id: key }, doc, { upsert: true });
210
+
211
+ await PnlIou.audit({
212
+ event: 'bucket_loss',
213
+ block,
214
+ contractId: Number(contractId),
215
+ propertyId: Number(propertyId),
216
+ loss: loss.toString(10),
217
+ amountBefore: current.toString(10),
218
+ amountAfter: updated.toString(10),
219
+ blockLosses: nextBlockLosses.toString(10),
220
+ blockProfits: prevBlockProfits.toString(10)
221
+ });
222
+
223
+ return doc;
224
+ }
225
+
226
+ // -----------------------
227
+ // Add a PROFIT to the bucket (positive amount = unfunded gains, creates IOU obligation)
228
+ // These are tracked separately and do NOT reduce the payout pool
229
+ // -----------------------
230
+ static async addProfit(contractId, propertyId, profitAmount, block) {
231
+ const profit = new BigNumber(profitAmount || 0);
232
+ if (profit.lte(0)) return null;
233
+
234
+ const key = PnlIou.key(contractId, propertyId);
235
+ const db = await dbInstance.getDatabase('iou');
236
+
237
+ let existing = null;
238
+ try { existing = await db.findOneAsync({ _id: key }); } catch (e) {}
239
+
240
+ const current = new BigNumber((existing && existing.amount) || 0);
241
+ const isNewBlock = !(existing && Number(existing.lastBlock) === Number(block));
242
+
243
+ const blockStart = isNewBlock
244
+ ? current
245
+ : new BigNumber((existing && existing.blockStartAmount) || current);
246
+
247
+ const prevBlockDelta = isNewBlock
248
+ ? new BigNumber(0)
249
+ : new BigNumber((existing && existing.blockDelta) || 0);
250
+
251
+ const prevBlockLosses = isNewBlock
252
+ ? new BigNumber(0)
253
+ : new BigNumber((existing && existing.blockLosses) || 0);
254
+
255
+ const prevBlockProfits = isNewBlock
256
+ ? new BigNumber(0)
257
+ : new BigNumber((existing && existing.blockProfits) || 0);
258
+
259
+ // Profit subtracts from bucket (negative delta - system owes more)
260
+ const nextBlockDelta = prevBlockDelta.minus(profit);
261
+ const nextBlockProfits = prevBlockProfits.plus(profit);
262
+ const updated = current.minus(profit);
263
+
264
+ const doc = {
265
+ _id: key,
266
+ contractId: Number(contractId),
267
+ propertyId: Number(propertyId),
268
+ amount: updated.toString(10),
269
+ lastBlock: block,
270
+ blockStartAmount: blockStart.toString(10),
271
+ blockDelta: nextBlockDelta.toString(10),
272
+ blockLosses: prevBlockLosses.toString(10),
273
+ blockProfits: nextBlockProfits.toString(10)
274
+ };
275
+
276
+ await db.updateAsync({ _id: key }, doc, { upsert: true });
277
+
278
+ await PnlIou.audit({
279
+ event: 'bucket_profit',
280
+ block,
281
+ contractId: Number(contractId),
282
+ propertyId: Number(propertyId),
283
+ profit: profit.toString(10),
284
+ amountBefore: current.toString(10),
285
+ amountAfter: updated.toString(10),
286
+ blockLosses: prevBlockLosses.toString(10),
287
+ blockProfits: nextBlockProfits.toString(10)
288
+ });
289
+
290
+ return doc;
291
+ }
292
+
293
+ // -----------------------
294
+ // DEPRECATED: Use addLoss/addProfit instead
295
+ // Kept for backward compatibility
296
+ // -----------------------
297
+ static async addDelta(contractId, propertyId, delta, block) {
298
+ const d = new BigNumber(delta || 0);
299
+ if (d.isZero()) return null;
300
+
301
+ // Positive delta = loss (tokens flowed into bucket)
302
+ // Negative delta = profit (system owes more)
303
+ if (d.gt(0)) {
304
+ return await PnlIou.addLoss(contractId, propertyId, d, block);
305
+ } else {
306
+ return await PnlIou.addProfit(contractId, propertyId, d.abs(), block);
307
+ }
308
+ }
309
+
310
+ static blockReductionTowardZero(doc) {
311
+ const start = new BigNumber((doc && doc.blockStartAmount) || 0);
312
+ const end = new BigNumber((doc && doc.amount) || 0);
313
+
314
+ const reduction = start.abs().minus(end.abs());
315
+ return reduction.gt(0) ? reduction : new BigNumber(0);
316
+ }
317
+
318
+ static async applyToLosers(contractId, markDelta, blockHeight, propertyId) {
319
+ let deficit = await this.get(contractId, propertyId);
320
+
321
+ if (deficit.gte(0)) return;
322
+ if (markDelta.lte(0)) return;
323
+
324
+ const payout = BigNumber.min(markDelta, deficit.abs());
325
+ await this.addDelta(contractId, propertyId, payout.negated(), blockHeight);
326
+ }
327
+
328
+ // -----------------------
329
+ // Pay outstanding IOUs using blockLosses (not blockDelta)
330
+ // This ensures profits don't reduce the payout pool
331
+ // -----------------------
332
+ static async payOutstandingIous(contractId, propertyId, markDelta, blockHeight) {
333
+ const BigNumber = require('bignumber.js');
334
+ const MarginMap = require('./marginMap.js');
335
+
336
+ const d = new BigNumber(markDelta || 0);
337
+ console.log('mark delta in payOutstandingIous: ' + markDelta);
338
+ if (d.lte(0)) return [];
339
+
340
+ // ------------------------------------
341
+ // 1) Load bucket
342
+ // ------------------------------------
343
+ const bucketDoc = await PnlIou.getBucket(contractId, propertyId);
344
+ console.log('bucket Doc: ' + JSON.stringify(bucketDoc));
345
+
346
+ if (!bucketDoc) return [];
347
+
348
+ // CRITICAL: Only pay if the bucket was updated THIS block
349
+ if (Number(bucketDoc.lastBlock) !== Number(blockHeight)) {
350
+ console.log(`[settleIous] Skipping - bucket last updated in block ${bucketDoc.lastBlock}, current is ${blockHeight}`);
351
+ return [];
352
+ }
353
+
354
+ // KEY CHANGE: Use blockLosses instead of blockDelta
355
+ // blockLosses = real tokens debited from losers this block
356
+ const availablePayout = bucketDoc.blockLosses || new BigNumber(0);
357
+ console.log('blockLosses available for payout: ' + availablePayout.toString());
358
+
359
+ if (availablePayout.lte(0)) {
360
+ console.log('[settleIous] No losses this block to pay out');
361
+ return [];
362
+ }
363
+
364
+ // markDelta ∩ availablePayout
365
+ const payoutCap = BigNumber.min(d, availablePayout);
366
+ if (payoutCap.lte(0)) return [];
367
+
368
+ // ------------------------------------
369
+ // 2) Load claim map
370
+ // ------------------------------------
371
+ const claimDoc = await PnlIou.getClaimMap(contractId, propertyId);
372
+ console.log('claimDoc: ' + JSON.stringify(claimDoc));
373
+ if (!claimDoc || !claimDoc.claims) return [];
374
+
375
+ const entries = Object.entries(claimDoc.claims)
376
+ .map(([address, v]) => ({
377
+ address,
378
+ claim: new BigNumber(v || 0)
379
+ }))
380
+ .filter(c => c.claim.gt(0));
381
+
382
+ if (!entries.length) return [];
383
+
384
+ const totalClaims = entries.reduce(
385
+ (acc, c) => acc.plus(c.claim),
386
+ new BigNumber(0)
387
+ );
388
+
389
+ const payout = BigNumber.min(payoutCap, totalClaims);
390
+ if (payout.lte(0)) return [];
391
+
392
+ // ------------------------------------
393
+ // 3) Audit payout summary
394
+ // ------------------------------------
395
+ await PnlIou.audit({
396
+ event: 'payout_summary',
397
+ block: blockHeight,
398
+ contractId,
399
+ propertyId,
400
+ payout: payout.toString(10),
401
+ blockLosses: availablePayout.toString(10),
402
+ totalClaims: totalClaims.toString(10),
403
+ claimants: entries.length
404
+ });
405
+
406
+ const mm = await MarginMap.getInstance(contractId);
407
+ const allocations = [];
408
+
409
+ // ------------------------------------
410
+ // 4) Allocate + credit + reduce claims
411
+ // ------------------------------------
412
+ console.log('entries in payout: ' + JSON.stringify(entries));
413
+ console.log('total claims: ' + totalClaims.toNumber());
414
+ console.log('payout amount: ' + payout.toNumber());
415
+
416
+ for (const c of entries) {
417
+ const share = payout.times(c.claim).div(totalClaims);
418
+
419
+ const remaining = c.claim.minus(share);
420
+ if (remaining.lte(0)) {
421
+ delete claimDoc.claims[c.address];
422
+ } else {
423
+ claimDoc.claims[c.address] = remaining.toString(10);
424
+ }
425
+ console.log('allocation to push: ' + c.address + ' ' + share);
426
+
427
+ allocations.push({
428
+ address: c.address,
429
+ amount: share
430
+ });
431
+
432
+ await PnlIou.audit({
433
+ event: 'payout_item',
434
+ block: blockHeight,
435
+ contractId,
436
+ propertyId,
437
+ address: c.address,
438
+ paid: share.toString(10),
439
+ claimAfter: BigNumber.max(remaining, 0).toString(10)
440
+ });
441
+ }
442
+
443
+ // ------------------------------------
444
+ // 5) Persist updated claim map
445
+ // ------------------------------------
446
+ claimDoc.lastBlock = blockHeight;
447
+ await PnlIou.saveClaimMap(claimDoc);
448
+
449
+ return allocations;
450
+ }
451
+
452
+ static async get(contractId, propertyId) {
453
+ const key = PnlIou.key(contractId, propertyId);
454
+ const db = await PnlIou._db();
455
+
456
+ try {
457
+ const doc = await db.findOneAsync({ _id: key });
458
+ if (!doc) return new BigNumber(0);
459
+ return new BigNumber(doc.amount);
460
+ } catch (err) {
461
+ return new BigNumber(0);
462
+ }
463
+ }
464
+
465
+ // -----------------------
466
+ // Get FULL IOU DOC for a (contractId, propertyId)
467
+ // -----------------------
468
+ static async getDoc(contractId, propertyId) {
469
+ const key = PnlIou.key(contractId, propertyId);
470
+ const db = await PnlIou._db();
471
+
472
+ try {
473
+ const doc = await db.findOneAsync({ _id: key });
474
+ return doc || null;
475
+ } catch (err) {
476
+ return null;
477
+ }
478
+ }
479
+
480
+ static async getTotalForProperty(propertyId) {
481
+ const db = await PnlIou._db();
482
+ const pId = Number(propertyId);
483
+
484
+ let docs;
485
+ try { docs = await db.findAsync({}); }
486
+ catch { return new BigNumber(0); }
487
+
488
+ let total = new BigNumber(0);
489
+ for (const doc of docs) {
490
+ if (doc.type !== 'audit' && Number(doc.propertyId) === pId) {
491
+ total = total.plus(doc.amount || 0);
492
+ }
493
+ }
494
+ if (total.gte(0)) { return total; } else { return 0; }
495
+ }
496
+
497
+ static async delete(contractId, propertyId) {
498
+ const key = PnlIou.key(contractId, propertyId);
499
+ const db = await PnlIou._db();
500
+ await db.removeAsync({ _id: key }, { multi: false });
501
+ }
502
+
503
+ static async deleteForProperty(propertyId) {
504
+ const db = await PnlIou._db();
505
+ await db.removeAsync({ propertyId: Number(propertyId) }, { multi: true });
506
+ }
507
+ }
508
+
509
+ module.exports = PnlIou;