Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
NEXTAUTH_SECRET=<secret>

# Created by Vercel CLI
KV_REST_API_READ_ONLY_TOKEN=<secret>
KV_REST_API_TOKEN=<secret>
KV_REST_API_URL=<secret>
KV_URL=<secret>

NEXTAUTH_URL=http://localhost:3000
# production
#NEXTAUTH_URL=https://exodus.qwerty.art

## Plaid

PLAID_CLIENT_ID=<secret>
PLAID_SECRET=<secret>
PLAID_ENV=sandbox
12 changes: 11 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
module.exports = {
root: true,
extends: ['next', 'next/core-web-vitals', 'prettier'],
plugins: ['@typescript-eslint'],
settings: {
next: {
rootDir: '.',
},
},
parserOptions: {
project: ['tsconfig.json'],
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'comma-dangle': ['error', 'always-multiline'],
'no-shadow': 'warn',
Expand Down Expand Up @@ -54,7 +64,7 @@ module.exports = {
],
},
],
quotes: ['error', 'single'],
quotes: ['error', 'single', { avoidEscape: true }],
'react-hooks/exhaustive-deps': 'error',
'react/no-unescaped-entities': 'off',
},
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

.vercel
8 changes: 8 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pnpm-lock.yaml
*.md

# files with special formatting
src/hooks/useCursor.tsx
src/hooks/useFormState.ts
src/hooks/useToggle.ts
src/global.d.ts
112 changes: 94 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,116 @@
This app is also deployed on https://exodus.qwerty.art/

---

This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
---

Secrets in `.env` are not included. Contact `qwerty@qwerty.xyz`.

---

## Working flows

1. User signs up with email and a custodial wallet is created in database
2. User signs in with email
3. User can sign out
4. User can connect their bank account with plaid
5. User can see their bank account in the plaid dashboard

There are numerous api endpoints that support both POST and GET requests for testing

---
---

# Exodus Full-Stack Code Challenge

## Project

The purpose of this project is to create a small custodial wallet app that demos an end-to-end purchase of bitcoin with fiat.

Work on this challenge as you would work as a member of a development team. Consider the other devs that will review your code as your teammates in this project.

Please **do not** work more than 8 hours on this without checking in with us to see if you're on the right path. We don't want to waste your time.

### Signup Flow

- The user can sign up for an account with an email and password (no need to verify their email)
- During sign-up, the user must also provide some basic personal information (e.g., their name)
- The user should be able to authenticate using the provided email address
- The user must then link their bank account via [Plaid](https://plaid.com) (in sandbox mode)
- The backend generates a bitcoin address for the user (each user has a single address)

### Purchase Flow

- An authenticated user that has linked their bank account should be allowed to purchase bitcoin (you will need to [set up a regtest bitcoin node](https://developer.bitcoin.org/examples/testing.html#regtest-mode) locally)
- The user should receive regtest bitcoin via a bitcoin transaction and see their balance update
- Do NOT worry about charging the user’s fake bank account, just connecting it is enough for the purpose of this exercise

### Bonus Track

_Note: [code quality](#code-guidelines) in the required features is more important than completing the bonus track!_

- Passwordless authentication using [passkeys](https://passkeys.dev) instead of email and password
- The user should NOT be able to purchase more bitcoin than what they can purchase with their current bank account balance (essentially, do a balance check before allowing them to purchase)
- The user can see their bank accounts with their corresponding balance, and chose which one to debit for the bitcoin purchase
- The user is automatically logged in after creating their account

## Rules

- Create either a web app with React or a mobile app with React Native
- Use [Plaid](https://plaid.com) to allow the user to connect their bank account
- Use Node.js for any backend development
- You can use ANY open source npm library

## Deployment

You will get bonus points if you deploy your working project to an infrastructure provider of your choice. We recommend either [Heroku](https://www.heroku.com), [Netlify](https://www.netlify.com), or [Vercel](https://vercel.com). If you need to, you can mirror this repo in a **private** repo in your GitHub account, so that you can connect and authorize these services there.

If you don't have time to deploy, please record a quick 1-5 minute demo on `localhost` of the flows you were able to implement.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
## Resources

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
- If you're not familiar with regtest, here’s a good [intro](https://bitcoin.stackexchange.com/questions/70156/difference-between-regtest-and-testnet)
- If you've never set up your own bitcoin regtest node, here’s a good [tutorial](https://gist.github.com/olistic/2d5e303da5eb9ff4fa5f794b39171842) for setting it up

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Code Guidelines

## Learn More
Please refer to this [document](https://github.com/ExodusMovementInterviews/exodus-hiring-code-guidelines) for things we'd like to see (and will be looking for) in your code.

To learn more about Next.js, take a look at the following resources:
__Please add project setup instructions in README.md.__

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
## FAQs

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
### Can I code the solution in Typescript?
No, please use only JavaScript. Although we use TypeScript for some projects internally, code challenges in JavaScript give us more flexibility when it comes to reviewing your code.

### Can I start right away?
Whatever works best for you. However, we don’t expect you to start until you have received your BTC payment.

### I have already spent 8 hours working on the code challenge, and it’s still a work in progress. What should I do?
1. Commit and push your work as it will help us know if you are on the right path
2. Reach out to our recruitment team (or the one who sent you the code challenge) and let them know about it
3. Our recruiter will get back to you at the earliest - letting you know whether adding more efforts to the code challenge is worth your time

### Can I add unit tests to my solution?
Yes, bonus points for these.

### I am stuck. What should I do?
Please reach out to our recruiter, and we will try our best to help you.

## Deploy on Vercel
If you still have questions, don't hesitate to ask your recruiter!

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
### If I'm using pull requests, should I merge them to master?

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Please do.
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,24 @@
"start": "next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"format": "prettier --check --ignore-path .gitignore .",
"format:fix": "prettier --write --ignore-path .gitignore .",
"format": "prettier --check --ignore-path .gitignore --ignore-path .prettierignore .",
"format:fix": "pnpm format --write",
"fix": "pnpm format:fix && pnpm lint:fix",
"types": "tsc --noEmit --incremental",
"types:watch": "tsc --noEmit --incremental --watch"
},
"dependencies": {
"@vercel/kv": "^2.0.0",
"bitcoinjs-lib": "^6.1.6",
"ecpair": "^2.1.0",
"iron-session": "^8.0.3",
"next": "14.2.7",
"next-auth": "^4.24.7",
"plaid": "^26.0.0",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"react-plaid-link": "^3.5.2",
"tiny-secp256k1": "^2.2.3"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
Loading