diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index c19ae407f..d8f3a99c1 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -113,4 +113,80 @@ export const valid = { return username; }, + metadata: () => ({ + "@context": { + "@language": "en-us", + CIP100: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-0100/README.md#", + CIPQQQ: + "https://github.com/cardano-foundation/CIPs/blob/master/CIP-QQQ/README.md#", + hashAlgorithm: "CIP100:hashAlgorithm", + body: { + "@id": "CIPQQQ:body", + "@context": { + references: { + "@id": "CIPQQQ:references", + "@container": "@set", + "@context": { + GovernanceMetadata: "CIP100:GovernanceMetadataReference", + Other: "CIP100:OtherReference", + label: "CIP100:reference-label", + uri: "CIP100:reference-uri", + referenceHash: { + "@id": "CIPQQQ:referenceHash", + "@context": { + hashDigest: "CIPQQQ:hashDigest", + hashAlgorithm: "CIP100:hashAlgorithm", + }, + }, + }, + }, + dRepName: "CIPQQQ:dRepName", + bio: "CIPQQQ:bio", + email: "CIPQQQ:email", + }, + }, + authors: { + "@id": "CIP100:authors", + "@container": "@set", + "@context": { + name: "http://xmlns.com/foaf/0.1/name", + witness: { + "@id": "CIP100:witness", + "@context": { + witnessAlgorithm: "CIP100:witnessAlgorithm", + publicKey: "CIP100:publicKey", + signature: "CIP100:signature", + }, + }, + }, + }, + }, + authors: [], + hashAlgorithm: { + "@value": "blake2b-256", + }, + body: { + bio: { + "@value": faker.lorem.sentences(), + }, + dRepName: { + "@value": faker.person.firstName(), + }, + email: { + "@value": faker.internet.email(), + }, + references: [ + { + "@type": "Other", + label: { + "@value": "Label", + }, + uri: { + "@value": faker.internet.url(), + }, + }, + ], + }, + }), }; diff --git a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts index 9c3657f95..1f87d923b 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -1,4 +1,9 @@ +import { faker } from "@faker-js/faker"; +import { valid as mockValid } from "@mock/index"; import { Download } from "@playwright/test"; +import metadataBucketService from "@services/metadataBucketService"; +const blake = require("blakejs"); + import * as fs from "fs"; export async function downloadMetadata(download: Download): Promise<{ @@ -11,3 +16,26 @@ export async function downloadMetadata(download: Download): Promise<{ const jsonData = JSON.parse(fileContent); return { name: download.suggestedFilename(), data: jsonData }; } + +function calculateMetadataHash() { + try { + const data = JSON.stringify(mockValid.metadata()); + + const buffer = Buffer.from(data, "utf8"); + const hexDigest = blake.blake2bHex(buffer, null, 32); + + const jsonData = JSON.parse(data); + return { hexDigest, jsonData }; + } catch (error) { + console.error("Error reading file:", error); + } +} + +export async function uploadMetadataAndGetJsonHash() { + const { hexDigest: dataHash, jsonData } = calculateMetadataHash(); + const url = await metadataBucketService.uploadMetadata( + faker.person.firstName(), + jsonData + ); + return { dataHash, url }; +} diff --git a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts index e8a04e3fc..5cc321295 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/transaction.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/transaction.ts @@ -5,6 +5,8 @@ import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; import { Logger } from "../../../cypress/lib/logger/logger"; import convertBufferToHex from "./convertBufferToHex"; import { ShelleyWallet } from "./crypto"; +import { uploadMetadataAndGetJsonHash } from "./metadata"; +import { WalletAndAnchorType } from "@types"; /** * Polls the transaction status until it's resolved or times out. @@ -112,9 +114,15 @@ export async function transferAdaForWallet( } export async function registerDRepForWallet(wallet: ShelleyWallet) { + const dataHashAndUrl = await uploadMetadataAndGetJsonHash(); + const metadataAnchorAndWallet: WalletAndAnchorType = { + ...dataHashAndUrl, + wallet: wallet.json(), + }; const registrationRes = await kuberService.dRepRegistration( convertBufferToHex(wallet.stakeKey.private), - convertBufferToHex(wallet.stakeKey.pkh) + convertBufferToHex(wallet.stakeKey.pkh), + metadataAnchorAndWallet ); await pollTransaction(registrationRes.txId, registrationRes.lockInfo); } diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index c0d4acf35..6ddc81a43 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -1,5 +1,10 @@ import { faucetWallet } from "@constants/staticWallets"; -import { KuberValue, ProtocolParams, StaticWallet } from "@types"; +import { + KuberValue, + ProtocolParams, + StaticWallet, + WalletAndAnchorType, +} from "@types"; import * as blake from "blakejs"; import environments from "lib/constants/environments"; import { LockInterceptor, LockInterceptorInfo } from "lib/lockInterceptor"; @@ -37,7 +42,11 @@ class Kuber { this.version = version; } - static generateCert(type: CertificateType, key: string) { + static generateCert( + type: CertificateType, + key: string, + metadata?: WalletAndAnchorType + ) { if (type === "registerstake" || type === "deregisterdrep") { return { type: type, @@ -48,9 +57,8 @@ class Kuber { type: "registerdrep", key: key, anchor: { - url: "https://bit.ly/3zCH2HL", - dataHash: - "1111111111111111111111111111111111111111111111111111111111111111", + url: metadata?.url || "", + dataHash: metadata?.dataHash || "", }, }; } @@ -178,27 +186,36 @@ const kuberService = { return kuber.signAndSubmitTx(req); }, - multipleDRepRegistration: (wallets: StaticWallet[]) => { + multipleDRepRegistration: (metadataAndWallets: WalletAndAnchorType[]) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); const req = { - certificates: wallets.map((wallet) => - Kuber.generateCert("registerdrep", wallet.stake.pkh) + certificates: metadataAndWallets.map((metadataAndWallet) => + Kuber.generateCert( + "registerdrep", + metadataAndWallet.wallet.stake.pkh, + metadataAndWallet + ) ), - selections: wallets.map((wallet) => { + selections: metadataAndWallets.map((metadata) => { return { type: "PaymentSigningKeyShelley_ed25519", description: "Stake Signing Key", - cborHex: `5820${wallet.stake.private}`, + cborHex: `5820${metadata.wallet.stake.private}`, }; }), }; return kuber.signAndSubmitTx(req); }, - dRepRegistration: (stakeSigningKey: string, pkh: string) => { + dRepRegistration: ( + stakeSigningKey: string, + pkh: string, + metadata: WalletAndAnchorType + ) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); + const req = { - certificates: [Kuber.generateCert("registerdrep", pkh)], + certificates: [Kuber.generateCert("registerdrep", pkh, metadata)], selections: [ { type: "PaymentSigningKeyShelley_ed25519", diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index 1b0cf3dfc..186d4dd7e 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -137,3 +137,9 @@ export type ProposedGovAction = { updatedAt: string; }; }; + +export type WalletAndAnchorType = { + url: string; + dataHash: string; + wallet: StaticWallet; +}; diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index 068ebaa6c..b872a7abe 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -2,6 +2,7 @@ import environments from "@constants/environments"; import { dRepWallets } from "@constants/staticWallets"; import { setAllureEpic, setAllureStory } from "@helpers/allure"; import { ShelleyWallet } from "@helpers/crypto"; +import { uploadMetadataAndGetJsonHash } from "@helpers/metadata"; import { pollTransaction } from "@helpers/transaction"; import { expect, test as setup } from "@playwright/test"; import kuberService from "@services/kuberService"; @@ -34,7 +35,15 @@ setup("Register DRep of static wallets", async () => { setup.setTimeout(environments.txTimeOut); try { - const res = await kuberService.multipleDRepRegistration(dRepWallets); + // Submit metadata to obtain a URL and generate hash value. + const metadataPromises = dRepWallets.map(async (dRepWallet) => { + return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; + }); + + const metadataAndDRepWallets = await Promise.all(metadataPromises); + const res = await kuberService.multipleDRepRegistration( + metadataAndDRepWallets + ); await pollTransaction(res.txId, res.lockInfo); } catch (err) { @@ -64,9 +73,16 @@ setup("Setup temporary DRep wallets", async () => { ]); await pollTransaction(initializeRes.txId, initializeRes.lockInfo); + // Submit metadata to obtain a URL and generate hash value. + const metadataPromises = dRepWallets.map(async (dRepWallet) => { + return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; + }); + + const metadatasAndDRepWallets = await Promise.all(metadataPromises); // register dRep - const registrationRes = - await kuberService.multipleDRepRegistration(dRepWallets); + const registrationRes = await kuberService.multipleDRepRegistration( + metadatasAndDRepWallets + ); await pollTransaction(registrationRes.txId, registrationRes.lockInfo); // transfer 600 ADA for dRep registration