From 80f95ee5766a2b5f6da7bb58901f2fe21e9c031e Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Wed, 5 Mar 2025 20:26:31 -0800 Subject: [PATCH] Got counteroffer to post to Nostr --- package-lock.json | 97 +++++++++++++++++++ package.json | 3 +- src/App.js | 8 +- .../app-body/nfts-for-sale/buy-button.js | 25 ++++- .../app-body/nfts-for-sale/token-card.js | 2 +- src/services/async-load.js | 26 ++++- src/services/nostr.js | 15 ++- 7 files changed, 163 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 55bd396..e301207 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,8 @@ "bch-nostr": "1.3.4", "bootstrap": "5.2.0", "crypto-browserify": "3.12.1", + "nostr-tools": "2.10.4", + "p2wdb": "2.4.1", "process": "0.11.10", "qrcode.react": "4.2.0", "query-string": "7.1.1", @@ -13174,6 +13176,31 @@ "ws": "^8.8.1" } }, + "node_modules/nostr-tools": { + "version": "2.10.4", + "resolved": "http://94.130.170.209:4873/nostr-tools/-/nostr-tools-2.10.4.tgz", + "integrity": "sha512-biU7sk+jxHgVASfobg2T5ttxOGGSt69wEVBC51sHHOEaKAAdzHBLV/I2l9Rf61UzClhliZwNouYhqIso4a3HYg==", + "license": "Unlicense", + "dependencies": { + "@noble/ciphers": "^0.5.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.1", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.1", + "@scure/bip39": "1.2.1" + }, + "optionalDependencies": { + "nostr-wasm": "0.1.0" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/nostr-wasm": { "version": "0.1.0", "license": "MIT", @@ -13519,6 +13546,76 @@ "node": ">=6" } }, + "node_modules/p2wdb": { + "version": "2.4.1", + "resolved": "http://94.130.170.209:4873/p2wdb/-/p2wdb-2.4.1.tgz", + "integrity": "sha512-f4YPl3atOD8BfonSQxasfYaDL/pJ64WJ3rB+BONDARRUfGJZdZ6tE6vp47Xo7nMJ+gKQLNYObLGWBfPMw6SoQg==", + "license": "MIT", + "dependencies": { + "@chris.troutner/retry-queue-commonjs": "1.0.8", + "apidoc": "0.52.0", + "axios": "0.24.0" + } + }, + "node_modules/p2wdb/node_modules/apidoc": { + "version": "0.52.0", + "resolved": "http://94.130.170.209:4873/apidoc/-/apidoc-0.52.0.tgz", + "integrity": "sha512-k0gaMI7LWxaqKt2D+twC6XpI8X5SHkJalfo8TmF72d2TSNABquqB8LyIrVYzLcadcHuLMRFDaDibOK271gD67w==", + "license": "MIT", + "os": [ + "darwin", + "freebsd", + "linux", + "openbsd", + "win32" + ], + "dependencies": { + "bootstrap": "3.4.1", + "commander": "^8.3.0", + "diff-match-patch": "^1.0.5", + "esbuild-loader": "^2.16.0", + "expose-loader": "^3.1.0", + "fs-extra": "^10.0.0", + "glob": "^7.2.0", + "handlebars": "^4.7.7", + "iconv-lite": "^0.6.3", + "jquery": "^3.6.0", + "klaw-sync": "^6.0.0", + "lodash": "^4.17.21", + "markdown-it": "^12.2.0", + "nodemon": "^2.0.15", + "prismjs": "^1.25.0", + "semver": "^7.3.5", + "style-loader": "^3.3.1", + "webpack": "^5.64.2", + "webpack-cli": "^4.9.1", + "winston": "^3.3.3" + }, + "bin": { + "apidoc": "bin/apidoc" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/p2wdb/node_modules/axios": { + "version": "0.24.0", + "resolved": "http://94.130.170.209:4873/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, + "node_modules/p2wdb/node_modules/bootstrap": { + "version": "3.4.1", + "resolved": "http://94.130.170.209:4873/bootstrap/-/bootstrap-3.4.1.tgz", + "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "license": "BlueOak-1.0.0" diff --git a/package.json b/package.json index caf61d9..7bb7934 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "bch-dex-taker-v2", "version": "1.0.0", "dependencies": { - "@chris.troutner/nostr-tools": "2.10.4", "@chris.troutner/react-jdenticon": "1.0.1", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-regular-svg-icons": "6.7.2", @@ -14,6 +13,8 @@ "bch-nostr": "1.3.4", "bootstrap": "5.2.0", "crypto-browserify": "3.12.1", + "nostr-tools": "2.10.4", + "p2wdb": "2.4.1", "process": "0.11.10", "qrcode.react": "4.2.0", "query-string": "7.1.1", diff --git a/src/App.js b/src/App.js index fea2703..49a0139 100644 --- a/src/App.js +++ b/src/App.js @@ -71,14 +71,18 @@ function App (props) { addToModal('Getting BCH spot price in USD', appData) await asyncLoad.getUSDExchangeRate(walletTemp, appData.updateBchWalletState, appData) + // Load the P2WDB libraries. + addToModal('Loading P2WDB Libraries', appData) + const {p2wdbRead, p2wdbWrite} = asyncLoad.getP2WDBLib({bchWallet: walletTemp}) + // Load the DEX library. addToModal('Loading DEX Library', appData) - const dexLib = await asyncLoad.getDexLib({bchWallet: walletTemp}) + const dexLib = asyncLoad.getDexLib({bchWallet: walletTemp, p2wdbRead, p2wdbWrite}) appData.setDexLib(dexLib) // Load the Nostr library. addToModal('Loading Nostr Library', appData) - const nostrLib = await asyncLoad.getNostrLib({bchWallet: walletTemp}) + const nostrLib = asyncLoad.getNostrLib({bchWallet: walletTemp}) appData.setNostr(nostrLib) // Update state diff --git a/src/components/app-body/nfts-for-sale/buy-button.js b/src/components/app-body/nfts-for-sale/buy-button.js index 31a94e3..2b3c8b1 100644 --- a/src/components/app-body/nfts-for-sale/buy-button.js +++ b/src/components/app-body/nfts-for-sale/buy-button.js @@ -8,10 +8,33 @@ import React, { useState } from 'react' import { Button, Modal, Container, Row, Col } from 'react-bootstrap' function BuyButton (props) { + const { token, appData } = props + const [show, setShow] = useState(false) - const handleBuy = () => { + const handleBuy = async () => { console.log('handleBuy()') + console.log('token: ', token) + console.log('appData: ', appData) + + const targetOffer = token.nostrEventId + console.log('targetOffer: ', targetOffer) + + // TODO: Launch modal to let user know that the purchase is in progress. + + // Generate a counter offer. + const bchDexLib = appData.dexLib + const { offerData, partialHex } = await bchDexLib.take.takeOffer(targetOffer) + + console.log('offerData: ', offerData) + console.log('partialHex: ', partialHex) + + // Upload the counter offer to Nostr. + const nostr = appData.nostr + const { eventId, noteId } = await nostr.testNostrUpload({ offerData, partialHex }) + + console.log(`Counter Offer uploaded to Nostr with this event ID: ${eventId}`) + console.log(`https://astral.psfoundation.info/${noteId}`) } const handleClose = () => { diff --git a/src/components/app-body/nfts-for-sale/token-card.js b/src/components/app-body/nfts-for-sale/token-card.js index 1d7e7b6..a1ea09b 100644 --- a/src/components/app-body/nfts-for-sale/token-card.js +++ b/src/components/app-body/nfts-for-sale/token-card.js @@ -72,7 +72,7 @@ function TokenCard (props) { - + diff --git a/src/services/async-load.js b/src/services/async-load.js index ae48ac2..f8c321f 100644 --- a/src/services/async-load.js +++ b/src/services/async-load.js @@ -9,6 +9,7 @@ import BchDexLib from 'bch-dex-lib' // Local libraries import GistServers from './gist-servers' import Nostr from './nostr' +import P2WDB from 'p2wdb' class AsyncLoad { constructor () { @@ -200,11 +201,11 @@ class AsyncLoad { } // Load the BchDexLib library. - async getDexLib (inObj = {}) { + getDexLib (inObj = {}) { try { - const { bchWallet } = inObj + const { bchWallet, p2wdbRead, p2wdbWrite } = inObj - const dexLib = new BchDexLib({bchWallet, p2wdbRead: {}, p2wdbWrite: {}}) + const dexLib = new BchDexLib({bchWallet, p2wdbRead, p2wdbWrite}) return dexLib } catch (error) { @@ -214,7 +215,7 @@ class AsyncLoad { } // Load the Nostr library. - async getNostrLib (inObj = {}) { + getNostrLib (inObj = {}) { try { const { bchWallet } = inObj @@ -226,8 +227,25 @@ class AsyncLoad { throw error } } + + // Load the P2WDB library. + getP2WDBLib (inObj = {}) { + try { + const { bchWallet } = inObj + + const p2wdbRead = new P2WDB.Read() + const p2wdbWrite = new P2WDB.Write({bchWallet}) + + return {p2wdbRead, p2wdbWrite} + } catch (error) { + console.error('Error in getP2WDBLib', error) + throw error + } + } } + + function sleep (ms) { return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/src/services/nostr.js b/src/services/nostr.js index d2443e7..ed44763 100644 --- a/src/services/nostr.js +++ b/src/services/nostr.js @@ -4,10 +4,15 @@ */ // Global npm libraries -import { finalizeEvent } from '@chris.troutner/nostr-tools/pure' -import { Relay } from '@chris.troutner/nostr-tools/relay' +// import { finalizeEvent } from '@chris.troutner/nostr-tools/pure' +// import { Relay } from '@chris.troutner/nostr-tools/relay' +// import BchNostr from 'bch-nostr' +// import * as nip19 from '@chris.troutner/nostr-tools/nip19' + +import { finalizeEvent } from 'nostr-tools/pure' +import { Relay } from 'nostr-tools/relay' import BchNostr from 'bch-nostr' -import * as nip19 from '@chris.troutner/nostr-tools/nip19' +import * as nip19 from 'nostr-tools/nip19' class NostrBrowser { constructor (localConfig = {}) { @@ -77,7 +82,9 @@ class NostrBrowser { const eventId = signedEvent.id // Connect to a relay. - const relay = await Relay.connect(relayWs) + const relay = await Relay.connect(relayWs, { + webSocket: WebSocket + }) // console.log(`connected to ${relay.url}`) // Publish the message to the relay.