@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
package/algoAPI.js
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
const io = require('socket.io-client');
|
|
2
|
+
const axios = require('axios')
|
|
3
|
+
const util = require('util'); // Add util to handle logging circular structures
|
|
4
|
+
const BigNumber = require('bignumber.js');
|
|
5
|
+
const OrderbookSession = require('./orderbook.js'); // Add the session class
|
|
6
|
+
let orderbookSession={}
|
|
7
|
+
const {createLitecoinClient, createBitcoinClient} = require('./client.js');
|
|
8
|
+
const walletListener = require('./tradelayer.js/src/walletInterface.js');
|
|
9
|
+
const { createTransport } = require('./ws-transport');
|
|
10
|
+
const { FundingManager } = require('./fundingManager');
|
|
11
|
+
const { DEFAULT_RELAYER_HOST, DEFAULT_RELAYER_PORT } = require('./relayerClient');
|
|
12
|
+
|
|
13
|
+
class ApiWrapper {
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} baseURL
|
|
16
|
+
* @param {number} port
|
|
17
|
+
* @param {boolean} test
|
|
18
|
+
* @param {boolean} tlAlreadyOn
|
|
19
|
+
* @param {string} address
|
|
20
|
+
* @param {string} pubkey
|
|
21
|
+
* @param {string} network
|
|
22
|
+
* @param {object} [relayerOpts] - Optional relayer config.
|
|
23
|
+
* Omit or pass {} to use defaults (try local, fallback to 170.75.168.246:8000).
|
|
24
|
+
* Pass { host, port } to override the relayer target.
|
|
25
|
+
* Pass false to disable relayer fallback entirely (local-only).
|
|
26
|
+
*/
|
|
27
|
+
constructor(baseURL, port,test,tlAlreadyOn=false,address,pubkey,network,relayerOpts) {
|
|
28
|
+
console.log('constructing API wrapper' +baseURL+' '+port+' test?'+test+' tlOn? '+tlAlreadyOn)
|
|
29
|
+
this.baseURL = baseURL;
|
|
30
|
+
this.port = port;
|
|
31
|
+
this.apiUrl = `${this.baseURL}:${this.port}`;
|
|
32
|
+
this.socket = null;
|
|
33
|
+
this.funding = new FundingManager();
|
|
34
|
+
const netloc = baseURL.replace(/^ws:\/\/|^wss:\/\//, '').replace(/^http:\/\/|^https:\/\//, '');
|
|
35
|
+
this.apiUrl = `http://${netloc}:${port}`; // REST endpoint
|
|
36
|
+
this.wsUrl = `ws://${netloc}:${port}/ws`; // WS endpoint // Create an instance of your TxService
|
|
37
|
+
this.network = network
|
|
38
|
+
this.myInfo = {address: address, keypair:{address: address, pubkey: pubkey}}; // Add buyer/seller info as needed
|
|
39
|
+
this.myInfo.otherAddrs = []
|
|
40
|
+
this.relayerOpts = relayerOpts
|
|
41
|
+
this.client = network && network.toUpperCase().startsWith('BTC')
|
|
42
|
+
? createBitcoinClient(test, relayerOpts)
|
|
43
|
+
: createLitecoinClient(test, relayerOpts); // Use a client or wallet service instance
|
|
44
|
+
this.test = test
|
|
45
|
+
this.channels = {}
|
|
46
|
+
this.myOrders = []
|
|
47
|
+
this.initUntilSuccess(tlAlreadyOn)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// Function to initialize a socket connection
|
|
52
|
+
_initializeSocket() {
|
|
53
|
+
this.socket = createTransport({ type: 'ws', url: this.wsUrl },{}, this.network);
|
|
54
|
+
console.log('this ws '+JSON.stringify(this.socket))
|
|
55
|
+
console.log('connect func '+this.socket.connect())
|
|
56
|
+
this.socket.connect(this.wsUrl).then(() => {
|
|
57
|
+
console.log(`Connected to Orderbook Server via WS event-bus`);
|
|
58
|
+
this.myInfo.socketId = null; // Not used in event-bus
|
|
59
|
+
orderbookSession = new OrderbookSession(this.socket, this.myInfo, this.client, this.test);
|
|
60
|
+
});
|
|
61
|
+
// Listen for connection success
|
|
62
|
+
this.socket.on('connect', () => {
|
|
63
|
+
console.log(`Connected to Orderbook Server with ID: ${this.socket.id}`);
|
|
64
|
+
this.myInfo.socketId = this.socket.id;
|
|
65
|
+
orderbookSession = new OrderbookSession(this.socket, this.myInfo, this.client, this.test);
|
|
66
|
+
// Save the socket id to this.myInfo
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/*this.socket.on('message', (raw) => {
|
|
70
|
+
try { console.log('[WS][raw]', typeof raw === 'string' ? raw : JSON.stringify(raw)); }
|
|
71
|
+
catch (_) {}
|
|
72
|
+
});*/
|
|
73
|
+
|
|
74
|
+
// Listen for disconnect events
|
|
75
|
+
this.socket.on('disconnect', (reason) => {
|
|
76
|
+
console.log(`Disconnected: ${reason}`);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Listen for order save confirmation
|
|
80
|
+
this.socket.on('order:saved', (orderUuid) => {
|
|
81
|
+
this.myOrders.push()
|
|
82
|
+
console.log(`Order saved with UUID: ${orderUuid}`);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
this.socket.on('order:canceled', (confirmation) => {
|
|
86
|
+
console.log('order canceled with id '+orderUuid)
|
|
87
|
+
this.myOrders.filter(order => order.id !== orderUuiD);
|
|
88
|
+
resolve(confirmation);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Listen for order errors
|
|
92
|
+
this.socket.on('order:error', (error) => {
|
|
93
|
+
//console.error('Order error:', error);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Listen for orderbook data updates
|
|
97
|
+
this.socket.on('orderbook-data', (data) => {
|
|
98
|
+
//console.log('Orderbook Data:', data);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
delay(ms) {
|
|
103
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async initUntilSuccess(tlOn) {
|
|
107
|
+
console.log('inside initUntilSuccess '+tlOn)
|
|
108
|
+
if(tlOn){
|
|
109
|
+
console.log('init without wallet listener await')
|
|
110
|
+
await this.init(this.myInfo.address)
|
|
111
|
+
return
|
|
112
|
+
}else{
|
|
113
|
+
await this.delay(2000)
|
|
114
|
+
try {
|
|
115
|
+
const response = await walletListener.initMain()
|
|
116
|
+
// Assuming the response contains a 'success' field
|
|
117
|
+
//console.log('Init response:', response.data);
|
|
118
|
+
await this.init()
|
|
119
|
+
return
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error('Error during init:', error.response ? error.response.data : error.message);
|
|
122
|
+
await new Promise(resolve => setTimeout(resolve, 15000)); // Wait before retrying
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Initialize function to check blockchain status
|
|
128
|
+
async init() {
|
|
129
|
+
try {
|
|
130
|
+
const response = await this.getBlockchainInfo(); // Use your client to fetch blockchain info
|
|
131
|
+
console.log('Blockchain Info:', response.blocks);
|
|
132
|
+
// Check if initial block download is complete
|
|
133
|
+
|
|
134
|
+
if (!response.initialblockdownload) {
|
|
135
|
+
console.log('Block indexing is complete. Calling wallet listener init.');
|
|
136
|
+
//await walletListener.initMain(); // Call initMain from walletListener
|
|
137
|
+
await this.getUTXOBalances(this.myInfo.address)
|
|
138
|
+
console.log('this socket? '+this.socket)
|
|
139
|
+
if(!this.socket){
|
|
140
|
+
console.log('initialize socket')
|
|
141
|
+
this._initializeSocket()
|
|
142
|
+
}
|
|
143
|
+
}else{
|
|
144
|
+
this.delay(10000)
|
|
145
|
+
return this.init()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
success: !response.initialblockdownload,
|
|
150
|
+
message: response.initialblockdownload ? 'Block indexing is complete.' : 'Block indexing is still in progress.'
|
|
151
|
+
};
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error('Initialization error:', error);
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
message: error.message
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async getUTXOBalances(address) {
|
|
162
|
+
//console.log('address in get balances ' + address);
|
|
163
|
+
try {
|
|
164
|
+
const utxos = await this.listUnspent(1, 9999999, [address]);
|
|
165
|
+
const unconfirmedUtxos = await this.getUnconfirmedTransactions(address);
|
|
166
|
+
|
|
167
|
+
let totalBalance = new BigNumber(0); // Initialize BigNumber for total balance
|
|
168
|
+
|
|
169
|
+
// Process confirmed UTXOs
|
|
170
|
+
for (const utxo of utxos) {
|
|
171
|
+
console.log('scanning utxos ' + utxo.address + ' ' + utxo.amount);
|
|
172
|
+
const utxoAmount = new BigNumber(utxo.amount);
|
|
173
|
+
if (utxo.address === address && this.myInfo.keypair.pubkey) {
|
|
174
|
+
totalBalance = totalBalance.plus(utxoAmount); // Add balance for the specific address
|
|
175
|
+
} else if (!this.myInfo.keypair.address || !this.myInfo.keypair.pubkey) {
|
|
176
|
+
this.myInfo.keypair.address = utxo.address;
|
|
177
|
+
this.myInfo.keypair.pubkey = await this.getPubKeyFromAddress(utxo.address);
|
|
178
|
+
console.log('logging pubkey ' + this.myInfo.keypair.pubkey + ' ' + this.myInfo.keypair.address);
|
|
179
|
+
totalBalance = totalBalance.plus(utxoAmount);
|
|
180
|
+
this._initializeSocket();
|
|
181
|
+
} else if (address === '' && this.myInfo.keypair.address) {
|
|
182
|
+
const pubkey = await this.getPubKeyFromAddress(utxo.address);
|
|
183
|
+
this.myInfo.otherAddrs.push({ address: utxo.address, pubkey: pubkey });
|
|
184
|
+
totalBalance = totalBalance.plus(utxoAmount);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Process unconfirmed UTXOs
|
|
189
|
+
if (unconfirmedUtxos.length > 0) {
|
|
190
|
+
for (const utxo of unconfirmedUtxos) {
|
|
191
|
+
console.log('scanning mempool utxos ' + utxo.address + ' ' + utxo.amount);
|
|
192
|
+
const utxoAmount = new BigNumber(utxo.amount);
|
|
193
|
+
if (utxo.address === address) {
|
|
194
|
+
totalBalance = totalBalance.plus(utxoAmount); // Add balance for the specific address
|
|
195
|
+
} else if (!this.myInfo.keypair.address && this.myInfo.keypair.pubkey) {
|
|
196
|
+
this.myInfo.keypair.address = utxo.address;
|
|
197
|
+
this.myInfo.keypair.pubkey = await this.getPubKeyFromAddress(utxo.address);
|
|
198
|
+
console.log('logging pubkey ' + this.myInfo.keypair.pubkey + ' ' + this.myInfo.keypair.address);
|
|
199
|
+
totalBalance = totalBalance.plus(utxoAmount);
|
|
200
|
+
this._initializeSocket();
|
|
201
|
+
} else if (address === '' && this.myInfo.keypair.address) {
|
|
202
|
+
const pubkey = await this.getPubKeyFromAddress(utxo.address);
|
|
203
|
+
this.myInfo.otherAddrs.push({ address: utxo.address, pubkey: pubkey });
|
|
204
|
+
totalBalance = totalBalance.plus(utxoAmount);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
this.funding.setConfirmedLtc(totalBalance.toNumber());
|
|
209
|
+
//console.log(`Total UTXO balance for address ${this.myInfo.keypair.address}:`, totalBalance.toString());
|
|
210
|
+
return totalBalance.toNumber(); // Return the balance as a string to preserve precision
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error('Error fetching UTXO balances:', error);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async checkIfAddressInWallet(address){
|
|
217
|
+
try {
|
|
218
|
+
// Check if the address is part of the wallet
|
|
219
|
+
const addressInfo = await this.getAddressInfo(address);
|
|
220
|
+
|
|
221
|
+
// Log the result to verify
|
|
222
|
+
//console.log("Address Info:", JSON.stringify(addressInfo, null, 2));
|
|
223
|
+
|
|
224
|
+
// Return whether the address is part of the wallet
|
|
225
|
+
return addressInfo.ismine; // true if the address is in the wallet
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.error("Error checking if address is in wallet:", error);
|
|
228
|
+
return false; // Return false if there's an error
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
async getUnconfirmedTransactions(address) {
|
|
233
|
+
try {
|
|
234
|
+
// Get all unconfirmed transactions from the mempool
|
|
235
|
+
const rawMempool = await this.getRawMempoolAsync(false);
|
|
236
|
+
const transactionsWithAddress = [];
|
|
237
|
+
|
|
238
|
+
for (const txid of rawMempool) {
|
|
239
|
+
// Fetch detailed information for each transaction
|
|
240
|
+
const txDetails = await this.getRawTransaction(txid, true);
|
|
241
|
+
// Iterate through each output (vout) of the transaction
|
|
242
|
+
for (const output of txDetails.vout) {
|
|
243
|
+
// Ensure output.scriptPubKey and addresses exist
|
|
244
|
+
if (output.scriptPubKey && Array.isArray(output.scriptPubKey.addresses)) {
|
|
245
|
+
const addresses = output.scriptPubKey.addresses;
|
|
246
|
+
|
|
247
|
+
if (!address) {
|
|
248
|
+
// If no specific address is provided, check if the address belongs to the wallet
|
|
249
|
+
const isMine = await this.checkIfAddressInWallet(addresses[0]);
|
|
250
|
+
if (isMine) {
|
|
251
|
+
console.log('Adding mempool tx to log', addresses[0], txid);
|
|
252
|
+
transactionsWithAddress.push({
|
|
253
|
+
txid,
|
|
254
|
+
vout: output.n,
|
|
255
|
+
amount: output.value,
|
|
256
|
+
address: addresses[0],
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
} else if (addresses.includes(address)) {
|
|
260
|
+
// If a specific address is provided, match it directly
|
|
261
|
+
transactionsWithAddress.push({
|
|
262
|
+
txid,
|
|
263
|
+
vout: output.n,
|
|
264
|
+
amount: output.value,
|
|
265
|
+
address: addresses[0],
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return transactionsWithAddress;
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error('Error fetching unconfirmed transactions:', error.message || error);
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async getPubKeyFromAddress(address) {
|
|
280
|
+
try {
|
|
281
|
+
const addressInfo = await this.getAddressInfo(address);
|
|
282
|
+
if (addressInfo && addressInfo.pubkey) {
|
|
283
|
+
return addressInfo.pubkey;
|
|
284
|
+
} else {
|
|
285
|
+
throw new Error('Public key not found for address');
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error('Error fetching pubkey:', error);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
getBlockchainInfo() {
|
|
293
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getblockchaininfo'))();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
getRawTransaction(txId, verbose = true, blockHash) {
|
|
297
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getrawtransaction'))(txId, verbose);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
getRawMempoolAsync(verbose = true,) {
|
|
301
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getrawmempool'))(verbose);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
getAddressInfo(address) {
|
|
305
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getaddressinfo'))(address);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
getNetworkInfo(){
|
|
310
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getnetworkinfo'))()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
getTransaction(txId) {
|
|
314
|
+
return util.promisify(this.client.cmd.bind(this.client, 'gettransaction'))(txId);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
getBlock(blockHash) {
|
|
318
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getblock'))(blockHash);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
getBlockHash(height) {
|
|
322
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getblockhash'))(height);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
createRawTransaction(...params) {
|
|
326
|
+
return util.promisify(this.client.cmd.bind(this.client, 'createrawtransaction'))(...params);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
listUnspent(minConf = 1, maxConf = 9999999, addresses = []) {
|
|
330
|
+
return util.promisify(this.client.cmd.bind(this.client, 'listunspent'))(minConf, maxConf, addresses);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
decoderawtransaction(...params) {
|
|
335
|
+
return util.promisify(this.client.cmd.bind(this.client, 'decoderawtransaction'))(...params);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
signrawtransactionwithwallet(...params) {
|
|
339
|
+
return util.promisify(this.client.cmd.bind(this.client, 'signrawtransactionwithwallet'))(...params);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
dumpprivkey(...params) {
|
|
343
|
+
return util.promisify(this.client.cmd.bind(this.client, 'dumpprivkey'))(...params);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
sendrawtransaction(...params) {
|
|
347
|
+
return util.promisify(this.client.cmd.bind(this.client, 'sendrawtransaction'))(...params);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
validateAddress(...params) {
|
|
351
|
+
return util.promisify(this.client.cmd.bind(this.client, 'validateaddress'))(...params);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
getBlockCount() {
|
|
355
|
+
return util.promisify(this.client.cmd.bind(this.client, 'getblockcount'))();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
loadWallet(...params) {
|
|
359
|
+
return util.promisify(this.client.cmd.bind(this.client, 'loadwallet'))(...params);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
async startOrderbookSession() {
|
|
364
|
+
// Initialize an OrderbookSession when the socket connects
|
|
365
|
+
this.orderbookSession = new OrderbookSession(this.socket, this.myInfo, this.txsService, this.client);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async getAllTokenBalancesForAddress(address){
|
|
369
|
+
//console.log('address before calling wallet interface '+address)
|
|
370
|
+
const tokens = await walletListener.getAllBalancesForAddress(address)
|
|
371
|
+
return tokens
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
async getAllUTXOsForAddress(address){
|
|
375
|
+
try {
|
|
376
|
+
// Fetch the unspent outputs for the given address
|
|
377
|
+
return await client.cmd('listunspent', 0, 9999999, [address]);
|
|
378
|
+
} catch (error) {
|
|
379
|
+
console.error('Error in getAllBalancesForAddress:', error.message || error);
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async getOnChainSpotOrderbook(id1, id2){
|
|
385
|
+
return await walletListener.getOrderBook({id1,id2})
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async getOnChainContractOrderbook(id){
|
|
389
|
+
return await walletListener.getContractOrderBook({id})
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async getPosition(address, contractId) {
|
|
393
|
+
return await walletListener.getContractPositionForAddressAndContractId({address,contractId})
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
async getFundingHistory(contractId){
|
|
397
|
+
return await walletListener.getFundingHistory(contractId)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Emit a new order
|
|
401
|
+
sendOrder(orderDetails) {
|
|
402
|
+
console.log('sending order')
|
|
403
|
+
if(this.socket){
|
|
404
|
+
if (!orderDetails.keypair) {
|
|
405
|
+
orderDetails.keypair = this.myInfo.keypair;
|
|
406
|
+
}
|
|
407
|
+
orderDetails.isLimitOrder = true;
|
|
408
|
+
console.log(JSON.stringify(orderDetails))
|
|
409
|
+
return new Promise((resolve, reject) => {
|
|
410
|
+
this.socket.emit('new-order', orderDetails);
|
|
411
|
+
this.socket.once('order:saved', (orderUuid) => {
|
|
412
|
+
console.log('saving order '+JSON.stringify({details: orderDetails, id: orderUuid }))
|
|
413
|
+
this.myOrders.push({details: orderDetails, id: orderUuid })
|
|
414
|
+
resolve(orderUuid);
|
|
415
|
+
});
|
|
416
|
+
this.socket.once('order:error', (error) => {
|
|
417
|
+
console.log('making note of err with order '+orderUUID)
|
|
418
|
+
//this.myOrders.push({details: orderDetails, id: orderUUID })
|
|
419
|
+
reject(error);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
}else{
|
|
423
|
+
console.log('Still loading orderbook server socket session')
|
|
424
|
+
// Return a rejected Promise to ensure the caller handles it
|
|
425
|
+
return Promise.reject(new Error('Socket is not connected.'));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
sendManyOrders(orderDetailsArray) {
|
|
430
|
+
if (this.socket != undefined || this.socket != null) {
|
|
431
|
+
// Add common metadata to all orders
|
|
432
|
+
const ordersWithMeta = orderDetailsArray.map((orderDetails) => ({
|
|
433
|
+
...orderDetails,
|
|
434
|
+
keypair: this.myInfo.keypair,
|
|
435
|
+
isLimitOrder: true,
|
|
436
|
+
}));
|
|
437
|
+
|
|
438
|
+
return new Promise((resolve, reject) => {
|
|
439
|
+
this.socket.emit('many-orders', ordersWithMeta);
|
|
440
|
+
|
|
441
|
+
// Listen for the "order:saved" event for confirmation
|
|
442
|
+
this.socket.once('order:saved', () => {
|
|
443
|
+
console.log('Batch of orders saved successfully');
|
|
444
|
+
this.myOrders.push(...ordersWithMeta); // Save orders locally
|
|
445
|
+
resolve(ordersWithMeta); // Resolve with the array of orders
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// Handle errors for the batch
|
|
449
|
+
this.socket.once('order:error', (error) => {
|
|
450
|
+
console.error('Error saving batch of orders:', error);
|
|
451
|
+
reject(error);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
} else {
|
|
455
|
+
console.log('Still loading orderbook server socket session');
|
|
456
|
+
// Return a rejected Promise to ensure the caller handles it
|
|
457
|
+
return Promise.reject(new Error('Socket is not connected.'));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
getMyInfo(){
|
|
462
|
+
return this.myInfo
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
getOrders({ state, symbol } = {}) {
|
|
466
|
+
let view = this.myOrders;
|
|
467
|
+
if (state) view = view.filter(o => o.state === state);
|
|
468
|
+
if (symbol) view = view.filter(o => o.symbol === symbol);
|
|
469
|
+
return Object.freeze(view.map(o => ({ ...o }))); // read-only snapshot
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Fetch the orderbook data through socket
|
|
473
|
+
getOrderbookData(filter) {
|
|
474
|
+
return new Promise((resolve, reject) => {
|
|
475
|
+
this.socket.emit('update-orderbook', filter);
|
|
476
|
+
this.socket.once('orderbook-data', (data) => {
|
|
477
|
+
resolve(data);
|
|
478
|
+
});
|
|
479
|
+
this.socket.once('order:error', (error) => {
|
|
480
|
+
reject(error);
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Cancel an existing order through socket
|
|
486
|
+
cancelOrder(orderUUID) {
|
|
487
|
+
if (!this.socket) return Promise.reject(new Error('Socket not connected'));
|
|
488
|
+
const id = (orderUUID && (orderUUID.orderUuid || orderUUID.uuid)) || orderUUID;
|
|
489
|
+
const hit = this.myOrders.find(o => o.id === id || o.orderUuid === id || o.uuid === id || o?.details?.uuid === id);
|
|
490
|
+
if (!hit) throw new Error(`Order ${id} not found`);
|
|
491
|
+
const details = hit.details ?? hit;
|
|
492
|
+
const props = details.props ?? details.order?.props ?? {};
|
|
493
|
+
// derive marketKey (spot or futures)
|
|
494
|
+
const f = props.id_for_sale ?? props.idForSale ?? props.first_token ?? props.firstToken;
|
|
495
|
+
const d = props.id_desired ?? props.idDesired ?? props.second_token ?? props.secondToken;
|
|
496
|
+
const cid = props.contract_id ?? props.contractId;
|
|
497
|
+
const exp = props.expiry ?? props.maturity_block ?? 'perp';
|
|
498
|
+
const marketKey = details.marketKey ?? details.order?.marketKey ??
|
|
499
|
+
(cid ? `${cid}-${exp}` :
|
|
500
|
+
(Number.isFinite(+f) && Number.isFinite(+d) ? ((+f < +d) ? `${+f}-${+d}` : `${+d}-${+f}`) : undefined));
|
|
501
|
+
|
|
502
|
+
return new Promise((resolve, reject) => {
|
|
503
|
+
this.socket.once('order:canceled', (ack) => {
|
|
504
|
+
this.myOrders = this.myOrders.filter(o => o.id !== id && o.orderUuid !== id && o.uuid !== id);
|
|
505
|
+
resolve(ack ?? { orderUUID: id });
|
|
506
|
+
});
|
|
507
|
+
this.socket.once('order:error', reject);
|
|
508
|
+
this.socket.emit('close-order', { orderUUID: id, ...(props && { props }), ...(marketKey && { marketKey }) });
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Modified getSpotMarkets with error handling for undefined response
|
|
513
|
+
// Modified getSpotMarkets with safer logging
|
|
514
|
+
async getSpotMarkets() {
|
|
515
|
+
const response = await axios.get(`${this.apiUrl}/markets/spot/${this.network}`);
|
|
516
|
+
|
|
517
|
+
// Log just the response data instead of the whole response
|
|
518
|
+
console.log('Spot Markets Response Data:', util.inspect(response.data, { depth: null }));
|
|
519
|
+
|
|
520
|
+
const payload = Array.isArray(response.data) ? response.data : response.data.data;
|
|
521
|
+
const markets = payload?.[0]?.markets;
|
|
522
|
+
if (markets){ return markets
|
|
523
|
+
}else{throw new Error('Invalid response format: spot markets not found')};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Modified getFuturesMarkets with safer logging
|
|
527
|
+
async getFuturesMarkets() {
|
|
528
|
+
const response = await axios.get(`${this.apiUrl}/markets/futures/${this.network}`);
|
|
529
|
+
|
|
530
|
+
// Log just the response data instead of the whole response
|
|
531
|
+
//console.log('Futures Markets Response Data:', util.inspect(response.data, { depth: null }));
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
const payload = Array.isArray(response.data) ? response.data : response.data.data;
|
|
535
|
+
const markets = payload?.[0]?.markets;
|
|
536
|
+
if (markets){ return markets
|
|
537
|
+
}else{throw new Error('Invalid response format: futures markets not found')};
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
async checkSync(){
|
|
541
|
+
const track = await walletListener.getTrackHeight()
|
|
542
|
+
const sync = await walletListener.checkSync()
|
|
543
|
+
|
|
544
|
+
return {realTimeModeHeight: track, txIndexHeight: sync.txIndex, consensusParseHeight: sync.consensus}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
module.exports = ApiWrapper
|
|
549
|
+
// Example usage
|
|
550
|
+
/*const api = new ApiWrapper('http://172.81.181.19', 9191);
|
|
551
|
+
|
|
552
|
+
// Example: Sending a new order
|
|
553
|
+
const newOrder = {
|
|
554
|
+
isLimitOrder: true,
|
|
555
|
+
props: {
|
|
556
|
+
id_desired: 1,
|
|
557
|
+
id_for_sale: 2,
|
|
558
|
+
amount: 100,
|
|
559
|
+
price: 0.05
|
|
560
|
+
},
|
|
561
|
+
action: 'BUY'
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
api.sendOrder(newOrder)
|
|
565
|
+
.then(orderUuid => {
|
|
566
|
+
console.log(`Order saved with UUID: ${orderUuid}`);
|
|
567
|
+
})
|
|
568
|
+
.catch(error => {
|
|
569
|
+
console.error(`Order failed: ${error}`);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Example: Fetching orderbook data
|
|
573
|
+
api.getOrderbookData({ first_token: 1, second_token: 2, type: 'SPOT' })
|
|
574
|
+
.then(data => {
|
|
575
|
+
console.log('Orderbook Data:', data);
|
|
576
|
+
})
|
|
577
|
+
.catch(error => {
|
|
578
|
+
console.error('Failed to fetch orderbook data:', error);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
*/
|
package/analyzepsbt.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const { Psbt, payments } = require('bitcoinjs-lib');
|
|
2
|
+
const {ECPairFactory} = require('ecpair')
|
|
3
|
+
const ecc = require('tiny-secp256k1')
|
|
4
|
+
const ECPair = ECPairFactory(ecc);
|
|
5
|
+
const { Buffer } = require('buffer');
|
|
6
|
+
|
|
7
|
+
// Helper function to verify signatures
|
|
8
|
+
const verifySignature = (pubkeyHex, sigHex, message) => {
|
|
9
|
+
const pubkey = Buffer.from(pubkeyHex, 'hex');
|
|
10
|
+
const signature = Buffer.from(sigHex, 'hex');
|
|
11
|
+
const keyPair = ECPair.fromPublicKey(pubkey);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const isValid = keyPair.verify(message, signature);
|
|
15
|
+
return isValid;
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error('Signature verification failed', e);
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Example PSBT - Replace with your actual PSBT data
|
|
23
|
+
const psbtHex = "70736274ff0100c50200000002343025a90f60c20c72637d18c3dcf46dd31b7e1abe409982c1daa3f1753f6b060000000000ffffffffd7a4390df4a8811be886b1251343af95fe927567e3cb450ec42d797076e2b7960000000000ffffffff03b4db060000000000160014f94801072fc65f8c35db2363f75803f16a9da94b1027000000000000160014396d64761fb3feb3fcaf95bf1c21c8f36d680a7e0000000000000000226a20746c33302c302e3030346e796d386571756170712c302c3770732c302c312c30000000000001012b5415000000000000220020a30d39561520a26d39248fb24062bb1997df52e8b73a22828534e9d58ecd58ff2202035d0c4cf2ea856bef98dba896f7e82bd9d80cedd08d117253e9ce225079f72b4b47304402204092a77ebdb1151a45c431539bf163471b8644f34c0855447d17c46d6e549c10022004f42545960abb8f7dfdb9b9a83ae171231fb34bfc8ebd5f5ca5d83e3ba169cd01220203f9967f334d7bcbe7bcefa41252ba488c3ceadf6da6c269bcada1ed0b9d600a5047304402205d097e72787447472f8b3edee44067c7ac313421725eb2b884fe01d7e6a3352a02200592f4809141b1c1fccaf900c351797ba8f8d7425298257967509e7f6668afc201010547522103f9967f334d7bcbe7bcefa41252ba488c3ceadf6da6c269bcada1ed0b9d600a5021035d0c4cf2ea856bef98dba896f7e82bd9d80cedd08d117253e9ce225079f72b4b52ae0001011f90f0060000000000160014f94801072fc65f8c35db2363f75803f16a9da94b2202035d0c4cf2ea856bef98dba896f7e82bd9d80cedd08d117253e9ce225079f72b4b48304502210095c96ae1bbb0bd91b11658d5263f261e4da61932a5de4826f791f22734e3b233022011372fc7a53a2f0591934f4957372b5f637263fcae4c64c2d2ebf759fe75214f0100000000";
|
|
24
|
+
|
|
25
|
+
// Decode the PSBT
|
|
26
|
+
const psbt = Psbt.fromHex(psbtHex);
|
|
27
|
+
|
|
28
|
+
// Analyze Inputs and Witness Data
|
|
29
|
+
psbt.data.inputs.forEach((input, index) => {
|
|
30
|
+
console.log(`Analyzing input ${index + 1} - TXID: ${input.txid}`);
|
|
31
|
+
|
|
32
|
+
// Get witness script and witness data
|
|
33
|
+
const witnessScript = input.witnessScript ? input.witnessScript.toString('hex') : null;
|
|
34
|
+
const signatures = input.partialSig || [];
|
|
35
|
+
|
|
36
|
+
console.log(`Witness Script: ${witnessScript}`);
|
|
37
|
+
|
|
38
|
+
// Verify signatures
|
|
39
|
+
signatures.forEach((sigData, sigIndex) => {
|
|
40
|
+
const pubkeyHex = sigData.pubkey.toString('hex');
|
|
41
|
+
const sigHex = sigData.signature.toString('hex');
|
|
42
|
+
const message = input.txid + input.vout; // Message for signature verification (customize as per your use case)
|
|
43
|
+
|
|
44
|
+
const isValid = verifySignature(pubkeyHex, sigHex, message);
|
|
45
|
+
console.log(`Signature ${sigIndex + 1} for input ${index + 1} is ${isValid ? 'valid' : 'invalid'}`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Check witness UTXO script (e.g., for P2WPKH or multisig)
|
|
49
|
+
if (input.witnessUtxo) {
|
|
50
|
+
const script = input.witnessUtxo.script.toString('hex');
|
|
51
|
+
console.log(`Witness UTXO script: ${script}`);
|
|
52
|
+
|
|
53
|
+
// Check if it's a P2WPKH or P2PKH
|
|
54
|
+
const p2wpkh = payments.p2wpkh({ output: Buffer.from(script, 'hex') });
|
|
55
|
+
const p2pkh = payments.p2pkh({ output: Buffer.from(script, 'hex') });
|
|
56
|
+
|
|
57
|
+
if (p2wpkh) {
|
|
58
|
+
console.log(`This input is P2WPKH`);
|
|
59
|
+
} else if (p2pkh) {
|
|
60
|
+
console.log(`This input is P2PKH`);
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`This input is an unknown type`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Check Outputs
|
|
68
|
+
psbt.data.outputs.forEach((output, index) => {
|
|
69
|
+
console.log(`Analyzing output ${index + 1} - Value: ${output.value}`);
|
|
70
|
+
|
|
71
|
+
const script = output.script.toString('hex');
|
|
72
|
+
console.log(`Output scriptPubKey for output ${index + 1}: ${script}`);
|
|
73
|
+
|
|
74
|
+
// Check if it's P2WPKH or P2PKH
|
|
75
|
+
const p2wpkh = payments.p2wpkh({ output: Buffer.from(script, 'hex') });
|
|
76
|
+
const p2pkh = payments.p2pkh({ output: Buffer.from(script, 'hex') });
|
|
77
|
+
|
|
78
|
+
if (p2wpkh) {
|
|
79
|
+
console.log("This is a P2WPKH output.");
|
|
80
|
+
} else if (p2pkh) {
|
|
81
|
+
console.log("This is a P2PKH output.");
|
|
82
|
+
} else {
|
|
83
|
+
console.log("This is an unknown output type.");
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Verify finalization of PSBT
|
|
88
|
+
if (psbt.finalized) {
|
|
89
|
+
console.log("PSBT is finalized (signed).");
|
|
90
|
+
} else {
|
|
91
|
+
console.log("PSBT is not finalized. It may still need signing.");
|
|
92
|
+
}
|