From 88ddda6475511a4c3bfd62d4fefeb277a0315dd5 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:47:22 +0545 Subject: [PATCH 1/4] chore: add mock metadata with random value --- .../playwright/lib/_mock/index.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index c19ae407f..30c278935 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -113,4 +113,82 @@ export const valid = { return username; }, + metadata: () => { + return { + "@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(), + }, + }, + ], + }, + }; + }, }; From 82061bb9334db83e0fa17c0d2cad48f63ae23194 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:48:14 +0545 Subject: [PATCH 2/4] chore: add function to upload mock metadata and calculate hash --- .../playwright/lib/helpers/metadata.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts index 9c3657f95..80f929e4a 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -1,5 +1,11 @@ +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"; +import path = require("path"); export async function downloadMetadata(download: Download): Promise<{ name: string; @@ -11,3 +17,29 @@ export async function downloadMetadata(download: Download): Promise<{ const jsonData = JSON.parse(fileContent); return { name: download.suggestedFilename(), data: jsonData }; } + +function calculateMetadataHash() { + try { + // Get the JSON data as a string + const data = JSON.stringify(mockValid.metadata()); + + // Convert the string to a buffer + const buffer = Buffer.from(data, "utf8"); + const hexDigest = blake.blake2bHex(buffer, null, 32); + + // Parse the JSON data + 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 }; +} From 3a9fe6eb2e3ca1fc2a1dac1e2d9bc29344d1bd69 Mon Sep 17 00:00:00 2001 From: niraj Date: Mon, 5 Aug 2024 18:51:25 +0545 Subject: [PATCH 3/4] chore: update register dRep anchor with uploaded metadata URL and generated data hash. --- .../playwright/lib/helpers/transaction.ts | 10 ++++- .../playwright/lib/services/kuberService.ts | 41 +++++++++++++------ .../govtool-frontend/playwright/lib/types.ts | 6 +++ .../playwright/tests/dRep.setup.ts | 22 ++++++++-- 4 files changed, 63 insertions(+), 16 deletions(-) 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..ceeff4714 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: (metadatasAndWallets: WalletAndAnchorType[]) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); const req = { - certificates: wallets.map((wallet) => - Kuber.generateCert("registerdrep", wallet.stake.pkh) + certificates: metadatasAndWallets.map((metadataAndWallet) => + Kuber.generateCert( + "registerdrep", + metadataAndWallet.wallet.stake.pkh, + metadataAndWallet + ) ), - selections: wallets.map((wallet) => { + selections: metadatasAndWallets.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..840e47d75 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 metadatasAndDRepWallets = await Promise.all(metadataPromises); + const res = await kuberService.multipleDRepRegistration( + metadatasAndDRepWallets + ); 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 From b850faf7f7fad7cd408103e03ab2b69cbf94efdb Mon Sep 17 00:00:00 2001 From: niraj Date: Tue, 6 Aug 2024 10:00:34 +0545 Subject: [PATCH 4/4] chore: refactor naming and valid matadata --- .../playwright/lib/_mock/index.ts | 132 +++++++++--------- .../playwright/lib/helpers/metadata.ts | 4 - .../playwright/lib/services/kuberService.ts | 6 +- .../playwright/tests/dRep.setup.ts | 4 +- 4 files changed, 70 insertions(+), 76 deletions(-) diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index 30c278935..d8f3a99c1 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -113,82 +113,80 @@ export const valid = { return username; }, - metadata: () => { - return { - "@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", - }, + 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", }, + 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: { + "@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", + }, + authors: [], + hashAlgorithm: { + "@value": "blake2b-256", + }, + body: { + bio: { + "@value": faker.lorem.sentences(), }, - 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(), - }, - }, - ], + 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 80f929e4a..1f87d923b 100644 --- a/tests/govtool-frontend/playwright/lib/helpers/metadata.ts +++ b/tests/govtool-frontend/playwright/lib/helpers/metadata.ts @@ -5,7 +5,6 @@ import metadataBucketService from "@services/metadataBucketService"; const blake = require("blakejs"); import * as fs from "fs"; -import path = require("path"); export async function downloadMetadata(download: Download): Promise<{ name: string; @@ -20,14 +19,11 @@ export async function downloadMetadata(download: Download): Promise<{ function calculateMetadataHash() { try { - // Get the JSON data as a string const data = JSON.stringify(mockValid.metadata()); - // Convert the string to a buffer const buffer = Buffer.from(data, "utf8"); const hexDigest = blake.blake2bHex(buffer, null, 32); - // Parse the JSON data const jsonData = JSON.parse(data); return { hexDigest, jsonData }; } catch (error) { diff --git a/tests/govtool-frontend/playwright/lib/services/kuberService.ts b/tests/govtool-frontend/playwright/lib/services/kuberService.ts index ceeff4714..6ddc81a43 100644 --- a/tests/govtool-frontend/playwright/lib/services/kuberService.ts +++ b/tests/govtool-frontend/playwright/lib/services/kuberService.ts @@ -186,17 +186,17 @@ const kuberService = { return kuber.signAndSubmitTx(req); }, - multipleDRepRegistration: (metadatasAndWallets: WalletAndAnchorType[]) => { + multipleDRepRegistration: (metadataAndWallets: WalletAndAnchorType[]) => { const kuber = new Kuber(faucetWallet.address, faucetWallet.payment.private); const req = { - certificates: metadatasAndWallets.map((metadataAndWallet) => + certificates: metadataAndWallets.map((metadataAndWallet) => Kuber.generateCert( "registerdrep", metadataAndWallet.wallet.stake.pkh, metadataAndWallet ) ), - selections: metadatasAndWallets.map((metadata) => { + selections: metadataAndWallets.map((metadata) => { return { type: "PaymentSigningKeyShelley_ed25519", description: "Stake Signing Key", diff --git a/tests/govtool-frontend/playwright/tests/dRep.setup.ts b/tests/govtool-frontend/playwright/tests/dRep.setup.ts index 840e47d75..b872a7abe 100644 --- a/tests/govtool-frontend/playwright/tests/dRep.setup.ts +++ b/tests/govtool-frontend/playwright/tests/dRep.setup.ts @@ -40,9 +40,9 @@ setup("Register DRep of static wallets", async () => { return { ...(await uploadMetadataAndGetJsonHash()), wallet: dRepWallet }; }); - const metadatasAndDRepWallets = await Promise.all(metadataPromises); + const metadataAndDRepWallets = await Promise.all(metadataPromises); const res = await kuberService.multipleDRepRegistration( - metadatasAndDRepWallets + metadataAndDRepWallets ); await pollTransaction(res.txId, res.lockInfo);