Skip to content

Commit

Permalink
send transction from backend
Browse files Browse the repository at this point in the history
  • Loading branch information
technophile-04 committed Nov 5, 2024
1 parent 0ac4b11 commit 242359d
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 50 deletions.
29 changes: 11 additions & 18 deletions packages/hardhat/contracts/YourContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,41 +90,34 @@ contract YourContract is ERC721, Groth16Verifier, Poseidon {

// Verify beauty
input[0] = attrs.beauty;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[0], "Invalid beauty value");
require(this.hash(input) == pubSignals[0], "Invalid beauty value");

// Verify biome
input[0] = attrs.biome;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[1], "Invalid biome value");
//
require(this.hash(input) == pubSignals[1], "Invalid biome value");

// Verify intelligence
input[0] = attrs.intelligence;
console.log(this.hash(input));
// require(
// this.hash(input) == pubSignals[2],
// "Invalid intelligence value"
// );
require(
this.hash(input) == pubSignals[3],
"Invalid intelligence value"
);

// Verify jump
input[0] = attrs.jump;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[3], "Invalid jump value");
require(this.hash(input) == pubSignals[4], "Invalid jump value");

// Verify owner
input[0] = attrs.owner;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[5], "Invalid owner value");
require(this.hash(input) == pubSignals[6], "Invalid owner value");

// Verify rarity
input[0] = attrs.rarity;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[6], "Invalid rarity value");
require(this.hash(input) == pubSignals[7], "Invalid rarity value");

// Verify speed
input[0] = attrs.speed;
console.log(this.hash(input));
// require(this.hash(input) == pubSignals[7], "Invalid speed value");
require(this.hash(input) == pubSignals[8], "Invalid speed value");

return true;
}
Expand Down
143 changes: 143 additions & 0 deletions packages/nextjs/app/api/mint/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// app/api/mint/route.ts
import { NextResponse } from "next/server";
import { createWalletClient, fallback, http, verifyMessage } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import deployedContracts from "~~/contracts/deployedContracts";
import scaffoldConfig from "~~/scaffold.config";
import { getAlchemyHttpUrl, getParsedError } from "~~/utils/scaffold-eth";

const wallet_private_key = (process.env.WALLET_PRIVATE_KEY ||
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") as `0x${string}`;

const { targetNetworks } = scaffoldConfig;

const mainNetwork = targetNetworks[0];
const alchemyHttpUrl = getAlchemyHttpUrl(mainNetwork.id);
const rpcFallbacks = alchemyHttpUrl ? [http(alchemyHttpUrl), http()] : [http()];

const walletClient = createWalletClient({
chain: mainNetwork,
transport: fallback(rpcFallbacks),
account: privateKeyToAccount(wallet_private_key),
});

type ProofData = {
pi_a: string[];
pi_b: string[][]; // Array of arrays for pi_b
pi_c: string[];
pubSignals: string[];
};

type FrogStats = {
beauty: string;
biome: string;
intelligence: string;
jump: string;
speed: string;
rarity: string;
owner: string;
name: string;
description: string;
};

type MintRequestBody = {
proof: ProofData;
frogStats: FrogStats;
signature: string;
address: string;
};

// Utility function to convert string arrays to BigInt arrays
const convertToBigIntArray = (arr: string[]): bigint[] => {
return arr.map(str => BigInt(str));
};

// Utility function to convert nested string arrays to nested BigInt arrays
const convertToBigIntNestedArray = (arr: string[][]): bigint[][] => {
return arr.map(subArr => subArr.map(str => BigInt(str)));
};

// Utility function to convert frog stats to BigInt
const convertFrogStatsToBigInt = (stats: Omit<FrogStats, "description">) => {
return {
beauty: BigInt(stats.beauty),
biome: BigInt(stats.biome),
intelligence: BigInt(stats.intelligence),
jump: BigInt(stats.jump),
speed: BigInt(stats.speed),
rarity: BigInt(stats.rarity),
owner: BigInt(stats.owner),
name: stats.name, // Keep as string
};
};

// Utility function to convert proof data to BigInt
const convertProofToBigInt = (proof: ProofData) => {
return {
pi_a: convertToBigIntArray(proof.pi_a),
pi_b: convertToBigIntNestedArray(proof.pi_b), // Using nested array conversion for pi_b
pi_c: convertToBigIntArray(proof.pi_c),
pubSignals: convertToBigIntArray(proof.pubSignals),
};
};

export async function POST(req: Request) {
try {
const body: MintRequestBody = await req.json();

// Convert string values to BigInt
const convertedProof = convertProofToBigInt(body.proof);
const { description, ...actualStats } = body.frogStats;
const convertedFrogStats = convertFrogStatsToBigInt(actualStats);

// Verify signature
const isValidSignature = await verifyMessage({
message: `I own ${body.frogStats.name}`,
signature: body.signature as `0x${string}`,
address: body.address as `0x${string}`,
});

if (!isValidSignature) {
return NextResponse.json({ error: "Invalid signature" }, { status: 400 });
}

console.log("The description values are: ", description);

const { address: contractAddress, abi: contractAbi } = deployedContracts[mainNetwork.id].YourContract;
const hash = await walletClient.writeContract({
address: contractAddress,
abi: contractAbi,
functionName: "mintFrog",
args: [
{
_pA: convertedProof.pi_a as any,
_pB: convertedProof.pi_b as any,
_pC: convertedProof.pi_c as any,
_pubSignals: convertedProof.pubSignals as any,
},
{
beauty: convertedFrogStats.beauty,
biome: convertedFrogStats.biome,
intelligence: convertedFrogStats.intelligence,
jump: convertedFrogStats.jump,
speed: convertedFrogStats.speed,
rarity: convertedFrogStats.rarity,
owner: convertedFrogStats.owner,
},
],
});

return NextResponse.json(
{
success: true,
message: "NFT minted successfully",
txHash: hash,
},
{ status: 200 },
);
} catch (error) {
const parsedErrorMessage = getParsedError(error);
console.error(error);
return NextResponse.json({ error: parsedErrorMessage }, { status: 500 });
}
}
74 changes: 44 additions & 30 deletions packages/nextjs/app/zpass/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { gpcPreVerify } from "@pcd/gpc";
import { ProtoPODGPC } from "@pcd/gpcircuits";
import { POD, PODEntries } from "@pcd/pod";
import { PartialDeep } from "type-fest";
import { useAccount } from "wagmi";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
import { notification } from "~~/utils/scaffold-eth";
import { useAccount, useSignMessage } from "wagmi";
import { getParsedError, notification } from "~~/utils/scaffold-eth";
import { replacer } from "~~/utils/scaffold-eth/common";

export interface PODData {
entries: PODEntries;
Expand Down Expand Up @@ -75,7 +75,7 @@ const ZuAuth = () => {
const [z, setZ] = useState<ParcnetAPI | null>(null);
const [isLoading, setIsLoading] = useState(false);

const { writeContractAsync: writeYourContractAsync } = useScaffoldWriteContract("YourContract");
const { signMessageAsync } = useSignMessage();

const handleAuth = async () => {
try {
Expand Down Expand Up @@ -137,16 +137,10 @@ const ZuAuth = () => {
if (result.success) {
const boundConfig = result.boundConfig;
const revealedClaims = result.revealedClaims;
console.log("The revealed claims", revealedClaims);
console.log("The proof is:", result.proof);

const circuit = gpcPreVerify(boundConfig, revealedClaims);
const pubSignals = ProtoPODGPC.makePublicSignals(circuit.circuitPublicInputs, circuit.circuitOutputs);
console.log("The public signals", pubSignals);

const frogStats = revealedClaims.pods.FROGCRYPTO?.entries;
console.log("The reveleadClaims", revealedClaims);
console.log("The frog stats", frogStats);
const frogName = frogStats?.name.value;

const beauty = frogStats?.beauty.value as any as bigint;
Expand All @@ -156,36 +150,56 @@ const ZuAuth = () => {
const speed = frogStats?.speed.value as any as bigint;
const rarity = frogStats?.rarity.value as any as bigint;
const owner = frogStats?.owner.value as any as bigint;
const description = frogStats?.description.value as any as string;

notification.info("Minting your Frog NFT...");
const signature = await signMessageAsync({
message: `I own ${frogName}`,
});

const mintResult = await writeYourContractAsync({
functionName: "mintFrog",
args: [
{
_pA: result.proof.pi_a.slice(0, -1),
_pB: result.proof.pi_b.slice(0, -1),
_pC: result.proof.pi_c.slice(0, -1),
_pubSignals: pubSignals as any,
},
// Send data to backend
const response = await fetch("/api/mint", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(
{
beauty,
biome,
intelligence,
jump,
speed,
rarity,
owner,
proof: {
pi_a: result.proof.pi_a.slice(0, -1),
pi_b: result.proof.pi_b.slice(0, -1),
pi_c: result.proof.pi_c.slice(0, -1),
pubSignals: pubSignals,
},
frogStats: {
beauty: beauty.toString(),
biome: biome.toString(),
intelligence: intelligence.toString(),
jump: jump.toString(),
speed: speed.toString(),
rarity: rarity.toString(),
owner: owner.toString(),
name: frogName,
description,
},
signature,
address: connectedAddress,
},
],
replacer,
),
});
const data = await response.json();

console.log("Mint transaction:", mintResult);
if (!response.ok) {
throw new Error(data.error);
}

console.log("The data is", data);
notification.success(`Successfully minted Frog NFT: ${frogName}`);
}
} catch (e) {
console.log("error", e);
notification.error("Failed to mint NFT");
const errorMessage = getParsedError(e);
notification.error(errorMessage);
} finally {
setIsLoading(false);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/contracts/deployedContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
const deployedContracts = {
31337: {
Poseidon: {
address: "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
abi: [
{
inputs: [
Expand All @@ -32,7 +32,7 @@ const deployedContracts = {
inheritedFunctions: {},
},
YourContract: {
address: "0x0165878A594ca255338adfa4d48449f69242Eb8F",
address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
abi: [
{
inputs: [],
Expand Down

0 comments on commit 242359d

Please sign in to comment.