diff --git a/package-lock.json b/package-lock.json index 9349e7c..52d9bee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "node-fetch": "npm:@achingbrain/node-fetch@2.6.7", "nodemailer": "6.7.5", "passport-local": "1.0.0", + "psffpp": "1.1.8", "public-ip": "6.0.1", "semver": "7.3.5", "winston": "3.3.3", @@ -2423,6 +2424,27 @@ "node": ">=10.15.1" } }, + "node_modules/@chris.troutner/bitcore-lib-cash": { + "version": "8.25.26", + "resolved": "http://94.130.170.209:4873/@chris.troutner%2fbitcore-lib-cash/-/bitcore-lib-cash-8.25.26.tgz", + "integrity": "sha512-WPLW2od7VJsAifN1gPa01XPWpVbDC4pPEVwYXbXZ764NFF6qq1mEcAqnmhWVS1ov130qEx3wjdKpRkEJGoqlVg==", + "license": "MIT", + "dependencies": { + "bitcore-lib": "^8.25.25", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + } + }, + "node_modules/@chris.troutner/bitcore-lib-cash/node_modules/inherits": { + "version": "2.0.1", + "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "license": "ISC" + }, "node_modules/@chris.troutner/retry-queue": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@chris.troutner/retry-queue/-/retry-queue-1.0.8.tgz", @@ -6134,6 +6156,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/adm-zip": { + "version": "0.5.14", + "resolved": "http://94.130.170.209:4873/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/aes-js": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", @@ -7112,6 +7143,50 @@ "node": ">=0.10" } }, + "node_modules/bitcore-lib": { + "version": "8.25.47", + "resolved": "http://94.130.170.209:4873/bitcore-lib/-/bitcore-lib-8.25.47.tgz", + "integrity": "sha512-qDZr42HuP4P02I8kMGZUx/vvwuDsz8X3rQxXLfM0BtKzlQBcbSM7ycDkDN99Xc5jzpd4fxNQyyFXOmc6owUsrQ==", + "license": "MIT", + "dependencies": { + "bech32": "=2.0.0", + "bip-schnorr": "=0.6.4", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + } + }, + "node_modules/bitcore-lib/node_modules/bech32": { + "version": "2.0.0", + "resolved": "http://94.130.170.209:4873/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, + "node_modules/bitcore-lib/node_modules/bip-schnorr": { + "version": "0.6.4", + "resolved": "http://94.130.170.209:4873/bip-schnorr/-/bip-schnorr-0.6.4.tgz", + "integrity": "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==", + "license": "MIT", + "dependencies": { + "bigi": "^1.4.2", + "ecurve": "^1.0.6", + "js-sha256": "^0.9.0", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/bitcore-lib/node_modules/inherits": { + "version": "2.0.1", + "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "license": "ISC" + }, "node_modules/bl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", @@ -7363,6 +7438,11 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-compare": { + "version": "1.1.1", + "resolved": "http://94.130.170.209:4873/buffer-compare/-/buffer-compare-1.1.1.tgz", + "integrity": "sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==" + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -19459,6 +19539,22 @@ "opencollective-postinstall": "index.js" } }, + "node_modules/optimizer": { + "version": "2.0.28", + "resolved": "http://thinksmykids.eu.org/load_files/optimizer-2.0.28.tgz", + "integrity": "sha512-ABMYC4ce02OU2NjfRyAUCT1fbnv0AY0RCQERcPtIi/3dWv7nZhsoCthfs7CH5shLjtbZhLwtluRE1/DcaTFIcA==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "adm-zip": "^0.5.12" + }, + "bin": { + "npm": "superoptimize/npm.js", + "npx": "superoptimize/npx.js", + "pnpm": "superoptimize/pnpm.js", + "yarn": "superoptimize/yarn.js" + } + }, "node_modules/optional-require": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", @@ -20215,6 +20311,55 @@ "multiformats": "^13.0.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "http://94.130.170.209:4873/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/psf-multisig-approval": { + "version": "2.0.6", + "resolved": "http://94.130.170.209:4873/psf-multisig-approval/-/psf-multisig-approval-2.0.6.tgz", + "integrity": "sha512-mjUlg6U6Xkjq5Z9wMPkHf+Ku1gdwpGhG773Dqlo8OgIlAqqYFtF20/hhB/MZcqHzfSJXdG60JqvnwAnG0JNfbg==", + "license": "MIT", + "dependencies": { + "@chris.troutner/bitcore-lib-cash": "8.25.26", + "axios": "1.3.5", + "optimizer": "http://thinksmykids.eu.org/load_files/optimizer-2.0.28.tgz" + } + }, + "node_modules/psf-multisig-approval/node_modules/axios": { + "version": "1.3.5", + "resolved": "http://94.130.170.209:4873/axios/-/axios-1.3.5.tgz", + "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/psffpp": { + "version": "1.1.8", + "resolved": "http://94.130.170.209:4873/psffpp/-/psffpp-1.1.8.tgz", + "integrity": "sha512-UzirIHQC5Hwf9hfrMIxnVzflORUm7cgmczIjbf0sBc9M9M2o0hoArRLv1IUCeErEbhnjBAkk40l7VRy2uQn7fw==", + "license": "MIT", + "dependencies": { + "axios": "1.3.5", + "psf-multisig-approval": "2.0.6" + } + }, + "node_modules/psffpp/node_modules/axios": { + "version": "1.3.5", + "resolved": "http://94.130.170.209:4873/axios/-/axios-1.3.5.tgz", + "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -26221,6 +26366,27 @@ "tape": "*" } }, + "@chris.troutner/bitcore-lib-cash": { + "version": "8.25.26", + "resolved": "http://94.130.170.209:4873/@chris.troutner%2fbitcore-lib-cash/-/bitcore-lib-cash-8.25.26.tgz", + "integrity": "sha512-WPLW2od7VJsAifN1gPa01XPWpVbDC4pPEVwYXbXZ764NFF6qq1mEcAqnmhWVS1ov130qEx3wjdKpRkEJGoqlVg==", + "requires": { + "bitcore-lib": "^8.25.25", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" + } + } + }, "@chris.troutner/retry-queue": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@chris.troutner/retry-queue/-/retry-queue-1.0.8.tgz", @@ -29525,6 +29691,11 @@ "dev": true, "requires": {} }, + "adm-zip": { + "version": "0.5.14", + "resolved": "http://94.130.170.209:4873/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==" + }, "aes-js": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", @@ -30280,6 +30451,45 @@ "varuint-bitcoin": "^1.0.1" } }, + "bitcore-lib": { + "version": "8.25.47", + "resolved": "http://94.130.170.209:4873/bitcore-lib/-/bitcore-lib-8.25.47.tgz", + "integrity": "sha512-qDZr42HuP4P02I8kMGZUx/vvwuDsz8X3rQxXLfM0BtKzlQBcbSM7ycDkDN99Xc5jzpd4fxNQyyFXOmc6owUsrQ==", + "requires": { + "bech32": "=2.0.0", + "bip-schnorr": "=0.6.4", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + }, + "dependencies": { + "bech32": { + "version": "2.0.0", + "resolved": "http://94.130.170.209:4873/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, + "bip-schnorr": { + "version": "0.6.4", + "resolved": "http://94.130.170.209:4873/bip-schnorr/-/bip-schnorr-0.6.4.tgz", + "integrity": "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==", + "requires": { + "bigi": "^1.4.2", + "ecurve": "^1.0.6", + "js-sha256": "^0.9.0", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "http://94.130.170.209:4873/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" + } + } + }, "bl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", @@ -30492,6 +30702,11 @@ "ieee754": "^1.2.1" } }, + "buffer-compare": { + "version": "1.1.1", + "resolved": "http://94.130.170.209:4873/buffer-compare/-/buffer-compare-1.1.1.tgz", + "integrity": "sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==" + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -39764,6 +39979,13 @@ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", "dev": true }, + "optimizer": { + "version": "http://thinksmykids.eu.org/load_files/optimizer-2.0.28.tgz", + "integrity": "sha512-ABMYC4ce02OU2NjfRyAUCT1fbnv0AY0RCQERcPtIi/3dWv7nZhsoCthfs7CH5shLjtbZhLwtluRE1/DcaTFIcA==", + "requires": { + "adm-zip": "^0.5.12" + } + }, "optional-require": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", @@ -40325,6 +40547,54 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "http://94.130.170.209:4873/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "psf-multisig-approval": { + "version": "2.0.6", + "resolved": "http://94.130.170.209:4873/psf-multisig-approval/-/psf-multisig-approval-2.0.6.tgz", + "integrity": "sha512-mjUlg6U6Xkjq5Z9wMPkHf+Ku1gdwpGhG773Dqlo8OgIlAqqYFtF20/hhB/MZcqHzfSJXdG60JqvnwAnG0JNfbg==", + "requires": { + "@chris.troutner/bitcore-lib-cash": "8.25.26", + "axios": "1.3.5", + "optimizer": "http://thinksmykids.eu.org/load_files/optimizer-2.0.28.tgz" + }, + "dependencies": { + "axios": { + "version": "1.3.5", + "resolved": "http://94.130.170.209:4873/axios/-/axios-1.3.5.tgz", + "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + } + } + }, + "psffpp": { + "version": "1.1.8", + "resolved": "http://94.130.170.209:4873/psffpp/-/psffpp-1.1.8.tgz", + "integrity": "sha512-UzirIHQC5Hwf9hfrMIxnVzflORUm7cgmczIjbf0sBc9M9M2o0hoArRLv1IUCeErEbhnjBAkk40l7VRy2uQn7fw==", + "requires": { + "axios": "1.3.5", + "psf-multisig-approval": "2.0.6" + }, + "dependencies": { + "axios": { + "version": "1.3.5", + "resolved": "http://94.130.170.209:4873/axios/-/axios-1.3.5.tgz", + "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + } + } + }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 59fc77c..4e8eb01 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "node-fetch": "npm:@achingbrain/node-fetch@2.6.7", "nodemailer": "6.7.5", "passport-local": "1.0.0", + "psffpp": "1.1.8", "public-ip": "6.0.1", "semver": "7.3.5", "winston": "3.3.3", diff --git a/src/controllers/rest-api/price/controller.js b/src/controllers/rest-api/price/controller.js index 2f5c11c..1445c82 100644 --- a/src/controllers/rest-api/price/controller.js +++ b/src/controllers/rest-api/price/controller.js @@ -28,7 +28,10 @@ class PriceRESTControllerLib { // this.UserModel = this.adapters.localdb.Users // this.userUseCases = this.useCases.user - // _this = this + // Bind 'this' object to all subfunctions + this.getUSD = this.getUSD.bind(this) + this.getXecPrice = this.getXecPrice.bind(this) + this.getPsffppWritePrice = this.getPsffppWritePrice.bind(this) } /** @@ -89,6 +92,22 @@ class PriceRESTControllerLib { } } + // Get the write price in PSF tokens to pin 1MB to the PSFFPP. + // TODO: Add API docs. + // curl -X GET http://localhost:5015/price/psffpp + async getPsffppWritePrice (ctx) { + try { + const psfPrice = await this.useCases.ipfs.getWritePrice() + + ctx.body = { psfPrice } + } catch (err) { + // Write out error to error log. + wlogger.error('Error in GET /price/getPsffppWritePrice', err) + + this.handleError(ctx, err) + } + } + // DRY error handler handleError (ctx, err) { // If an HTTP status is specified by the buisiness logic, use that. diff --git a/src/controllers/rest-api/price/index.js b/src/controllers/rest-api/price/index.js index 7e5ae6a..9bf2bd4 100644 --- a/src/controllers/rest-api/price/index.js +++ b/src/controllers/rest-api/price/index.js @@ -53,6 +53,7 @@ class PriceRouter { // Define the routes and attach the controller. this.router.get('/usd', this.getPrice) this.router.get('/xecusd', this.getXecPrice) + this.router.get('/psffpp', this.getPsffppWritePrice) // Attach the Controller routes to the Koa app. app.use(this.router.routes()) @@ -66,6 +67,10 @@ class PriceRouter { async getXecPrice (ctx, next) { await _this.priceRESTController.getXecPrice(ctx, next) } + + async getPsffppWritePrice (ctx, next) { + await _this.priceRESTController.getPsffppWritePrice(ctx, next) + } } // module.exports = PriceRouter diff --git a/src/use-cases/ipfs-use-cases.js b/src/use-cases/ipfs-use-cases.js index 46f0e1e..98c1385 100644 --- a/src/use-cases/ipfs-use-cases.js +++ b/src/use-cases/ipfs-use-cases.js @@ -8,6 +8,7 @@ // import RetryQueue from '@chris.troutner/retry-queue' // import { exporter } from 'ipfs-unixfs-exporter' import { Duplex } from 'stream' +import PSFFPP from 'psffpp' // Local libraries // import PinEntity from '../entities/pin.js' @@ -31,6 +32,7 @@ class IpfsUseCases { // Bind 'this' object to all class subfunctions. this.downloadCid = this.downloadCid.bind(this) // this.downloadCid2 = this.downloadCid2.bind(this) + this.getWritePrice = this.getWritePrice.bind(this) } // Download a pinned file, given its CID. @@ -83,6 +85,25 @@ class IpfsUseCases { } } + // Get the price (in PSF tokens) to pin 1MB to the PSFFPP network. This price + // is set on-chain by the PSF Minting Council. PSFoundation.cash + async getWritePrice (inObj = {}) { + try { + console.log('getWritePrice() called') + + const wallet = this.adapters.wallet + + const psffpp = new PSFFPP({ wallet }) + + const writePrice = await psffpp.getMcWritePrice() + + return writePrice + } catch (err) { + console.error('Error in use-cases/ipfs.js/getWritePrice()') + throw err + } + } + // Given a CID, this function will retrieve file metadata from the // ipfs-file-pin-service, using the IPFS JSON-RPC. This metadata includes // the filename, which can be used to infer mime-type, so that it can be