Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jair-rosa-cb committed Dec 11, 2024
0 parents commit ae49736
Show file tree
Hide file tree
Showing 16 changed files with 2,024 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PORT=5000
APP_ENV=<production|development>
SDK_API_KEY_NAME="organizations/****/apiKeys/*****"
SDK_API_KEY_PRIVATE_KEY="<YOUR_KEY_HERE>"
79 changes: 79 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# node-waf configuration
.lock-wscript

build

# Dependency directories
node_modules/
jspm_packages/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.*
!.env.example

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Serverless directories
.serverless/

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.vscode

.vercel
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Coinbase Wallet History Demo Backend

![NodeJs](https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
![TypeScript](https://img.shields.io/badge/-TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
![Coinbase](https://img.shields.io/badge/Coinbase-0052FF?style=for-the-badge&logo=Coinbase&logoColor=white)

<hr/>

## Prerequisites

- [Node](https://nodejs.org/en/download)
- [pnpm](https://pnpm.io/installation)

## Installation

```bash
pnpm i
```

- Fill in the environment variables in the `.env` file, refer to the `.env.example` file for the required variables. You'll need to create a [CDP API key](https://portal.cdp.coinbase.com/access/api) fill it on the `.env` file.

---

## Development Usage

Start the Express Server

```bash
pnpm run dev
```

---

## Production Usage

Build the project

```bash
pnpm run build
```

Start the Express Server

```bash
pnpm start
```

## Deploying to Vercel

1. Install Vercel client: `npm i -g vercel`
2. Login on your terminal by running the command: `vercel login` and use the browser to login.
3. Then, on the project folder, run `vercel --prod` to deploy it and it will be deployed after a few seconds. You'll be asked for a few configs the first time, you can use the default ones.
26 changes: 26 additions & 0 deletions controllers/helpers.controllers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { NextFunction, Request, Response } from "express";

function errorHandler(
err: Error,
_req: Request,
res: Response,
next: NextFunction
) {
console.log('Error happened: ', err);
if (err) {
let status = 200;
status = res.statusCode == 200 ? 500 : res.statusCode;
const message = err?.message || "Something went wrong";
res.status(status).json(message);
} else next();
}

function healthCheck(_req: Request, res: Response) {
res.status(200).send("OK");
}

function notFound(_req: Request, res: Response) {
res.status(404).send("Not found");
}

export { errorHandler, healthCheck, notFound };
2 changes: 2 additions & 0 deletions controllers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { errorHandler, healthCheck, notFound } from "./helpers.controllers";
export { getWalletHistory } from "./walletHistory.controllers";
35 changes: 35 additions & 0 deletions controllers/walletHistory.controllers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { NextFunction, Request, Response } from "express";
import { Address, Coinbase } from "@coinbase/coinbase-sdk";

export async function getWalletHistory(req: Request, res: Response, next: NextFunction) {
console.log(req.body);
const { limit, network, walletAddress } = req.body;
if (!limit || !network || !walletAddress) {
return res.status(400).send('Missing required params.')
}

try {
if (!process.env.SDK_API_KEY_NAME || !process.env.SDK_API_KEY_PRIVATE_KEY) {
console.error('ERROR! KEYS NOT FOUND ON ENV!');
return res.status(500)
} else {
console.log('Configuring SDK keys:');
console.log('SDK_API_KEY_NAME', process.env.SDK_API_KEY_NAME);
console.log('SDK_API_KEY_PRIVATE_KEY', process.env.SDK_API_KEY_PRIVATE_KEY);

Coinbase.configure({
apiKeyName: process.env.SDK_API_KEY_NAME,
privateKey: process.env.SDK_API_KEY_PRIVATE_KEY,
});
}

const add = new Address(network, walletAddress);
let transactions = (await add.listTransactions({ limit })).data;
console.log('transactions received:', transactions.length);


return res.status(200).json(JSON.parse(JSON.stringify(transactions)));
} catch (error) {
next(error);
}
}
31 changes: 31 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "dotenv/config";
import middlewares from "./middlewares";
import router from "./routes";
import express from "express";

async function gracefulShutdown() {
try {
process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
}

process.on("SIGINT", gracefulShutdown);
process.on("SIGTERM", gracefulShutdown);

let app = express();

app = middlewares(app);
app.use(router);

app.listen(process.env.PORT || 5000, async () => {
try {
console.log(`🚀 Server running on port ${process.env.PORT || 5000}`);
} catch (error) {
await gracefulShutdown();
}
});

export default app;
18 changes: 18 additions & 0 deletions middlewares/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import cors from "cors";
import * as express from "express";
import { Express } from "express";

function middlewares(server: Express): Express {
console.log('process.env.FRONTEND_ALLOWED_DOMAIN', process.env.FRONTEND_ALLOWED_DOMAIN);
const corsOptions = {
origin: process.env.FRONTEND_ALLOWED_DOMAIN,
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
maxAge: 84600
}
server.use(cors(corsOptions));
server.use(express.json());

return server;
}

export default middlewares;
6 changes: 6 additions & 0 deletions nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": ["./", "./*"],
"ext": ".ts,.js",
"ignore": [],
"exec": "npx ts-node --files ./index.ts"
}
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "wallet-history-demo-backend",
"version": "1.0.0",
"description": "",
"exports": "./build/index.js",
"scripts": {
"dev": "NODE_OPTIONS='--no-warnings --loader ts-node/esm' npx nodemon",
"start": "node build/index.js",
"build": "npx tsc -p .",
"test": "echo \"Error: no test\" && exit 1"
},
"dependencies": {
"@coinbase/coinbase-sdk": "^0.10.0",
"axios": "^1.6.5",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.11.0",
"nodemon": "^3.0.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=18"
}
}
Loading

0 comments on commit ae49736

Please sign in to comment.