Skip to content

Instantly share code, notes, and snippets.

@dumebi
Last active January 19, 2020 12:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dumebi/291bda845eda79866723d225af66bc86 to your computer and use it in GitHub Desktop.
Save dumebi/291bda845eda79866723d225af66bc86 to your computer and use it in GitHub Desktop.
Functions for a Token Exchange
const HttpStatus = require('http-status-codes');
const TokenModel = require('../models/token');
const UserModel = require('../models/user');
const UserTokenModel = require('../models/user-token');
const OHLVCModel = require('../models/ohlvc');
const TransactionModel = require('../models/transaction');
const {
paramsNotValid, generateTransactionReference, handleError, handleSuccess
} = require('../utils/utils');
const {
createToken,
getTokenBalance,
getToken,
getTokenContract,
getBuyOrderBook,
getSellOrderBook,
sellToken,
buyToken,
cancelOrder,
transferToken
} = require('../libraries/blockchainLib.js');
const publisher = require('../utils/rabbitmq');
const TokenController = {
/**
* Initialize token
* @description initialize a token
* @return {object} token
*/
async init(req, res) {
try {
const token = await TokenModel.findOne({ $or: [{ name: req.body.name }, { symbol: req.body.symbol }] });
if (token) {
return handleError(res, HttpStatus.BAD_REQUEST, 'Token already exists', null)
}
const reference = generateTransactionReference(7)
const newtoken = {
symbol: `${req.body.symbol}`,
id: reference,
name: `${req.body.name}`,
supply: parseInt(req.body.supply, 10),
rate: parseInt(req.body.rate, 10),
currency: 'BA',
creator: req.jwtUser.address
}
const result = await createToken(newtoken);
console.log('user address: %o', req.jwtUser.address)
if (!result.tx) return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'Error creating token in blockchain', null)
// Get token contract
const address = await getTokenContract(req.body.symbol);
console.log(address)
let mongoToken = new TokenModel({
reference,
name: req.body.name,
image: req.body.image,
symbol: req.body.symbol,
price: Number(req.body.rate),
supply: Number(req.body.supply),
contract: address,
creator: req.jwtUser._id,
})
mongoToken = await mongoToken.save();
mongoToken = await mongoToken.populate('creator').execPopulate()
await Promise.all([
TokenController.updateTokenTransactionDetails(req, mongoToken),
TransactionModel.create({
user: req.jwtUser._id,
token: token._id,
type: TransactionModel.Type.CREATE,
status: TransactionModel.Status.COMPLETED
})
])
return handleSuccess(res, HttpStatus.OK, mongoToken, 'Token created successfully');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured creating token, please contact an administrator', error)
}
},
/**
* OHLVC
* @description get OHLVC details of a token
* @return {object} token
*/
async ohlvc(req, res) {
try {
const ohlvc = await OHLVCModel.find({ token: req.params.id });
return handleSuccess(res, HttpStatus.OK, ohlvc, 'ohlvc details gotten successfully');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting OHLVC, please contact an administrator', error)
}
},
/**
* Get token
* @description Get a token on the BA platform
* @return {object} token
*/
async one(req, res) {
try {
const token = await TokenModel.findById(req.params.id, { min: 0, max: 0 });
if (token) {
return handleSuccess(res, HttpStatus.OK, token, 'Token gotten successfully');
}
return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* Get token by symbol
* @description Get a token on the BA platform
* @return {object} token
*/
async token_by_symbol(req, res) {
try {
// console.log('The sent symbol: ', `${req.params.symbol}`);
const token = await getToken(req.params.symbol);
if (token) {
return handleSuccess(res, HttpStatus.OK, token, 'Token gotten successfully');
}
return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* Get token balance by symbol
* @description Get user token balance on the BA platform
* @return {object} token
*/
async token_balance(req, res) {
try {
const balance = await getTokenBalance(req.params.symbol, req.jwtUser.address);
return handleSuccess(res, HttpStatus.OK, balance, 'Token gotten successfully');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* Get tokens
* @description Get all tokens on the BA platform
* @return {Array(Object)} tokens
*/
async all(req, res) {
try {
const tokens = await TokenModel.find().populate('creator');
if (tokens) {
return handleSuccess(res, HttpStatus.OK, tokens, 'tokens gotten successfully');
}
return res.status(HttpStatus.NOT_FOUND).json({ status: 'success', message: 'Token has not been initialized' });
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* Get tokens
* @description Get all tokens on the BA platform
* @return {Array(Object)} tokens
*/
async top(req, res) {
try {
const tokens = await TokenModel.find({}).sort({ vol: -1, price: -1 });
if (tokens) {
return handleSuccess(res, HttpStatus.OK, tokens, 'tokens gotten successfully');
}
return res.status(HttpStatus.NOT_FOUND).json({ status: 'success', message: 'Token has not been initialized' });
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* Get user tokens
* @description Get user tokens on the BA platform
* @return {Array(Object)} tokens
*/
async user(req, res) {
try {
const user_tokens = await TokenModel.find({ creator: req.jwtUser._id }).populate('token').populate('creator');
let balances = user_tokens.map(user_token => getTokenBalance(user_token.symbol, req.jwtUser.address))
balances = Promise.all(balances)
user_tokens.balances = balances
return handleSuccess(res, HttpStatus.OK, user_tokens, 'User tokens gotten successfully')
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token, please contact an administrator', error)
}
},
/**
* ORDER BOOK - BID ORDERS
* @description Get Buy Order book for token
* @return {object} buy book
*/
async buyOrderBook(req, res) {
try {
const token = await TokenModel.findById(req.params.id);
// console.log('This is the token', token);
if (token) {
const buybook = await getBuyOrderBook(token.symbol);
console.log('This is the orderbook', buybook);
console.log('This is the type of', token.symbol);
return handleSuccess(res, HttpStatus.OK, buybook, 'Token buy book gotten successfully');
}
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token buy-book, please contact an administrator', error)
}
},
/**
* ORDER BOOK - ASK ORDERS
* @description Get Sell Order book for token
* @return {object} sell book
*/
async sellOrderBook(req, res) {
try {
const token = await TokenModel.findById(req.params.id);
if (token) {
const sellbook = await getSellOrderBook(token.symbol)
return handleSuccess(res, HttpStatus.OK, sellbook, 'Token sell book gotten successfully');
}
return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting token sell-book, please contact an administrator', error)
}
},
/**
* Buy Token
* @description Buy a token
* @param {string} token Token ID
*/
async buy(req, res) {
try {
const user = req.jwtUser
const token = await TokenModel.findById(req.params.id);
if (!token) return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
const price = Number(req.body.price);
const amount = Number(req.body.amount);
const bought = await buyToken(token.symbol, price, amount, user.address);
await Promise.all([
TokenController.updateTokenTransactionDetails(req, token),
TokenModel.findByIdAndUpdate(token._id, {
price, vol: token.vol + amount, high: Math.max(token.high, price), min: Math.min(token.low, price)
}, { new: true }),
TransactionModel.create({
user: req.jwtUser._id,
token: token._id,
type: TransactionModel.Type.BUY,
status: TransactionModel.Status.PENDING
})
]);
return handleSuccess(res, HttpStatus.OK, bought, 'Your buy order has been processed');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured processing your buy order, please contact an administrator', error)
}
},
/**
* Sell Token
* @description Sell a token
* @param {string} token Token ID
*/
async sell(req, res) {
try {
const user = req.jwtUser
const token = await TokenModel.findById(req.params.id);
if (!token) return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
const price = Number(req.body.price);
const amount = Number(req.body.amount);
console.log(price, amount)
const sold = await sellToken(token.symbol, price, amount, user.address);
console.log(sold.logs)
await Promise.all([
TokenController.updateTokenTransactionDetails(req, token),
TokenModel.findByIdAndUpdate(token._id, {
price, vol: token.vol + amount, high: Math.max(token.high, price), min: Math.min(token.low, price)
}, { new: true }),
TransactionModel.create({
user: req.jwtUser._id,
token: token._id,
type: TransactionModel.Type.SELL,
status: TransactionModel.Status.PENDING
})
]);
return handleSuccess(res, HttpStatus.OK, sold, 'Your sell order has been processed');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured processing your sell order, please contact an administrator', error)
}
},
/**
* Cancel Offer
* @description Cancel a buy or sell offer
* @param {string} id Offer ID
*/
async cancel(req, res) {
try {
const user = req.jwtUser
const token = await TokenModel.findById(req.params.id);
if (!token) return handleError(res, HttpStatus.NOT_FOUND, 'Token not found', null)
const price = req.body.price;
const key = req.body.key;
const type = req.body.type === 'sell'
const canceled = await cancelOrder(token.symbol, type, price, key, user.address);
console.log('canceled: o%', canceled)
return handleSuccess(res, HttpStatus.OK, null, 'Your cancel order is being processed');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured processing your sell order, please contact an administrator', error)
}
},
/**
* User Transactions
* @description Get all transactions made by a user on the platform
* @param {string} id Token ID
*/
async user_transactions(req, res) {
try {
const pageQuery = parseInt(req.query.page, 10) || 1;
const options = {
page: pageQuery,
populate: ['user', 'token', 'wallet'],
sort: '-createdAt',
limit: req.query.limit || 20,
collation: {
locale: 'en'
}
};
const transactions = await TransactionModel.paginate({ user: req.jwtUser._id }, options);
const data = {
page: transactions.page,
pages: transactions.totalPages,
count: transactions.totalDocs,
transactions: transactions.docs
};
// const transactions = await TransactionModel.find({ user: req.jwtUser._id }).populate('token').populate('wallet').sort('-createdAt');
return handleSuccess(res, HttpStatus.OK, data, 'User transactions gotten successfully');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting user transactions, please contact an administrator', error)
}
},
/**
* All Transactions
* @description Get all transactions made on the platform
*/
async transactions(req, res) {
try {
const pageQuery = parseInt(req.query.page, 10) || 1;
const options = {
page: pageQuery,
populate: ['user', 'token', 'wallet'],
sort: '-createdAt',
limit: req.query.limit || 20,
collation: {
locale: 'en'
}
};
const transactions = await TransactionModel.paginate({}, options);
const data = {
page: transactions.page,
pages: transactions.totalPages,
count: transactions.totalDocs,
transactions: transactions.docs
};
// const transactions = await TransactionModel.find().populate('user').populate('token').populate('wallet').sort('-createdAt');
return handleSuccess(res, HttpStatus.OK, data, 'Transactions gotten successfully');
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting all transactions, please contact an administrator', error)
}
},
async updateTokenTransactionDetails(req, token) {
const [user_token] = await Promise.all([
UserTokenModel.find({ user: req.jwtUser._id, token: token._id })
]);
if (!user_token) {
const _user_token = new UserTokenModel({
user: req.jwtUser._id,
token: token._id
})
await _user_token.save()
}
},
async transferTokens(req, res) {
try {
const symbol = req.body.symbol;
const amount = req.body.amount;
const from = req.body.from;
const to = req.body.to;
console.log('token ba balance before transfer: ', await getTokenBalance('BA', to));
const result = await transferToken(symbol, amount, to, from);
console.log('token ba balance after transfer: ', await getTokenBalance('BA', to));
console.log(result);
return result
} catch (error) {
return handleError(res, HttpStatus.INTERNAL_SERVER_ERROR, 'An error occured getting while transferring tokens', error)
}
}
};
module.exports = TokenController;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment