@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/buyer.js
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
const litecore = require('bitcore-lib-ltc');
|
|
2
|
+
const Encode = require('./tradelayer.js/src/txEncoder.js'); // Use encoder.js for payload generation
|
|
3
|
+
const BigNumber = require('bignumber.js');
|
|
4
|
+
const { buildLitecoinTransaction, buildTokenTradeTransaction, buildFuturesTransaction, buildSignAndBroadcastCommitTx, signPsbtRawTx } = require('./litecoreTxBuilder');
|
|
5
|
+
const WalletListener = require('./tradelayer.js/src/walletInterface.js'); // Import WalletListener to use tl_getChannelColumn
|
|
6
|
+
const util = require('util');
|
|
7
|
+
const {Psbt}= require('bitcoinjs-lib')
|
|
8
|
+
|
|
9
|
+
class BuySwapper {
|
|
10
|
+
constructor(
|
|
11
|
+
typeTrade, // New parameter for trade type ('BUY')
|
|
12
|
+
tradeInfo, // Trade information
|
|
13
|
+
buyerInfo, // Buyer information
|
|
14
|
+
sellerInfo, // Seller information
|
|
15
|
+
client, // Litecoin client or another client service
|
|
16
|
+
socket, // Socket for communication
|
|
17
|
+
test,
|
|
18
|
+
tradeUUID
|
|
19
|
+
) {
|
|
20
|
+
this.typeTrade = typeTrade; // 'BUY' or 'SELL'
|
|
21
|
+
this.tradeInfo = tradeInfo; // Trade information (e.g., amount, price, etc.)
|
|
22
|
+
this.myInfo = buyerInfo; // Information about the buyer
|
|
23
|
+
this.cpInfo = sellerInfo; // Information about the seller
|
|
24
|
+
this.socket = socket; // Socket connection for real-time events
|
|
25
|
+
this.client = client; // Client for making RPC calls
|
|
26
|
+
this.test= test
|
|
27
|
+
this.multySigChannelData = null; // Initialize multisig channel data
|
|
28
|
+
this.tradeUUID = tradeUUID
|
|
29
|
+
// Promisify methods for the given client
|
|
30
|
+
this.getRawTransactionAsync = util.promisify(this.client.getRawTransaction.bind(this.client));
|
|
31
|
+
this.getBlockDataAsync = util.promisify(this.client.getBlock.bind(this.client));
|
|
32
|
+
this.createRawTransactionAsync = util.promisify(this.client.createRawTransaction.bind(this.client));
|
|
33
|
+
this.listUnspentAsync = util.promisify(this.client.cmd.bind(this.client, 'listunspent'));
|
|
34
|
+
this.decoderawtransactionAsync = util.promisify(this.client.cmd.bind(this.client, 'decoderawtransaction'));
|
|
35
|
+
this.dumpprivkeyAsync = util.promisify(this.client.cmd.bind(this.client, 'dumpprivkey'));
|
|
36
|
+
this.sendrawtransactionAsync = util.promisify(this.client.cmd.bind(this.client, 'sendrawtransaction'));
|
|
37
|
+
this.validateAddress = util.promisify(this.client.cmd.bind(this.client, 'validateaddress'));
|
|
38
|
+
this.getBlockCountAsync = util.promisify(this.client.cmd.bind(this.client, 'getblockcount'));
|
|
39
|
+
this.addMultisigAddressAsync = util.promisify(this.client.cmd.bind(this.client, 'addmultisigaddress'));
|
|
40
|
+
this.signrawtransactionwithwalletAsync = util.promisify(this.client.cmd.bind(this.client, 'signrawtransactionwithwallet'));
|
|
41
|
+
this.signrawtransactionwithkeyAsync = util.promisify(this.client.cmd.bind(this.client, 'signrawtransactionwithkey'));
|
|
42
|
+
this.importmultiAsync = util.promisify(client.cmd.bind(client, 'importmulti'));
|
|
43
|
+
|
|
44
|
+
this.handleOnEvents(); // Set up event listeners
|
|
45
|
+
this.onReady(); // Prepare for trade execution
|
|
46
|
+
this.tradeStartTime = Date.now();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Other methods for the BuySwapper class (e.g., handleOnEvents, onReady, etc.)
|
|
50
|
+
onReady() {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
this.readyRes = resolve;
|
|
53
|
+
// If the readyRes is not called within 60 seconds, terminate the trade
|
|
54
|
+
setTimeout(() => this.terminateTrade('Undefined Error code 1'), 60000);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
logTime(stage) {
|
|
59
|
+
const currentTime = Date.now();
|
|
60
|
+
console.log(`Time taken for ${stage}: ${currentTime - this.tradeStartTime} ms`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
bip67SortPubKeys(pubKeys) {
|
|
64
|
+
return [...pubKeys].sort((a, b) =>
|
|
65
|
+
Buffer.from(a, 'hex').compare(Buffer.from(b, 'hex'))
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
removePreviousListeners() {
|
|
70
|
+
// Correctly using template literals with backticks
|
|
71
|
+
this.socket.off(`${this.cpInfo.socketId}::swap`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
delay(ms) {
|
|
75
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async ensureFuturesMargin(tradeProps) {
|
|
79
|
+
if (this._futuresMargin) return this._futuresMargin;
|
|
80
|
+
|
|
81
|
+
if (!tradeProps || !tradeProps.contract_id || !tradeProps.price || !tradeProps.amount) {
|
|
82
|
+
throw new Error('Invalid futures trade props for margin calculation');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const { contract_id, price, amount } = tradeProps;
|
|
86
|
+
|
|
87
|
+
// 1) Fetch contract info
|
|
88
|
+
const contractInfo = await WalletListener.getContractInfo(contract_id);
|
|
89
|
+
if (!contractInfo) {
|
|
90
|
+
throw new Error(`No contract info for contract ${contract_id}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2) Per-contract margin
|
|
94
|
+
const perContractMargin = await WalletListener.getInitialMargin(
|
|
95
|
+
contract_id,
|
|
96
|
+
price
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
if (!perContractMargin || perContractMargin <= 0) {
|
|
100
|
+
throw new Error('Invalid per-contract margin');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 3) Scale by number of contracts
|
|
104
|
+
const initMargin = perContractMargin * amount;
|
|
105
|
+
|
|
106
|
+
// 4) Collateral propertyId
|
|
107
|
+
const collateral = contractInfo.collateralPropertyId;
|
|
108
|
+
|
|
109
|
+
if (!collateral || initMargin <= 0) {
|
|
110
|
+
throw new Error('Computed invalid futures margin parameters');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this._futuresMargin = {
|
|
114
|
+
collateral,
|
|
115
|
+
initMargin,
|
|
116
|
+
perContractMargin,
|
|
117
|
+
leverage: contractInfo.leverage,
|
|
118
|
+
inverse: contractInfo.inverse
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
console.log('[FUTURES] margin prepared', this._futuresMargin);
|
|
122
|
+
return this._futuresMargin;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
async sendTxWithSpecRetry(rawTx) {
|
|
127
|
+
const _sendTxWithRetry = async (rawTx, retriesLeft, ms) => {
|
|
128
|
+
try {
|
|
129
|
+
// Attempt to send the transaction
|
|
130
|
+
const result = await this.sendrawtransactionAsync(rawTx);
|
|
131
|
+
// If there's an error and retries are left, try again
|
|
132
|
+
if (result.error && result.error.includes('bad-txns-inputs-missingorspent') && retriesLeft > 0) {
|
|
133
|
+
await new Promise(resolve => setTimeout(resolve, ms));
|
|
134
|
+
console.log('Retrying to send the transaction... Remaining retries:', retriesLeft);
|
|
135
|
+
return _sendTxWithRetry(rawTx, retriesLeft - 1, ms);
|
|
136
|
+
}
|
|
137
|
+
// If successful, return the result
|
|
138
|
+
return result;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
// If an error occurs during sendrawtransactionAsync, handle it here
|
|
141
|
+
console.error('Error during transaction send:', error.message);
|
|
142
|
+
if (retriesLeft > 0) {
|
|
143
|
+
console.log('Retrying after error... Remaining retries:', retriesLeft);
|
|
144
|
+
await new Promise(resolve => setTimeout(resolve, ms));
|
|
145
|
+
return _sendTxWithRetry(rawTx, retriesLeft - 1, ms);
|
|
146
|
+
}
|
|
147
|
+
return { error: 'Transaction failed after retries' }; // Return an error after all retries
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Start the retry process with 15 retries and 800ms interval
|
|
152
|
+
return _sendTxWithRetry(rawTx, 15, 1200);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async importMultisigNoRescan(address, redeemScriptHex) {
|
|
156
|
+
const request = [{
|
|
157
|
+
scriptPubKey: { address },
|
|
158
|
+
redeemscript: redeemScriptHex,
|
|
159
|
+
watchonly: true,
|
|
160
|
+
timestamp: 'now'
|
|
161
|
+
}];
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const result = await this.importmultiAsync(request, { rescan: false });
|
|
165
|
+
|
|
166
|
+
const r = result?.[0];
|
|
167
|
+
if (!r) return;
|
|
168
|
+
|
|
169
|
+
if (!r.success) {
|
|
170
|
+
if (r.error?.code === -4) {
|
|
171
|
+
// Already imported → OK
|
|
172
|
+
console.log('Multisig already present, continuing');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
throw new Error(r.error?.message || 'importmulti failed');
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
terminateTrade(reason){
|
|
183
|
+
// Emit the TERMINATE_TRADE event to the socket
|
|
184
|
+
const eventData = {event:'TERMINATE_TRADE', socketId: this.myInfo.socketId, reason: reason};
|
|
185
|
+
const tag = `${this.myInfo.socketId}::swap`; // Correct string concatenation
|
|
186
|
+
this.socket.emit(tag, eventData);
|
|
187
|
+
this.removePreviousListeners();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
handleOnEvents() {
|
|
191
|
+
const eventName = `${this.cpInfo.socketId}::swap`;
|
|
192
|
+
console.log('Received event:', JSON.stringify(eventName));
|
|
193
|
+
this.socket.on(eventName, (eventData) => {
|
|
194
|
+
console.log('event name '+eventData.eventName)
|
|
195
|
+
const { socketId, data } = eventData;
|
|
196
|
+
if (eventData.data?.tradeUUID && eventData.data.tradeUUID !== this.tradeUUID){
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
switch (eventData.eventName) {
|
|
201
|
+
case 'SELLER:STEP1':
|
|
202
|
+
this.onStep1(socketId,data);
|
|
203
|
+
break;
|
|
204
|
+
case 'SELLER:STEP3':
|
|
205
|
+
this.onStep3(socketId,data);
|
|
206
|
+
break;
|
|
207
|
+
case 'SELLER:STEP5':
|
|
208
|
+
console.log('about to call step 5 func ' +socketId+' '+JSON.stringify(data))
|
|
209
|
+
this.onStep5(socketId,data);
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Step 1: Create multisig address and verify
|
|
218
|
+
async onStep1(cpId, msData) {
|
|
219
|
+
console.log('cp socket Id '+JSON.stringify(cpId)+'my CP socketId '+ this.cpInfo.socketId)
|
|
220
|
+
console.log('examining trade info obj '+JSON.stringify(this.tradeInfo))
|
|
221
|
+
|
|
222
|
+
const startStep1Time = Date.now(); // Start timing Step 1
|
|
223
|
+
try {
|
|
224
|
+
// Check that the provided cpId matches the expected socketId
|
|
225
|
+
if (cpId !== this.cpInfo.socketId) {
|
|
226
|
+
console.log('cp socket mismatch '+Boolean(cpId !== this.cpInfo.socketId))
|
|
227
|
+
return new Error(`Error with p2p connection: Socket ID mismatch.`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let pubKeys = bip67SortPubKeys([
|
|
231
|
+
this.cpInfo.keypair.pubkey,
|
|
232
|
+
this.myInfo.keypair.pubkey,
|
|
233
|
+
]);
|
|
234
|
+
if (this.typeTrade === 'SPOT' && 'propIdDesired' in this.tradeInfo.props){
|
|
235
|
+
let { propIdDesired, propIdForSale } = this.tradeInfo.props;
|
|
236
|
+
if(propIdDesired==0||propIdForSale==0){
|
|
237
|
+
pubKeys = [this.myInfo.keypair.pubkey,this.cpInfo.keypair.pubkey];
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
console.log(JSON.stringify(pubKeys))
|
|
241
|
+
const multisigAddress = await this.addMultisigAddressAsync(2, pubKeys);
|
|
242
|
+
console.log('Created Multisig address:', multisigAddress.address, msData.address);
|
|
243
|
+
|
|
244
|
+
if (multisigAddress.address !== msData.address){
|
|
245
|
+
console.log('multisig address mismatch '+msData.address+multisigAddress.address+Boolean(multisigAddress.toString() !== msData.address))
|
|
246
|
+
return new Error('Multisig address mismatch');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Step 4: Validate redeemScript
|
|
250
|
+
if (multisigAddress.redeemScript !== msData.redeemScript) {
|
|
251
|
+
console.log('redeem script mismatch '+multisigAddress.redeemScript+msData.redeemScript+Boolean(multisigAddress.redeemScript !== msData.redeemScript))
|
|
252
|
+
return new Error('Redeem script mismatch');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
await this.importMultisigNoRescan(multisigAddress.address,multisigAddress.redeemscript)
|
|
256
|
+
|
|
257
|
+
// Step 5: Store the multisig data
|
|
258
|
+
this.multySigChannelData = msData;
|
|
259
|
+
|
|
260
|
+
// Emit the event to the correct socketId
|
|
261
|
+
console.log('about to emit step 2 '+this.myInfo.socketId)
|
|
262
|
+
|
|
263
|
+
const step1Time = Date.now() - startStep1Time; // Time taken for Step 1
|
|
264
|
+
console.log(`Time taken for Step 1: ${step1Time} ms`);
|
|
265
|
+
this.socket.emit(`${this.myInfo.socketId}::swap`, { eventName: 'BUYER:STEP2', socketId: this.myInfo.socketId });
|
|
266
|
+
|
|
267
|
+
} catch (error) {
|
|
268
|
+
this.terminateTrade(`Step 1: ${error.message}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async onStep3(cpId, commitUTXO) {
|
|
273
|
+
const startStep3Time = Date.now();
|
|
274
|
+
try {
|
|
275
|
+
console.log('cpId and socketId '+cpId+' '+this.cpInfo?.socketId)
|
|
276
|
+
// --- guards ---
|
|
277
|
+
if (cpId !== this.cpInfo?.socketId) throw new Error(`Error with p2p connection`);
|
|
278
|
+
|
|
279
|
+
console.log('multi '+!this.multySigChannelData?.address)
|
|
280
|
+
|
|
281
|
+
if (!this.multySigChannelData?.address) throw new Error(`Wrong Multisig Data Provided`);
|
|
282
|
+
|
|
283
|
+
// --- block height -> expiryBlock ---
|
|
284
|
+
const gbcRes = await this.getBlockCountAsync();
|
|
285
|
+
console.log('gbcRes '+gbcRes)
|
|
286
|
+
if (!Number.isFinite(gbcRes)) throw new Error('Failed to get block count from Litecoin node');
|
|
287
|
+
const bbData = Number(gbcRes) + 10;
|
|
288
|
+
|
|
289
|
+
// --- normalize trade kind (SPOT / FUTURES) ---
|
|
290
|
+
const ti = this.tradeInfo ?? {};
|
|
291
|
+
const props = ti.props ?? {};
|
|
292
|
+
const kindRaw = String(this.typeTrade || ti.type || '').toUpperCase();
|
|
293
|
+
const isSpot = (kindRaw === 'SPOT') || ('propIdDesired' in props) || ('propIdForSale' in props);
|
|
294
|
+
const isFutures = (kindRaw === 'FUTURES') || ('contract_id' in ti) || ('contractId' in ti);
|
|
295
|
+
console.log('isFutures '+isFutures)
|
|
296
|
+
if (!isSpot && !isFutures) throw new Error('Unrecognized Trade Type');
|
|
297
|
+
|
|
298
|
+
// --- column A/B (prefer RPC if available) ---
|
|
299
|
+
let isA = 1; // default A
|
|
300
|
+
try {
|
|
301
|
+
if (typeof WalletListener?.getColumn === 'function') {
|
|
302
|
+
const col = await WalletListener.getColumn(this.myInfo?.keypair?.address, this.cpInfo?.keypair?.address);
|
|
303
|
+
const tag = col?.data ?? col;
|
|
304
|
+
isA = (tag === 'A') ? 0 : 1;
|
|
305
|
+
}
|
|
306
|
+
} catch (_) {
|
|
307
|
+
// keep default isA = 1
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log('column '+isA)
|
|
311
|
+
|
|
312
|
+
// =========================
|
|
313
|
+
// SPOT
|
|
314
|
+
// =========================
|
|
315
|
+
if (isSpot) {
|
|
316
|
+
// safer props
|
|
317
|
+
let {
|
|
318
|
+
propIdDesired = props.propertyId ?? 0,
|
|
319
|
+
amountDesired = props.amount ?? 0,
|
|
320
|
+
amountForSale = props.amountForSale ?? 0,
|
|
321
|
+
propIdForSale = props.propIdForSale ?? 0,
|
|
322
|
+
transfer = props.transfer ?? false,
|
|
323
|
+
sellerIsMaker = props.sellerIsMaker ?? false,
|
|
324
|
+
} = props;
|
|
325
|
+
|
|
326
|
+
const columnAIsMaker = (isA === 1)
|
|
327
|
+
? (sellerIsMaker ? 1 : 0) // seller is A
|
|
328
|
+
: (!sellerIsMaker ? 1 : 0); // seller is B
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
// LTC vs token trade
|
|
333
|
+
let ltcTrade = false;
|
|
334
|
+
let ltcForSale = false;
|
|
335
|
+
if (propIdDesired === 0) {
|
|
336
|
+
ltcTrade = true; // buyer wants LTC -> tokens
|
|
337
|
+
ltcForSale = false;
|
|
338
|
+
} else if (propIdForSale === 0) {
|
|
339
|
+
ltcTrade = true; // seller offers LTC -> buyer pays tokens
|
|
340
|
+
ltcForSale = true; // <-- this was wrong in one earlier snippet
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (ltcTrade) {
|
|
344
|
+
// ========== LTC <-> TOKEN (IT) ==========
|
|
345
|
+
const tokenId = ltcForSale ? propIdDesired : propIdForSale;
|
|
346
|
+
const tokensSold = ltcForSale ? amountDesired : amountForSale;
|
|
347
|
+
const satsExpected = ltcForSale ? amountForSale : amountDesired;
|
|
348
|
+
|
|
349
|
+
const payload = Encode.encodeTradeTokenForUTXO({
|
|
350
|
+
propertyId: tokenId,
|
|
351
|
+
amount: tokensSold,
|
|
352
|
+
columnA: isA != 1, // boolean
|
|
353
|
+
satsExpected, // sats expected on-chain
|
|
354
|
+
tokenOutput: 1, // token output index preference (as in your code)
|
|
355
|
+
payToAddress: 0 // same as your call surface
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const network = this.test ? "LTCTEST" : "LTC";
|
|
359
|
+
const buildOptions = {
|
|
360
|
+
buyerKeyPair: this.myInfo.keypair,
|
|
361
|
+
sellerKeyPair: this.cpInfo.keypair,
|
|
362
|
+
commitUTXOs: [commitUTXO],
|
|
363
|
+
payload,
|
|
364
|
+
amount: satsExpected,
|
|
365
|
+
network
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const rawHexRes = await buildLitecoinTransaction(buildOptions, this.client);
|
|
369
|
+
if (!rawHexRes?.data?.psbtHex) throw new Error(`Build IT Trade: No PSBT returned`);
|
|
370
|
+
|
|
371
|
+
const step3Time = Date.now() - startStep3Time;
|
|
372
|
+
console.log(`Time taken for Step 3: ${step3Time} ms`);
|
|
373
|
+
|
|
374
|
+
const eventData = {
|
|
375
|
+
eventName: 'BUYER:STEP4',
|
|
376
|
+
socketId: this.myInfo.socketId,
|
|
377
|
+
psbtHex: rawHexRes.data.psbtHex,
|
|
378
|
+
commitTxId: '' // not available here; commit comes from SELLER
|
|
379
|
+
};
|
|
380
|
+
this.socket.emit(`${this.myInfo.socketId}::swap`, eventData);
|
|
381
|
+
|
|
382
|
+
} else {
|
|
383
|
+
// ========== TOKEN <-> TOKEN (Channel) ==========
|
|
384
|
+
// First, fund (commit or transfer) buyer-to-channel for the side they must fund:
|
|
385
|
+
const commitPayload = transfer
|
|
386
|
+
? Encode.encodeTransfer({
|
|
387
|
+
propertyId: propIdDesired,
|
|
388
|
+
amount: amountDesired,
|
|
389
|
+
isColumnA: isA === 1,
|
|
390
|
+
destinationAddr: this.multySigChannelData.address,
|
|
391
|
+
})
|
|
392
|
+
: Encode.encodeCommit({
|
|
393
|
+
amount: amountDesired,
|
|
394
|
+
propertyId: propIdDesired,
|
|
395
|
+
channelAddress: this.multySigChannelData.address,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
const network = this.test ? "LTCTEST" : "LTC";
|
|
399
|
+
|
|
400
|
+
// Your NPM flow uses custom builder(s); keeping surface:
|
|
401
|
+
const commitTxConfig = {
|
|
402
|
+
fromKeyPair: this.myInfo.address, // keeping your original shape
|
|
403
|
+
toKeyPair: this.cpInfo.keypair,
|
|
404
|
+
payload: commitPayload,
|
|
405
|
+
network
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const commitTxRes = await buildTokenTradeTransaction(commitTxConfig, this.client);
|
|
409
|
+
if (!commitTxRes?.signedHex) throw new Error('Failed to sign and send the token transaction');
|
|
410
|
+
|
|
411
|
+
// Extract UTXO from commit hex for chaining
|
|
412
|
+
const utxoData = await getUTXOFromCommit(commitTxRes.signedHex, this.client);
|
|
413
|
+
if (!utxoData) throw new Error('Failed to extract UTXO from commit');
|
|
414
|
+
|
|
415
|
+
// Channel trade payload (tokens-for-tokens)
|
|
416
|
+
const tradePayload = Encode.encodeTradeTokensChannel({
|
|
417
|
+
propertyId1: propIdDesired,
|
|
418
|
+
propertyId2: propIdForSale,
|
|
419
|
+
amountOffered1: amountDesired,
|
|
420
|
+
amountDesired2: amountForSale,
|
|
421
|
+
columnAIsOfferer: isA,
|
|
422
|
+
expiryBlock: bbData,
|
|
423
|
+
columnAIsMaker: columnAIsMaker
|
|
424
|
+
});
|
|
425
|
+
console.log('keypairs '+JSON.stringify(this.myInfo.keypair)+' '+JSON.stringify(this.cpInfo.keypair))
|
|
426
|
+
|
|
427
|
+
const tradeOptions = {
|
|
428
|
+
buyerKeyPair: this.myInfo.keypair,
|
|
429
|
+
sellerKeyPair: this.cpInfo.keypair,
|
|
430
|
+
commitUTXOs: [commitUTXO, utxoData],
|
|
431
|
+
payload: tradePayload,
|
|
432
|
+
amount: 0,
|
|
433
|
+
network
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const rawHexRes = await buildTokenTradeTransaction(tradeOptions, this.client);
|
|
437
|
+
if (!rawHexRes?.psbtHex) throw new Error(`Build Trade: Failed to build token trade`);
|
|
438
|
+
|
|
439
|
+
const step3Time = Date.now() - startStep3Time;
|
|
440
|
+
console.log(`Time taken for Step 3: ${step3Time} ms`);
|
|
441
|
+
|
|
442
|
+
this.socket.emit(
|
|
443
|
+
`${this.myInfo.socketId}::swap`,
|
|
444
|
+
{ eventName: 'BUYER:STEP4', socketId: this.myInfo.socketId, psbtHex: rawHexRes.psbtHex, commitTxId: commitTxRes.signedHex }
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return; // done with SPOT
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// =========================
|
|
452
|
+
// FUTURES
|
|
453
|
+
// =========================
|
|
454
|
+
if(isFutures){
|
|
455
|
+
const trade = ti; // your desktop shape puts futures fields at top-level, not in props
|
|
456
|
+
const {
|
|
457
|
+
contract_id,
|
|
458
|
+
amount,
|
|
459
|
+
price,
|
|
460
|
+
transfer = props.transfer ?? false,
|
|
461
|
+
sellerIsMaker = props.sellerIsMaker ?? false
|
|
462
|
+
} = trade.props;
|
|
463
|
+
|
|
464
|
+
console.log('trade props '+JSON.stringify(ti)+' '+JSON.stringify(trade))
|
|
465
|
+
|
|
466
|
+
const margin = await this.ensureFuturesMargin(trade.props)
|
|
467
|
+
const initMargin= margin.initMargin
|
|
468
|
+
const collateral= margin.collateral
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
console.log('margin and collateral '+initMargin+' '+collateral)
|
|
472
|
+
|
|
473
|
+
// column/maker role (desktop logic)
|
|
474
|
+
const columnAIsMaker = (isA === 1)
|
|
475
|
+
? (sellerIsMaker ? 1 : 0) // seller is A
|
|
476
|
+
: (!sellerIsMaker ? 1 : 0); // seller is B
|
|
477
|
+
|
|
478
|
+
// commit or transfer futures collateral
|
|
479
|
+
const commitPayload = transfer
|
|
480
|
+
? Encode.encodeTransfer({
|
|
481
|
+
propertyId: collateral,
|
|
482
|
+
amount: initMargin,
|
|
483
|
+
isColumnA: isA === 1,
|
|
484
|
+
destinationAddr: this.multySigChannelData.address,
|
|
485
|
+
})
|
|
486
|
+
: Encode.encodeCommit({
|
|
487
|
+
propertyId: collateral,
|
|
488
|
+
amount: initMargin,
|
|
489
|
+
channelAddress: this.multySigChannelData.address,
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
console.log('payload '+commitPayload)
|
|
493
|
+
// In buyer's onStep3:
|
|
494
|
+
|
|
495
|
+
// Build, sign, and broadcast the commit transaction
|
|
496
|
+
// This function will call listUnspent internally to get buyer's UTXO
|
|
497
|
+
const commitTxRes = await buildSignAndBroadcastCommitTx({
|
|
498
|
+
buyerKeyPair: this.myInfo.keypair,
|
|
499
|
+
sellerKeyPair: this.cpInfo.keypair,
|
|
500
|
+
payload: commitPayload, // The commit payload (tl45...)
|
|
501
|
+
multySigChannelData: this.multySigChannelData
|
|
502
|
+
}, this.client);
|
|
503
|
+
|
|
504
|
+
console.log('[STEP3] Commit tx broadcast:', JSON.stringify({
|
|
505
|
+
txid: commitTxRes.txid,
|
|
506
|
+
broadcast: commitTxRes.broadcast
|
|
507
|
+
}));
|
|
508
|
+
|
|
509
|
+
// The commit UTXO is already in the response
|
|
510
|
+
const utxoData = commitTxRes.commitUtxoData;
|
|
511
|
+
console.log('[STEP3] Commit UTXO:', JSON.stringify(utxoData));
|
|
512
|
+
|
|
513
|
+
// Now build the settlement transaction payload
|
|
514
|
+
const channelPayload = Encode.encodeTradeContractChannel({
|
|
515
|
+
contractId: contract_id,
|
|
516
|
+
amount,
|
|
517
|
+
price,
|
|
518
|
+
expiryBlock: bbData,
|
|
519
|
+
columnAIsSeller: isA,
|
|
520
|
+
insurance: false,
|
|
521
|
+
columnAIsMaker
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
// Build the settlement transaction (unsigned)
|
|
525
|
+
const settlementTxRes = await buildFuturesTransaction({
|
|
526
|
+
buyerKeyPair: this.myInfo.keypair,
|
|
527
|
+
sellerKeyPair: this.cpInfo.keypair,
|
|
528
|
+
commitUTXOs: [utxoData], // The UTXO we just created
|
|
529
|
+
payload: channelPayload
|
|
530
|
+
}, this.client);
|
|
531
|
+
|
|
532
|
+
// Emit to seller
|
|
533
|
+
this.socket.emit(`${this.myInfo.socketId}::swap`, {
|
|
534
|
+
eventName: 'BUYER:STEP4',
|
|
535
|
+
socketId: this.myInfo.socketId,
|
|
536
|
+
data: {
|
|
537
|
+
psbtHex: settlementTxRes.psbtHex,
|
|
538
|
+
commitHex: commitTxRes.signedHex,
|
|
539
|
+
commitTxId: commitTxRes.txid,
|
|
540
|
+
prevTxs: settlementTxRes.prevTxs
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
throw new Error(`Unrecognized Trade Type: ${this.typeTrade}`);
|
|
548
|
+
} catch (error) {
|
|
549
|
+
const errorMessage = error?.message || 'Undefined Error';
|
|
550
|
+
this.terminateTrade(`Step 3: ${errorMessage}`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
// Step 5: Sign the PSBT using Litecore and send the final transaction
|
|
556
|
+
async onStep5(cpId, psbtHex) {
|
|
557
|
+
const startStep5Time = Date.now();
|
|
558
|
+
|
|
559
|
+
/*let signed = await signpsbtAsync(psbtHex.data.psbt)
|
|
560
|
+
const final = await finalizeAsync(signed.psbt)
|
|
561
|
+
console.log('final '+JSON.stringify(final))
|
|
562
|
+
|
|
563
|
+
const timeToCoSign = Date.now()-this.tradeStartTime
|
|
564
|
+
console.log('Cosigned trade in '+timeToCoSign)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
console.log(sentTx)
|
|
568
|
+
const psbt = Psbt.fromHex(psbtHex);
|
|
569
|
+
const bigIntReplacer = (key, value) => {
|
|
570
|
+
if (typeof value === 'bigint') {
|
|
571
|
+
return value.toString(); // Convert BigInt to string
|
|
572
|
+
}
|
|
573
|
+
return value;
|
|
574
|
+
};*/
|
|
575
|
+
|
|
576
|
+
// Now, use this replacer when calling JSON.stringify
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
// Ensure that each input has the necessary witness data
|
|
580
|
+
|
|
581
|
+
try{
|
|
582
|
+
// Sign the PSBT transaction using the wallet
|
|
583
|
+
let wif = await this.dumpprivkeyAsync(this.myInfo.keypair.address)
|
|
584
|
+
console.log('wif '+wif)
|
|
585
|
+
let network = "LTC"
|
|
586
|
+
if(this.test==true){
|
|
587
|
+
network = "LTCTEST"
|
|
588
|
+
}
|
|
589
|
+
//console.log('network')
|
|
590
|
+
//const signedPsbt = await signpsbtAsync(psbtHex,true)
|
|
591
|
+
const signedPsbt = await signPsbtRawTx({wif:wif,network:network,psbtHex:psbtHex}, this.client);
|
|
592
|
+
wif = ''
|
|
593
|
+
//if (!signedPsbt || !signedPsbt.hex) return new Error('Failed to sign PSBT');
|
|
594
|
+
const timeToCoSign = Date.now()-this.tradeStartTime
|
|
595
|
+
console.log('Cosigned trade in '+timeToCoSign)
|
|
596
|
+
console.log('complete psbt hex, finished? '+signedPsbt.data.isFinished+' '+signedPsbt.data.psbtHex)
|
|
597
|
+
|
|
598
|
+
/*const psbtDecode = await decodepsbtAsync(signedPsbt.data.psbtHex)
|
|
599
|
+
console.log(psbtDecode)*/
|
|
600
|
+
|
|
601
|
+
const sentTx = await this.sendTxWithSpecRetry(signedPsbt.data.finalHex);
|
|
602
|
+
//console.log(JSON.stringify(Psbt.fromHex(signedPsbt.data.psbtHex), bigIntReplacer))
|
|
603
|
+
/*const decode = await decoderawtransactionAsync(signedPsbt.data.hex)
|
|
604
|
+
console.log('decoded final tx '+ JSON.stringify(decode))
|
|
605
|
+
|
|
606
|
+
// Send the signed transaction
|
|
607
|
+
const sentTx = await sendrawtransactionAsync(signedPsbt.data.hex);
|
|
608
|
+
if (!sentTx) return new Error('Failed to send the transaction');
|
|
609
|
+
*/
|
|
610
|
+
// Emit the next step event
|
|
611
|
+
const step5Time = Date.now() - startStep5Time; // Time taken for Step 3
|
|
612
|
+
//console.log(`Time taken for Step 5: ${step5Time} ms`);
|
|
613
|
+
|
|
614
|
+
console.log('checking socket id'+this.myInfo.socketId)
|
|
615
|
+
this.socket.emit(`${this.myInfo.socketId}::swap`, { eventName: 'BUYER:STEP6', socketId: this.myInfo.socketId, data: sentTx });
|
|
616
|
+
} catch (error) {
|
|
617
|
+
this.terminateTrade(`Step 5: ${error.message}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
module.exports = BuySwapper;
|
package/client.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const Litecoin = require('litecoin');
|
|
2
|
+
const Bitcoin = require('bitcoin')
|
|
3
|
+
const { RelayerClient, createFallbackClient, DEFAULT_RELAYER_HOST, DEFAULT_RELAYER_PORT } = require('./relayerClient');
|
|
4
|
+
|
|
5
|
+
const createLitecoinClient = (test = true, relayerOpts) => {
|
|
6
|
+
const config = {
|
|
7
|
+
host: '127.0.0.1',
|
|
8
|
+
port: test ? 19332 : 9332, // Switch between testnet and mainnet
|
|
9
|
+
user: 'user', // Make sure to replace these with your actual credentials
|
|
10
|
+
pass: 'pass',
|
|
11
|
+
timeout: 10000
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const local = new Litecoin.Client(config);
|
|
15
|
+
|
|
16
|
+
if (relayerOpts === false) {
|
|
17
|
+
// Explicitly disabled
|
|
18
|
+
return local;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return createFallbackClient(local, relayerOpts || {});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const createBitcoinClient = (test = true, relayerOpts) => {
|
|
25
|
+
const config = {
|
|
26
|
+
host: '127.0.0.1',
|
|
27
|
+
port: test ? 18332 : 8332, // Switch between testnet and mainnet
|
|
28
|
+
user: 'user', // Make sure to replace these with your actual credentials
|
|
29
|
+
pass: 'pass',
|
|
30
|
+
timeout: 10000
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const local = new Bitcoin.Client(config);
|
|
34
|
+
|
|
35
|
+
if (relayerOpts === false) {
|
|
36
|
+
return local;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return createFallbackClient(local, relayerOpts || {});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a relayer-only client (no local node needed).
|
|
44
|
+
*/
|
|
45
|
+
const createRelayerOnlyClient = (opts) => {
|
|
46
|
+
return new RelayerClient(opts);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
module.exports = {createLitecoinClient, createBitcoinClient, createRelayerOnlyClient};
|