0% found this document useful (0 votes)
11 views35 pages

Build Paytm-Like App Backend Tutorial

This document outlines a tutorial for building the backend of a Paytm-like application using Express and MongoDB. It provides a step-by-step guide including user authentication, routing, and database schema setup. The tutorial emphasizes hands-on learning and encourages following along with the provided code examples.

Uploaded by

Hc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views35 pages

Build Paytm-Like App Backend Tutorial

This document outlines a tutorial for building the backend of a Paytm-like application using Express and MongoDB. It provides a step-by-step guide including user authentication, routing, and database schema setup. The tutorial emphasizes hands-on learning and encourages following along with the provided code examples.

Uploaded by

Hc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Week 8.2
Recap Everything, Build PayTM Backend

In this lecture, Harkirat guides us through an end-to-end tutorial on building a comprehensive


full-stack application resembling Paytm While there are no specific notes provided for this
section, a mini guide is outlined below to assist you in navigating through each step of the tutorial.
Therefore, it is strongly advised to actively follow along during the lecture for a hands-on learning
experience.

It's important to note that this session primarily focuses on the backend section
of the application. For the frontend portion, be sure to check out the content
covered in the subsequent 8.4 lecture.

Recap Everything, Build PayTM Backend

Step 1 - What are we building, Clone the starter repo

Things to do

Explore the repository

Backend

Frontend

Step 2 - User Mongoose schemas

Solution

Step 3 - Create routing file structure

[Link] 1/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 1

Solution

Step 2

Solution

Step 4 - Route user requests

1. Create a new user router

Solution

2. Create a new user router

Solution

Step 5 - Add cors, body parser and jsonwebtoken

1. Add cors

Hint

Solution

2. Add body-parser

Hint

Solution

3. Add jsonwebtoken

4. Export JWT_SECRET

Solution

5. Listen on port 3000

Solution

Step 6 - Add backend auth routes

1. Signup

Solution

2. Route to sign in

Solution

Solution

Step 7 - Middleware

Solution

Step 8 - User routes

1. Route to update user information

Solution

2. Route to get users from the backend, filterable via firstName/lastName

[Link] 2/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Hints

Solution

Step 9 - Create Bank related Schema

Accounts table

Solution

By the end of it, [Link] should look lie this

Step 10 - Transactions in databases

Solution

Step 11 - Initialize balances on signup

Solution

Step 12 - Create a new router for accounts

1. Create a new router

Solution

2. Route requests to it

Solution

Step 13 - Balance and transfer Endpoints

1. An endpoint for user to get their balance.

Solution

2. An endpoint for user to transfer money to another account

Bad Solution (doesn’t use transactions)

Good solution (uses txns in db

Problems you might run into

Final Solution

Finally, the [Link] file should look like this

Experiment to ensure transactions are working as expected

Code

Error

Step 14 - Checkpoint your solution

Get balance

Make transfer

Get balance again (notice it went down)

Mongo should look something like this

[Link] 3/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 1 - What are we building, Clone the starter repo


We’re building a PayTM like application that let’s users send money to each other given an initial
dummy balance

Things to do
Clone the 8.2 repository from [Link]

git clone [Link]

💡
Please keep a MongoDB URL handy before you proceed. This will be your primary database for this
assignment
1. Create a free one here - [Link]
2. There is a Dockerfile in the codebase, you can run mongo locally using it.

Explore the repository


The repo is a basic express + react + tailwind boilerplate

Backend
1. Express - HTTP Server

2. mongoose - ODM to connect to MongoDB

3. zod - Input validation

[Link] 4/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

// [Link]
const express = require("express");
const app = express();

Frontend
1. React - Frontend framework

2. Tailwind - Styling framework

// [Link]
function App() {

return (
<div>
Hello world
</div>
)
}

export default App

Step 2 - User Mongoose schemas

We need to support 3 routes for user authentication

1. Allow user to sign up.

2. Allow user to sign in.

3. Allow user to update their information (firstName, lastName, password).

To start off, create the mongo schema for the users table

1. Create a new file ([Link]) in the root folder

2. Import mongoose and connect to a database of your choice

3. Create the mongoose schema for the users table

4. Export the mongoose model from the file (call it User)

[Link] 5/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Solution
Simple solution

// backend/[Link]
const mongoose = require('mongoose');

// Create a Schema for Users


const userSchema = new [Link]({
username: String,
password: String,
firstName: String,
lastName: String
});

// Create a model from the schema


const User = [Link]('User', userSchema);

[Link] = {
User
};

Elegant Solution

// backend/[Link]
const mongoose = require('mongoose');

// Create a Schema for Users


const userSchema = new [Link]({
username: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
minLength: 3,
maxLength: 30
},
password: {
type: String,
required: true,
minLength: 6
},
firstName: {
type: String,
required: true,
trim: true,
[Link] 6/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

maxLength: 50
},
lastName: {
type: String,
required: true,
trim: true,
maxLength: 50
}
});

// Create a model from the schema


const User = [Link]('User', userSchema);

[Link] = {
User
};

Step 3 - Create routing file structure


In the [Link] file, route all the requests to /api/v1 to a apiRouter defined in
backend/routes/[Link]

Step 1
Create a new file backend/routes/[Link] that exports a new express router.
( How to create a router - [Link] )

Solution
// backend/api/[Link]
const express = require('express');

const router = [Link]();

[Link] = router;

Step 2
Import the router in [Link] and route all requests from /api/v1 to it

[Link] 7/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Solution
// backend/[Link]
const express = require("express");
const rootRouter = require("./routes/index");

const app = express();

[Link]("/api/v1", rootRouter);

Step 4 - Route user requests

1. Create a new user router


Define a new router in backend/routes/[Link] and import it in the index router.
Route all requests that go to /api/v1/user to the user router.

Solution
// backend/routes/[Link]
const express = require('express');

const router = [Link]();

[Link] = router;

2. Create a new user router


Import the userRouter in backend/routes/[Link] so all requests to /api/v1/user get routed to
the userRouter.

Solution

// backend/routes/[Link]
const express = require('express');
[Link] 8/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

const userRouter = require("./user");

const router = [Link]();

[Link]("/user", userRouter)

[Link] = router;

Step 5 - Add cors, body parser and jsonwebtoken

1. Add cors
Since our frontend and backend will be hosted on separate routes, add the cors middleware to
backend/[Link]

Hint
Look at [Link]

Solution
// backend/[Link]
const express = require('express');
const cors = require("cors");

[Link](cors());

const app = express();

[Link] = router;

2. Add body-parser
Since we have to support the JSON body in post requests, add the express body parser middleware
to backend/[Link]
You can use the body-parser npm library, or use [Link]

[Link] 9/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Hint
[Link]
335803cd048c

Solution
// backend/[Link]
const express = require('express');
const cors = require("cors");
const rootRouter = require("./routes/index");

const app = express();

[Link](cors());
[Link]([Link]());

[Link]("/api/v1", rootRouter);

3. Add jsonwebtoken
We will be adding authentication soon to our application, so install jsonwebtoken library. It’ll be
useful in the next slide

npm install jsonwebtoken

4. Export JWT_SECRET
Export a JWT_SECRET from a new file backend/[Link]

Solution
//backend/[Link]
[Link] = {
JWT_SECRET: "your-jwt-secret"
}

[Link] 10/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

5. Listen on port 3000


Make the express app listen on PORT 3000 of your machine

Solution
// backend/[Link]
... Existing code

[Link](3000);

Step 6 - Add backend auth routes


In the user router ( backend/routes/user ), add 3 new routes.

1. Signup
This route needs to get user information, do input validation using zod and store the information in
the database provided

1. Inputs are correct (validated via zod)

2. Database doesn’t already contain another user

If all goes well, we need to return the user a jwt which has their user id encoded as follows -

{
userId: "userId of newly added user"
}

💡
Note - We are not hashing passwords before putting them in the database. This is standard practise
that should be done, you can find more details here - [Link]
passwords-in-nodejs/
Method: POST
Route: /api/v1/user/signup
Body:

{
username: "name@[Link]",

[Link] 11/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

firstName: "name",
lastName: "name",
password: "123456"
}

Response:

Status code - 200

{
message: "User created successfully",
token: "jwt"
}

Status code - 411

{
message: "Email already taken / Incorrect inputs"
}

Solution
const zod = require("zod");
const { User } = require("../db");
const jwt = require("jsonwebtoken");
const { JWT_SECRET } = require("../config");

const signupBody = [Link]({


username: [Link]().email(),
firstName: [Link](),
lastName: [Link](),
password: [Link]()
})

[Link]("/signup", async (req, res) => {


const { success } = [Link]([Link])
if (!success) {
return [Link](411).json({
message: "Email already taken / Incorrect inputs"
})
}

const existingUser = await [Link]({


username: [Link]
})

[Link] 12/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

if (existingUser) {
return [Link](411).json({
message: "Email already taken/Incorrect inputs"
})
}

const user = await [Link]({


username: [Link],
password: [Link],
firstName: [Link],
lastName: [Link],
})
const userId = user._id;

const token = [Link]({


userId
}, JWT_SECRET);

[Link]({
message: "User created successfully",
token: token
})
})

2. Route to sign in
Let’s an existing user sign in to get back a token.
Method: POST
Route: /api/v1/user/signin
Body:

{
username: "name@[Link]",
password: "123456"
}

Response:
Status code - 200

{
token: "jwt"
}

[Link] 13/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Status code - 411

{
message: "Error while logging in"
}

Solution
const signinBody = [Link]({
username: [Link]().email(),
password: [Link]()
})

[Link]("/signin", async (req, res) => {


const { success } = [Link]([Link])
if (!success) {
return [Link](411).json({
message: "Incorrect inputs"
})
}

const user = await [Link]({


username: [Link],
password: [Link]
});

if (user) {
const token = [Link]({
userId: user._id
}, JWT_SECRET);

[Link]({
token: token
})
return;
}

[Link](411).json({
message: "Error while logging in"
})
})

[Link] 14/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

By the end, routes/[Link] should look like follows

Solution
// backend/routes/[Link]
const express = require('express');

const router = [Link]();


const zod = require("zod");
const { User } = require("../db");
const jwt = require("jsonwebtoken");
const { JWT_SECRET } = require("../config");

const signupBody = [Link]({


username: [Link]().email(),
firstName: [Link](),
lastName: [Link](),
password: [Link]()
})

[Link]("/signup", async (req, res) => {


const { success } = [Link]([Link])
if (!success) {
return [Link](411).json({
message: "Email already taken / Incorrect inputs"
})
}

const existingUser = await [Link]({


username: [Link]
})

if (existingUser) {
return [Link](411).json({
message: "Email already taken/Incorrect inputs"
})
}

const user = await [Link]({


username: [Link],
password: [Link],
firstName: [Link],
lastName: [Link],
})
const userId = user._id;

[Link] 15/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

const token = [Link]({


userId
}, JWT_SECRET);

[Link]({
message: "User created successfully",
token: token
})
})

const signinBody = [Link]({


username: [Link]().email(),
password: [Link]()
})

[Link]("/signin", async (req, res) => {


const { success } = [Link]([Link])
if (!success) {
return [Link](411).json({
message: "Email already taken / Incorrect inputs"
})
}

const user = await [Link]({


username: [Link],
password: [Link]
});

if (user) {
const token = [Link]({
userId: user._id
}, JWT_SECRET);

[Link]({
token: token
})
return;
}

[Link](411).json({
message: "Error while logging in"
})
})

[Link] = router;

[Link] 16/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 7 - Middleware
Now that we have a user account, we need to gate routes which authenticated users can hit.
For this, we need to introduce an auth middleware

Create a [Link] file that exports an authMiddleware function

1. Checks the headers for an Authorization header Bearer <token>

2. Verifies that the token is valid

3. Puts the userId in the request object if the token checks out.

4. If not, return a 403 status back to the user

Header -
Authorization: Bearer <actual token>

Solution
const { JWT_SECRET } = require("./config");
const jwt = require("jsonwebtoken");

const authMiddleware = (req, res, next) => {


const authHeader = [Link];

if (!authHeader || ![Link]('Bearer ')) {


return [Link](403).json({});
}

const token = [Link](' ')[1];

try {
const decoded = [Link](token, JWT_SECRET);

[Link] = [Link];

next();
} catch (err) {
return [Link](403).json({});
}
};

[Link] = {
authMiddleware
}

[Link] 17/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 8 - User routes

1. Route to update user information


User should be allowed to optionally send either or all of

1. password

2. firstName

3. lastName

Whatever they send, we need to update it in the database for the user.
Use the middleware we defined in the last section to authenticate the user
Method: PUT
Route: /api/v1/user
Body:

{
password: "new_password",
firstName: "updated_first_name",
lastName: "updated_first_name",
}

Response:
Status code - 200

{
message: "Updated successfully"
}

Status code - 411 (Password is too small…)

{
message: "Error while updating information"
}

Solution

[Link] 18/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

const { authMiddleware } = require("../middleware");

// other auth routes

const updateBody = [Link]({


password: [Link]().optional(),
firstName: [Link]().optional(),
lastName: [Link]().optional(),
})

[Link]("/", authMiddleware, async (req, res) => {


const { success } = [Link]([Link])
if (!success) {
[Link](411).json({
message: "Error while updating information"
})
}

await [Link]([Link], {
_id: [Link]
})

[Link]({
message: "Updated successfully"
})
})

2. Route to get users from the backend, filterable via


firstName/lastName
This is needed so users can search for their friends and send them money
Method: GET
Route: /api/v1/user/bulk
Query Parameter: ?filter=harkirat
Response:
Status code - 200

{
users: [{
firstName: "",
lastName: "",
_id: "id of the user"

[Link] 19/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

}]
}

Hints
[Link]
not-work-properly
[Link]

Solution
[Link]("/bulk", async (req, res) => {
const filter = [Link] || "";

const users = await [Link]({


$or: [{
firstName: {
"$regex": filter
}
}, {
lastName: {
"$regex": filter
}
}]
})

[Link]({
user: [Link](user => ({
username: [Link],
firstName: [Link],
lastName: [Link],
_id: user._id
}))
})
})

Step 9 - Create Bank related Schema


Update the [Link] file to add one new schemas and export the respective models

Accounts table
The Accounts table will store the INR balances of a user.
[Link] 20/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

The schema should look something like this -

{
userId: ObjectId (or string),
balance: float/number
}

In the real world, you shouldn’t store `floats` for balances in the database.
You usually store an integer which represents the INR value with
decimal places (for eg, if someone has 33.33 rs in their account,
you store 3333 in the database).

There is a certain precision that you need to support (which for india is
2/4 decimal places) and this allows you to get rid of precision
errors by storing integers in your DB

You should reference the users table in the schema (Hint -


[Link]

Solution
const accountSchema = new [Link]({
userId: {
type: [Link], // Reference to User model
ref: 'User',
required: true
},
balance: {
type: Number,
required: true
}
});

const Account = [Link]('Account', accountSchema);

[Link] = {
Account
}

[Link] 21/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

By the end of it, [Link] should look lie this


// backend/[Link]
const mongoose = require('mongoose');

[Link]("mongodb://localhost:27017/paytm")

// Create a Schema for Users


const userSchema = new [Link]({
username: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
minLength: 3,
maxLength: 30
},
password: {
type: String,
required: true,
minLength: 6
},
firstName: {
type: String,
required: true,
trim: true,
maxLength: 50
},
lastName: {
type: String,
required: true,
trim: true,
maxLength: 50
}
});

const accountSchema = new [Link]({


userId: {
type: [Link], // Reference to User model
ref: 'User',
required: true
},
balance: {
type: Number,
required: true
}
});

[Link] 22/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

const Account = [Link]('Account', accountSchema);


const User = [Link]('User', userSchema);

[Link] = {
User,
Account,
};

Step 10 - Transactions in databases


A lot of times, you want multiple databases transactions to be atomic
Either all of them should update, or none should
This is super important in the case of a bank
Can you guess what’s wrong with the following code -

const mongoose = require('mongoose');


const Account = require('./path-to-your-account-model');

const transferFunds = async (fromAccountId, toAccountId, amount) => {


// Decrement the balance of the fromAccount
await [Link](fromAccountId, { $inc: { balance: -amount } });

// Increment the balance of the toAccount


await [Link](toAccountId, { $inc: { balance: amount } });
}

// Example usage
transferFunds('fromAccountID', 'toAccountID', 100);

Solution
1. What if the database crashes right after the first request (only the balance is decreased for one
user, and not for the second user)

2. What if the [Link] crashes after the first update?


It would lead to a database inconsistency . Amount would get debited from the first user, and
not credited into the other users account.
If a failure ever happens, the first txn should rollback.
This is what is called a transaction in a database. We need to implement a transaction on
the next set of endpoints that allow users to transfer INR
[Link] 23/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 11 - Initialize balances on signup


Update the signup endpoint to give the user a random balance between 1 and 10000.
This is so we don’t have to integrate with banks and give them random balances to start with.

Solution
[Link]("/signup", async (req, res) => {
const { success } = [Link]([Link])
if (!success) {
return [Link](411).json({
message: "Email already taken / Incorrect inputs"
})
}

const existingUser = await [Link]({


username: [Link]
})

if (existingUser) {
return [Link](411).json({
message: "Email already taken/Incorrect inputs"
})
}

const user = await [Link]({


username: [Link],
password: [Link],
firstName: [Link],
lastName: [Link],
})
const userId = user._id;

/// ----- Create new account ------

await [Link]({
userId,
balance: 1 + [Link]() * 10000
})

/// ----- ------

const token = [Link]({


userId
}, JWT_SECRET);

[Link]({
[Link] 24/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

message: "User created successfully",


token: token
})
})

Step 12 - Create a new router for accounts


1. Create a new router
All user balances should go to a different express router (that handles all requests on
/api/v1/account ).

Create a new router in routes/[Link] and add export it

Solution
// backend/routes/[Link]
const express = require('express');

const router = [Link]();

[Link] = router;

2. Route requests to it
Send all requests from /api/v1/account/* in routes/[Link] to the router created in step 1.

Solution
// backend/user/[Link]
const express = require('express');
const userRouter = require("./user");
const accountRouter = require("./account");

const router = [Link]();

[Link]("/user", userRouter);
[Link]("/account", accountRouter);

[Link] = router;

[Link] 25/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Step 13 - Balance and transfer Endpoints


Here, you’ll be writing a bunch of APIs for the core user balances. There are 2 endpoints that we need
to implement

1. An endpoint for user to get their balance.


Method: GET
Route: /api/v1/account/balance
Response:
Status code - 200

{
balance: 100
}

Solution
[Link]("/balance", authMiddleware, async (req, res) => {
const account = await [Link]({
userId: [Link]
});

[Link]({
balance: [Link]
})
});

2. An endpoint for user to transfer money to another account


Method: POST
Route: /api/v1/account/transfer
Body

{
to: string,
amount: number
}

[Link] 26/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Response:
Status code - 200

{
message: "Transfer successful"
}

Status code - 400

{
message: "Insufficient balance"
}

Status code - 400

{
message: "Invalid account"
}

Bad Solution (doesn’t use transactions)


[Link]("/transfer", authMiddleware, async (req, res) => {
const { amount, to } = [Link];

const account = await [Link]({


userId: [Link]
});

if ([Link] < amount) {


return [Link](400).json({
message: "Insufficient balance"
})
}

const toAccount = await [Link]({


userId: to
});

if (!toAccount) {
return [Link](400).json({
message: "Invalid account"
})
}

await [Link]({
userId: [Link]

[Link] 27/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

}, {
$inc: {
balance: -amount
}
})

await [Link]({
userId: to
}, {
$inc: {
balance: amount
}
})

[Link]({
message: "Transfer successful"
})
});

Good solution (uses txns in db


[Link]("/transfer", authMiddleware, async (req, res) => {
const session = await [Link]();

[Link]();
const { amount, to } = [Link];

// Fetch the accounts within the transaction


const account = await [Link]({ userId: [Link] }).session(session);

if (!account || [Link] < amount) {


await [Link]();
return [Link](400).json({
message: "Insufficient balance"
});
}

const toAccount = await [Link]({ userId: to }).session(session);

if (!toAccount) {
await [Link]();
return [Link](400).json({
message: "Invalid account"
});
}

[Link] 28/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

// Perform the transfer


await [Link]({ userId: [Link] }, { $inc: { balance: -amount } }).session(
await [Link]({ userId: to }, { $inc: { balance: amount } }).session(session);

// Commit the transaction


await [Link]();
[Link]({
message: "Transfer successful"
});
});

Problems you might run into


Problems you might run into If you run into the problem mentioned above, feel free to proceed
with the bad solution
[Link]
transaction-numbers-are-only-allowed-on-a

Final Solution

Finally, the [Link] file should look like this

Experiment to ensure transactions are working as expected


Try running this code locally. It calls transfer twice on the same account ~almost concurrently

Code
[Link] 29/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

// backend/routes/[Link]
const express = require('express');
const { authMiddleware } = require('../middleware');
const { Account } = require('../db');
const { default: mongoose } = require('mongoose');

const router = [Link]();

[Link]("/balance", authMiddleware, async (req, res) => {


const account = await [Link]({
userId: [Link]
});

[Link]({
balance: [Link]
})
});

async function transfer(req) {


const session = await [Link]();

[Link]();
const { amount, to } = [Link];

// Fetch the accounts within the transaction


const account = await [Link]({ userId: [Link] }).session(session);

if (!account || [Link] < amount) {


await [Link]();
[Link]("Insufficient balance")
return;
}

const toAccount = await [Link]({ userId: to }).session(session);

if (!toAccount) {
await [Link]();
[Link]("Invalid account")
return;
}

// Perform the transfer


await [Link]({ userId: [Link] }, { $inc: { balance: -amount } }).session(
await [Link]({ userId: to }, { $inc: { balance: amount } }).session(session);

// Commit the transaction


await [Link]();
[Link]("done")
}

[Link] 30/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

transfer({
userId: "65ac44e10ab2ec750ca666a5",
body: {
to: "65ac44e40ab2ec750ca666aa",
amount: 100
}
})

transfer({
userId: "65ac44e10ab2ec750ca666a5",
body: {
to: "65ac44e40ab2ec750ca666aa",
amount: 100
}
})
[Link] = router;

Error

Step 14 - Checkpoint your solution


A completely working backend can be found here - [Link]
2/paytm/tree/backend-solution
[Link] 31/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Try to send a few calls via postman to ensure you are able to sign up/sign in/get balance

Get balance

Make transfer

[Link] 32/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Get balance again (notice it went down)

[Link] 33/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

Mongo should look something like this

[Link] 34/35
6/17/24, 10:49 AM Take your development skills from 0 to 100 and join the 100xdevs community

[Link] 35/35

You might also like