Skip to content

Commit

Permalink
Add schema validation to send transaction (#1132)
Browse files Browse the repository at this point in the history
* add schema validation to send notification

* add transaction validation
  • Loading branch information
andy-t-wang authored Jan 13, 2025
1 parent 24f336c commit 4a7917f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 23 deletions.
51 changes: 30 additions & 21 deletions web/api/v2/minikit/transaction/[transaction_id]/index.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,61 @@
import { errorResponse } from "@/api/helpers/errors";
import { validateRequestSchema } from "@/api/helpers/validate-request-schema";
import { logger } from "@/lib/logger";
import { TransactionTypes } from "@/lib/types";
import { createSignedFetcher } from "aws-sigv4-fetch";
import { NextRequest, NextResponse } from "next/server";
import * as yup from "yup";

function corsHandler(response: NextResponse) {
response.headers.set("Access-Control-Allow-Origin", "*");
response.headers.set("Access-Control-Allow-Methods", "GET, OPTIONS");
return response;
}

const appIdRegex = /^app_[a-f0-9]{32}$/;
const transactionIdRegex = /^0x[a-f0-9]{64}$/;

const schema = yup.object({
app_id: yup
.string()
.matches(appIdRegex, "app_id must be in format app_{32 hex chars}")
.required(),
type: yup.string().oneOf(Object.values(TransactionTypes)).required(),
});

export const GET = async (
req: NextRequest,
{ params: routeParams }: { params: { transaction_id: string } },
) => {
const { searchParams } = new URL(req.url);
const transactionId = routeParams.transaction_id;

const appId = searchParams.get("app_id");
const type = searchParams.get("type") ?? TransactionTypes.Payment;

if (
type !== TransactionTypes.Payment &&
type !== TransactionTypes.Transaction
) {
// Add transaction_id validation
if (!transactionIdRegex.test(transactionId)) {
return corsHandler(
errorResponse({
statusCode: 400,
code: "invalid_request",
detail: "Invalid transaction type.",
attribute: "type",
code: "invalid_parameter",
detail: "Invalid transaction ID",
attribute: "transaction_id",
req,
}),
);
}

if (!appId) {
return corsHandler(
errorResponse({
statusCode: 400,
code: "invalid_request",
detail: "App ID is required.",
attribute: "app_id",
req,
}),
);
const { isValid, parsedParams, handleError } = await validateRequestSchema({
schema,
value: {
app_id: searchParams.get("app_id"),
type: searchParams.get("type") ?? TransactionTypes.Payment,
},
});

if (!isValid) {
return handleError(req);
}

const transactionId = routeParams.transaction_id;
const { app_id: appId, type } = parsedParams;

const signedFetch = createSignedFetcher({
service: "execute-api",
Expand Down
5 changes: 3 additions & 2 deletions web/tests/api/v2/minikit-transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ const validApiKeyResponse = {
is_active: true,
team: {
id: "team_dd2ecd36c6c45f645e8e5d9a31abdee1",
apps: [{ id: "app_staging_9cdd0a714aec9ed17dca660bc9ffe72a" }],
apps: [{ id: "app_9cdd0a714aec9ed17dca660bc9ffe72a" }],
},
},
};

const validAppId = validApiKeyResponse.api_key_by_pk.team.apps[0].id;
const validTransactionId = "transaction_123";
const validTransactionId =
"0x8004b63530b968a2a2c9ff414e01fc06a3ec5e4068d36d923df6aa4334744369";
const validApiKey = `api_${apiKeyValue}`;

// #endregion
Expand Down

0 comments on commit 4a7917f

Please sign in to comment.