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