Skip to content

Commit c5c5972

Browse files
authored
Merge pull request #26 from syscoin/mongodb-migrate
Mongodb migrate
2 parents 9b4f2dd + 7ec0551 commit c5c5972

File tree

13 files changed

+329
-35
lines changed

13 files changed

+329
-35
lines changed

.github/workflows/aws.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ on:
66
push:
77
branches:
88
- main
9+
- mongodb-migrate
910

1011
env:
1112
AWS_REGION: us-east-1 # set this to your preferred AWS region, e.g. us-west-1
@@ -35,7 +36,7 @@ jobs:
3536
id: login-ecr
3637
uses: aws-actions/amazon-ecr-login@v1
3738

38-
- name: Build, tag, and push image to Amazon ECR
39+
- name: Build, tag, and push release image to Amazon ECR
3940
id: build-image
4041
if: github.ref_type == 'tag'
4142
env:
@@ -46,7 +47,18 @@ jobs:
4647
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
4748
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
4849
49-
- name: Build, tag, and push image to Amazon ECR
50+
- name: Build, tag, and push branch image to Amazon ECR
51+
id: build-image-branch
52+
if: github.ref_type == 'branch'
53+
env:
54+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
55+
IMAGE_TAG: ${{ github.ref_name }}
56+
run: |
57+
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
58+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
59+
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
60+
61+
- name: Build, tag, and push latest image to Amazon ECR
5062
id: build-image-main
5163
if: github.ref_type == 'branch' && github.ref_name == 'main'
5264
env:

api/services/transfer.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { ITransfer } from "@contexts/Transfer/types";
22
import { UserCredential, signInWithEmailAndPassword } from "firebase/auth";
33
import firebase from "firebase-setup";
44
import { doc, getDoc } from "firebase/firestore";
5+
import dbConnect from "lib/mongodb";
6+
import TransferModel from "models/transfer";
57

68
export class TransferService {
79
private isAuthenticated = false;
@@ -22,15 +24,62 @@ export class TransferService {
2224
});
2325
}
2426
}
27+
28+
async getAll(params: Partial<ITransfer>): Promise<ITransfer[]> {
29+
const filters: (keyof ITransfer)[] = [
30+
"nevmAddress",
31+
"utxoAddress",
32+
"utxoXpub",
33+
];
34+
const queryConstraints = filters.reduce((acc, key) => {
35+
if (key in params && typeof params[key] === "string") {
36+
acc.push({ [key]: params[key] as string });
37+
}
38+
return acc;
39+
}, [] as Record<string, string>[]);
40+
return TransferModel.find({
41+
$or: queryConstraints,
42+
});
43+
}
44+
2545
async getTransfer(id: string): Promise<ITransfer> {
46+
const transfer = await TransferModel.findOne({ id });
47+
48+
if (!transfer) {
49+
return this.getTransferFirebase(id);
50+
}
51+
52+
return transfer as unknown as ITransfer;
53+
}
54+
55+
async getTransferFirebase(id: string): Promise<ITransfer> {
2656
await this.authenticate();
2757
const document = await getDoc(
2858
doc(firebase.firestore, "transfers", id as string)
2959
);
60+
3061
if (!document.exists()) {
3162
throw new Error("Transfer not found");
3263
}
3364

34-
return document.data() as ITransfer;
65+
const transferData = document.data() as ITransfer;
66+
67+
return this.upsertTransfer(transferData);
68+
}
69+
70+
async upsertTransfer(transfer: ITransfer): Promise<ITransfer> {
71+
const results = await TransferModel.updateOne(
72+
{ id: transfer.id },
73+
{ ...transfer, updatedAt: Date.now() },
74+
{ upsert: true }
75+
);
76+
77+
if (!results.acknowledged) {
78+
throw new Error("Transfer not updated");
79+
}
80+
81+
const updatedTransfer = await TransferModel.findOne({ id: transfer.id });
82+
83+
return updatedTransfer as ITransfer;
3584
}
3685
}

components/Bridge/v3/Steps/ConfirmNEVMTransaction.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { ITransferLog, TransferStatus } from "@contexts/Transfer/types";
22
import { useTransfer } from "../context/TransferContext";
33
import { useWeb3 } from "../context/Web";
4-
import { Alert, CircularProgress, Typography } from "@mui/material";
4+
import { Alert, CircularProgress, Link, Typography } from "@mui/material";
55
import { useNevmTransaction } from "../hooks/useNevmTransaction";
66
import { useEffect } from "react";
7+
import { NEVM_TX_BLOCKCHAIN_URL } from "@constants";
78

89
type Props = {
910
successStatus: TransferStatus;
@@ -61,6 +62,10 @@ const BridgeV3ConfirmNEVMTransaction: React.FC<Props> = ({
6162
>
6263
{loadingMessage}
6364
<CircularProgress size={"1rem"} />
65+
<br />
66+
<Link href={`${NEVM_TX_BLOCKCHAIN_URL}${sourceTxHash}`} target="_blank">
67+
View on Explorer
68+
</Link>
6469
</Alert>
6570
);
6671
};

components/Bridge/v3/Steps/ConfirmUTXOTransaction.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Alert, Box, CircularProgress } from "@mui/material";
1+
import { Alert, Box, CircularProgress, Link } from "@mui/material";
22
import { useTransfer } from "../context/TransferContext";
33
import { useUtxoTransaction } from "components/Bridge/v3/hooks/useUtxoTransaction";
44
import { ITransferLog, TransferStatus } from "@contexts/Transfer/types";
55
import { useEffect } from "react";
6+
import { SYSCOIN_TX_BLOCKCHAIN_URL } from "@constants";
67

78
type Props = {
89
invalidStateMessage: string;
@@ -67,6 +68,10 @@ const BridgeV3StepConfirmUTXOTransaction: React.FC<Props> = ({
6768
>
6869
{loadingMessage} &nbsp;
6970
<CircularProgress size={"1rem"} />
71+
<br />
72+
<Link href={`${SYSCOIN_TX_BLOCKCHAIN_URL}${txId}`} target="_blank">
73+
View on Explorer
74+
</Link>
7075
</Alert>
7176
);
7277
};

constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ export const MIN_AMOUNT = 0.00015;
22

33
export const RELAY_CONTRACT_ADDRESS =
44
"0xD822557aC2F2b77A1988617308e4A29A89Cb95A6";
5+
6+
export const SYSCOIN_TX_BLOCKCHAIN_URL = "https://blockbook.elint.services/tx/";
7+
export const NEVM_TX_BLOCKCHAIN_URL = "https://explorer.syscoin.org/tx/";

lib/mongodb.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import mongoose, { ConnectOptions } from "mongoose";
2+
declare global {
3+
var mongoose: any; // This must be a `var` and not a `let / const`
4+
}
5+
6+
const MONGODB_URI = process.env.MONGODB_URI!;
7+
8+
if (!MONGODB_URI) {
9+
throw new Error(
10+
"Please define the MONGODB_URI environment variable inside .env.local"
11+
);
12+
}
13+
14+
let cached = global.mongoose;
15+
16+
if (!cached) {
17+
cached = global.mongoose = { conn: null, promise: null };
18+
}
19+
20+
async function dbConnect() {
21+
if (cached.conn) {
22+
return cached.conn;
23+
}
24+
if (!cached.promise) {
25+
const opts: ConnectOptions = {
26+
bufferCommands: false,
27+
};
28+
console.log({ MONGODB_URI, opts });
29+
cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
30+
return mongoose;
31+
});
32+
}
33+
try {
34+
cached.conn = await cached.promise;
35+
} catch (e) {
36+
cached.promise = null;
37+
throw e;
38+
}
39+
40+
return cached.conn;
41+
}
42+
43+
export default dbConnect;

models/transfer.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { ITransfer, ITransferLog } from "@contexts/Transfer/types";
2+
import mongoose from "mongoose";
3+
4+
export type Transfer = mongoose.Document & ITransfer;
5+
6+
const TransferLogSchema = new mongoose.Schema<ITransferLog>({
7+
date: {
8+
type: Number,
9+
},
10+
status: {
11+
type: String,
12+
},
13+
payload: {
14+
type: Object,
15+
},
16+
});
17+
18+
const TransferSchema = new mongoose.Schema<Transfer>({
19+
id: {
20+
type: String,
21+
},
22+
type: {
23+
type: String,
24+
},
25+
status: {
26+
type: String,
27+
},
28+
logs: [TransferLogSchema],
29+
createdAt: {
30+
type: Number,
31+
},
32+
updatedAt: {
33+
type: Number,
34+
},
35+
utxoAddress: {
36+
type: String,
37+
},
38+
utxoXpub: {
39+
type: String,
40+
},
41+
nevmAddress: {
42+
type: String,
43+
},
44+
version: {
45+
type: String,
46+
},
47+
amount: {
48+
type: String,
49+
},
50+
});
51+
52+
export default mongoose.models.Transfer ||
53+
mongoose.model("Transfer", TransferSchema);

next.config.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ const nextConfig = {
66

77
return config;
88
},
9-
env: {
10-
MONGODB_URI: "mongodb://admin:admin@localhost:27017/syscoin-bridge",
11-
},
12-
output: 'standalone',
9+
output: "standalone",
1310
images: {
14-
domains: ['syscoin.github.io']
15-
}
11+
domains: ["syscoin.github.io"],
12+
},
1613
};
1714

1815
module.exports = nextConfig;
1916

20-
2117
// Injected content via Sentry wizard below
2218

2319
const { withSentryConfig } = require("@sentry/nextjs");

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"bitcoinjs-lib": "^6.0.1",
2424
"firebase": "^9.22.1",
2525
"firebase-admin": "^10.2.0",
26+
"mongoose": "^7.5.0",
2627
"next": "13.2.4",
2728
"react": "18.1.0",
2829
"react-dom": "18.1.0",

pages/api/transfer/[id].ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
import firebase from "firebase-setup";
22
import type { NextApiRequest, NextApiResponse } from "next";
3-
import { doc, getDoc, setDoc, updateDoc } from "firebase/firestore";
3+
import { doc, getDoc } from "firebase/firestore";
44
import { signInWithEmailAndPassword } from "firebase/auth";
5+
import { TransferService } from "api/services/transfer";
6+
import dbConnect from "lib/mongodb";
7+
8+
const transferService = new TransferService();
59

610
const getRequest = async (req: NextApiRequest, res: NextApiResponse) => {
711
const { id } = req.query;
12+
13+
if (!id) {
14+
return res.status(400).json({ message: "Missing id" });
15+
}
16+
17+
try {
18+
const transfer = await transferService.getTransfer(id as string);
19+
return res.status(200).json(transfer);
20+
} catch (e) {}
21+
822
if (process.env.NODE_ENV !== "development" && firebase.auth) {
923
await signInWithEmailAndPassword(
1024
firebase.auth,
@@ -27,30 +41,21 @@ const patchRequest = async (req: NextApiRequest, res: NextApiResponse) => {
2741
if (!id) {
2842
return res.status(400).json({ message: "Missing id" });
2943
}
30-
if (process.env.NODE_ENV !== "development" && firebase.auth) {
31-
await signInWithEmailAndPassword(
32-
firebase.auth,
33-
process.env.FIREBASE_AUTH_EMAIL!,
34-
process.env.FIREBASE_AUTH_PASSWORD!
35-
);
36-
}
37-
const document = doc(firebase.firestore, "transfers", id as string);
38-
39-
const transferBody = req.body;
40-
41-
const results = await getDoc(document);
4244

43-
if (results.exists()) {
44-
transferBody.updatedAt = Date.now()
45-
await updateDoc(document, transferBody);
46-
} else {
47-
await setDoc(document, transferBody);
45+
try {
46+
const updated = await transferService.upsertTransfer(req.body);
47+
res.status(200).json(updated);
48+
} catch (e) {
49+
if (e instanceof Error) {
50+
res.status(500).json({ message: e.message });
51+
} else {
52+
res.status(500).json({ message: "Unknown error" });
53+
}
4854
}
49-
const updated = await getDoc(document);
50-
res.status(200).json(updated.data());
5155
};
5256

5357
async function handler(req: NextApiRequest, res: NextApiResponse) {
58+
await dbConnect();
5459
if (req.method === "GET") {
5560
await getRequest(req, res);
5661
return;

0 commit comments

Comments
 (0)