Compare commits

...
8 Commits
12 changed files with 373 additions and 87 deletions
+273 -66
View File
@@ -34,7 +34,7 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "^0.36.2",
"line-reader": "0.4.0",
"minimal-slp-wallet": "../minimal-slp-wallet/",
"minimal-slp-wallet": "5.2.1",
"mongoose": "5.13.14",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.7.5",
@@ -58,36 +58,6 @@
"uuid": "8.3.2"
}
},
"../minimal-slp-wallet": {
"version": "5.0.0",
"license": "MIT",
"dependencies": {
"@psf/bch-js": "6.4.5",
"apidoc": "0.51.0",
"bch-consumer": "1.3.1",
"bch-donation": "1.1.2",
"crypto-js": "4.0.0"
},
"devDependencies": {
"browserify": "17.0.0",
"chai": "4.2.0",
"coveralls": "3.1.0",
"eslint": "7.17.0",
"eslint-config-prettier": "7.1.0",
"eslint-config-standard": "16.0.2",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-standard": "4.0.1",
"husky": "4.3.8",
"lodash.clonedeep": "4.5.0",
"mocha": "9.2.1",
"nyc": "15.1.0",
"semantic-release": "19.0.3",
"sinon": "9.2.0",
"standard": "16.0.4",
"tinyify": "3.0.0"
}
},
"node_modules/@babel/code-frame": {
"version": "7.18.6",
"dev": true,
@@ -2083,9 +2053,87 @@
"node": ">=4.5.0"
}
},
"node_modules/bch-consumer": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bch-consumer/-/bch-consumer-1.3.1.tgz",
"integrity": "sha512-8ZoyFp4pLJFAOzM482K22sVL2FpuxhkYRtZuLLsMH9L442mRABjsAP7fTh91W5er40r8RGN/CSKi2TMyUmrY1Q==",
"dependencies": {
"@psf/bch-js": "6.4.5",
"apidoc": "0.51.0",
"axios": "0.25.0"
}
},
"node_modules/bch-consumer/node_modules/apidoc": {
"version": "0.51.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.51.0.tgz",
"integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==",
"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",
"path-to-regexp": "^6.2.0",
"prismjs": "^1.25.0",
"semver": "^7.3.5",
"style-loader": "^3.3.1",
"url-parse": "^1.5.3",
"webpack": "^5.64.2",
"webpack-cli": "^4.9.1",
"winston": "^3.3.3"
},
"bin": {
"apidoc": "bin/apidoc"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/bch-consumer/node_modules/axios": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"dependencies": {
"follow-redirects": "^1.14.7"
}
},
"node_modules/bch-consumer/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/bch-donation": {
"version": "1.1.2",
"dev": true,
"license": "MIT",
"dependencies": {
"apidoc": "0.51.0"
@@ -2093,7 +2141,6 @@
},
"node_modules/bch-donation/node_modules/apidoc": {
"version": "0.51.0",
"dev": true,
"license": "MIT",
"os": [
"darwin",
@@ -2135,7 +2182,6 @@
},
"node_modules/bch-donation/node_modules/glob": {
"version": "7.2.3",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
@@ -3381,6 +3427,11 @@
"node": ">=0.8.0"
}
},
"node_modules/crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
"integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
},
"node_modules/crypto-random-string": {
"version": "2.0.0",
"license": "MIT",
@@ -7968,8 +8019,77 @@
}
},
"node_modules/minimal-slp-wallet": {
"resolved": "../minimal-slp-wallet",
"link": true
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/minimal-slp-wallet/-/minimal-slp-wallet-5.2.1.tgz",
"integrity": "sha512-1m71QxFlSdrfk01BOF0tQCgyTp8SCvvZST8bBOMZTz+iPwerDTbpPk4p3Niv12socT7QIaSf8odSVdFDjyqB8w==",
"dependencies": {
"@psf/bch-js": "6.4.5",
"apidoc": "0.51.0",
"bch-consumer": "1.3.1",
"bch-donation": "1.1.2",
"crypto-js": "4.0.0"
}
},
"node_modules/minimal-slp-wallet/node_modules/apidoc": {
"version": "0.51.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.51.0.tgz",
"integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==",
"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",
"path-to-regexp": "^6.2.0",
"prismjs": "^1.25.0",
"semver": "^7.3.5",
"style-loader": "^3.3.1",
"url-parse": "^1.5.3",
"webpack": "^5.64.2",
"webpack-cli": "^4.9.1",
"winston": "^3.3.3"
},
"bin": {
"apidoc": "bin/apidoc"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/minimal-slp-wallet/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
@@ -12213,7 +12333,6 @@
},
"node_modules/querystringify": {
"version": "2.2.0",
"dev": true,
"license": "MIT"
},
"node_modules/queue-microtask": {
@@ -12701,7 +12820,6 @@
},
"node_modules/requires-port": {
"version": "1.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/resolve": {
@@ -14968,7 +15086,6 @@
},
"node_modules/url-parse": {
"version": "1.5.10",
"dev": true,
"license": "MIT",
"dependencies": {
"querystringify": "^2.1.1",
@@ -16973,16 +17090,76 @@
"resolved": "https://registry.npmjs.org/bc-bip68/-/bc-bip68-1.0.5.tgz",
"integrity": "sha512-GzaMlN7pNthrY5BhReVhnfr4Ixx+GUSfyNRHYh0QiMUF0d0+0YaD8MpEdv6AjFBksg/zlqL1fVCBBm6PpTt2Rg=="
},
"bch-consumer": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bch-consumer/-/bch-consumer-1.3.1.tgz",
"integrity": "sha512-8ZoyFp4pLJFAOzM482K22sVL2FpuxhkYRtZuLLsMH9L442mRABjsAP7fTh91W5er40r8RGN/CSKi2TMyUmrY1Q==",
"requires": {
"@psf/bch-js": "6.4.5",
"apidoc": "0.51.0",
"axios": "0.25.0"
},
"dependencies": {
"apidoc": {
"version": "0.51.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.51.0.tgz",
"integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==",
"requires": {
"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",
"path-to-regexp": "^6.2.0",
"prismjs": "^1.25.0",
"semver": "^7.3.5",
"style-loader": "^3.3.1",
"url-parse": "^1.5.3",
"webpack": "^5.64.2",
"webpack-cli": "^4.9.1",
"winston": "^3.3.3"
}
},
"axios": {
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"requires": {
"follow-redirects": "^1.14.7"
}
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"bch-donation": {
"version": "1.1.2",
"dev": true,
"requires": {
"apidoc": "0.51.0"
},
"dependencies": {
"apidoc": {
"version": "0.51.0",
"dev": true,
"requires": {
"bootstrap": "3.4.1",
"commander": "^8.3.0",
@@ -17010,7 +17187,6 @@
},
"glob": {
"version": "7.2.3",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -17845,6 +18021,11 @@
"boom": "0.4.x"
}
},
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
"integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg=="
},
"crypto-random-string": {
"version": "2.0.0"
},
@@ -20880,30 +21061,59 @@
"dev": true
},
"minimal-slp-wallet": {
"version": "file:../minimal-slp-wallet",
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/minimal-slp-wallet/-/minimal-slp-wallet-5.2.1.tgz",
"integrity": "sha512-1m71QxFlSdrfk01BOF0tQCgyTp8SCvvZST8bBOMZTz+iPwerDTbpPk4p3Niv12socT7QIaSf8odSVdFDjyqB8w==",
"requires": {
"@psf/bch-js": "6.4.5",
"apidoc": "0.51.0",
"bch-consumer": "1.3.1",
"bch-donation": "1.1.2",
"browserify": "17.0.0",
"chai": "4.2.0",
"coveralls": "3.1.0",
"crypto-js": "4.0.0",
"eslint": "7.17.0",
"eslint-config-prettier": "7.1.0",
"eslint-config-standard": "16.0.2",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-standard": "4.0.1",
"husky": "4.3.8",
"lodash.clonedeep": "4.5.0",
"mocha": "9.2.1",
"nyc": "15.1.0",
"semantic-release": "19.0.3",
"sinon": "9.2.0",
"standard": "16.0.4",
"tinyify": "3.0.0"
"crypto-js": "4.0.0"
},
"dependencies": {
"apidoc": {
"version": "0.51.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.51.0.tgz",
"integrity": "sha512-3P4srhm6NA+kE/YRM4qL5jESElpQQJL+Z8n7hyr4uC+1DSwGzmE6adXPVxuT/hpDyShrqmRlHk8hf40RSqEsNw==",
"requires": {
"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",
"path-to-regexp": "^6.2.0",
"prismjs": "^1.25.0",
"semver": "^7.3.5",
"style-loader": "^3.3.1",
"url-parse": "^1.5.3",
"webpack": "^5.64.2",
"webpack-cli": "^4.9.1",
"winston": "^3.3.3"
}
},
"glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"minimalistic-assert": {
@@ -23726,8 +23936,7 @@
}
},
"querystringify": {
"version": "2.2.0",
"dev": true
"version": "2.2.0"
},
"queue-microtask": {
"version": "1.2.3",
@@ -24042,8 +24251,7 @@
"peer": true
},
"requires-port": {
"version": "1.0.0",
"dev": true
"version": "1.0.0"
},
"resolve": {
"version": "1.22.1",
@@ -25497,7 +25705,6 @@
},
"url-parse": {
"version": "1.5.10",
"dev": true,
"requires": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
+1 -1
View File
@@ -53,7 +53,7 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "^0.36.2",
"line-reader": "0.4.0",
"minimal-slp-wallet": "../minimal-slp-wallet/",
"minimal-slp-wallet": "5.2.1",
"mongoose": "5.13.14",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.7.5",
+1 -1
View File
@@ -43,7 +43,7 @@ services:
#build:
# context: ./p2wdb/
# dockerfile: Dockerfile
image: christroutner/p2wdb-rpi:v3.1.8
image: christroutner/p2wdb-rpi:v3.1.9
container_name: p2wdb
environment:
CONSUMER_URL: 'https://wa-usa-bch-consumer.fullstackcash.nl'
+1 -1
View File
@@ -359,7 +359,7 @@ class WalletAdapter {
}
// Update the UTXO store of the wallet.
await this.bchWallet.getUtxos()
await this.bchWallet.initialize()
// Get the token type of the token being moved.
// Combine Fungible and NFT token UTXOs.
+11
View File
@@ -33,6 +33,7 @@ class TimerControllers {
startTimers () {
setInterval(this.gcOrders, 60000 * 5)
setInterval(this.gcOffers, 60000 * 5)
setInterval(this.checkDupOffers, 60000 * 4.5)
}
// Garbage Collect the Orders.
@@ -54,6 +55,16 @@ class TimerControllers {
console.log('Error in timer-controllers.js/gcOffers(): ', err)
}
}
// Remove duplicate Offers
checkDupOffers () {
try {
_this.useCases.offer.removeDuplicateOffers()
} catch (err) {
// Do not throw an error. This is a top-level function.
console.log('Error in timer-controllers.js/checkDupOffers(): ', err)
}
}
}
export default TimerControllers
+39
View File
@@ -512,6 +512,45 @@ class OfferUseCases {
}
}
// TODO: Write unit tests for this function, then add it to the Timer Controllers
// Looks for duplicate offers and removes the duplicate.
// Duplicates are checked for when an offer is created, and so should not
// exist. But emperical testing shows that they do. This function is called
// periodically by a timer, to clean up any duplicates that slipped through
// the cracks.
async removeDuplicateOffers () {
try {
const now = new Date()
console.log(`Starting removeDuplicateOffers() at ${now.toLocaleString()}`)
let duplicateFound = false
// Get all Offers in the database.
const offers = await this.OfferModel.find({})
// console.log('offers: ', offers)
const offerZcids = []
for (let i = 0; i < offers.length; i++) {
const thisOffer = offers[i]
if (offerZcids.includes(thisOffer.p2wdbHash)) {
await thisOffer.remove()
duplicateFound = true
continue
}
// Add the zcid to the array.
offerZcids.push(thisOffer.p2wdbHash)
}
return duplicateFound
} catch (err) {
console.error('Error in removeDuplicateOffers()')
throw err
}
}
// This function is called by the garbage collection timer controller. It
// checks the UTXO associated with each Offer in the database. If the UTXO
// has been spent, the Offer is deleted from the database.
@@ -160,4 +160,35 @@ describe('#offer-use-case', () => {
assert.equal(result, 'fungible')
})
})
describe('#removeDuplicateOffers', () => {
it('should remove duplicate entries and return true', async () => {
// Mock dependencies and force desired code path.
sandbox.stub(uut.OfferModel, 'find').resolves([
{ p2wdbHash: 'a', remove: async () => {} },
{ p2wdbHash: 'a', remove: async () => {} },
{ p2wdbHash: 'b', remove: async () => {} }
])
// sandbox.stub(uut.OfferModel, 'remove').resolves()
const result = await uut.removeDuplicateOffers()
console.log('result: ', result)
assert.equal(result, true)
})
it('should return false if there are no duplicate entries', async () => {
// Mock dependencies and force desired code path.
sandbox.stub(uut.OfferModel, 'find').resolves([
{ p2wdbHash: 'a', remove: async () => {} },
{ p2wdbHash: 'b', remove: async () => {} }
])
// sandbox.stub(uut.OfferModel, 'remove').resolves()
const result = await uut.removeDuplicateOffers()
console.log('result: ', result)
assert.equal(result, false)
})
})
})
+3 -3
View File
@@ -2,15 +2,15 @@
This script has not been customized for offers yet.
*/
const mongoose = require('mongoose')
import mongoose from 'mongoose'
// Force test environment
// make sure environment variable is set before this file gets called.
// see test script in package.json.
// process.env.KOA_ENV = 'test'
const config = require('../../config')
import config from '../../config'
const User = require('../../src/models/users')
import User from '../../src/models/users'
async function deleteUsers () {
// Connect to the Mongo Database.
+3 -4
View File
@@ -2,11 +2,10 @@
Get all Offers in the database.
*/
const mongoose = require('mongoose')
import mongoose from 'mongoose'
const config = require('../../config')
const Offer = require('../../src/adapters/localdb/models/offer')
import config from '../../config/index.js'
import Offer from '../../src/adapters/localdb/models/offer.js'
async function getOffers () {
// Connect to the Mongo Database.
+3 -3
View File
@@ -1,12 +1,12 @@
const mongoose = require('mongoose')
import mongoose from 'mongoose'
// Force test environment
// make sure environment variable is set before this file gets called.
// see test script in package.json.
// process.env.KOA_ENV = 'test'
const config = require('../../config')
import config from '../../config'
const User = require('../../src/models/users')
import User from '../../src/models/users'
async function deleteUsers () {
// Connect to the Mongo Database.
+3 -5
View File
@@ -1,8 +1,6 @@
const mongoose = require('mongoose')
const config = require('../../config')
const Order = require('../../src/adapters/localdb/models/order')
import mongoose from 'mongoose'
import config from '../../config'
import Order from '../../src/adapters/localdb/models/order'
async function getOrder () {
// Connect to the Mongo Database.
+4 -3
View File
@@ -7,11 +7,12 @@
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
const BchTokenSweep = require('bch-token-sweep/index')
import BCHJS from '@psf/bch-js'
import BchTokenSweep from 'bch-token-sweep/index'
// Local libraries
const WalletAdapter = require('../../src/adapters/wallet')
import WalletAdapter from '../../src/adapters/wallet'
// Constants
const EMTPY_ADDR_CUTOFF = 15