Debugging counter-offer

This commit is contained in:
Chris Troutner
2024-12-07 20:33:25 -08:00
parent d15fee7c7a
commit 2a78145170
7 changed files with 125 additions and 58 deletions
+12 -12
View File
@@ -26,7 +26,7 @@
"@psf/bch-js": "6.7.3",
"axios": "0.27.2",
"bch-message-lib": "2.2.1",
"bch-nostr": "1.3.2",
"bch-nostr": "1.3.3",
"bch-token-sweep": "2.2.1",
"bcryptjs": "2.4.3",
"bitcoincashjs-lib": "3.3.3",
@@ -53,7 +53,7 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "1.9.1",
"line-reader": "0.4.0",
"minimal-slp-wallet": "5.12.0",
"minimal-slp-wallet": "5.12.1",
"mongoose": "5.13.14",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.7.5",
@@ -7420,9 +7420,9 @@
}
},
"node_modules/bch-consumer": {
"version": "1.6.1",
"resolved": "http://94.130.170.209:4873/bch-consumer/-/bch-consumer-1.6.1.tgz",
"integrity": "sha512-ZhyZ54kgF6f3sB7J4ylMBJHSoBXozUdM2bvsm2nTz31515LFfHra9d9w4Ommlmy5BvuDkdX4lUeGSLRvggXnFg==",
"version": "1.5.1",
"resolved": "http://94.130.170.209:4873/bch-consumer/-/bch-consumer-1.5.1.tgz",
"integrity": "sha512-tEmds6Mk7g074+fGflm0d9At2ZV8DFhWErEN0nUzzW4vG5Ega9+yjREY16P/QuwwykzodnleQqOsNwcmvvgnAg==",
"license": "MIT",
"dependencies": {
"@psf/bch-js": "6.7.3",
@@ -7597,9 +7597,9 @@
}
},
"node_modules/bch-nostr": {
"version": "1.3.2",
"resolved": "http://94.130.170.209:4873/bch-nostr/-/bch-nostr-1.3.2.tgz",
"integrity": "sha512-MdbuuTns1MhEd205uabl7Y8X+caphnb6ZgHs574bet+cSE0aw4QoMr6hpc+EmLtuKK90r5Eqob1peuQ9jzVlIg==",
"version": "1.3.3",
"resolved": "http://94.130.170.209:4873/bch-nostr/-/bch-nostr-1.3.3.tgz",
"integrity": "sha512-2Mod/PEDr/GJzQq20oSJKwJDtiXYm/Qj5KxIvFqsvBY1SYsHGyDu1FMBQ1UvOhY3ZP5fgiVLbIGvMRuWXqS4oQ==",
"license": "MIT",
"dependencies": {
"apidoc": "0.53.0",
@@ -17185,15 +17185,15 @@
}
},
"node_modules/minimal-slp-wallet": {
"version": "5.12.0",
"resolved": "http://94.130.170.209:4873/minimal-slp-wallet/-/minimal-slp-wallet-5.12.0.tgz",
"integrity": "sha512-zSJcBLF/tt7NH0xkuukTJ4BxnC2GIR8kjUJRWW91/LwhI6c2K9qNVV/G5E7SjYx125aHkGk5lq3pjGePsJ18rA==",
"version": "5.12.1",
"resolved": "http://94.130.170.209:4873/minimal-slp-wallet/-/minimal-slp-wallet-5.12.1.tgz",
"integrity": "sha512-DnggKv1KC/Y6qxT6GiplrxfKPgBOdYbu7uK4bWVO+6RgTtcgMxrd4pxCFh4kHV3nV7vKBpE1wsmVZgtZ3x9qcg==",
"license": "MIT",
"dependencies": {
"@chris.troutner/retry-queue-commonjs": "1.0.8",
"@psf/bch-js": "6.8.0",
"apidoc": "0.51.0",
"bch-consumer": "1.6.1",
"bch-consumer": "1.5.1",
"bch-donation": "1.1.2",
"crypto-js": "4.0.0"
}
+2 -2
View File
@@ -45,7 +45,7 @@
"@psf/bch-js": "6.7.3",
"axios": "0.27.2",
"bch-message-lib": "2.2.1",
"bch-nostr": "1.3.2",
"bch-nostr": "1.3.3",
"bch-token-sweep": "2.2.1",
"bcryptjs": "2.4.3",
"bitcoincashjs-lib": "3.3.3",
@@ -72,7 +72,7 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "1.9.1",
"line-reader": "0.4.0",
"minimal-slp-wallet": "5.12.0",
"minimal-slp-wallet": "5.12.1",
"mongoose": "5.13.14",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.7.5",
+8 -1
View File
@@ -2,8 +2,10 @@
Adapter library for working with Nostr.
*/
// Global npm libraries
import BchNostr from 'bch-nostr'
import { RelayPool } from 'nostr'
import RetryQueue from '@chris.troutner/retry-queue'
class NostrAdapter {
constructor (localConfig = { nostrRelay: '', nostrTopic: '' }) {
@@ -25,6 +27,11 @@ class NostrAdapter {
// Encapsulate dependencies
this.bchNostr = new BchNostr()
this.RelayPool = RelayPool
this.retryQueue = new RetryQueue({
concurrency: 1,
attempts: 5,
retryPeriod: 1000
})
// Bind the 'this' object
this.start = this.start.bind(this)
@@ -71,7 +78,7 @@ class NostrAdapter {
msg,
tags: [['t', this.topic]]
}
const eventId = await this.bchNostr.post.uploadToNostr(inObj)
const eventId = await this.retryQueue.addToQueue(this.bchNostr.post.uploadToNostr, inObj)
return eventId
} catch (error) {
console.log(`Error in nostr.js/post() ${error.message} `)
+10 -4
View File
@@ -5,12 +5,11 @@
// Public npm libraries
import BchWallet from 'minimal-slp-wallet'
import BchTokenSweep from 'bch-token-sweep/index.js'
import bitcoinJs from 'bitcoincashjs-lib'
import RetryQueue from '@chris.troutner/retry-queue'
// Local libraries
import JsonFiles from './json-files.js'
import config from '../../config/index.js'
// Hack to get __dirname back.
@@ -35,6 +34,11 @@ class WalletAdapter {
this.BchWallet = BchWallet
this.bchWallet = {} // Will be replaced when initialized.
// this.advancedConfig = localConfig.advancedConfig
this.retryQueue = new RetryQueue({
concurrency: 1,
attempts: 5,
retryPeriod: 5000
})
// Bind the 'this' object
this.moveTokens = this.moveTokens.bind(this)
@@ -441,7 +445,7 @@ class WalletAdapter {
return txObj2
} catch (err) {
console.error('Error in wallet.js/deserializePartialTx()')
console.error('Error in wallet.js/deserializeTx()')
throw err
}
}
@@ -508,7 +512,9 @@ class WalletAdapter {
// return csTxHex
// Broadcast transaction to the network
const txid = await this.bchWallet.ar.sendTx(csTxHex)
// const txid = await this.bchWallet.ar.sendTx(csTxHex)
const txid = await this.retryQueue.addToQueue(this.bchWallet.broadcast, { hex: csTxHex })
console.log('completeTx() txid: ', txid)
return txid
} catch (err) {
+2 -2
View File
@@ -17,7 +17,7 @@ class OfferEntity {
)
}
console.log('offer entity validate() offerData: ', offerData)
// console.log('offer entity validate() offerData: ', offerData)
const {
messageType,
@@ -105,7 +105,7 @@ class OfferEntity {
tokenType,
nostrEventId
}
console.log('offer entity validatedOfferData: ', validatedOfferData)
// console.log('offer entity validatedOfferData: ', validatedOfferData)
return validatedOfferData
}
+46 -35
View File
@@ -94,7 +94,7 @@ class OfferUseCases {
}
// const utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo)
const utxoStatus = await this.retryQueue.addToQueue(this.adapters.wallet.bchWallet.utxoIsValid, utxo)
console.log('utxoStatus: ', utxoStatus)
// console.log('utxoStatus: ', utxoStatus)
// if (utxoStatus === null) return false
if (!utxoStatus) return false
@@ -175,7 +175,7 @@ class OfferUseCases {
const nsfwSetTrue = mutableData.nsfw === true
const nsfwStringTrue = mutableData.nsfw === 'true'
const nsfwDetected = hasNsfw && (nsfwSetTrue || nsfwStringTrue)
console.log(`hasNsfw: ${hasNsfw}, nsfwSetTrue: ${nsfwSetTrue}, nsfwStringTrue: ${nsfwStringTrue}, nsfwDetected: ${nsfwDetected}`)
// console.log(`hasNsfw: ${hasNsfw}, nsfwSetTrue: ${nsfwSetTrue}, nsfwStringTrue: ${nsfwStringTrue}, nsfwDetected: ${nsfwDetected}`)
if (nsfwDetected) {
console.log('NSFW flag set as true')
@@ -318,7 +318,7 @@ class OfferUseCases {
// Note : should be added to retry-queue?
const utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo)
console.log('utxoStatus: ', utxoStatus)
// console.log('utxoStatus: ', utxoStatus)
if (!utxoStatus) {
console.log(`utxo txid: ${offerInfo.utxoTxid}, vout: ${offerInfo.utxoVout}`)
@@ -377,11 +377,11 @@ class OfferUseCases {
data: takenOfferInfo,
appId: this.config.p2wdbAppId
}
const resultEventId = await this.adapters.nostr.post(nostrData)
const resultEventId = await this.adapters.nostr.post(JSON.stringify(nostrData))
// Delete the Offer from the database, so that the user doesn't attempt
// to take the offer more than once.
offerInfo.remove()
// offerInfo.remove()
// Return the P2WDB CID
return resultEventId
@@ -472,27 +472,27 @@ class OfferUseCases {
}
async findOfferByTxid (utxoTxid) {
try {
// try {
if (typeof utxoTxid !== 'string' || !utxoTxid) {
throw new Error('utxoTxid must be a string')
}
const offer = await this.OfferModel.findOne({ utxoTxid })
// TODO: Offer should be found by TXID, then if there is more than one
// result, they should be filtered by the vout property. That will leave
// one remaining UTXO.
if (!offer) {
throw new Error('offer not found')
}
return offer
} catch (error) {
console.error('Error in use-cases/offer/findOfferByTxid(): ', error.message)
throw error
// try {
// try {
if (typeof utxoTxid !== 'string' || !utxoTxid) {
throw new Error('utxoTxid must be a string')
}
const offer = await this.OfferModel.findOne({ utxoTxid })
// TODO: Offer should be found by TXID, then if there is more than one
// result, they should be filtered by the vout property. That will leave
// one remaining UTXO.
if (!offer) {
throw new Error('offer not found')
}
return offer
// } catch (error) {
// // console.error('Error in use-cases/offer/findOfferByTxid(): ', error.message)
// throw error
// }
}
// This function is called by the P2WDB webhook REST API handler. When a
@@ -505,17 +505,18 @@ class OfferUseCases {
// See if this instance of bch-dex is managing the Order associated with
// the incoming Counter Offer.
// Note : this should be handle by nostrEvent id or UtxoId?
const orderHash = offerData.data.nostrEventId
console.log('ping11')
// Note : this should be handled by nostrEvent id or UtxoId?
// const orderHash = offerData.data.nostrEventId
let orderData = {}
try {
orderData = await this.orderUseCase.findOrderByEvent(orderHash)
orderData = await this.orderUseCase.findOrderByUtxo(offerData)
console.log(`orderData: ${JSON.stringify(orderData, null, 2)}`)
} catch (err) {
console.log('Order matching this Counter Offer is not managed by this instance of bch-dex. Exiting.')
console.log('Order matching this Counter Offer is not managed by this instance of bch-dex. Skipping.')
return 'N/A'
}
console.log('ping12')
// Deserialize the partially signed transaction.
const txHex = offerData.data.partialTxHex
@@ -549,7 +550,7 @@ class OfferUseCases {
return txid
} catch (err) {
console.error('Error in acceptCounterOffer()')
console.error('Error in acceptCounterOffer(): ', err)
throw err
}
}
@@ -637,7 +638,7 @@ class OfferUseCases {
// If the Offer UTXO is spent, delete the Offer model.
if (utxoStatus === false) {
console.log('utxoStatus: ', utxoStatus)
// console.log('utxoStatus: ', utxoStatus)
console.log(`Spent UTXO detected. Deleting this Offer: ${JSON.stringify(thisOffer, null, 2)}`)
await thisOffer.remove()
}
@@ -698,7 +699,7 @@ class OfferUseCases {
try {
// Retrieve offers array.
const offers = await this.adapters.nostr.read()
console.log('offers: ', offers)
// console.log('offers: ', offers)
for (let i = 0; i < offers.length; i++) {
try {
@@ -709,9 +710,19 @@ class OfferUseCases {
// Append the Nostr Event ID to the offer object
offerObj.data.nostrEventId = offer.eventId
// console.log('loadOffers() offerObj: ', offerObj)
// Try to create new offer
await this.createOffer(offerObj)
if (offerObj.data.dataType === 'offer') {
// Try to create new offer
await this.createOffer(offerObj)
}
if (offerObj.data.dataType === 'counter-offer') {
console.log('Counter offer detected: ', offerObj)
await this.acceptCounterOffer(offerObj)
}
// Ignore the post if it doesn't fit the above filters.
} catch (error) {
/* exit quietly */
}
+45 -2
View File
@@ -31,6 +31,8 @@ class OrderLib {
// Bind subfunctions to the 'this' object.
this.ensureFunds = this.ensureFunds.bind(this)
this.createOrder = this.createOrder.bind(this)
this.findOrderByUtxo = this.findOrderByUtxo.bind(this)
}
// Create a new order model and add it to the Mongo database.
@@ -191,6 +193,47 @@ class OrderLib {
}
}
// Retrieve an Order model from the database. Find it by its UTXO (TXID & Vout)
async findOrderByUtxo (offerData = {}) {
try {
console.log('findOrderByUtxo() offerData: ', offerData)
// if (typeof nostrEventId !== 'string' || !nostrEventId) {
// throw new Error('nostrEventId must be a string')
// }
console.log('ping01')
// const allOrders = await this.OrderModel.find({})
// console.log('allOrders: ', allOrders)
console.log('ping02')
// const order = await this.OrderModel.findOne({ nostrEventId })
const order = await this.OrderModel.findOne({ utxoTxid: offerData.data.utxoTxid, utxoVout: offerData.data.utxoVout })
// const order = await this.OrderModel.findOne({ utxoTxid: offerData.data.utxoTxid })
// const order = await this.OrderModel.findOne({ tokenId: offerData.data.tokenId })
console.log('findOrderByUtxo() order: ', order)
console.log('ping03')
if (!order) {
throw new Error('order not found')
}
if (!order.nostrEventId) {
throw new Error('order not found')
}
const orderObject = order.toObject()
// return this.offerEntity.validateFromModel(offerObject)
return orderObject
} catch (err) {
console.error('Error in findOrderByUtxo(): ', err)
throw err
}
}
// This function is called by the garbage collection timer controller. It
// checks the UTXO associated with each Order in the database. If the UTXO
// has been spent, the Order is deleted from the database.
@@ -201,7 +244,7 @@ class OrderLib {
// Get all Orders in the database.
const orders = await this.OrderModel.find({})
console.log('orders: ', orders)
// console.log('orders: ', orders)
// Loop through each Order and ensure the UTXO is still valid.
for (let i = 0; i < orders.length; i++) {
@@ -239,7 +282,7 @@ class OrderLib {
// If the Order UTXO is spent, delete the Order model.
if (utxoStatus === false) {
console.log('utxoStatus: ', utxoStatus)
// console.log('utxoStatus: ', utxoStatus)
console.log(`Spent UTXO detected. Deleting this Order: ${JSON.stringify(thisOrder, null, 2)}`)
await thisOrder.remove()
}