Skip to content

Commit

Permalink
Merge pull request #68 from IntersectMBO/feat/add-validation-check-me…
Browse files Browse the repository at this point in the history
…tadata-uri

Feat/add validation check metadata uri
  • Loading branch information
elenabardho authored Feb 11, 2025
2 parents b84f470 + f6a2ccb commit 0712962
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
17 changes: 13 additions & 4 deletions src/app/components/transaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as CLS from "@emurgo/cardano-serialization-lib-browser";
import ReactJsonPretty from 'react-json-pretty';
import * as txValidationUtils from "../utils/txValidationUtils";
import { TransactionChecks } from "./validationChecks";
import { decodeHextoTx,convertGAToBech,getCardanoScanURL} from "../utils/txUtils";
import { decodeHextoTx,convertGAToBech,getCardanoScanURL,getDataHashFromURI} from "../utils/txUtils";
import { VotingDetails } from "./votingDetails";


Expand All @@ -30,6 +30,7 @@ export const TransactionButton = () => {
isSameNetwork: false,
hasICCCredentials: false,
isInOutputPlutusData: false,
isMetadataAnchorValid: false,
});
const resetValidationState = () => {
setValidationState((prev) => ({
Expand All @@ -40,6 +41,7 @@ export const TransactionButton = () => {
isSameNetwork: false,
hasICCCredentials: false,
isInOutputPlutusData: false,
isMetadataAnchorValid: false,
}));
};

Expand Down Expand Up @@ -89,8 +91,12 @@ export const TransactionButton = () => {
const voting_procedures= transactionBody.to_js_value().voting_procedures;
if (!voting_procedures) throw new Error("Transaction has no voting procedures.");
const votes=voting_procedures[0].votes;
if (!votes) throw new Error("Transaction has no votes.");
const hasOneVote = txValidationUtils.hasOneVoteOnTransaction(transactionBody);
const vote = voting_procedures[0].votes[0].voting_procedure.vote;
if(!votes[0].voting_procedure.anchor) throw new Error("Vote has no anchor.");
const voteMetadataURL = votes[0].voting_procedure.anchor.anchor_url;
const voteMetadataHash = votes[0].voting_procedure.anchor.anchor_data_hash;

setValidationState({
isPartOfSigners: await txValidationUtils.isPartOfSigners(transactionBody, stakeCred),
Expand All @@ -99,6 +105,7 @@ export const TransactionButton = () => {
isSameNetwork: txValidationUtils.isSameNetwork(transactionBody, network),
hasICCCredentials: txValidationUtils.hasValidICCCredentials(transactionBody, network),
isInOutputPlutusData: txValidationUtils.isSignerInPlutusData(transactionBody, stakeCred),
isMetadataAnchorValid: await txValidationUtils.checkMetadataAnchor(voteMetadataURL,voteMetadataHash),
});

//********************************************Voting Details *********************************************************************/
Expand All @@ -108,13 +115,15 @@ export const TransactionButton = () => {
if (votes && hasOneVote) {

const govActionID = convertGAToBech(votes[0].action_id.transaction_id, votes[0].action_id.index);

setvoteChoice(vote === 'Yes' ? 'Constitutional' : vote === 'No' ? 'Unconstitutional' : 'Abstain');
setgovActionID(govActionID);
if(!votes[0].voting_procedure.anchor) throw new Error("Vote has no anchor.");
setmetadataAnchorURL(votes[0].voting_procedure.anchor.anchor_url);
setMetadataAnchorHash(votes[0].voting_procedure.anchor.anchor_data_hash);
setmetadataAnchorURL(voteMetadataURL);
setMetadataAnchorHash(voteMetadataHash);
setCardanoscan(getCardanoScanURL(govActionID,transactionNetworkID));
}
}



}
Expand Down
6 changes: 6 additions & 0 deletions src/app/components/validationChecks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface TransactionChecksProps {
isSameNetwork: boolean;
hasICCCredentials: boolean;
isInOutputPlutusData: boolean;
isMetadataAnchorValid: boolean;
}

export const TransactionChecks = ({
Expand All @@ -16,6 +17,7 @@ export const TransactionChecks = ({
isSameNetwork,
hasICCCredentials,
isInOutputPlutusData,
isMetadataAnchorValid,
}: TransactionChecksProps) => {
return (

Expand Down Expand Up @@ -43,6 +45,10 @@ export const TransactionChecks = ({
<Typography display="flex" flexDirection="column" width="45%" variant="body1" fontWeight="bold">
Is stake credential in plutus data?: {isInOutputPlutusData ? "✅" : "❌"}
</Typography>

<Typography display="flex" flexDirection="column" width="45%" variant="body1" fontWeight="bold">
Does the metadata match the provided hash? ?: {isMetadataAnchorValid ? "✅" : "❌"}
</Typography>
</Box>

);
Expand Down
22 changes: 21 additions & 1 deletion src/app/utils/txUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as CLS from "@emurgo/cardano-serialization-lib-browser";
import { deserializeAddress } from "@meshsdk/core";
import dotevn from "dotenv";
import * as blake from 'blakejs';
dotevn.config();
const NEXT_PUBLIC_REST_IPFS_GATEWAY=process.env.NEXT_PUBLIC_REST_IPFS_GATEWAY;

Expand Down Expand Up @@ -62,4 +63,23 @@ export const openInNewTab = (url: string) => {
? "https://" + NEXT_PUBLIC_REST_IPFS_GATEWAY + url?.slice(7)
: "https://" + url;
window.open(fullUrl, "_blank", "noopener,noreferrer");
};
};

export const getDataHashFromURI = async (anchorURL: string) => {
console.log('Callllll fuuunctioooon');
if (anchorURL !== "") {
console.log("Anchor data null")
}
if (anchorURL.startsWith("ipfs")) {
anchorURL = "https://" + NEXT_PUBLIC_REST_IPFS_GATEWAY + anchorURL.slice(7);
}
// anchorURL='https://ipfs.io/ipfs/bafkreidsmyjjfrsvj3czrsu5roy2undco2bhhcnqdgbievolgbyi7lptxy'
const data = await fetch(anchorURL);
const text = await data.text();
console.log('THEEEEE TEXT',text);
const hash = blake.blake2bHex(text,undefined, 32);
console.log("Hash from text:", hash);
return hash
}


17 changes: 17 additions & 0 deletions src/app/utils/txValidationUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {getDataHashFromURI} from "../utils/txUtils";

/**
* Checks if the given stake credential is part of the required signers of the transaction.
* @param transactionBody the body of the transaction to check.
Expand Down Expand Up @@ -156,3 +158,18 @@ export const isSignerInPlutusData = (transactionBody: any, stakeCredential: stri
return false;
};

/**
* Checks if the given anchor URL produces the given anchor data hash.
* @param anchorURL The URL of the anchor to check.
* @param anchor_data_hash The expected anchor data hash.
* @returns {Promise<boolean>} True if the anchor URL produces the expected hash, false otherwise.
*/
export const checkMetadataAnchor = async (anchorURL: string, anchor_data_hash: string): Promise<boolean> => {
try {
const producedHash = await getDataHashFromURI(anchorURL);
return producedHash === anchor_data_hash;
} catch (error) {
console.error("Error fetching metadata:", error);
return false;
}
};

0 comments on commit 0712962

Please sign in to comment.