Compare commits

...
19 Commits
Author SHA1 Message Date
Chris Troutner 0ed4a03314 Merge pull request #19 from Permissionless-Software-Foundation/ct-unstable
Ct unstable
2022-04-30 19:34:42 -07:00
Chris Troutner 5eb8464469 fix(README): Adding link to setup video 2022-04-30 16:49:30 -07:00
Chris Troutner d1dc4dd198 Updating README 2022-04-15 06:42:20 -07:00
Chris Troutner 1ba3633fac Updating README 2022-04-15 06:37:06 -07:00
Chris Troutner 69dd2c2627 Updating README 2022-04-15 06:35:19 -07:00
Chris Troutner 0a838b7fd7 Adding install force 2022-04-14 17:11:54 -07:00
Chris Troutner de9ede9859 fix(ui): Adding new UI to RPi docker 2022-04-12 15:40:22 -07:00
Chris Troutner 8273ae29d0 Switching UI to bch-dex-ui2 2022-04-12 13:24:51 -07:00
Chris Troutner 4d733f0995 Merge pull request #18 from Permissionless-Software-Foundation/ct-unstable
Better Offer UX
2022-04-01 20:39:22 -07:00
Chris Troutner f812580169 fix(production): Added sweep-wallet.js 2022-04-01 20:20:16 -07:00
Chris Troutner ec8dc91d36 feat(offers): Deleting offers older than 7 days 2022-04-01 20:10:38 -07:00
Chris Troutner 03214fd7df feat(offer): Deleting Offer model after broadcasting Counter Offer. 2022-04-01 19:50:33 -07:00
Chris Troutner 9aae6da4a7 feat(offer/list): Returning Offers sorted by newest first 2022-04-01 19:05:31 -07:00
Chris Troutner 6e7ab40dea Merge pull request #17 from Permissionless-Software-Foundation/ct-unstable
fix(webhook): Fixing default webhook URL
2022-03-31 18:51:04 -07:00
Chris Troutner 3b45e3c2c4 fix(domain): Detecting domain for working with back-end 2022-03-31 18:48:05 -07:00
Chris Troutner 756002dd8c fix(webhook): Fixing default webhook URL 2022-03-31 18:04:13 -07:00
Chris Troutner 86da41b6c8 Making instruction steps a numbered list 2022-03-29 11:07:44 -07:00
Chris Troutner c2838b6117 Updating install step 2022-03-29 11:03:11 -07:00
Chris Troutner af33de3f9a Adding links to videos 2022-03-29 09:27:29 -07:00
13 changed files with 2710 additions and 333 deletions
+34 -22
View File
@@ -2,12 +2,20 @@
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Join the chat at https://gitter.im/Permissionless-Software-Foundation/psf-dex-dev](https://badges.gitter.im/Permissionless-Software-Foundation/psf-dex-dev.svg)](https://gitter.im/Permissionless-Software-Foundation/psf-dex-dev?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
`bch-dex` is a decentralized exchange for permissionless trading of [SLP tokens](https://github.com/simpleledger/slp-specifications/blob/master/slp-token-type-1.md) and [NFTs](https://github.com/simpleledger/slp-specifications/blob/master/slp-nft-1.md). Trading fees are incredibly small, compared to other DEX platforms. The software is based entirely on open protocols and open source software. It's not a '.com' website that you visit, but software you run on your own computer, in the confort of your own home. So long as you have an internet connection and the technical knowledge to run this software, no one can stop you from trading tokens. `bch-dex` software is maintained by the [Permissionless Software Foundation](https://psfoundation.cash/).
- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video)
This is a prototype web service that monitors the [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service) for trading signals, to trade BCH and SLP tokens. It's inspired by the [SWaP Protocol](https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md).
This repository contains the back end code. The user interface is contained in the [bch-dex-ui](https://github.com/Permissionless-Software-Foundation/bch-dex-ui) repository.
**Warning**: This repository is under active development. Things will be constantly changing and breaking.
## Media
- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video)
- [Developer walk-through for installing and hacking on bch-dex](https://youtu.be/T5XI43-SWJo) (Video)
## Participate
This is an open source project, and we encourage other JavaScript developers to participate in its creation and maintenance. We have two chat rooms for the community:
- [Telegram Channel](https://t.me/psf_dex_dev)
@@ -26,32 +34,36 @@ The above software is orchestrated using [Docker](https://www.docker.com/) and D
Instructions for setting up Node.js, Docker, and Docker Compose can be found in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd). Walk-through videos can also be found on the [PSF Videos page](https://psfoundation.cash/video/).
Building the Docker containers and getting the app working involve these steps:
- Follow the direction in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd) to install Node.js, Docker, and Docker Compose.
- Clone the repository with `git clone https://github.com/Permissionless-Software-Foundation/bch-dex` and enter it with `cd bch-dex`.
- Install dependencies by running `npm install`
- Create a wallet by executing the [create-wallet.js script](./production/scripts/create-wallet.js) with `node create-wallet.js`
- Move the `wallet.json` file to the [x86 Docker folder](./production/docker/bch-dex) or the [RPi Docker folder](./production/rpi-docker/bch-dex/) depending on your hardware target.
- Change directory to the `docker` or `rpi-docker` folder depending on your hardware target.
- Build the Docker containers with `docker-compose build --no-cache`.
- Start the Docker containers with `docker-compose up -d`
- Wait for the containers to run for about a minute, then bring them down with `docker-compose down`. That will create the needed folders in `production/data`.
- Copy the `swarm.key` into the `production/data/go-ipfs/data/` directory. This will allow the IPFS node to connect to the PSF private network.
- Bring the containers back up with `docker-compose up -d`.
- Wait for the P2WDB to sync and populate bch-dex with trade data. You can monitor it with `docker logs --tail 20 -f p2wdb`.
- Open a web browser and navigate the `http://localhost:4500`. You'll be able to see new Offers as they come in and are detected by bch-dex.
- To take the other side of the trade, click the `Take` button in the UI.
- You can add the 12-word mnemonic from the `wallet.json` file to the the web wallet, which will mirror your wallet in the UI, and allow you to perform basic wallet functions (send and receive BCH and tokens).
1. Follow the direction in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd) to install Node.js, Docker, and Docker Compose.
1. Clone the repository with `git clone https://github.com/Permissionless-Software-Foundation/bch-dex` and enter it with `cd bch-dex`.
1. Install dependencies by running `npm install`
1. Create a wallet by executing the [create-wallet.js script](./production/scripts/create-wallet.js) with `node create-wallet.js`
1. Move the `wallet.json` file to the `bch-dex` folder in either the [x86 Docker folder](./production/docker/bch-dex) or the [RPi Docker folder](./production/rpi-docker/bch-dex/) depending on your hardware target.
1. Change directory to the `docker` or `rpi-docker` folder depending on your hardware target.
1. Build the Docker containers with `docker-compose build --no-cache`.
1. Start the Docker containers with `docker-compose up -d`
1. Wait for the containers to run for about a minute, then bring them down with `docker-compose down`. That will create the needed folders in `production/data`.
1. Copy the `swarm.key` into the `production/data/go-ipfs/data/` directory. This will allow the IPFS node to connect to the PSF private network.
1. Bring the containers back up with `docker-compose up -d`.
1. Wait for the P2WDB to sync and populate bch-dex with trade data. You can monitor it with `docker logs --tail 20 -f p2wdb`.
1. Open a web browser and navigate the `http://localhost:4500`. You'll be able to see new Offers as they come in and are detected by bch-dex.
1. To take the other side of the trade, click the `Take` button in the UI.
1. You can add the 12-word mnemonic from the `wallet.json` file to the the web wallet, which will mirror your wallet in the UI, and allow you to perform basic wallet functions (send and receive BCH and tokens).
### Applying Software Updates
As this is an active project, software updates will happen frequently. To apply a software update, perform these steps.
- Enter the `docker` or `rpi-docker` folder, depending on your hardware target.
- Bring down the Docker containers with `docker-compose down`.
- Pull in the software updates with `git pull`
- Update dependencies with `npm install`
- Rebuild the Docker containers with `docker-compose build --no-cache`
- Clean up disk space by deleting old Docker images with `./cleanup-images.sh`
- Start the Docker containers with `docker-compose up -d`
<ol>
<li>Enter the `docker` or `rpi-docker` folder, depending on your hardware target.</li>
<li>Bring down the Docker containers with `docker-compose down`.</li>
<li>Pull in the software updates with `git pull`</li>
<li>Update dependencies with `npm install`</li>
<li>Rebuild the Docker containers with `docker-compose build --no-cache`</li>
<li>Clean up disk space by deleting old Docker images with `./cleanup-images.sh`</li>
<li>Start the Docker containers with `docker-compose up -d`</li>
</ol>
Sometimes it may be necessary to delete the databases before applying a software update. This can be done by stopping the Docker containers and deleting the `production/data` directory. When the Docker containers are restarted, they will recreate that directory. The P2WDB will re-sync and bch-dex will be populated with fresh trade data.
+1 -1
View File
@@ -88,7 +88,7 @@ module.exports = {
p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-test557',
webhookTarget: process.env.WEBHOOKTARGET
? process.env.WEBHOOKTARGET
: 'http://localhost:5700/offer',
: 'http://localhost:5700/p2wdb',
// IPFS Ports
ipfsTcpPort: process.env.IPFS_TCP_PORT ? process.env.IPFS_TCP_PORT : 4001,
+2550 -291
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -27,9 +27,9 @@
},
"repository": "Permissionless-Software-Foundation/bch-dex",
"dependencies": {
"@psf/bch-js": "6.2.1",
"@psf/bch-js": "6.2.5",
"axios": "0.21.1",
"bch-message-lib": "2.1.4",
"bch-message-lib": "2.2.0",
"bcryptjs": "2.4.3",
"bitcoincashjs-lib": "3.3.3",
"glob": "7.1.6",
@@ -52,7 +52,7 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "^0.36.2",
"line-reader": "0.4.0",
"minimal-slp-wallet": "4.4.5",
"minimal-slp-wallet": "4.4.7",
"mongoose": "5.13.13",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.4.17",
+4 -4
View File
@@ -46,11 +46,11 @@ RUN npm set registry http://94.130.170.209:4873/
# Clone the rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui2
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/bch-dex-ui
WORKDIR /home/safeuser/bch-dex-ui2
# For development: switch to unstable branch
RUN git checkout ct-unstable
@@ -58,7 +58,7 @@ RUN git checkout ct-unstable
# Install dependencies
#RUN mkdir .ipfsdata
#RUN npm install -g @mapbox/node-pre-gyp
RUN npm install
RUN npm install --force
# Build the site
RUN CI=true npm run build
@@ -68,6 +68,6 @@ FROM nginx
EXPOSE 80
# Copy the files built in the first container to the new NGINX container.
COPY --from=builder /home/safeuser/bch-dex-ui/public /usr/share/nginx/html
COPY --from=builder /home/safeuser/bch-dex-ui2/public /usr/share/nginx/html
#USER safeuser
+2
View File
@@ -89,6 +89,8 @@ services:
context: ./bch-dex-ui/
dockerfile: Dockerfile
container_name: dex-ui
environment:
SERVER: 'http://192.168.2.3'
logging:
driver: 'json-file'
options:
+3 -3
View File
@@ -46,11 +46,11 @@ RUN npm set registry http://94.130.170.209:4873/
# Clone the rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui2
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/bch-dex-ui
WORKDIR /home/safeuser/bch-dex-ui2
# For development: switch to unstable branch
RUN git checkout ct-unstable
@@ -68,6 +68,6 @@ FROM nginx
EXPOSE 80
# Copy the files built in the first container to the new NGINX container.
COPY --from=builder /home/safeuser/bch-dex-ui/public /usr/share/nginx/html
COPY --from=builder /home/safeuser/bch-dex-ui2/public /usr/share/nginx/html
#USER safeuser
+3 -3
View File
@@ -8,8 +8,8 @@
const axios = require('axios')
// const LOCALHOST = 'http://localhost:5700'
const LOCALHOST = 'http://172.17.0.1:5700'
const LOCALHOST = 'http://localhost:5700'
// const LOCALHOST = 'http://172.17.0.1:5700'
async function start () {
try {
@@ -22,7 +22,7 @@ async function start () {
buyOrSell: 'sell',
rateInBaseUnit: 5000,
minUnitsToExchange: 5000,
numTokens: 1
numTokens: 2
}
const options = {
+82
View File
@@ -0,0 +1,82 @@
/*
This script will travers the HD wallet and sweep funds and tokens back
into the root address (index 0). That root address needs to have funds
to pay for the transactions.
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
const BchTokenSweep = require('bch-token-sweep/index')
// Local libraries
const WalletAdapter = require('../../src/adapters/wallet')
// Constants
const EMTPY_ADDR_CUTOFF = 10
async function sweepFunds () {
try {
// Open the wallet files.
const wallet = new WalletAdapter()
const walletInfo = await wallet.openWallet()
console.log('walletInfo: ', walletInfo)
const rootAddr = walletInfo.cashAddress
const rootWif = walletInfo.privateKey
console.log(`Sweeping all funds into root address ${rootAddr}...`)
// Generate an HD tree
const bchjs = new BCHJS()
const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic)
const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
let emptyAddrCnt = 0
let hdIndex = 1
do {
// Generate a keypair from the HD wallet.
const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`)
const cashAddress = bchjs.HDNode.toCashAddress(childNode)
const wifToSweep = bchjs.HDNode.toWIF(childNode)
console.log(`\nSweeping ${cashAddress}`)
try {
// Sweep tokens from address
const sweeper = new BchTokenSweep(
wifToSweep,
rootWif,
bchjs,
550,
rootAddr
)
await sweeper.populateObjectFromNetwork()
const hex = await sweeper.sweepTo(rootAddr)
// console.log(`hex: ${hex}`)
const txid = await sweeper.blockchain.broadcast(hex)
// console.log('Transaction ID', txid)
console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`)
emptyAddrCnt = 0
// Wait between loop iterations.
await bchjs.Util.sleep(3000)
} catch (err) {
console.log(`error message with index ${hdIndex}: ${err.message}`)
emptyAddrCnt++
}
hdIndex++
} while (emptyAddrCnt < EMTPY_ADDR_CUTOFF)
console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`)
console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n')
} catch (err) {
console.error('Error in sweepFunds(): ', err)
}
}
sweepFunds()
+2 -1
View File
@@ -23,7 +23,8 @@ const Offer = new mongoose.Schema({
sigMsg: { type: String },
// Utility data
timestamp: { type: String },
timestamp: { type: Number },
globalTimestamp: { type: String },
localTimestamp: { type: String },
// SWaP Protocol Properties
+2 -1
View File
@@ -49,7 +49,8 @@ class Wlogger {
}
notifyRotation (oldFilename, newFilename) {
this.wlogger.info('Rotating log files')
// this.wlogger.info('Rotating log files')
console.log('Rotating log files')
}
outputToConsole () {
+6 -1
View File
@@ -70,6 +70,10 @@ class OfferEntity {
throw new Error("Property 'ticker' must be a string.")
}
// Convert the timestamp to a number.
let timestamp = new Date(offerData.timestamp)
timestamp = timestamp.getTime()
const validatedOfferData = {
messageType,
messageClass,
@@ -80,7 +84,8 @@ class OfferEntity {
numTokens,
utxoTxid,
utxoVout,
timestamp: offerData.timestamp,
timestamp,
globaltimestamp: offerData.timestamp,
localTimestamp: offerData.localTimeStamp,
txid: offerData.txid,
p2wdbHash: offerData.hash,
+18 -3
View File
@@ -93,7 +93,7 @@ class OfferUseCases {
async listOffers () {
try {
return this.OfferModel.find({})
return this.OfferModel.find({}).sort('-timestamp')
} catch (error) {
console.error('Error in use-cases/offer/listOffers()')
throw error
@@ -188,6 +188,10 @@ class OfferUseCases {
}
const hash = await this.adapters.p2wdb.write(p2wdbObj)
// Delete the Offer from the database, so that the user doesn't attempt
// to take the offer more than once.
offerInfo.remove()
// Return the P2WDB CID
return hash
@@ -261,10 +265,12 @@ class OfferUseCases {
throw new Error('offer not found')
}
const offerObject = offer.toObject()
return offer
// const offerObject = offer.toObject()
// return this.offerEntity.validateFromModel(offerObject)
return offerObject
// return offerObject
// } catch (err) {
// // console.error('Error in findOffer(): ', err)
// throw err
@@ -367,6 +373,15 @@ class OfferUseCases {
console.log(`Spent UTXO detected. Deleting this Offer: ${JSON.stringify(thisOffer, null, 2)}`)
await thisOffer.remove()
}
// If the Offer is older than 7 days, delete it.
const nowMs = now.getTime()
const sevenDays = 1000 * 60 * 60 * 24 * 7
const sevenDaysAgo = nowMs - sevenDays
if (thisOffer.timestamp < sevenDaysAgo) {
console.log('Offer older than 7 days. Deleting.')
await thisOffer.remove()
}
}
} catch (err) {
console.error('Error in removeStaleOffers()')