@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.
- package/.claude/settings.local.json +13 -0
- package/.claude/skills/tl-algo/SKILL.md +255 -0
- package/.gitattributes +2 -0
- package/.github/workflows/publish.yaml +26 -0
- package/4mm.js +163 -0
- package/LICENSE +21 -0
- package/NPMSwapRefactor.zip +0 -0
- package/README.md +217 -0
- package/address.sh +26 -0
- package/algoAPI.js +581 -0
- package/analyzepsbt.js +92 -0
- package/apiEx.js +99 -0
- package/bb_hyperscalper.js +290 -0
- package/bbo_demo.js +111 -0
- package/buyer.js +622 -0
- package/client.js +50 -0
- package/createTxTest.js +26 -0
- package/createWallet.js +75 -0
- package/daytrader.js +531 -0
- package/decodeTest.js +69 -0
- package/fundingManager.js +144 -0
- package/index.js +4 -0
- package/listener.js +27 -0
- package/litecoreTxBuilder.js +1128 -0
- package/mmEx.js +356 -0
- package/networks.js +51 -0
- package/orderbook.js +200 -0
- package/package.json +34 -0
- package/perTradeQueue.js +36 -0
- package/projectsTLNPMTLNPM/package-lock.json +162 -0
- package/projectsTLNPMTLNPM/package.json +5 -0
- package/quick.js +32 -0
- package/quickFut.js +37 -0
- package/quickSell.js +37 -0
- package/relayerClient.js +117 -0
- package/run4mm.js +80 -0
- package/run_bbo_tracker.js +241 -0
- package/seller.js +443 -0
- package/session.js +45 -0
- package/setup-lin-ltc.sh +139 -0
- package/setup-lin.sh +203 -0
- package/setup-win-ltc.bat +108 -0
- package/setup-win.bat +167 -0
- package/spam_screamer_futures.js +222 -0
- package/tradelayer.js/.gitattributes +2 -0
- package/tradelayer.js/README.md +2 -0
- package/tradelayer.js/oldTests/activationTest.js +6 -0
- package/tradelayer.js/oldTests/base58.test.js +23 -0
- package/tradelayer.js/oldTests/base64Decode.test.js +16 -0
- package/tradelayer.js/oldTests/blocksRefactor.js +140 -0
- package/tradelayer.js/oldTests/checkVestBalance.js +25 -0
- package/tradelayer.js/oldTests/consensusHashProto.js +151 -0
- package/tradelayer.js/oldTests/contractOrderbook.js +243 -0
- package/tradelayer.js/oldTests/createPayload.js +0 -0
- package/tradelayer.js/oldTests/createTestnetAddr.js +43 -0
- package/tradelayer.js/oldTests/decode.js +205 -0
- package/tradelayer.js/oldTests/decodeTest.js +50 -0
- package/tradelayer.js/oldTests/displayTallyMap.js +19 -0
- package/tradelayer.js/oldTests/encodeDecode.js +340 -0
- package/tradelayer.js/oldTests/expressTest.js +29 -0
- package/tradelayer.js/oldTests/extractBlocksVanilla.js +214 -0
- package/tradelayer.js/oldTests/extractBlocksVanillaa.js +179 -0
- package/tradelayer.js/oldTests/extractPubkeyTest.js +60 -0
- package/tradelayer.js/oldTests/fillInputCacheProto.js +111 -0
- package/tradelayer.js/oldTests/getRawTxTest.js +22 -0
- package/tradelayer.js/oldTests/indexTest.js +26 -0
- package/tradelayer.js/oldTests/initTokensTest.js +32 -0
- package/tradelayer.js/oldTests/interfaceChild.js +129 -0
- package/tradelayer.js/oldTests/listenerChild.js +112 -0
- package/tradelayer.js/oldTests/opdecode.js +26 -0
- package/tradelayer.js/oldTests/options.js +79 -0
- package/tradelayer.js/oldTests/optxtest.js +116 -0
- package/tradelayer.js/oldTests/optxtest1.js +64 -0
- package/tradelayer.js/oldTests/oracle.test.js +32 -0
- package/tradelayer.js/oldTests/orderbook.test.js +36 -0
- package/tradelayer.js/oldTests/parsing.js +93 -0
- package/tradelayer.js/oldTests/payload.js +13 -0
- package/tradelayer.js/oldTests/persistenceUnitTest.js +23 -0
- package/tradelayer.js/oldTests/property.test.js +53 -0
- package/tradelayer.js/oldTests/propertyLevel.js +75 -0
- package/tradelayer.js/oldTests/propertyTest.js +32 -0
- package/tradelayer.js/oldTests/queryAddressTest.js +17 -0
- package/tradelayer.js/oldTests/salter.js +14 -0
- package/tradelayer.js/oldTests/tally.js +81 -0
- package/tradelayer.js/oldTests/tally.test.js +48 -0
- package/tradelayer.js/oldTests/tally2.js +124 -0
- package/tradelayer.js/oldTests/tally3.js +142 -0
- package/tradelayer.js/oldTests/tallyDiag.js +38 -0
- package/tradelayer.js/oldTests/testGetRaw.js +40 -0
- package/tradelayer.js/oldTests/testHexConvert.js +47 -0
- package/tradelayer.js/oldTests/testNewEncoding.js +96 -0
- package/tradelayer.js/oldTests/testNewEncoding2.js +113 -0
- package/tradelayer.js/oldTests/testNewEncoding3 +112 -0
- package/tradelayer.js/oldTests/testNewEncoding3.js +168 -0
- package/tradelayer.js/oldTests/testOPReturn.js +102 -0
- package/tradelayer.js/oldTests/testPayload.js +23 -0
- package/tradelayer.js/oldTests/testRaw.js +50 -0
- package/tradelayer.js/oldTests/testSendTooMuch.js +20 -0
- package/tradelayer.js/oldTests/testTxBuild +28 -0
- package/tradelayer.js/oldTests/testTxBuild.js +42 -0
- package/tradelayer.js/oldTests/tokenOrderbook.js +243 -0
- package/tradelayer.js/oldTests/txUtilsA.js +515 -0
- package/tradelayer.js/oldTests/validityUnitTest.js +53 -0
- package/tradelayer.js/oldTests/vaults.js +72 -0
- package/tradelayer.js/oldTests/volumeIndex.js +117 -0
- package/tradelayer.js/oldTests/volumeIndex2.js +88 -0
- package/tradelayer.js/output_base64.txt +1 -0
- package/tradelayer.js/package-lock.json +9967 -0
- package/tradelayer.js/package.json +61 -0
- package/tradelayer.js/server/index.js +88 -0
- package/tradelayer.js/server/litecoind.exe +0 -0
- package/tradelayer.js/src/activation.js +303 -0
- package/tradelayer.js/src/adjuster.js +77 -0
- package/tradelayer.js/src/amm.js +400 -0
- package/tradelayer.js/src/base256.js +55 -0
- package/tradelayer.js/src/base94.js +79 -0
- package/tradelayer.js/src/channels.js +1163 -0
- package/tradelayer.js/src/clearing.js +3109 -0
- package/tradelayer.js/src/clearlist.js +364 -0
- package/tradelayer.js/src/client.js +295 -0
- package/tradelayer.js/src/consensus.js +613 -0
- package/tradelayer.js/src/contractRegistry.js +964 -0
- package/tradelayer.js/src/db.js +89 -0
- package/tradelayer.js/src/init.js +24 -0
- package/tradelayer.js/src/insurance.js +347 -0
- package/tradelayer.js/src/interface.js +218 -0
- package/tradelayer.js/src/interfaceExpress.js +178 -0
- package/tradelayer.js/src/iou.js +509 -0
- package/tradelayer.js/src/listener.js +226 -0
- package/tradelayer.js/src/logic.js +1702 -0
- package/tradelayer.js/src/main.js +927 -0
- package/tradelayer.js/src/marginMap.js +2165 -0
- package/tradelayer.js/src/options.js +126 -0
- package/tradelayer.js/src/oracle.js +394 -0
- package/tradelayer.js/src/orderbook.js +4123 -0
- package/tradelayer.js/src/persistence.js +554 -0
- package/tradelayer.js/src/property.js +411 -0
- package/tradelayer.js/src/reOrg.js +41 -0
- package/tradelayer.js/src/scaling.js +145 -0
- package/tradelayer.js/src/tally.js +1275 -0
- package/tradelayer.js/src/tradeHistoryManager.js +552 -0
- package/tradelayer.js/src/txDecoder.js +584 -0
- package/tradelayer.js/src/txEncoder.js +610 -0
- package/tradelayer.js/src/txIndex.js +502 -0
- package/tradelayer.js/src/txUtils.js +1392 -0
- package/tradelayer.js/src/types.js +429 -0
- package/tradelayer.js/src/validity.js +3077 -0
- package/tradelayer.js/src/vaults.js +430 -0
- package/tradelayer.js/src/vesting.js +491 -0
- package/tradelayer.js/src/volumeIndex.js +618 -0
- package/tradelayer.js/src/walletInterface.js +220 -0
- package/tradelayer.js/src/walletListener.js +665 -0
- package/tradelayer.js/tests/256decode.js +82 -0
- package/tradelayer.js/tests/UTXOracle.js +205 -0
- package/tradelayer.js/tests/base94test.js +23 -0
- package/tradelayer.js/tests/cancelTxTest.js +62 -0
- package/tradelayer.js/tests/contractInterfaceTest.js +48 -0
- package/tradelayer.js/tests/decimalTest.js +65 -0
- package/tradelayer.js/tests/decoderTest.js +100 -0
- package/tradelayer.js/tests/deltaCount.js +47 -0
- package/tradelayer.js/tests/deltaCount2.js +60 -0
- package/tradelayer.js/tests/interfaceTest.js +37 -0
- package/tradelayer.js/tests/mainTest.js +53 -0
- package/tradelayer.js/tests/makeActivationTest.js +24 -0
- package/tradelayer.js/tests/maxHeightTest.js +49 -0
- package/tradelayer.js/tests/reverseHash.js +72 -0
- package/tradelayer.js/tests/sensitiveConsoleOutput.txt +267 -0
- package/tradelayer.js/tests/tallyTest.js +40 -0
- package/tradelayer.js/tests/testBuybacks.js +46 -0
- package/tradelayer.js/tests/testCodeHash.js +49 -0
- package/tradelayer.js/tests/testConsensusHash.js +91 -0
- package/tradelayer.js/tests/testDecode.js +30 -0
- package/tradelayer.js/tests/testEncodingLengths.js +129 -0
- package/tradelayer.js/tests/testGetTx +32 -0
- package/tradelayer.js/tests/testGetTx.js +32 -0
- package/tradelayer.js/tests/testHexHash.js +32 -0
- package/tradelayer.js/tests/testIndexHash.js +35 -0
- package/tradelayer.js/tests/testInitContracts.js +38 -0
- package/tradelayer.js/tests/testMaxConsensus.js +12 -0
- package/tradelayer.js/tests/testMaxSynth.js +44 -0
- package/tradelayer.js/tests/testMint.js +21 -0
- package/tradelayer.js/tests/testNetwork.js +33 -0
- package/tradelayer.js/tests/testOrderbookLoad.js +62 -0
- package/tradelayer.js/tests/testRebates.js +32 -0
- package/tradelayer.js/tests/testRedeem.js +22 -0
- package/tradelayer.js/tests/testTokenTrade.js +39 -0
- package/tradelayer.js/tests/testTxBuild.js +42 -0
- package/tradelayer.js/tests/testUTXOTrade.js +27 -0
- package/tradelayer.js/tests/tokenTradeHistory.js +27 -0
- package/tradelayer.js/tests/tradeFutures.js +40 -0
- package/tradelayer.js/tests/tradeHistoryExample.js +35 -0
- package/tradelayer.js/tests/tradeHistoryLoad.js +15 -0
- package/tradelayer.js/tests/txScanTest.js +134 -0
- package/tradelayer.js/tests/validateTest.js +136 -0
- package/tradelayer.js/tests/vestingTest.js +37 -0
- package/tradelayer.js/utils/activateMainnet.js +59 -0
- package/tradelayer.js/utils/activateMainnetDoge.js +63 -0
- package/tradelayer.js/utils/autocompactdb.js +23 -0
- package/tradelayer.js/utils/base64toHex.js +32 -0
- package/tradelayer.js/utils/broadcastDoge.js +38 -0
- package/tradelayer.js/utils/calcRedeem.js +19 -0
- package/tradelayer.js/utils/checkNetwork.js +27 -0
- package/tradelayer.js/utils/createAddress.js +48 -0
- package/tradelayer.js/utils/createAttestation.js +133 -0
- package/tradelayer.js/utils/createContract.js +118 -0
- package/tradelayer.js/utils/createOracle.js +94 -0
- package/tradelayer.js/utils/createwallet.js +20 -0
- package/tradelayer.js/utils/crossFuturesTrades.js +57 -0
- package/tradelayer.js/utils/crossTokenTrades.js +62 -0
- package/tradelayer.js/utils/dumpPriv.js +29 -0
- package/tradelayer.js/utils/generateChannel.js +34 -0
- package/tradelayer.js/utils/getInfo.js +21 -0
- package/tradelayer.js/utils/hardWipe.js +20 -0
- package/tradelayer.js/utils/hexTo64.js +16 -0
- package/tradelayer.js/utils/importAddress.js +28 -0
- package/tradelayer.js/utils/importpriv.js +20 -0
- package/tradelayer.js/utils/issueOracleContract.js +67 -0
- package/tradelayer.js/utils/issueTokens.js +41 -0
- package/tradelayer.js/utils/listunspent.js +66 -0
- package/tradelayer.js/utils/litecoinClient.js +30 -0
- package/tradelayer.js/utils/loadwallet.js +20 -0
- package/tradelayer.js/utils/publishOracle.js +113 -0
- package/tradelayer.js/utils/sendActivation.js +21 -0
- package/tradelayer.js/utils/sendChannelContractTrade.js +34 -0
- package/tradelayer.js/utils/sendChannelTokenTrade.js +34 -0
- package/tradelayer.js/utils/sendCommit.js +24 -0
- package/tradelayer.js/utils/sendDoge.js +62 -0
- package/tradelayer.js/utils/sendDogeMain.js +67 -0
- package/tradelayer.js/utils/sendDogeTx.js +46 -0
- package/tradelayer.js/utils/sendLTC.js +63 -0
- package/tradelayer.js/utils/sendMainnet.js +62 -0
- package/tradelayer.js/utils/sendTransfer.js +19 -0
- package/tradelayer.js/utils/sendVestTest.js +88 -0
- package/tradelayer.js/utils/sendWithdrawal.js +26 -0
- package/tradelayer.js/utils/simpleStart.js +8 -0
- package/tradelayer.js/utils/startStop.js +27 -0
- package/tradelayer.js/utils/structuredTrades.js +136 -0
- package/tradelayer.js/utils/verifySignature.js +90 -0
- package/tradelayer.js/utils/verifyWitnessAndScriptPubkey.js +41 -0
- package/tradelayer.js/utils/walletCache.js +172 -0
- package/tradelayer.js/utils/walletContractInterface.js +48 -0
- package/tradelayer.js/utils/walletFetchTxs.js +66 -0
- package/tradelayer.js/utils/walletUtils.js +97 -0
- package/tradelayer.js/utils/wipeDB.js +55 -0
- package/tradelayer.js/utils/wipeDBNotTx.js +50 -0
- package/txEncoder.js +529 -0
- package/utility.js +28 -0
- package/verifymessage.js +38 -0
- package/ws-transport.js +311 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const litecoin = require('litecoin');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const json = require('big-json');
|
|
4
|
+
const blockData = [];
|
|
5
|
+
var chainHeight = 0
|
|
6
|
+
var protocolBlocks = [{ height: 0, omTx: [], tlTx: [] }]
|
|
7
|
+
var txIndexomni = []
|
|
8
|
+
var indexPlaceholder = 0
|
|
9
|
+
var thisBlockOm = []
|
|
10
|
+
var thisBlockTl = []
|
|
11
|
+
var omniTxCount = 0
|
|
12
|
+
|
|
13
|
+
const client = new litecoin.Client({
|
|
14
|
+
host: '127.0.0.1',
|
|
15
|
+
port: 8332,
|
|
16
|
+
user: 'user',
|
|
17
|
+
pass: 'pass',
|
|
18
|
+
timeout: 10000
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function decodeOPReturnPayload(hexPayload) {
|
|
22
|
+
// Decode the payload and return the decoded data
|
|
23
|
+
// ...
|
|
24
|
+
|
|
25
|
+
// Example code
|
|
26
|
+
const decodedData = Buffer.from(hexPayload, 'hex').toString('utf8');
|
|
27
|
+
return decodedData;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function extractBlockData(startHeight) {
|
|
31
|
+
client.getBlockCount(function (error, chainTip) {
|
|
32
|
+
if (error) {
|
|
33
|
+
console.error('Error retrieving chain tip:', error);
|
|
34
|
+
return;
|
|
35
|
+
} else { chainHeight = chainTip }
|
|
36
|
+
|
|
37
|
+
getBlockData(startHeight);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getBlockData(height) {
|
|
42
|
+
console.log(height)
|
|
43
|
+
client.getBlockHash(height, function (error, blockHash) {
|
|
44
|
+
if (error) {
|
|
45
|
+
console.error('Error retrieving block hash:', error);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
client.getBlock(blockHash, function (error, currentBlock) {
|
|
50
|
+
if (error) {
|
|
51
|
+
console.error('Error retrieving block data:', error);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
blockData.push(currentBlock);
|
|
56
|
+
|
|
57
|
+
if (currentBlock.height === startHeight + 3) {
|
|
58
|
+
console.log('Block data extraction completed.');
|
|
59
|
+
extractProtocolTx(startHeight, false)
|
|
60
|
+
} else {
|
|
61
|
+
getBlockData(height + 1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function makeFile(filename, pojo) {
|
|
68
|
+
|
|
69
|
+
const stringifyStream = json.createStringifyStream({
|
|
70
|
+
body: pojo
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
stringifyStream.on('data', function (strChunk) {
|
|
74
|
+
fs.appendFile(filename, strChunk, function (err) {
|
|
75
|
+
if (err) throw err;
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Example usage
|
|
82
|
+
const startHeight = 2098224;
|
|
83
|
+
extractBlockData(startHeight);
|
|
84
|
+
|
|
85
|
+
function extractProtocolTx(start, finishBlock) {
|
|
86
|
+
//console.log(blockData)
|
|
87
|
+
if (finishBlock == true) {
|
|
88
|
+
if (protocolBlocks.omTx != [] || tlTx != []) {
|
|
89
|
+
protocolBlocks.push({ height: start, omTx: thisBlockOm, tlTX: thisBlockTl })
|
|
90
|
+
thisBlockOm = []
|
|
91
|
+
thisBlockTl = []
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
indexPlaceholder = start
|
|
95
|
+
var placement = start - startHeight
|
|
96
|
+
console.log(placement, start)
|
|
97
|
+
var thisBlock = blockData[placement]
|
|
98
|
+
|
|
99
|
+
if (start >= startHeight + 200000) {
|
|
100
|
+
var obj = JSON.stringify(protocolBlocks)
|
|
101
|
+
makeFile('protocolTxIndex.json', protocolBlocks)
|
|
102
|
+
console.log("ta da!!")
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
loopThroughBlock(thisBlock, 0)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function loopThroughBlock(block, i) {
|
|
109
|
+
if (block != undefined) {
|
|
110
|
+
console.log(block.height, i, block.tx.length);
|
|
111
|
+
} else { extractProtocolTx(null, true) }
|
|
112
|
+
|
|
113
|
+
if (block === undefined) {
|
|
114
|
+
console.log("Jim, abort! Block undefined");
|
|
115
|
+
return extractProtocolTx(indexPlaceholder + 1, true)
|
|
116
|
+
} else if (i >= block.tx.length) {
|
|
117
|
+
console.log("Jim, abort! i >= tx.length block done!");
|
|
118
|
+
return extractProtocolTx(block.height + 1, true)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
var tx = block.tx[i];
|
|
122
|
+
|
|
123
|
+
if (tx === undefined || tx === '') {
|
|
124
|
+
console.log("Jim, abort!");
|
|
125
|
+
return loopThroughBlock(block, i + 1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
client.getRawTransaction(tx, true, function (err, rawtx) {
|
|
130
|
+
|
|
131
|
+
if (err && err.code === -5) {
|
|
132
|
+
// "No such mempool transaction" error, skip this transaction
|
|
133
|
+
console.error("Skipping transaction:", tx, "Error:", err.message);
|
|
134
|
+
return loopThroughBlock(block, i + 1);
|
|
135
|
+
} else if (err) {
|
|
136
|
+
// Handle other errors as needed
|
|
137
|
+
console.error("Error processing transaction:", err);
|
|
138
|
+
return loopThroughBlock(block, i + 1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Process the transaction as normal
|
|
142
|
+
|
|
143
|
+
let confirmations;
|
|
144
|
+
try {
|
|
145
|
+
confirmations = rawtx.confirmations;
|
|
146
|
+
} catch {
|
|
147
|
+
return loopThroughBlock(block, i + 1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
var thisConfirmations = confirmations;
|
|
151
|
+
|
|
152
|
+
for (let v = 0; v < rawtx.vout.length; v++) {
|
|
153
|
+
// ... Rest of your code
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Move to the next transaction
|
|
157
|
+
loopThroughBlock(block, i + 1);
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error("Error processing transaction:", error);
|
|
161
|
+
// Handle the error gracefully if necessary
|
|
162
|
+
loopThroughBlock(block, i + 1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function decodeOmniPayload(hexPayload) {
|
|
167
|
+
const marker = hexPayload.slice(0, 4);
|
|
168
|
+
|
|
169
|
+
if (marker === '6f6d') {
|
|
170
|
+
// Decode 'om' marker
|
|
171
|
+
return "omni"
|
|
172
|
+
} else if (marker === '746c') {
|
|
173
|
+
// Decode 'tl' marker
|
|
174
|
+
return "tl"
|
|
175
|
+
} else {
|
|
176
|
+
// Unknown marker
|
|
177
|
+
return { error: 'Unknown marker' };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const Litecoin = require('litecoin');
|
|
2
|
+
const util = require('util');
|
|
3
|
+
const client = new Litecoin.Client({
|
|
4
|
+
host: '127.0.0.1',
|
|
5
|
+
port: 18332,
|
|
6
|
+
user: 'user',
|
|
7
|
+
pass: 'pass',
|
|
8
|
+
timeout: 10000
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// Promisify the necessary RPC commands
|
|
12
|
+
const getrawtransactionAsync = util.promisify(client.cmd.bind(client, 'getrawtransaction'));
|
|
13
|
+
const decoderawtransactionAsync = util.promisify(client.cmd.bind(client, 'decoderawtransaction'));
|
|
14
|
+
|
|
15
|
+
async function getScriptPubKeyFromRawTx(rawTx, address) {
|
|
16
|
+
try {
|
|
17
|
+
// Decode the raw transaction
|
|
18
|
+
const decodedTx = await decoderawtransactionAsync('decoderawtransaction', rawTx);
|
|
19
|
+
|
|
20
|
+
// Find the output with the matching address
|
|
21
|
+
const matchingOutput = decodedTx.vout.find(output =>
|
|
22
|
+
output.scriptPubKey.addresses && output.scriptPubKey.addresses.includes(address));
|
|
23
|
+
|
|
24
|
+
if (matchingOutput) {
|
|
25
|
+
console.log(`ScriptPubKey for address ${address}:`, matchingOutput.scriptPubKey.hex);
|
|
26
|
+
return matchingOutput.scriptPubKey.hex;
|
|
27
|
+
} else {
|
|
28
|
+
throw new Error(`Address not found in transaction outputs`);
|
|
29
|
+
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error(`Error retrieving scriptPubKey:`, error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function getAndDecodeRawTransaction(txid) {
|
|
37
|
+
try {
|
|
38
|
+
// Retrieve the raw transaction hex string using the transaction ID
|
|
39
|
+
const rawTx = await getrawtransactionAsync(txid);
|
|
40
|
+
console.log(`Raw Transaction Hex: ${rawTx}`);
|
|
41
|
+
|
|
42
|
+
// Decode the raw transaction
|
|
43
|
+
const decodedTx = await decoderawtransactionAsync('decoderawtransaction', rawTx);
|
|
44
|
+
console.log('Decoded Transaction:', decodedTx);
|
|
45
|
+
|
|
46
|
+
// Get the scriptPubKey for a specific address
|
|
47
|
+
await getScriptPubKeyFromRawTx(rawTx, 'tltc1qa0kd2d39nmeph3hvcx8ytv65ztcywg5sazhtw8');
|
|
48
|
+
|
|
49
|
+
return decodedTx;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error(`Error retrieving and decoding raw transaction:`, error);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Example usage
|
|
57
|
+
const txid = '57dbb47d8db6249b720421d78052e6f168664f3c062f1fbe187270ff5edd4dc5';
|
|
58
|
+
getAndDecodeRawTransaction(txid)
|
|
59
|
+
.then(decodedTx => console.log(`Decoded Transaction:`, decodedTx))
|
|
60
|
+
.catch(error => console.error(`Error: ${error.message}`));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const nCacheSize = 500000; // Define the cache size (you can adjust this value)
|
|
2
|
+
|
|
3
|
+
async function fillTxInputCache(tx, removedCoins) {
|
|
4
|
+
// Simulate clearing the cache when it exceeds the cache size
|
|
5
|
+
if (viewCacheSize > nCacheSize) {
|
|
6
|
+
console.log(`${fillTxInputCache.name}: clearing cache before insertion [size=${viewCacheSize}]`);
|
|
7
|
+
await flushView();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
for (const txIn of tx.vin) {
|
|
11
|
+
const prevout = txIn.prevout;
|
|
12
|
+
const coin = await accessCoin(prevout);
|
|
13
|
+
|
|
14
|
+
if (!coin.isSpent) {
|
|
15
|
+
nCacheHits++;
|
|
16
|
+
} else {
|
|
17
|
+
nCacheMiss++;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let txPrev, hashBlock;
|
|
21
|
+
let newcoin = new Coin(); // Create a new coin
|
|
22
|
+
|
|
23
|
+
if (removedCoins && removedCoins[prevout.toString()]) {
|
|
24
|
+
newcoin = removedCoins[prevout.toString()];
|
|
25
|
+
} else if (await getTransaction(prevout.hash, txPrev, Params().getConsensus(), hashBlock)) {
|
|
26
|
+
const nOut = prevout.n;
|
|
27
|
+
newcoin.out.scriptPubKey = txPrev.vout[nOut].scriptPubKey;
|
|
28
|
+
newcoin.out.nValue = txPrev.vout[nOut].nValue;
|
|
29
|
+
|
|
30
|
+
const blockIndex = mapBlockIndex[hashBlock];
|
|
31
|
+
newcoin.nHeight = blockIndex ? blockIndex.nHeight : 1;
|
|
32
|
+
} else {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await addCoin(prevout, newcoin, true);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Simulated view cache size and related functions
|
|
43
|
+
let viewCacheSize = 0;
|
|
44
|
+
const viewCache = {}; // Simulated coin view cache
|
|
45
|
+
|
|
46
|
+
async function accessCoin(prevout) {
|
|
47
|
+
const key = prevout.toString();
|
|
48
|
+
if (viewCache[key]) {
|
|
49
|
+
return viewCache[key];
|
|
50
|
+
}
|
|
51
|
+
// Simulate coin retrieval logic here if not in cache
|
|
52
|
+
return new Coin();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function addCoin(prevout, coin, isSpent) {
|
|
56
|
+
viewCache[prevout.toString()] = coin;
|
|
57
|
+
viewCacheSize++;
|
|
58
|
+
// Simulate adding the coin to the cache
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function flushView() {
|
|
62
|
+
viewCacheSize = 0;
|
|
63
|
+
viewCache = {};
|
|
64
|
+
// Simulate clearing the cache
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Simulated Coin and related functions
|
|
68
|
+
class Coin {
|
|
69
|
+
constructor() {
|
|
70
|
+
this.isSpent = true; // Simulated spent state
|
|
71
|
+
this.out = {
|
|
72
|
+
scriptPubKey: '',
|
|
73
|
+
nValue: 0,
|
|
74
|
+
};
|
|
75
|
+
this.nHeight = 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Simulated getTransaction function
|
|
80
|
+
async function getTransaction(hash, txPrev, consensus, hashBlock) {
|
|
81
|
+
// Simulate transaction retrieval logic here
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Simulated Params class and related functions
|
|
86
|
+
class Params {
|
|
87
|
+
getConsensus() {
|
|
88
|
+
// Simulate getting consensus parameters
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Simulated nCacheHits and nCacheMiss
|
|
94
|
+
let nCacheHits = 0;
|
|
95
|
+
let nCacheMiss = 0;
|
|
96
|
+
|
|
97
|
+
// Example usage:
|
|
98
|
+
const removedCoins = {}; // Simulated removedCoins map
|
|
99
|
+
const tx = {}; // Simulated transaction
|
|
100
|
+
|
|
101
|
+
fillTxInputCache(tx, removedCoins)
|
|
102
|
+
.then((result) => {
|
|
103
|
+
if (result) {
|
|
104
|
+
console.log('Successfully filled the transaction input cache.');
|
|
105
|
+
} else {
|
|
106
|
+
console.error('Failed to fill the transaction input cache.');
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
.catch((error) => {
|
|
110
|
+
console.error('An error occurred:', error);
|
|
111
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const litecoin = require('litecoin');
|
|
2
|
+
|
|
3
|
+
const client = new litecoin.Client({
|
|
4
|
+
host: '127.0.0.1',
|
|
5
|
+
port: 8332,
|
|
6
|
+
user: 'user',
|
|
7
|
+
pass: 'pass',
|
|
8
|
+
timeout: 10000
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const tx = "85f459ae3422aff3e01c2ba240605f997befd2a639d87b3b72b5456a8aeaf610";
|
|
12
|
+
|
|
13
|
+
console.log("Fetching raw transaction...");
|
|
14
|
+
|
|
15
|
+
client.getRawTransaction(tx, true, function(err, rawtx) {
|
|
16
|
+
if (err) {
|
|
17
|
+
console.error(err);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(rawtx);
|
|
22
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const TxIndex = require('./txIndex.js');
|
|
2
|
+
|
|
3
|
+
async function runUnitTest() {
|
|
4
|
+
const genesisBlock = 3082500;
|
|
5
|
+
try {
|
|
6
|
+
console.log(`Initializing index from genesis block: ${genesisBlock}`);
|
|
7
|
+
await TxIndex.initializeIndex(genesisBlock,true);
|
|
8
|
+
|
|
9
|
+
console.log(`Extracting block data starting from block: ${genesisBlock}`);
|
|
10
|
+
await TxIndex.extractBlockData(genesisBlock);
|
|
11
|
+
|
|
12
|
+
if (txIndex.transparentIndex.includes('00')) {
|
|
13
|
+
console.log("Payload 'tl00' found in the index.");
|
|
14
|
+
} else {
|
|
15
|
+
console.log("Payload 'tl00' not found in the index.");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const loadedIndex = await TxIndex.loadIndex(); // Corrected to call static method
|
|
19
|
+
console.log('Loaded index:', loadedIndex);
|
|
20
|
+
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error during unit test:', error);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
runUnitTest();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const TxIndex = require('./txIndex.js')
|
|
2
|
+
const Main = require('./main.js'); // Replace with the correct path
|
|
3
|
+
const TallyMap = require('./tally.js'); // Replace with the correct path
|
|
4
|
+
|
|
5
|
+
// Define the admin address
|
|
6
|
+
const adminAddress = "tltc1qa0kd2d39nmeph3hvcx8ytv65ztcywg5sazhtw8";
|
|
7
|
+
|
|
8
|
+
async function runIntegrationTest() {
|
|
9
|
+
console.log("Starting integration test...");
|
|
10
|
+
|
|
11
|
+
// Access the singleton instance of Main
|
|
12
|
+
//await TxIndex.clearTxIndex()
|
|
13
|
+
//await TxIndex.resetIndexFlag();
|
|
14
|
+
const mainProcessor = Main.getInstance(test=true);
|
|
15
|
+
await mainProcessor.initialize(); // Assuming init() initializes the entire flow
|
|
16
|
+
|
|
17
|
+
// Monitor the progress
|
|
18
|
+
console.log("Transaction Index Completed");
|
|
19
|
+
console.log("Consensus Completed");
|
|
20
|
+
|
|
21
|
+
// Trigger activation transaction (tx type "0")
|
|
22
|
+
//await mainProcessor.triggerActivationTransaction(adminAddress, 0);
|
|
23
|
+
console.log("Activation Transaction Processed");
|
|
24
|
+
|
|
25
|
+
// Check the balance in the tally map for the admin address
|
|
26
|
+
const balance = await TallyMap.getAddressBalances(adminAddress);
|
|
27
|
+
console.log(`Balance for admin address ${adminAddress}:`, balance);
|
|
28
|
+
|
|
29
|
+
console.log("Integration test completed.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
runIntegrationTest().catch(console.error);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const { fork } = require('child_process');
|
|
2
|
+
|
|
3
|
+
class InterfaceChild {
|
|
4
|
+
constructor() {
|
|
5
|
+
// Forking the main process
|
|
6
|
+
this.mainProcess = fork('./main.js');
|
|
7
|
+
|
|
8
|
+
this.mainProcess.on('message', (message) => {
|
|
9
|
+
console.log('Message from main process:', message);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
this.mainProcess.on('error', (error) => {
|
|
13
|
+
console.error('Error in main process:', error);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this.mainProcess.on('exit', (code) => {
|
|
17
|
+
console.log(`Main process exited with code ${code}`);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async sendCommandToMainProcess(command, args) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
this.mainProcess.send({ command, args });
|
|
24
|
+
this.mainProcess.once('message', (response) => {
|
|
25
|
+
if (response.error) {
|
|
26
|
+
reject(response.error);
|
|
27
|
+
} else {
|
|
28
|
+
resolve(response.data);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async initMain() {
|
|
35
|
+
return await this.sendCommandToMainProcess('initMain');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Example method: Get balances for an address
|
|
39
|
+
async getAllBalancesForAddress(address) {
|
|
40
|
+
return await this.sendCommandToMainProcess('getAllBalancesForAddress', { address });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Method: Get transaction details
|
|
44
|
+
async getTransaction(txid) {
|
|
45
|
+
return await this.sendCommandToMainProcess('getTransaction', { txid });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Method: Get property details
|
|
49
|
+
async getProperty(propertyId) {
|
|
50
|
+
return await this.sendCommandToMainProcess('getProperty', { propertyId });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ... Integrate all other methods from Interface.js ...
|
|
54
|
+
|
|
55
|
+
// For example, a method to list all properties
|
|
56
|
+
async listProperties() {
|
|
57
|
+
return await this.sendCommandToMainProcess('listProperties');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Method to list all activations
|
|
61
|
+
async listActivations() {
|
|
62
|
+
return await this.sendCommandToMainProcess('listActivations');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async getConsensusHashForBlock(blockHeight) {
|
|
67
|
+
return await this.sendCommandToMainProcess('getConsensusHashForBlock', { blockHeight });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async getFeatureActivationStatus(featureId) {
|
|
71
|
+
return await this.sendCommandToMainProcess('getFeatureActivationStatus', { featureId });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async getAllBalancesForAddress(address) {
|
|
75
|
+
return await this.sendCommandToMainProcess('getAllBalancesForAddress', { address });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getTotalTokens(propertyId) {
|
|
79
|
+
return await this.sendCommandToMainProcess('getTotalTokens', { propertyId });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async getBalancesAcrossAllWallets() {
|
|
83
|
+
return await this.sendCommandToMainProcess('getBalancesAcrossAllWallets');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async isTransactionTypeActive(txType) {
|
|
87
|
+
return await this.sendCommandToMainProcess('isTransactionTypeActive', { txType });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async getAllActiveTransactionTypes() {
|
|
91
|
+
return await this.sendCommandToMainProcess('getAllActiveTransactionTypes');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async getAddressesWithBalanceForProperty(propertyId) {
|
|
95
|
+
return await this.sendCommandToMainProcess('getAddressesWithBalanceForProperty', { propertyId });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async getTransaction(txid) {
|
|
99
|
+
return await this.sendCommandToMainProcess('getTransaction', { txid });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async getProperty(propertyId) {
|
|
103
|
+
return await this.sendCommandToMainProcess('getProperty', { propertyId });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async listProperties() {
|
|
107
|
+
return await this.sendCommandToMainProcess('listProperties');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async getGrants(propertyId) {
|
|
111
|
+
return await this.sendCommandToMainProcess('getGrants', { propertyId });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async getPayToToken(propertyId) {
|
|
115
|
+
return await this.sendCommandToMainProcess('getPayToToken', { propertyId });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async listBlockTransactions(blockIndex) {
|
|
119
|
+
return await this.sendCommandToMainProcess('listBlockTransactions', { blockIndex });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async listPendingTransactions(addressFilter) {
|
|
123
|
+
return await this.sendCommandToMainProcess('listPendingTransactions', { addressFilter });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ... Continue adding all methods from Interface.js ...
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
module.exports = InterfaceChild;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const TallyMap = require('./tally');
|
|
2
|
+
const TxIndex = require('./TxIndex');
|
|
3
|
+
const PropertyManager = require('./property');
|
|
4
|
+
const Interface = require('./Interface');
|
|
5
|
+
const interfaceInstance = new Interface();
|
|
6
|
+
const Main = require('./main.js')
|
|
7
|
+
|
|
8
|
+
// ... Import other necessary modules ...
|
|
9
|
+
|
|
10
|
+
async function listen() {
|
|
11
|
+
process.on('message', async (message) => {
|
|
12
|
+
console.log('Child process received message:', message);
|
|
13
|
+
try {
|
|
14
|
+
const { command, args } = message;
|
|
15
|
+
switch (command) {
|
|
16
|
+
|
|
17
|
+
case 'initMain':
|
|
18
|
+
console.log('initializing')
|
|
19
|
+
const mainProcessor = Main.getInstance(test = true); // Assuming 'test' is a parameter for testing
|
|
20
|
+
mainProcessor.initialize();
|
|
21
|
+
|
|
22
|
+
// Send a response back to the child process to indicate successful initialization
|
|
23
|
+
process.send({ data: 'Main process initialized successfully' });
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case 'getAllBalancesForAddress':
|
|
27
|
+
const balances = await TallyMap.getAddressBalances(args.address);
|
|
28
|
+
process.send({ data: balances });
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case 'getTransaction':
|
|
32
|
+
const transaction = await TxIndex.getTransactionDetails(args.txid);
|
|
33
|
+
process.send({ data: transaction });
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
case 'getConsensusHashForBlock':
|
|
38
|
+
result = await interfaceInstance.getConsensusHashForBlock(args.blockHeight);
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case 'getFeatureActivationStatus':
|
|
42
|
+
result = await interfaceInstance.getFeatureActivationStatus(args.featureId);
|
|
43
|
+
break;
|
|
44
|
+
|
|
45
|
+
case 'getAllBalancesForAddress':
|
|
46
|
+
result = await interfaceInstance.getAllBalancesForAddress(args.address);
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case 'getTotalTokens':
|
|
50
|
+
result = await interfaceInstance.getTotalTokens(args.propertyId);
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case 'getBalancesAcrossAllWallets':
|
|
54
|
+
result = await interfaceInstance.getBalancesAcrossAllWallets();
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
case 'isTransactionTypeActive':
|
|
58
|
+
result = await interfaceInstance.isTransactionTypeActive(args.txType);
|
|
59
|
+
break;
|
|
60
|
+
|
|
61
|
+
case 'getAllActiveTransactionTypes':
|
|
62
|
+
result = await interfaceInstance.getAllActiveTransactionTypes();
|
|
63
|
+
break;
|
|
64
|
+
|
|
65
|
+
case 'getAddressesWithBalanceForProperty':
|
|
66
|
+
result = await interfaceInstance.getAddressesWithBalanceForProperty(args.propertyId);
|
|
67
|
+
break;
|
|
68
|
+
|
|
69
|
+
case 'getTransaction':
|
|
70
|
+
result = await interfaceInstance.getTransaction(args.txid);
|
|
71
|
+
break;
|
|
72
|
+
|
|
73
|
+
case 'getProperty':
|
|
74
|
+
result = await interfaceInstance.getProperty(args.propertyId);
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
case 'listProperties':
|
|
78
|
+
result = await interfaceInstance.listProperties();
|
|
79
|
+
break;
|
|
80
|
+
|
|
81
|
+
case 'getGrants':
|
|
82
|
+
result = await interfaceInstance.getGrants(args.propertyId);
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
case 'getPayToToken':
|
|
86
|
+
result = await interfaceInstance.getPayToToken(args.propertyId);
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case 'listBlockTransactions':
|
|
90
|
+
result = await interfaceInstance.listBlockTransactions(args.blockIndex);
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case 'listBlocksTransactions':
|
|
94
|
+
result = await interfaceInstance.listBlocksTransactions(args.firstBlock, args.lastBlock);
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
case 'listPendingTransactions':
|
|
98
|
+
result = await interfaceInstance.listPendingTransactions(args.addressFilter);
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
// ... Add other cases for each method in Interface.js ...
|
|
102
|
+
|
|
103
|
+
default:
|
|
104
|
+
process.send({ error: 'Unknown command' });
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
process.send({ error: error.message });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = listen;
|