diff --git a/.gitignore b/.gitignore index a3c198da..57d8d11b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,6 @@ package-lock.json .DS_Store yarn.lock -/local +/tests .idea diff --git a/functions/index.js b/functions/index.js index d5df1ca6..165ecc1d 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,18 +1,18 @@ const functions = require('firebase-functions'); const axios = require('axios').default; -const VOUCHER_KERNEL_ADDRESS = functions.config().poc1.voucherkerneladdress; -const CASHIER_ADDRESS = functions.config().poc1.cashieraddress; +const VOUCHER_KERNEL_ADDRESS = functions.config().scheduledkeepers.voucherkerneladdress; +const CASHIER_ADDRESS = functions.config().scheduledkeepers.cashieraddress; const VoucherKernel = require("./abis/VoucherKernel.json"); const Cashier = require("./abis/Cashier.json"); const ethers = require('ethers'); -const EXECUTOR_PRIVATE_KEY = functions.config().poc1.executorsecret; -const NETWORK_NAME = functions.config().poc1.networkname; -const ETHERSCAN_API_KEY = functions.config().poc1.etherscanapikey; -const INFURA_API_KEY = functions.config().poc1.infuraapikey; +const EXECUTOR_PRIVATE_KEY = functions.config().scheduledkeepers.executorsecret; +const NETWORK_NAME = functions.config().scheduledkeepers.networkname; +const ETHERSCAN_API_KEY = functions.config().scheduledkeepers.etherscanapikey; +const INFURA_API_KEY = functions.config().scheduledkeepers.infuraapikey; const provider = ethers.getDefaultProvider(NETWORK_NAME, { etherscan: ETHERSCAN_API_KEY, @@ -20,11 +20,11 @@ const provider = ethers.getDefaultProvider(NETWORK_NAME, { }); const executor = new ethers.Wallet(EXECUTOR_PRIVATE_KEY, provider); -const API_URL = functions.config().poc1.apiurl; -const ALL_VOUCHERS_URL = `${API_URL}/user-vouchers/all`; -const CHECK_PAYMENTS_BY_VOUCHER_URL = `${API_URL}/payments/check-payment`; -const FINALIZE_VOUCHER_URL = `${API_URL}/user-vouchers/finalize`; -const WITHDRAW_VOUCHER_URL = `${API_URL}/payments/create-payment`; +const API_URL = functions.config().scheduledkeepers.apiurl; +const ALL_VOUCHERS_URL = `${ API_URL }/user-vouchers/all`; +const CHECK_PAYMENTS_BY_VOUCHER_URL = `${ API_URL }/payments/check-payment`; +const FINALIZE_VOUCHER_URL = `${ API_URL }/user-vouchers/finalize`; +const WITHDRAW_VOUCHER_URL = `${ API_URL }/payments/create-payment`; const COMMIT_IDX = 7; // usingHelpers contract const GAS_LIMIT = '300000'; @@ -62,33 +62,16 @@ exports.scheduledKeepers = functions.https.onRequest(async (request, response) = response.send("Аll keepers were executed successfully!"); }); -exports.scheduledKeepersDev = functions.https.onRequest(async (request, response) => { - // Expiration process - await triggerExirations(); - - // Finalization process - await triggerFinalizations(); - - // Withdrawal process - await triggerWithdrawals(); - - response.send("Аll keepers were executed successfully!"); -}); - async function triggerExirations() { - let hasErrors = false; let voucherKernelContractExecutor = new ethers.Contract(VOUCHER_KERNEL_ADDRESS, VoucherKernel.abi, executor); let vouchers; try { vouchers = await axios.get(ALL_VOUCHERS_URL); } catch (e) { - hasErrors = true; - console.error(`Error while getting all vouchers from the DB. Error: ${e}`); + console.error(`Error while getting all vouchers from the DB. Error: ${ e }`); } - if (typeof vouchers === 'undefined' || !vouchers.hasOwnProperty('data')) return; - for (let i = 0; i < vouchers.data.vouchersDocuments.length; i++) { let voucher = vouchers.data.vouchersDocuments[i]; let voucherID = voucher._tokenIdVoucher; @@ -98,54 +81,46 @@ async function triggerExirations() { let voucherStatus = await voucherKernelContractExecutor.getVoucherStatus(voucherID); isStatusCommit = voucherStatus[0] == (0 | 1 << COMMIT_IDX); // condition is borrowed from helper contract } catch (e) { - hasErrors = true; - console.error(`Error while checking voucher status toward the contract. Error: ${e}`); + console.error(`Error while checking voucher status toward the contract. Error: ${ e }`); } if (!isStatusCommit || EXPIRATION_BLACKLISTED_VOUCHER_IDS.includes(voucherID)) { continue; } - console.log(`Voucher: ${voucherID} is with commit status. The expiration is triggered.`); + console.log(`Voucher: ${ voucherID } is with commit status. The expiration is triggered.`); try { let txOrder = await voucherKernelContractExecutor.triggerExpiration(voucherID); await txOrder.wait(); } catch (e) { - hasErrors = true; - console.error(`Error while triggering expiration of the voucher. Error: ${e}`); + console.error(`Error while triggering expiration of the voucher. Error: ${ e }`); } } - let infoMsg = hasErrors ? 'triggerExirations function finished with errors' : 'triggerExirations function finished successfully' - - console.info(infoMsg); + console.info(`triggerExirations function finished successfully`); } async function triggerFinalizations() { - let hasErrors = false; let voucherKernelContractExecutor = new ethers.Contract(VOUCHER_KERNEL_ADDRESS, VoucherKernel.abi, executor); let vouchers; try { vouchers = await axios.get(ALL_VOUCHERS_URL); } catch (e) { - console.error(`Error while getting all vouchers from the DB. Error: ${e}`); - return; + console.error(`Error while getting all vouchers from the DB. Error: ${ e }`); } - if (typeof vouchers === 'undefined' || !vouchers.hasOwnProperty('data')) return; - for (let i = 0; i < vouchers.data.vouchersDocuments.length; i++) { let voucher = vouchers.data.vouchersDocuments[i]; let voucherID = voucher._tokenIdVoucher; if (voucher.FINALIZED || FINALIZATION_BLACKLISTED_VOUCHER_IDS.includes(voucherID)) { - console.log(`Voucher: ${voucherID} is already finalized`); + console.log(`Voucher: ${ voucherID } is already finalized`); continue; } - console.log(`Voucher: ${voucherID}. The finalization has started.`); + console.log(`Voucher: ${ voucherID }. The finalization has started.`); let txOrder; let receipt; @@ -155,9 +130,7 @@ async function triggerFinalizations() { receipt = await txOrder.wait(); } catch (e) { - hasErrors = true; - console.error(`Error while triggering finalization of the voucher. Error: ${e}`); - continue; + console.error(`Error while triggering finalization of the voucher. Error: ${ e }`); } let parsedEvent = await findEventByName(receipt, 'LogFinalizeVoucher', '_tokenIdVoucher', '_triggeredBy'); @@ -168,28 +141,23 @@ async function triggerFinalizations() { status: "FINALIZED" }]; - console.log(`Voucher: ${voucherID}. The finalization finished.`); + console.log(`Voucher: ${ voucherID }. The finalization finished.`); try { await axios.patch(FINALIZE_VOUCHER_URL, payload); - console.log(`Voucher: ${voucherID}. Database updated.`); + console.log(`Voucher: ${ voucherID }. Database updated.`); } catch (e) { - hasErrors = true; console.log(e); - console.error(`Error while updating the DB related to finalization of the voucher. Error: ${e}`); - continue; + console.error(`Error while updating the DB related to finalization of the voucher. Error: ${ e }`); } } } - let infoMsg = hasErrors ? 'triggerFinalizations function finished with errors' : 'triggerFinalizations function finished successfully' - - console.info(infoMsg); + console.info(`triggerFinalizations function finished successfully`); } async function triggerWithdrawals() { - let hasErrors = false; let cashierContractExecutor = new ethers.Contract(CASHIER_ADDRESS, Cashier.abi, executor); let voucherKernelContractExecutor = new ethers.Contract(VOUCHER_KERNEL_ADDRESS, VoucherKernel.abi, executor); let vouchers; @@ -197,11 +165,9 @@ async function triggerWithdrawals() { try { vouchers = await axios.get(ALL_VOUCHERS_URL); } catch (e) { - console.error(`Error while getting all vouchers from the DB. Error: ${e}`); + console.error(`Error while getting all vouchers from the DB. Error: ${ e }`); } - if (typeof vouchers === 'undefined' || !vouchers.hasOwnProperty('data')) return; - for (let i = 0; i < vouchers.data.vouchersDocuments.length; i++) { let voucher = vouchers.data.vouchersDocuments[i]; let voucherID = voucher._tokenIdVoucher; @@ -212,17 +178,15 @@ async function triggerWithdrawals() { isPaymentAndDepositsReleased = voucherStatus[1] && voucherStatus[2]; } catch (e) { - hasErrors = true; - console.error(`Error while checking existing payments for a voucher from the DB. Error: ${e}`); - continue; + console.error(`Error while checking existing payments for a voucher from the DB. Error: ${ e }`); } if (isPaymentAndDepositsReleased || WITHDRAWAL_BLACKLISTED_VOUCHER_IDS.includes(voucherID)) { - console.log(`Voucher: ${voucherID} - a payment and deposits withdrawal completed `); + console.log(`Voucher: ${ voucherID } - a payment and deposits withdrawal completed `); continue; } - console.log(`Voucher: ${voucherID}. The withdraw process has started`); + console.log(`Voucher: ${ voucherID }. The withdraw process has started`); let txOrder; let receipt; @@ -231,37 +195,26 @@ async function triggerWithdrawals() { txOrder = await cashierContractExecutor.withdraw([voucherID], { gasLimit: GAS_LIMIT }); receipt = await txOrder.wait(); } catch (e) { - hasErrors = true; - console.error(`Error while executing withdraw process. Error: ${e}`); - continue; + console.error(`Error while executing withdraw process. Error: ${ e }`); } - console.log(`Voucher: ${voucherID}. The withdraw process finished`); + console.log(`Voucher: ${ voucherID }. The withdraw process finished`); let events = await findEventByName(receipt, 'LogWithdrawal', '_caller', '_payee', '_payment') try { - if (Array.isArray(events) - && typeof events[0] === 'object' - && events[0].hasOwnProperty('_tokenIdVoucher')) { - await sendPayments(events); - } + await sendPayments(events); } catch (e) { - hasErrors = true; - console.error(`Error while executing a create payment call to the backend . Error: ${e}`); + console.error(`Error while executing a create payment call to the backend . Error: ${ e }`); } - console.log(`Voucher: ${voucherID}. Database updated`); + console.log(`Voucher: ${ voucherID }. Database updated`); } - let infoMsg = hasErrors ? 'triggerWithdrawals function finished with errors' : 'triggerWithdrawals function finished successfully' - - console.info(infoMsg); + console.info(`triggerWithdrawals function finished successfully`); } async function findEventByName(txReceipt, eventName, ...eventFields) { - if (typeof txReceipt !== 'object' && txReceipt !== null) return - let eventsArr = []; for (const key in txReceipt.events) { diff --git a/src/api/controllers/admin-controller.js b/src/api/controllers/admin-controller.js index e18afca8..12eb3b65 100644 --- a/src/api/controllers/admin-controller.js +++ b/src/api/controllers/admin-controller.js @@ -24,19 +24,14 @@ class AdminController { return next(new ApiError(400, `Provided address: ${address} is not a valid ETH address!`)) } - try { - const user = await mongooseService.getUser(address) - - if (!user) { - return next(new ApiError(400, `Provided user does not exist in the DB!`)) - } - - await mongooseService.makeAdmin(address); + const user = await mongooseService.getUser(address) - } catch (error) { - return next(new ApiError(400, `Provided address: ${address} was not set as admin!`)) + if (!user) { + return next(new ApiError(400, `Provided user does not exist in the DB!`)) } + await mongooseService.makeAdmin(address); + res.status(200).send({updated: true}) } } diff --git a/src/api/controllers/payment-controller.js b/src/api/controllers/payment-controller.js index 92851600..c764de50 100644 --- a/src/api/controllers/payment-controller.js +++ b/src/api/controllers/payment-controller.js @@ -89,14 +89,7 @@ class PaymentController { static async getPaymentsByVoucherID(req, res, next) { const tokenIdVoucher = req.params.tokenIdVoucher; - let payments; - - try { - payments = await mongooseService.getPaymentsByVoucherID(tokenIdVoucher); - } catch (error) { - console.error(error) - return next(new APIError(400, `Get payment for voucher id: ${ tokenIdVoucher } could not be completed.`)) - } + const payments = await mongooseService.getPaymentsByVoucherID(tokenIdVoucher); res.status(200).send({ payments }) } diff --git a/src/api/controllers/user-vouchers-controller.js b/src/api/controllers/user-vouchers-controller.js index b14fdbb6..78b7766c 100644 --- a/src/api/controllers/user-vouchers-controller.js +++ b/src/api/controllers/user-vouchers-controller.js @@ -11,19 +11,14 @@ class UserVoucherController { const voucherData = [] const address = res.locals.address; - try { - const promises = [] - const userVouchersDocuments = await mongooseService.getMyVouchers(address) + const userVouchersDocuments = await mongooseService.getMyVouchers(address) - userVouchersDocuments.forEach(e => { - promises.push(mongooseService.getVouchersDetails(e, voucherData)) - }) + const promises = [] + userVouchersDocuments.forEach(e => { + promises.push(mongooseService.getVouchersDetails(e, voucherData)) + }) - await Promise.all(promises) - } catch (error) { - console.error(error.message); - return next(`Error processing User Vouchers for user: ${address}`); - } + await Promise.all(promises) res.status(200).send({ voucherData }) } @@ -36,7 +31,7 @@ class UserVoucherController { vouchers = await mongooseService.findAllUsersByVoucherID(voucherID, owner) } catch (error) { console.error(error.message); - return next(`Error fetching all buyers for Voucher: ${voucherID}`); + } res.status(200).send({vouchers}); } @@ -44,47 +39,39 @@ class UserVoucherController { static async getVoucherDetails(req, res, next) { const myVoucherID = req.params.voucherID - let voucher; - try { - const myVoucherDocument = await mongooseService.getMyVoucherByID(myVoucherID) - const voucherDetailsDocument = await mongooseService.getVoucher(myVoucherDocument.voucherID) - - voucher = { - _id: myVoucherDocument.id, - _tokenIdVoucher: myVoucherDocument._tokenIdVoucher, - _holder: myVoucherDocument._holder, - _tokenIdSupply: myVoucherDocument._tokenIdSupply, - buyerStatus: myVoucherDocument.status, - CANCELLED: myVoucherDocument.CANCELLED, - COMMITTED: myVoucherDocument.COMMITTED, - COMPLAINED: myVoucherDocument.COMPLAINED, - REDEEMED: myVoucherDocument.REDEEMED, - REFUNDED: myVoucherDocument.REFUNDED, - FINALIZED: myVoucherDocument.FINALIZED, - voucherID: voucherDetailsDocument.id, - voucherStatus: voucherUtils.calcVoucherStatus(voucherDetailsDocument.startDate, voucherDetailsDocument.expiryDate, voucherDetailsDocument.qty), - title: voucherDetailsDocument.title, - qty: voucherDetailsDocument.qty, - description: voucherDetailsDocument.description, - location: voucherDetailsDocument.location, - contact: voucherDetailsDocument.contact, - conditions: voucherDetailsDocument.conditions, - imagefiles: voucherDetailsDocument.imagefiles, - category: voucherDetailsDocument.category, - startDate: voucherDetailsDocument.startDate, - expiryDate: voucherDetailsDocument.expiryDate, - price: voucherDetailsDocument.price, - buyerDeposit: voucherDetailsDocument.buyerDeposit, - sellerDeposit: voucherDetailsDocument.sellerDeposit, - voucherOwner: voucherDetailsDocument.voucherOwner, - } - } catch (error) { - console.error(error.message); - return next(`Error fetching Voucher Details for voucher: ${ myVoucherID }`); + const myVoucherDocument = await mongooseService.getMyVoucherByID(myVoucherID) + const voucherDetailsDocument = await mongooseService.getVoucher(myVoucherDocument.voucherID) + + const voucher = { + _id: myVoucherDocument.id, + _tokenIdVoucher: myVoucherDocument._tokenIdVoucher, + _holder: myVoucherDocument._holder, + _tokenIdSupply: myVoucherDocument._tokenIdSupply, + buyerStatus: myVoucherDocument.status, + CANCELLED: myVoucherDocument.CANCELLED, + COMMITTED: myVoucherDocument.COMMITTED, + COMPLAINED: myVoucherDocument.COMPLAINED, + REDEEMED: myVoucherDocument.REDEEMED, + REFUNDED: myVoucherDocument.REFUNDED, + FINALIZED: myVoucherDocument.FINALIZED, + voucherID: voucherDetailsDocument.id, + voucherStatus: voucherUtils.calcVoucherStatus(voucherDetailsDocument.startDate, voucherDetailsDocument.expiryDate, voucherDetailsDocument.qty), + title: voucherDetailsDocument.title, + qty: voucherDetailsDocument.qty, + description: voucherDetailsDocument.description, + location: voucherDetailsDocument.location, + contact: voucherDetailsDocument.contact, + conditions: voucherDetailsDocument.conditions, + imagefiles: voucherDetailsDocument.imagefiles, + category: voucherDetailsDocument.category, + startDate: voucherDetailsDocument.startDate, + expiryDate: voucherDetailsDocument.expiryDate, + price: voucherDetailsDocument.price, + buyerDeposit: voucherDetailsDocument.buyerDeposit, + sellerDeposit: voucherDetailsDocument.sellerDeposit, + voucherOwner: voucherDetailsDocument.voucherOwner, } - - res.status(200).send({ voucher }) } @@ -117,14 +104,7 @@ class UserVoucherController { } static async getAllVouchers(req, res, next) { - let vouchersDocuments; - - try { - vouchersDocuments = await mongooseService.getAllVouchers(); - } catch (error) { - console.error(error) - return next(new APIError(400, `Error fetching all vouchers.`)) - } + const vouchersDocuments = await mongooseService.getAllVouchers(); res.status(200).send({ vouchersDocuments }) } diff --git a/src/api/controllers/users-controller.js b/src/api/controllers/users-controller.js index c36fa411..bad9faad 100644 --- a/src/api/controllers/users-controller.js +++ b/src/api/controllers/users-controller.js @@ -5,17 +5,18 @@ const APIError = require('../api-error') class UserController { + static async isUserRegistered(req, res, next) { + const address = req.params.address.toLowerCase() + const isRegistered = await mongooseService.isUserRegistered(address); + + res.status(200).json({ isRegistered }); + } + static async generateNonce(req, res, next) { - const address = req.params.address; - let randomNonce; - try { - randomNonce = nonceUtils.generateRandomNumber(); - await mongooseService.preserveNonce(address.toLowerCase(), randomNonce) - } catch (error) { - console.error(error) - return next(new APIError(400, `Could not preserve nonce for user: ${address}.`)) - } + const address = req.params.address; + const randomNonce = nonceUtils.generateRandomNumber(); + await mongooseService.preserveNonce(address.toLowerCase(), randomNonce) res.status(200).json( randomNonce @@ -24,17 +25,10 @@ class UserController { static async verifySignature(req, res, next) { const address = req.params.address - - try { - const nonce = await mongooseService.getNonce(address.toLowerCase()) + const nonce = await mongooseService.getNonce(address.toLowerCase()) - if (!await AuthValidator.isSignatureVerified(address, nonce, req.body.signature)) { - return next(new APIError(401, 'Unauthorized.')) - } - - } catch (error) { - console.error(error) - return next(new APIError(400, `Signature was not verified!`)) + if (!await AuthValidator.isSignatureVerified(address, nonce, req.body.signature)) { + return next(new APIError(401, 'Unauthorized.')) } const authToken = AuthValidator.generateAccessToken(address) @@ -44,6 +38,7 @@ class UserController { static async commitToBuy(req, res, next) { const voucherID = req.params.voucherID const metadata = req.body; + const buyer = res.locals.address let userVoucher; try { diff --git a/src/api/controllers/vouchers-controller.js b/src/api/controllers/vouchers-controller.js index fa2967c7..52c73159 100644 --- a/src/api/controllers/vouchers-controller.js +++ b/src/api/controllers/vouchers-controller.js @@ -22,7 +22,7 @@ class VouchersController { voucher.voucherStatus = voucherStatus } catch (error) { console.error(error) - return next(new APIError(400, `Could not get voucher with ID: ${req.params.id}`)); + return next(new APIError(400, `${error.message}`)); } res.status(200).send({ @@ -117,7 +117,7 @@ class VouchersController { await mongooseService.createVoucher(req.body, fileRefs, voucherOwner) } catch (error) { console.error(`An error occurred while user [${voucherOwner}] tried to create Voucher.`); - console.error(error.errors) + console.error(error) return next(new APIError(400, 'Invalid voucher model')); } @@ -168,7 +168,13 @@ class VouchersController { res.status(200).send({ success: true }); } - + + + static async buy(req, res, next) { + + await mongooseService.buy(); + res.status(200).send({ success: true }); + } } module.exports = VouchersController; \ No newline at end of file diff --git a/src/api/middlewares/voucher-validator.js b/src/api/middlewares/voucher-validator.js index 5fe8913f..c8e30f77 100644 --- a/src/api/middlewares/voucher-validator.js +++ b/src/api/middlewares/voucher-validator.js @@ -32,21 +32,6 @@ class VoucherValidator { next(); } - static async ValidateDates(req, res, next) { - const start = new Date(); - start.setHours(0,0,0,0); - const today = new Date(start).getTime() - const startDateToMillis = new Date(req.body.startDate).getTime() - const endDateToMillis = new Date(req.body.expiryDate).getTime() - - - if (startDateToMillis < today || endDateToMillis < startDateToMillis) { - return next(new APIError(400, 'Invalid Dates.')) - } - - next(); - } - } module.exports = VoucherValidator; \ No newline at end of file diff --git a/src/api/routes/users-route.js b/src/api/routes/users-route.js index 9aa3a19b..749991a1 100644 --- a/src/api/routes/users-route.js +++ b/src/api/routes/users-route.js @@ -8,6 +8,9 @@ class UsersRouter { static route(expressApp) { let router = expressApp.Router(); + router.get('/:address/is-registered', + ErrorHandlers.globalErrorHandler(usersController.isUserRegistered)); + router.post('/:address', ErrorHandlers.globalErrorHandler(usersController.generateNonce)); diff --git a/src/api/routes/vouchers-route.js b/src/api/routes/vouchers-route.js index 1544e6e1..bf9d0b2f 100644 --- a/src/api/routes/vouchers-route.js +++ b/src/api/routes/vouchers-route.js @@ -17,7 +17,6 @@ class VouchersRouter { router.post('/', ErrorHandlers.globalErrorHandler(authenticationMiddleware.authenticateToken), ErrorHandlers.globalErrorHandler(upload.array('fileToUpload', FILE_LIMIT)), - ErrorHandlers.globalErrorHandler(voucherValidator.ValidateDates), ErrorHandlers.globalErrorHandler(vouchersController.createVoucher)); router.get('/:id', diff --git a/src/database/User/user.js b/src/database/User/user.js index 359e7342..f539afef 100644 --- a/src/database/User/user.js +++ b/src/database/User/user.js @@ -4,6 +4,11 @@ const userRoles = require('./user-roles'); class UserService { + static async isUserRegistered(address) { + let user = await User.findOne({ address }) + return user ? true : false; + } + static async getNonce(address) { let user = await User.findOne({ address }) return user.nonce; diff --git a/src/database/UserVoucher/userVoucher.js b/src/database/UserVoucher/userVoucher.js index 3cfa919d..1145d6a5 100644 --- a/src/database/UserVoucher/userVoucher.js +++ b/src/database/UserVoucher/userVoucher.js @@ -22,7 +22,7 @@ class UserVoucherService { actionDate: new Date().getTime() }, { new: true, upsert: true } - ) + ) } static async getMyVouchers(userAddress) { diff --git a/src/database/index.js b/src/database/index.js index b1ba8560..450c4aa7 100644 --- a/src/database/index.js +++ b/src/database/index.js @@ -6,6 +6,7 @@ const Payment = require('./Payment/payment') const MongooseService = { getNonce: User.getNonce, preserveNonce: User.preserveNonce, + isUserRegistered: User.isUserRegistered, getUser: User.getUser, makeAdmin: User.setUserToAdmin, getVoucher: Voucher.getVoucher,