Skip to content

Commit

Permalink
Merge pull request #1 from amhedcb/amhed/confirmation-code
Browse files Browse the repository at this point in the history
Adds confirmation code
  • Loading branch information
justin-lee-cb authored Sep 26, 2024
2 parents ceea242 + 1920b59 commit c5e64fb
Show file tree
Hide file tree
Showing 21 changed files with 1,209 additions and 1,112 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Run Tests

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build
run: yarn build
- name: Run tests
run: yarn test
16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"start": "next start",
"lint": "next lint",
"test": "jest",
"postinstall": "prisma generate"
"postinstall": "prisma generate",
"prepush": "yarn test"
},
"dependencies": {
"@prisma/client": "^3.6.0",
Expand All @@ -28,10 +29,19 @@
"eslint": "^8.2.0",
"eslint-config-next": "^12.0.0",
"eslint-config-prettier": "^8.3.0",
"jest": "^27.0.6",
"jest": "^29.7.0",
"lint-staged": "^12.0.6",
"prettier": "^2.4.1",
"prisma": "^3.6.0",
"ts-jest": "^29.2.5",
"typescript": "^4.4.4"
}
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"jest --bail --findRelatedTests"
]
},
"packageManager": "[email protected]+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
}
38 changes: 38 additions & 0 deletions prisma/migrations/20240925193950_simplify_tables/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Warnings:
- You are about to drop the `ContactlessPaymentMessage` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `ContactlessPaymentTxData` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `Nonce` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `PaymentTx` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropTable
DROP TABLE "ContactlessPaymentMessage";

-- DropTable
DROP TABLE "ContactlessPaymentTxData";

-- DropTable
DROP TABLE "Nonce";

-- DropTable
DROP TABLE "PaymentTx";

-- CreateTable
CREATE TABLE "ContactlessPaymentTxOrMsg" (
"uuid" TEXT NOT NULL,
"verificationCode" TEXT NOT NULL,
"toAddress" TEXT NOT NULL,
"chainId" TEXT NOT NULL,
"contractAddress" TEXT NOT NULL,
"value" TEXT NOT NULL,
"txParams" JSONB,
"rpcProxySubmissionParams" JSONB,
"dappName" TEXT,
"dappUrl" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "ContactlessPaymentTxOrMsg_pkey" PRIMARY KEY ("uuid")
);
12 changes: 12 additions & 0 deletions prisma/migrations/20240925194407_simplify_more/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Warnings:
- You are about to drop the column `contractAddress` on the `ContactlessPaymentTxOrMsg` table. All the data in the column will be lost.
- You are about to drop the column `toAddress` on the `ContactlessPaymentTxOrMsg` table. All the data in the column will be lost.
- You are about to drop the column `value` on the `ContactlessPaymentTxOrMsg` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "ContactlessPaymentTxOrMsg" DROP COLUMN "contractAddress",
DROP COLUMN "toAddress",
DROP COLUMN "value";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:
- Added the required column `payloadType` to the `ContactlessPaymentTxOrMsg` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "ContactlessPaymentTxOrMsg" ADD COLUMN "payloadType" TEXT NOT NULL;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "ContactlessPaymentTxOrMsg" ADD COLUMN "additionalPayload" JSONB;
44 changes: 4 additions & 40 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,16 @@ datasource db {
url = env("DATABASE_URL")
}

model PaymentTx {
model ContactlessPaymentTxOrMsg {
uuid String @id
toAddress String
verificationCode String
payloadType String
chainId String
contractAddress String
value String
data Json?
dappName String?
dappUrl String?
rpcProxySubmissionParams Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model ContactlessPaymentTxData {
uuid String @id
chainId String
requiresSenderAddress Boolean?
contractAbi String?
placeholderSenderAddress String?
approveTxs Json?
txParams Json?
rpcProxySubmissionParams Json?
paymentTx Json
dappName String?
dappUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model ContactlessPaymentMessage {
uuid String @id
chainId String
rpcProxySubmissionParams Json @default("{}")
message Json
additionalPayload Json?
dappName String?
dappUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model Nonce {
id Int @id @default(autoincrement())
chainId String
address String
nonce BigInt @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
2 changes: 2 additions & 0 deletions src/FiatTokenAbi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// TODO: Amhed: Move these to /types folder

export const fiatTokenAbi = [
{
anonymous: false,
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/cleanup-payments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export async function cleanupOldPayments() {
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);

try {
const result = await prisma.paymentTx.deleteMany({
const result = await prisma.contactlessPaymentTxOrMsg.deleteMany({
where: {
createdAt: {
lt: fiveMinutesAgo
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/formatTxDataResponse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ethers } from "ethers";


// TODO: Justin, can we separate helpers related to slice unto their own folder?
type Props = {
txData: any;
buyerAddress?: string;
Expand Down
8 changes: 8 additions & 0 deletions src/helpers/generate-random-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function generateRandomString(length = 8): string {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
58 changes: 14 additions & 44 deletions src/pages/api/paymentTxParams/[uuid].ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,33 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { getPrismaClient } from '@helpers/database';
import { formatTxDataResponse } from '@/helpers/formatTxDataResponse';
import { ethers } from 'ethers';
import { formatTxMessageResponse } from '@/helpers/formatTxMessageResponse';
import { getPaymentTxOrMsg } from '@/services/paymentTxOrMsgService';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const prisma = getPrismaClient();

if (req.method === 'GET') {
try {
const { uuid, buyerAddress } = req.query;
const { uuid, senderAddress } = req.query;

if (typeof uuid !== 'string') {
if (!uuid || typeof uuid !== 'string') {
return res.status(400).json({ message: 'Invalid UUID' });
}

if (!!buyerAddress && ((typeof buyerAddress !== 'string') || !ethers.utils.isAddress(buyerAddress))) {
return res.status(400).json({ message: 'Invalid buyer address' });
if (
!!senderAddress &&
(typeof senderAddress !== 'string' || !ethers.utils.isAddress(senderAddress))
) {
return res.status(400).json({ message: 'Invalid sender address' });
}

const paymentTxPromise = prisma.paymentTx.findUnique({
where: { uuid },
});
const txDataPromise = prisma.contactlessPaymentTxData.findUnique({
where: { uuid },
});
const txMessagePromise = prisma.contactlessPaymentMessage.findUnique({
where: { uuid },
});

const [paymentTx, txData, txMessage] = (await Promise.allSettled([paymentTxPromise, txDataPromise, txMessagePromise])).map(promiseResult => {
if (promiseResult.status === 'fulfilled') {
return promiseResult.value
};

return undefined;
});

if (!txData && !paymentTx && !txMessage) {
return res.status(404).json({ message: 'Not Found' });
}

if (paymentTx) {
res.status(200).json({ payloadType: 'eip681', ...paymentTx });
} else if (txData) {
// Substitute the buyer address into the tx call data if applicable
const formattedTxData = await formatTxDataResponse({ txData, buyerAddress });
res.status(200).json({ payloadType: 'contractCall', ...formattedTxData })
} else {
// Substitute the buyer address into the message's from field if applicable
const formattedTxMessage = formatTxMessageResponse({ txMessage, buyerAddress });
res.status(200).json({ payloadType: 'eip712', ...formattedTxMessage });
}
const paymentTxOrMsg = await getPaymentTxOrMsg(uuid as string);
res.status(200).json(paymentTxOrMsg);
} catch (error) {
console.error('Error retrieving payment transaction:', error);
res.status(500).json({ message: `Error retrieving payment transaction: ${(error as Error).message}` });
res
.status(500)
.json({ message: `Error retrieving payment transaction: ${(error as Error).message}` });
}
} else {
res.setHeader('Allow', ['GET']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
}
Loading

0 comments on commit c5e64fb

Please sign in to comment.