Skip to content

Commit

Permalink
feat: /batch-transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavkparti committed Oct 3, 2023
1 parent 936f06b commit 492155a
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
6 changes: 5 additions & 1 deletion server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ Sentry.init({ dsn: config.sentry_dsn });
app.use(
// eslint-disable-next-line consistent-return
handlerWrapper(async (req, res, next) => {
if (req.path === '/wallets/batch-create-wallet' && req.method === 'POST') {
if (
(req.path === '/wallets/batch-create-wallet' ||
req.path === '/wallets/batch-transfer') &&
req.method === 'POST'
) {
if (
!req.headers['content-type'] ||
!req.headers['content-type'].includes('multipart/form-data')
Expand Down
29 changes: 29 additions & 0 deletions server/handlers/walletHandler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
walletPostSchema,
walletBatchCreateBodySchema,
csvValidationSchema,
walletBatchTransferBodySchema,
} = require('./schemas');

const walletGet = async (req, res) => {
Expand Down Expand Up @@ -130,10 +131,38 @@ const walletBatchCreate = async (req, res) => {
res.status(201).send(result);
};

const walletBatchTransfer = async (req, res) => {
const validatedBody = await walletBatchTransferBodySchema.validateAsync(
req.body,
{ abortEarly: false },
);

const { path } = req.file;
const jsonResult = await csvtojson().fromFile(path);
const validatedCsvFile = await csvValidationSchema.validateAsync(jsonResult, {
abortEarly: false,
});

const { sender_wallet, token_transfer_amount_default } = validatedBody;
const { wallet_id } = req;
const walletService = new WalletService();

const result = await walletService.batchTransferWallet(
sender_wallet,
token_transfer_amount_default,
wallet_id,
validatedCsvFile,
path,
);

res.status(200).send(result);
};

module.exports = {
walletPost,
walletGetTrustRelationships,
walletGet,
walletSingleGet,
walletBatchCreate,
walletBatchTransfer,
};
6 changes: 6 additions & 0 deletions server/handlers/walletHandler/schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,17 @@ const csvValidationSchema = Joi.array()
.min(1)
.max(2500);

const walletBatchTransferBodySchema = Joi.object({
sender_wallet: Joi.string().required(),
token_transfer_amount_default: Joi.number().integer(),
}).with('token_transfer_amount_default', 'sender_wallet');

module.exports = {
walletGetQuerySchema,
walletIdParamSchema,
walletGetTrustRelationshipsSchema,
walletPostSchema,
walletBatchCreateBodySchema,
csvValidationSchema,
walletBatchTransferBodySchema,
};
7 changes: 7 additions & 0 deletions server/routes/walletRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const {
walletPost,
walletSingleGet,
walletBatchCreate,
walletBatchTransfer,
} = require('../handlers/walletHandler');

router.get('/', handlerWrapper(walletGet));
Expand All @@ -46,5 +47,11 @@ router.post(
handlerWrapper(walletBatchCreate),
);

router.post(
'/batch-transfer',
upload.single('csv'),
handlerWrapper(walletBatchTransfer),
);

routerWrapper.use('/wallets', apiKeyHandler, verifyJWTHandler, router);
module.exports = routerWrapper;
57 changes: 57 additions & 0 deletions server/services/WalletService.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,63 @@ class WalletService {
});
return response.body;
}

async batchTransferWallet(
sender_wallet,
token_transfer_amount_default,
wallet_id,
csvJson,
filePath,
) {
try {
await this._session.beginTransaction();

const senderWallet = await this.getByName(sender_wallet);

const recipientWallets = [];
let totalAmountToTransfer = 0;

// eslint-disable-next-line no-restricted-syntax
for (const { wallet_name, token_transfer_amount_overwrite } of csvJson) {
const amount =
token_transfer_amount_overwrite || token_transfer_amount_default;
if (amount && !sender_wallet) {
throw new HttpError(422, 'sender_wallet is required for transfer.');
}
if (amount) {
totalAmountToTransfer += +amount;
}
const walletDetails = await this.getByName(wallet_name);
recipientWallets.push({ amount, walletDetails });
}

const tokenModel = new Token(this._session);
const tokenCount = await tokenModel.countTokenByWallet(senderWallet);

if (totalAmountToTransfer > tokenCount)
throw new HttpError(422, 'sender does not have enough tokens');

const transferModel = new Transfer(this._session);

// eslint-disable-next-line no-restricted-syntax
for (const { walletDetails, amount } of recipientWallets) {
if (amount) {
// claim is false for now
await transferModel.transferBundle(
wallet_id,
senderWallet,
walletDetails,
amount,
false,
);
}
}
} catch (e) {
await this._session.rollbackTransaction();
await fs.unlink(filePath);
throw e;
}
}
}

module.exports = WalletService;

0 comments on commit 492155a

Please sign in to comment.