@windingtree/wt-write-api
Version:
API to write data to the Winding Tree platform
93 lines (87 loc) • 3 kB
JavaScript
const { errors: wtJsLibsErrors } = require('@windingtree/wt-js-libs');
const WT = require('./services/wt');
const Account = require('./models/account');
const { UploaderConfig } = require('./services/uploaders');
const { HttpBadGatewayError, HttpPaymentRequiredError, Http404Error,
HttpForbiddenError, HttpUnauthorizedError, HttpServiceUnavailable } = require('./errors');
const { ACCESS_KEY_HEADER, WALLET_PASSWORD_HEADER } = require('./constants');
/**
* Attach account to req based on the provided access key.
*/
module.exports.attachAccount = async (req, res, next) => {
try {
const wt = WT.get(),
accessKey = req.header(ACCESS_KEY_HEADER),
walletPassword = req.header(WALLET_PASSWORD_HEADER);
if (!accessKey || !walletPassword) {
throw new HttpUnauthorizedError();
}
const account = await Account.getByKey(accessKey);
if (!account) {
throw new HttpUnauthorizedError('unauthorized', 'Invalid access key.');
}
req.account = Object.assign({}, account, {
uploaders: UploaderConfig.fromAccount(account),
withWallet: async (fn) => {
const wallet = wt.createWallet(account.wallet);
try {
wallet.unlock(walletPassword);
} catch (err) {
if (err instanceof wtJsLibsErrors.WalletPasswordError) {
throw new HttpUnauthorizedError('unauthorized', 'Invalid password.');
}
throw err;
}
try {
return (await fn(wallet));
} finally {
wallet.lock();
}
},
});
next();
} catch (err) {
next(err);
}
};
/**
* Replace well-defined on-chain errors with the corresponding
* HTTP errors.
*/
module.exports.handleOnChainErrors = (err, req, res, next) => {
if (!err) {
return next();
}
if (err instanceof wtJsLibsErrors.WalletSigningError) {
return next(new HttpForbiddenError());
}
if (err instanceof wtJsLibsErrors.InsufficientFundsError) {
return next(new HttpPaymentRequiredError());
}
if (err instanceof wtJsLibsErrors.InaccessibleEthereumNodeError) {
const msg = 'Ethereum node not reachable. Please try again later.';
return next(new HttpBadGatewayError('badGatewayError', msg));
}
if (err instanceof wtJsLibsErrors.TransactionDidNotComeThroughError) {
return next(new HttpServiceUnavailable(null, null, err.message, {
'Retry-After': 20, // Should be safe for another ETH block to get mined
}));
}
if (err instanceof wtJsLibsErrors.OrganizationNotFoundError) {
return next(new Http404Error('notFound', 'Hotel not found.'));
}
next(err);
};
/**
* Replace well-defined off-chain errors with the corresponding
* HTTP errors.
*/
module.exports.handleDataFetchingErrors = (err, req, res, next) => {
if (!err) {
return next();
}
if (err instanceof wtJsLibsErrors.StoragePointerError) {
return next(new HttpBadGatewayError('hotelNotAccessible', err.message, 'Cannot access off-chain data'));
}
next(err);
};