Skip to content

Commit

Permalink
feat: add transaction payload validation (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
michalstruck authored Jan 7, 2025
1 parent 9034392 commit 00cb744
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
20 changes: 20 additions & 0 deletions packages/core/helpers/transaction/validate-payload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { SendTransactionInput } from "types/commands";
type ValidationReturn = { isValid: true } | { isValid: false };

const validate = (payload: any): ValidationReturn => {
if (typeof payload === "string") return { isValid: true };
if (typeof payload === "object") {
const isValid = Object.values(payload).every(
(value) => validate(value).isValid
);
return { isValid };
}
if (Array.isArray(payload)) {
const isValid = payload.every((value) => validate(value).isValid);
return { isValid };
}
return { isValid: false };
};

export const validateSendTransactionPayload = (payload: SendTransactionInput) =>
validate(payload);
8 changes: 8 additions & 0 deletions packages/core/minikit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { validateWalletAuthCommandInput } from "helpers/siwe/validate-wallet-aut
import { generateSiweMessage } from "helpers/siwe/siwe";
import { validatePaymentPayload } from "helpers/payment/client";
import { getUserProfile } from "helpers/usernames";
import { validateSendTransactionPayload } from "helpers/transaction/validate-payload";
import { User } from "./types/user";
import {
MiniKitInstallErrorCodes,
Expand Down Expand Up @@ -399,6 +400,13 @@ export class MiniKit {
return null;
}

if (!validateSendTransactionPayload(payload).isValid) {
console.error(
"Invalid sendTransaction payload - some object properties are not strings"
);
return null;
}

sendMiniKitEvent<WebViewBasePayload>({
command: Command.SendTransaction,
version: 1,
Expand Down
115 changes: 115 additions & 0 deletions tests/validate-payload.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// import { validateSendTransactionPayload } from "@worldcoin/minikit-js/core/helpers/transaction/validate-transaction";
const validate = (payload) => {
if (typeof payload === "string") return { isValid: true };
if (typeof payload === "object") {
const isValid = Object.values(payload).every(
(value) => validate(value).isValid
);
return { isValid };
}
if (Array.isArray(payload)) {
const isValid = payload.every((value) => validate(value).isValid);
return { isValid };
}
return { isValid: false };
};

export const validateSendTransactionPayload = (payload) => validate(payload);

describe("validateSendTransactionPayload", () => {
it("should validate simple string values", () => {
const payload = {
transaction: [
{
address: "0x123",
functionName: "transfer",
args: ["0x456", "1000000000000000000"],
},
],
};
expect(validateSendTransactionPayload(payload)).toMatchObject({
isValid: true,
});
});

it("should validate nested objects", () => {
const payload = {
transaction: [
{
address: "0x123",
abi: [
{
name: "transfer",
type: "function",
inputs: [
{ name: "recipient", type: "address" },
{ name: "amount", type: "uint256" },
],
},
],
functionName: "transfer",
args: ["0x456", "1000000000000000000"],
},
],
};
expect(validateSendTransactionPayload(payload)).toMatchObject({
isValid: true,
});
});

it("should validate with permit2 data", () => {
const payload = {
transaction: [
{
address: "0x123",
functionName: "transfer",
args: ["0x456", "1000000000000000000"],
},
],
permit2: [
{
permitted: {
token: "0x789",
amount: "1000000000000000000",
},
spender: "0xabc",
nonce: "1",
deadline: "1234567890",
},
],
};
expect(validateSendTransactionPayload(payload)).toMatchObject({
isValid: true,
});
});

it("should reject invalid values like numbers", () => {
const payload = {
transaction: [
{
address: "0x123",
functionName: "transfer",
args: [123, "1000000000000000000"], // number instead of string
},
],
};
expect(validateSendTransactionPayload(payload)).toMatchObject({
isValid: false,
});
});

it("should reject invalid values like booleans", () => {
const payload = {
transaction: [
{
address: "0x123",
functionName: "transfer",
args: [true, "1000000000000000000"], // boolean instead of string
},
],
};
expect(validateSendTransactionPayload(payload)).toMatchObject({
isValid: false,
});
});
});

0 comments on commit 00cb744

Please sign in to comment.