From 94fdb4a0482ab051442d20ff9edd4ce620c7176a Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 11 Feb 2025 10:27:25 +0545 Subject: [PATCH 1/6] fix: update intercept logic for usersnap and bucket --- .../6-miscellaneous/miscellaneous.spec.ts | 66 +++++++++++++++---- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts index 77316a04f..b97d16beb 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts @@ -13,7 +13,8 @@ import { faker } from "@faker-js/faker"; import { test } from "@fixtures/walletExtension"; import { setAllureEpic } from "@helpers/allure"; import { isMobile, openDrawer } from "@helpers/mobile"; -import { expect } from "@playwright/test"; +import { expect, Page } from "@playwright/test"; +import { randomUUID } from "crypto"; import environments from "lib/constants/environments"; test.beforeEach(async () => { @@ -172,17 +173,60 @@ test.describe("User Snap", () => { const attachmentInputSelector = "input[type=file]"; const feedbackApiUrl = "https://widget.usersnap.com/api/widget/xhrrpc?submit_feedback"; + const bucketUrl = + "https://s3.eu-central-1.amazonaws.com/upload.usersnap.com"; const mockAttachmentPath = "./lib/_mock/mockAttachment.png"; - test("6Q. Should report an issue", async ({ page }) => { - // Intercept Usersnap submit API + const interceptBucket = async (page: Page) => { + await page.route(bucketUrl, async (route) => + route.fulfill({ + status: 204, + }) + ); + }; + + const interceptUsersnap = async (page: Page) => { await page.route(feedbackApiUrl, async (route) => route.fulfill({ - status: 403, - body: JSON.stringify({ error: "Blocked by test" }), + status: 200, + body: JSON.stringify({ + status: true, + data: { + feedback: { + feedback_id: randomUUID(), + assignee_id: randomUUID(), + labels: [], + }, + screen_recording_url: null, + attachment_urls: [ + { + url: bucketUrl, + fields: { + "Content-Type": "image/png", + key: randomUUID(), + "x-amz-algorithm": "AWS4-HMAC-SHA256", + "x-amz-credential": + "ASIAQL7JRYTOEKCBSNV5/20250211/eu-central-1/s3/aws4_request", + "x-amz-date": "20250211T041923Z", + "x-amz-security-token": + "IQoJb3JpZ2luX2VjELT//////////wEaDGV1LWNlbnRyYWwtMSJHMEUCIBxFIrw90W0SUrmqdkLwJj9CPik/Zdp/IbpnZAzNQ88hAiEAxzNolOJbTyUDY/8jUBruYe41G2/hVVZ5Klhzjrc9utcq4QQIzf//////////ARAAGgwwMjU3MjI3MzM3ODgiDKC6DC3BTvvNZGmdYCq1BBCGKULckA+wyt7ByvNgfMEGjhxF5pM4EAGWp5t/t4X4LEK6Atf+LQ5LGL4ZdpLfIIqUzIGGdjDf17rKPqtI4W9XgMceCFVBaZGQJGdX9IjhHQs/rd+Vdn3yPVz0uoHPFqBIWw5ErEa8U/R9UxO2ayusznotuCsLKPMg3GsglPSEZrBm5lmppYxUPCRp2L2tr7tFWTCTV1tv5/KrUeSl41scZWz0dwcIV5skNuVY0K+LxqLunld9X0/i3BPllW3CTv+v5Qz020L6z4JGFhWgP/qLudX3D2VI34d6aO8a+hjObXFWp46yT1Gb69D3PDaa/ee9jO9nc6vIjsk3I5eK+Zte26M0NHOSXnueCiJAgJ4VaEAVR0KjVl8a9t3pOlWzt7qP3XL7wc8/cRREULY1BAm8TRjcVJD4I/udKjMuU5dBIyBPZ29D5AQrgtsbFNkokGCWah5lCjLA1Wo2KwJklWvGR/fislBH27ybcMK9t1PEZxDwZuad5uxlfa0ZTDw4a+jE5xEHwXQUyCfS10n19h8E6tlfrMfTjDAfxcKwjeMKV+gNg/fKsEhk7RWwrrdm74zGlBsGut93pJ7VWpEopdZSrzNniaRIjSmS6u5NgNHmQl+rN4wX9tjm8Q9PacuVvx2lV4WlkpJ/sd7Y02RsXqPiAsc1hsXa7sDxaLn7CdQd+nveObYjqLYu3U2S1BVxpDujFOqdxeUziHE3NJexqmsue6LYNTIKCDwDvL5gRbD8H26jylwwqZOrvQY6pwHLPFojxcR61xtvWxFpYxewobGXGVCBJWHikZWASmmmO+OL3PdoVKu0xOks0Dd6DvkZhYTaxlg/ER77nyapOTOPMWBCxVJlQ3iCs3NEFOznhj8akqEsTo/U8/uII3RX1iGWQdm7VgZUH5kgTOdPV3NdMNoahja2c7qMRZBoNPXDnREYnwaOBSbVSmnGIX9Gq4eNa7N1nNsCgaU2JtfS8qUjZy9OKiW69Q==", + policy: + "eyJleHBpcmF0aW9uIjogIjIwMjUtMDItMTFUMDQ6MjQ6MjNaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDIwOTcxNTIwMF0sIFsiZXEiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS9qcGVnIl0sIHsiYnVja2V0IjogInVwbG9hZC51c2Vyc25hcC5jb20ifSwgeyJrZXkiOiAiMGRkZDJkODgtYmJkNy00MWE1LWFmOWItMjBlNWI3N2Q4ZWQ2In0sIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFTSUFRTDdKUllUT0VLQ0JTTlY1LzIwMjUwMjExL2V1LWNlbnRyYWwtMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwMjExVDA0MTkyM1oifSwgeyJ4LWFtei1zZWN1cml0eS10b2tlbiI6ICJJUW9KYjNKcFoybHVYMlZqRUxULy8vLy8vLy8vL3dFYURHVjFMV05sYm5SeVlXd3RNU0pITUVVQ0lCeEZJcnc5MFcwU1VybXFka0x3Smo5Q1Bpay9aZHAvSWJwblpBek5RODhoQWlFQXh6Tm9sT0piVHlVRFkvOGpVQnJ1WWU0MUcyL2hWVlo1S2xoempyYzl1dGNxNFFRSXpmLy8vLy8vLy8vL0FSQUFHZ3d3TWpVM01qSTNNek0zT0RnaURLQzZEQzNCVHZ2TlpHbWRZQ3ExQkJDR0tVTGNrQSt3eXQ3Qnl2TmdmTUVHamh4RjVwTTRFQUdXcDV0L3Q0WDRMRUs2QXRmK0xRNUxHTDRaZHBMZklJcVV6SUdHZGpEZjE3cktQcXRJNFc5WGdNY2VDRlZCYVpHUUpHZFg5SWpoSFFzL3JkK1ZkbjN5UFZ6MHVvSFBGcUJJV3c1RXJFYThVL1I5VXhPMmF5dXN6bm90dUNzTEtQTWczR3NnbFBTRVpyQm01bG1wcFl4VVBDUnAyTDJ0cjd0RldUQ1RWMXR2NS9LclVlU2w0MXNjWld6MGR3Y0lWNXNrTnVWWTBLK0x4cUx1bmxkOVgwL2kzQlBsbFczQ1R2K3Y1UXowMjBMNno0SkdGaFdnUC9xTHVkWDNEMlZJMzRkNmFPOGEraGpPYlhGV3A0NnlUMUdiNjlEM1BEYWEvZWU5ak85bmM2dklqc2szSTVlSytadGUyNk0wTkhPU1hudWVDaUpBZ0o0VmFFQVZSMEtqVmw4YTl0M3BPbFd6dDdxUDNYTDd3YzgvY1JSRVVMWTFCQW04VFJqY1ZKRDRJL3VkS2pNdVU1ZEJJeUJQWjI5RDVBUXJndHNiRk5rb2tHQ1dhaDVsQ2pMQTFXbzJLd0prbFd2R1IvZmlzbEJIMjd5YmNNSzl0MVBFWnhEd1p1YWQ1dXhsZmEwWlREdzRhK2pFNXhFSHdYUVV5Q2ZTMTBuMTloOEU2dGxmck1mVGpEQWZ4Y0t3amVNS1YrZ05nL2ZLc0VoazdSV3dycmRtNzR6R2xCc0d1dDkzcEo3VldwRW9wZFpTcnpObmlhUklqU21TNnU1TmdOSG1RbCtyTjR3WDl0am04UTlQYWN1VnZ4MmxWNFdsa3BKL3NkN1kwMlJzWHFQaUFzYzFoc1hhN3NEeGFMbjdDZFFkK252ZU9iWWpxTFl1M1UyUzFCVnhwRHVqRk9xZHhlVXppSEUzTkpleHFtc3VlNkxZTlRJS0NEd0R2TDVnUmJEOEgyNmp5bHd3cVpPcnZRWTZwd0hMUEZvanhjUjYxeHR2V3hGcFl4ZXdvYkdYR1ZDQkpXSGlrWldBU21tbU8rT0wzUGRvVkt1MHhPa3MwRGQ2RHZrWmhZVGF4bGcvRVI3N255YXBPVE9QTVdCQ3hWSmxRM2lDczNORUZPem5oajhha3FFc1RvL1U4L3VJSTNSWDFpR1dRZG03VmdaVUg1a2dUT2RQVjNOZE1Ob2FoamEyYzdxTVJaQm9OUFhEblJFWW53YU9CU2JWU21uR0lYOUdxNGVOYTdOMW5Oc0NnYVUySnRmUzhxVWpaeTlPS2lXNjlRPT0ifV19", + "x-amz-signature": + "b3eb39a9084457b61fc99d1c8ec4cb0170371aaa6327500eafae23dcb4abecb5", + }, + }, + ], + }, + }), }) ); + }; + test("6Q. Should report an issue", async ({ page }) => { + // Intercept Usersnap submit API + await interceptUsersnap(page); + await interceptBucket(page); await page .getByRole("button", { name: "Report an issue Something", @@ -196,17 +240,13 @@ test.describe("User Snap", () => { await page.getByRole("button", { name: "Submit" }).click(); - await expect(page.getByText("Feedback was not submitted,")).toBeVisible(); + await expect(page.getByText("Thank you!")).toBeVisible(); }); test("6R. Should submit an idea or new feature", async ({ page }) => { // Intercept Usersnap submit API - await page.route(feedbackApiUrl, async (route) => - route.fulfill({ - status: 403, - body: JSON.stringify({ error: "Blocked by test" }), - }) - ); + await interceptUsersnap(page); + await interceptBucket(page); await page .getByRole("button", { @@ -227,7 +267,7 @@ test.describe("User Snap", () => { await page.getByRole("button", { name: "Submit" }).click(); - await expect(page.getByText("Feedback was not submitted,")).toBeVisible(); + await expect(page.getByText("Thank you!")).toBeVisible(); }); }); }); From d7a16a8084e6c483eb2dc82da5a947f9be883e2f Mon Sep 17 00:00:00 2001 From: Niraj Date: Tue, 11 Feb 2025 12:42:02 +0545 Subject: [PATCH 2/6] chore: remove sensitive AWS credentials from user snap test --- .../tests/6-miscellaneous/miscellaneous.spec.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts index b97d16beb..aaa88a863 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts @@ -204,16 +204,6 @@ test.describe("User Snap", () => { fields: { "Content-Type": "image/png", key: randomUUID(), - "x-amz-algorithm": "AWS4-HMAC-SHA256", - "x-amz-credential": - "ASIAQL7JRYTOEKCBSNV5/20250211/eu-central-1/s3/aws4_request", - "x-amz-date": "20250211T041923Z", - "x-amz-security-token": - "IQoJb3JpZ2luX2VjELT//////////wEaDGV1LWNlbnRyYWwtMSJHMEUCIBxFIrw90W0SUrmqdkLwJj9CPik/Zdp/IbpnZAzNQ88hAiEAxzNolOJbTyUDY/8jUBruYe41G2/hVVZ5Klhzjrc9utcq4QQIzf//////////ARAAGgwwMjU3MjI3MzM3ODgiDKC6DC3BTvvNZGmdYCq1BBCGKULckA+wyt7ByvNgfMEGjhxF5pM4EAGWp5t/t4X4LEK6Atf+LQ5LGL4ZdpLfIIqUzIGGdjDf17rKPqtI4W9XgMceCFVBaZGQJGdX9IjhHQs/rd+Vdn3yPVz0uoHPFqBIWw5ErEa8U/R9UxO2ayusznotuCsLKPMg3GsglPSEZrBm5lmppYxUPCRp2L2tr7tFWTCTV1tv5/KrUeSl41scZWz0dwcIV5skNuVY0K+LxqLunld9X0/i3BPllW3CTv+v5Qz020L6z4JGFhWgP/qLudX3D2VI34d6aO8a+hjObXFWp46yT1Gb69D3PDaa/ee9jO9nc6vIjsk3I5eK+Zte26M0NHOSXnueCiJAgJ4VaEAVR0KjVl8a9t3pOlWzt7qP3XL7wc8/cRREULY1BAm8TRjcVJD4I/udKjMuU5dBIyBPZ29D5AQrgtsbFNkokGCWah5lCjLA1Wo2KwJklWvGR/fislBH27ybcMK9t1PEZxDwZuad5uxlfa0ZTDw4a+jE5xEHwXQUyCfS10n19h8E6tlfrMfTjDAfxcKwjeMKV+gNg/fKsEhk7RWwrrdm74zGlBsGut93pJ7VWpEopdZSrzNniaRIjSmS6u5NgNHmQl+rN4wX9tjm8Q9PacuVvx2lV4WlkpJ/sd7Y02RsXqPiAsc1hsXa7sDxaLn7CdQd+nveObYjqLYu3U2S1BVxpDujFOqdxeUziHE3NJexqmsue6LYNTIKCDwDvL5gRbD8H26jylwwqZOrvQY6pwHLPFojxcR61xtvWxFpYxewobGXGVCBJWHikZWASmmmO+OL3PdoVKu0xOks0Dd6DvkZhYTaxlg/ER77nyapOTOPMWBCxVJlQ3iCs3NEFOznhj8akqEsTo/U8/uII3RX1iGWQdm7VgZUH5kgTOdPV3NdMNoahja2c7qMRZBoNPXDnREYnwaOBSbVSmnGIX9Gq4eNa7N1nNsCgaU2JtfS8qUjZy9OKiW69Q==", - policy: - "eyJleHBpcmF0aW9uIjogIjIwMjUtMDItMTFUMDQ6MjQ6MjNaIiwgImNvbmRpdGlvbnMiOiBbWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEsIDIwOTcxNTIwMF0sIFsiZXEiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS9qcGVnIl0sIHsiYnVja2V0IjogInVwbG9hZC51c2Vyc25hcC5jb20ifSwgeyJrZXkiOiAiMGRkZDJkODgtYmJkNy00MWE1LWFmOWItMjBlNWI3N2Q4ZWQ2In0sIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFTSUFRTDdKUllUT0VLQ0JTTlY1LzIwMjUwMjExL2V1LWNlbnRyYWwtMS9zMy9hd3M0X3JlcXVlc3QifSwgeyJ4LWFtei1kYXRlIjogIjIwMjUwMjExVDA0MTkyM1oifSwgeyJ4LWFtei1zZWN1cml0eS10b2tlbiI6ICJJUW9KYjNKcFoybHVYMlZqRUxULy8vLy8vLy8vL3dFYURHVjFMV05sYm5SeVlXd3RNU0pITUVVQ0lCeEZJcnc5MFcwU1VybXFka0x3Smo5Q1Bpay9aZHAvSWJwblpBek5RODhoQWlFQXh6Tm9sT0piVHlVRFkvOGpVQnJ1WWU0MUcyL2hWVlo1S2xoempyYzl1dGNxNFFRSXpmLy8vLy8vLy8vL0FSQUFHZ3d3TWpVM01qSTNNek0zT0RnaURLQzZEQzNCVHZ2TlpHbWRZQ3ExQkJDR0tVTGNrQSt3eXQ3Qnl2TmdmTUVHamh4RjVwTTRFQUdXcDV0L3Q0WDRMRUs2QXRmK0xRNUxHTDRaZHBMZklJcVV6SUdHZGpEZjE3cktQcXRJNFc5WGdNY2VDRlZCYVpHUUpHZFg5SWpoSFFzL3JkK1ZkbjN5UFZ6MHVvSFBGcUJJV3c1RXJFYThVL1I5VXhPMmF5dXN6bm90dUNzTEtQTWczR3NnbFBTRVpyQm01bG1wcFl4VVBDUnAyTDJ0cjd0RldUQ1RWMXR2NS9LclVlU2w0MXNjWld6MGR3Y0lWNXNrTnVWWTBLK0x4cUx1bmxkOVgwL2kzQlBsbFczQ1R2K3Y1UXowMjBMNno0SkdGaFdnUC9xTHVkWDNEMlZJMzRkNmFPOGEraGpPYlhGV3A0NnlUMUdiNjlEM1BEYWEvZWU5ak85bmM2dklqc2szSTVlSytadGUyNk0wTkhPU1hudWVDaUpBZ0o0VmFFQVZSMEtqVmw4YTl0M3BPbFd6dDdxUDNYTDd3YzgvY1JSRVVMWTFCQW04VFJqY1ZKRDRJL3VkS2pNdVU1ZEJJeUJQWjI5RDVBUXJndHNiRk5rb2tHQ1dhaDVsQ2pMQTFXbzJLd0prbFd2R1IvZmlzbEJIMjd5YmNNSzl0MVBFWnhEd1p1YWQ1dXhsZmEwWlREdzRhK2pFNXhFSHdYUVV5Q2ZTMTBuMTloOEU2dGxmck1mVGpEQWZ4Y0t3amVNS1YrZ05nL2ZLc0VoazdSV3dycmRtNzR6R2xCc0d1dDkzcEo3VldwRW9wZFpTcnpObmlhUklqU21TNnU1TmdOSG1RbCtyTjR3WDl0am04UTlQYWN1VnZ4MmxWNFdsa3BKL3NkN1kwMlJzWHFQaUFzYzFoc1hhN3NEeGFMbjdDZFFkK252ZU9iWWpxTFl1M1UyUzFCVnhwRHVqRk9xZHhlVXppSEUzTkpleHFtc3VlNkxZTlRJS0NEd0R2TDVnUmJEOEgyNmp5bHd3cVpPcnZRWTZwd0hMUEZvanhjUjYxeHR2V3hGcFl4ZXdvYkdYR1ZDQkpXSGlrWldBU21tbU8rT0wzUGRvVkt1MHhPa3MwRGQ2RHZrWmhZVGF4bGcvRVI3N255YXBPVE9QTVdCQ3hWSmxRM2lDczNORUZPem5oajhha3FFc1RvL1U4L3VJSTNSWDFpR1dRZG03VmdaVUg1a2dUT2RQVjNOZE1Ob2FoamEyYzdxTVJaQm9OUFhEblJFWW53YU9CU2JWU21uR0lYOUdxNGVOYTdOMW5Oc0NnYVUySnRmUzhxVWpaeTlPS2lXNjlRPT0ifV19", - "x-amz-signature": - "b3eb39a9084457b61fc99d1c8ec4cb0170371aaa6327500eafae23dcb4abecb5", }, }, ], From beb6448395d39fbd9ab34f20aa63217100c091e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Wed, 5 Feb 2025 14:02:31 +0100 Subject: [PATCH 3/6] feat(#2258): add support for submitting all governance action types --- CHANGELOG.md | 1 + docs/GOVERNANCE_ACTION_SUBMISSION.md | 113 +++++-- govtool/frontend/src/context/wallet.tsx | 302 +++++++++++++++--- .../frontend/src/types/governanceAction.ts | 27 ++ 4 files changed, 378 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b02bc7455..91ab52bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ changes. - Add metadata url and hash to drep details [Issue 2911](https://github.com/IntersectMBO/govtool/issues/2911) - Add CC votes percentages, not voted and Ratification threshold +- Add support for submitting all 7 governance action types [Issue 2258](https://github.com/IntersectMBO/govtool/issues/2258) ### Fixed diff --git a/docs/GOVERNANCE_ACTION_SUBMISSION.md b/docs/GOVERNANCE_ACTION_SUBMISSION.md index 140b6b0e0..1c6a29d99 100644 --- a/docs/GOVERNANCE_ACTION_SUBMISSION.md +++ b/docs/GOVERNANCE_ACTION_SUBMISSION.md @@ -33,16 +33,16 @@ interface GovernanceAction { references: [{ label: string; uri: string }]; } -interface InfoProps { - hash: string; +type VotingAnchor = { url: string; + hash: string; } -interface TreasuryProps { - amount: string; - hash: string; +type InfoProps = VotingAnchor; + +type TreasuryProps { withdrawals: { receivingAddress: string; amount: string }[]; -} +} & VotingAnchor; type ProtocolParamsUpdate = { adaPerUtxo: string; @@ -77,14 +77,44 @@ type ProtocolParamsUpdate = { treasuryGrowthRate: UnitInterval; }; -interface ProtocolParameterChangeProps { +type ProtocolParameterChangeProps { prevGovernanceActionHash: string; prevGovernanceActionIndex: number; - url: string; - hash: string; - protocolParamsUpdate: Partial; -} +} & VotingAnchor; + +type HardForkInitiationProps = { + prevGovernanceActionHash: string; + prevGovernanceActionIndex: number; + major: number; + minor: number; +} & VotingAnchor; + +type NewConstitutionProps = { + prevGovernanceActionHash: string; + prevGovernanceActionIndex: number; + constitutionUrl: string; + constitutionHash: string; + scriptHash: string; +} & VotingAnchor; + +type UpdateCommitteeProps = { + prevGovernanceActionHash?: string; + prevGovernanceActionIndex?: number; + quorumThreshold: QuorumThreshold; + newCommittee?: CommitteeToAdd[]; + removeCommittee?: string[]; +} & VotingAnchor; + +type CommitteeToAdd = { + expiryEpoch: number; + committee: string; +}; + +type QuorumThreshold = { + numerator: number; + denominator: number; +}; const createGovernanceActionJsonLD: ( governanceAction: GovernanceAction @@ -100,6 +130,22 @@ const buildTreasuryGovernanceAction: ( treasuryProps: TreasuryProps ) => Promise; +const buildProtocolParameterChangeGovernanceAction: ( + protocolParameterChangeProps: ProtocolParameterChangeProps +) => Promise; + +const buildHardForkInitiationGovernanceAction: ( + hardForkInitiationProps: HardForkInitiationProps +) => Promise; + +const buildNewConstitutionGovernanceAction: ( + newConstitutionProps: NewConstitutionProps +) => Promise; + +const buildUpdateCommitteeGovernanceAction: ( + updateCommitteeProps: UpdateCommitteeProps +) => Promise; + const buildSignSubmitConwayCertTx: (params: { govActionBuilder: VotingProposalBuilder; type: "createGovAction"; @@ -165,32 +211,28 @@ const { buildNewInfoGovernanceAction, buildProtocolParameterChangeGovernanceAction, buildHardForkInitiationGovernanceAction, + buildTreasuryGovernanceAction, + buildNewConstitutionGovernanceAction, + buildUpdateCommitteeGovernanceAction, + buildNoConfidenceGovernanceAction, } = useCardano(); // Info Governance Action -const govActionBuilder = await buildNewInfoGovernanceAction({ hash, url }); +let govActionBuilder = await buildNewInfoGovernanceAction({ hash, url }); -// sign and submit the transaction -await buildSignSubmitConwayCertTx({ - govActionBuilder, - type: "createGovAction", -}); +// And for the other type of governance actions: -// Treasury Governance Action -const { buildTreasuryGovernanceAction } = useCardano(); +govActionBuilder = await buildNoConfidenceGovernanceAction({ hash, url }); // hash of the generated Governance Action metadata, url of the metadata, amount of the transaction, receiving address is the stake key address -const govActionBuilder = await buildTreasuryGovernanceAction({ +govActionBuilder = await buildTreasuryGovernanceAction({ hash, url, withdrawals: [{ amount, receivingAddress }], }); -// Protocol Parameter Change Governance Action -const { buildProtocolParameterChangeGovernanceAction } = useCardano(); - // hash of the previous Governance Action, index of the previous Governance Action, url of the metadata, hash of the metadata, and the updated protocol parameters -const govActionBuilder = await buildProtocolParameterChangeGovernanceAction({ +govActionBuilder = await buildProtocolParameterChangeGovernanceAction({ prevGovernanceActionHash, prevGovernanceActionIndex, url, @@ -198,11 +240,8 @@ const govActionBuilder = await buildProtocolParameterChangeGovernanceAction({ protocolParamsUpdate, }); -// Hard Fork Initiation Governance Action -const { buildHardForkInitiationGovernanceAction } = useCardano(); - // hash of the previous Governance Action, index of the previous Governance Action, url of the metadata, hash of the metadata, and the major and minor numbers of the hard fork initiation -const govActionBuilder = await buildHardForkInitiationGovernanceAction({ +govActionBuilder = await buildHardForkInitiationGovernanceAction({ prevGovernanceActionHash, prevGovernanceActionIndex, url, @@ -211,6 +250,24 @@ const govActionBuilder = await buildHardForkInitiationGovernanceAction({ minor, }); +// hash of the previous Governance Action, index of the previous Governance Action, url of the metadata, hash of the metadata, and the constitution script hash +govActionBuilder = await buildNewConstitutionGovernanceAction({ + prevGovernanceActionHash, + prevGovernanceActionIndex, + constitutionUrl, + constitutionHash, + scriptHash, +}); + +// hash of the previous Governance Action, index of the previous Governance Action, url of the metadata, hash of the metadata, and the quorum threshold and the new committee members +govActionBuilder = await buildUpdateCommitteeGovernanceAction({ + prevGovernanceActionHash, + prevGovernanceActionIndex, + quorumThreshold, + newCommittee, + removeCommittee, +}); + // sign and submit the transaction await buildSignSubmitConwayCertTx({ govActionBuilder, diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index a698f5ae5..4c6427b5c 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -64,6 +64,12 @@ import { CostModel, Language, TxInputsBuilder, + NoConfidenceAction, + Constitution, + NewConstitutionAction, + UpdateCommitteeAction, + Committee, + Credentials, } from "@emurgo/cardano-serialization-lib-asmjs"; import { Buffer } from "buffer"; import { useNavigate } from "react-router-dom"; @@ -109,15 +115,56 @@ interface EnableResponse { error?: string; } -type InfoProps = { - hash: string; +type VotingAnchor = { url: string; + hash: string; }; +type InfoProps = VotingAnchor; + +type NoConfidenceProps = VotingAnchor; + type TreasuryProps = { - hash: string; - url: string; withdrawals: { receivingAddress: string; amount: string }[]; +} & VotingAnchor; + +type ProtocolParameterChangeProps = { + prevGovernanceActionHash: string; + prevGovernanceActionIndex: number; + protocolParamsUpdate: Partial; +} & VotingAnchor; + +type HardForkInitiationProps = { + prevGovernanceActionHash: string; + prevGovernanceActionIndex: number; + major: number; + minor: number; +} & VotingAnchor; + +type NewConstitutionProps = { + prevGovernanceActionHash: string; + prevGovernanceActionIndex: number; + constitutionUrl: string; + constitutionHash: string; + scriptHash: string; +} & VotingAnchor; + +type UpdateCommitteeProps = { + prevGovernanceActionHash?: string; + prevGovernanceActionIndex?: number; + quorumThreshold: QuorumThreshold; + newCommittee?: CommitteeToAdd[]; + removeCommittee?: string[]; +} & VotingAnchor; + +export type CommitteeToAdd = { + expiryEpoch: number; + committee: string; +}; + +export type QuorumThreshold = { + numerator: number; + denominator: number; }; type ProtocolParamsUpdate = { @@ -153,23 +200,6 @@ type ProtocolParamsUpdate = { treasuryGrowthRate: UnitInterval; }; -type ProtocolParameterChangeProps = { - prevGovernanceActionHash: string; - prevGovernanceActionIndex: number; - url: string; - hash: string; - protocolParamsUpdate: Partial; -}; - -type HardForkInitiationProps = { - prevGovernanceActionHash: string; - prevGovernanceActionIndex: number; - url: string; - hash: string; - major: number; - minor: number; -}; - type BuildSignSubmitConwayCertTxArgs = { certBuilder?: CertificatesBuilder | Certificate; govActionBuilder?: VotingProposalBuilder; @@ -231,6 +261,15 @@ interface CardanoContextType { buildHardForkGovernanceAction: ( hardForkInitiationProps: HardForkInitiationProps, ) => Promise; + buildNewConstitutionGovernanceAction: ( + newConstitutionProps: NewConstitutionProps, + ) => Promise; + buildUpdateCommitteeGovernanceAction: ( + updateCommitteeProps: UpdateCommitteeProps, + ) => Promise; + buildNoConfidenceGovernanceAction: ( + noConfidenceProps: NoConfidenceProps, + ) => Promise; } type Utxos = { @@ -735,13 +774,24 @@ const CardanoProvider = (props: Props) => { ], ); + const buildCredentialFromBech32Key = useCallback(async (key: string) => { + try { + const keyHash = Ed25519KeyHash.from_hex(key); + return Credential.from_keyhash(keyHash); + } catch (e) { + console.error(e); + throw e; + } + }, []); + const buildStakeKeyRegCert = useCallback(async (): Promise => { try { if (!stakeKey) { throw new Error(t("errors.noStakeKeySelected")); } - const stakeKeyHash = Ed25519KeyHash.from_hex(stakeKey.substring(2)); - const stakeCred = Credential.from_keyhash(stakeKeyHash); + const stakeCred = await buildCredentialFromBech32Key( + stakeKey.substring(2), + ); const stakeKeyRegCert = StakeRegistration.new_with_explicit_deposit( stakeCred, BigNum.from_str(`${epochParams.key_deposit}`), @@ -761,8 +811,9 @@ const CardanoProvider = (props: Props) => { throw new Error(t("errors.noStakeKeySelected")); } // Remove network tag from stake key hash - const stakeKeyHash = Ed25519KeyHash.from_hex(stakeKey.substring(2)); - const stakeCred = Credential.from_keyhash(stakeKeyHash); + const stakeCred = await buildCredentialFromBech32Key( + stakeKey.substring(2), + ); // Create correct DRep let targetDRep; @@ -797,8 +848,7 @@ const CardanoProvider = (props: Props) => { ): Promise => { try { // Get wallet's DRep key - const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); - const dRepCred = Credential.from_keyhash(dRepKeyHash); + const dRepCred = await buildCredentialFromBech32Key(dRepID); let dRepRegCert; // If there is an anchor @@ -833,8 +883,7 @@ const CardanoProvider = (props: Props) => { ): Promise => { try { // Get wallet's DRep key - const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); - const dRepCred = Credential.from_keyhash(dRepKeyHash); + const dRepCred = await buildCredentialFromBech32Key(dRepID); let dRepUpdateCert; // If there is an anchor @@ -858,8 +907,7 @@ const CardanoProvider = (props: Props) => { async (voterDeposit: string): Promise => { try { // Get wallet's DRep key - const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); - const dRepCred = Credential.from_keyhash(dRepKeyHash); + const dRepCred = await buildCredentialFromBech32Key(dRepID); const dRepRetirementCert = DRepDeregistration.new( dRepCred, @@ -884,12 +932,10 @@ const CardanoProvider = (props: Props) => { cip95MetadataHash?: string, ): Promise => { try { - // Get wallet's DRep key - const dRepKeyHash = Ed25519KeyHash.from_hex(dRepID); - // Vote things - const voter = Voter.new_drep_credential( - Credential.from_keyhash(dRepKeyHash), - ); + // Get wallet's DRep credential + const dRepCredential = await buildCredentialFromBech32Key(dRepID); + // Vote credential + const voter = Voter.new_drep_credential(dRepCredential); const govActionId = GovernanceActionId.new( // placeholder TransactionHash.from_hex(txHash), @@ -978,6 +1024,150 @@ const CardanoProvider = (props: Props) => { [], ); + // new constitution action + const buildNewConstitutionGovernanceAction = useCallback( + async ({ + prevGovernanceActionHash, + prevGovernanceActionIndex, + constitutionUrl, + constitutionHash, + url, + hash, + scriptHash, + }: NewConstitutionProps) => { + const govActionBuilder = VotingProposalBuilder.new(); + try { + const constitutionAnchor = generateAnchor( + constitutionUrl, + constitutionHash, + ); + const anchor = generateAnchor(url, hash); + + const rewardAddr = await getRewardAddress(); + if (!rewardAddr) throw new Error("Can not get reward address"); + + let constitution; + if (scriptHash) { + constitution = Constitution.new_with_script_hash( + constitutionAnchor, + ScriptHash.from_hex(scriptHash), + ); + } else { + constitution = Constitution.new(constitutionAnchor); + } + + let newConstitution; + if (prevGovernanceActionHash && prevGovernanceActionIndex) { + const prevGovernanceActionId = GovernanceActionId.new( + TransactionHash.from_hex(prevGovernanceActionHash), + prevGovernanceActionIndex, + ); + newConstitution = NewConstitutionAction.new_with_action_id( + prevGovernanceActionId, + constitution, + ); + } else { + newConstitution = NewConstitutionAction.new(constitution); + } + + const newConstitutionAction = + GovernanceAction.new_new_constitution_action(newConstitution); + + // Create voting proposal + const votingProposal = VotingProposal.new( + newConstitutionAction, + anchor, + rewardAddr, + BigNum.from_str(epochParams?.gov_action_deposit.toString()), + ); + + govActionBuilder.add(votingProposal); + + return govActionBuilder; + } catch (e) { + console.error(e); + } + }, + [], + ); + + // update committee action + const buildUpdateCommitteeGovernanceAction = useCallback( + async ({ + prevGovernanceActionHash, + prevGovernanceActionIndex, + url, + hash, + newCommittee, + removeCommittee, + quorumThreshold, + }: UpdateCommitteeProps) => { + const govActionBuilder = VotingProposalBuilder.new(); + try { + const anchor = generateAnchor(url, hash); + const rewardAddr = await getRewardAddress(); + if (!rewardAddr) throw new Error("Can not get reward address"); + + const threshold = UnitInterval.new( + BigNum.from_str(quorumThreshold.numerator.toString()), + BigNum.from_str(quorumThreshold.denominator.toString()), + ); + + const committeeToAdd = Committee.new(threshold); + if (newCommittee) { + newCommittee.forEach(async (member) => { + const credential = await buildCredentialFromBech32Key( + member.committee, + ); + committeeToAdd.add_member(credential, member.expiryEpoch); + }); + } + const committeeToRemoveCredentials = Credentials.new(); + if (removeCommittee) { + removeCommittee.forEach(async (member) => { + const credential = await buildCredentialFromBech32Key(member); + committeeToRemoveCredentials.add(credential); + }); + } + + let updateCommitteeAction; + if (prevGovernanceActionHash && prevGovernanceActionIndex) { + const prevGovernanceActionId = GovernanceActionId.new( + TransactionHash.from_hex(prevGovernanceActionHash), + prevGovernanceActionIndex, + ); + updateCommitteeAction = UpdateCommitteeAction.new_with_action_id( + prevGovernanceActionId, + committeeToAdd, + committeeToRemoveCredentials, + ); + } else { + updateCommitteeAction = UpdateCommitteeAction.new( + committeeToAdd, + committeeToRemoveCredentials, + ); + } + + const updateCommitteeGovernanceAction = + GovernanceAction.new_new_committee_action(updateCommitteeAction); + + const votingProposal = VotingProposal.new( + updateCommitteeGovernanceAction, + anchor, + rewardAddr, + BigNum.from_str(epochParams?.gov_action_deposit.toString()), + ); + + govActionBuilder.add(votingProposal); + + return govActionBuilder; + } catch (e) { + console.error(e); + } + }, + [], + ); + // info action const buildNewInfoGovernanceAction = useCallback( async ({ hash, url }: InfoProps) => { @@ -1009,6 +1199,38 @@ const CardanoProvider = (props: Props) => { [epochParams, getRewardAddress], ); + // no confidence action + const buildNoConfidenceGovernanceAction = useCallback( + async ({ hash, url }: NoConfidenceProps) => { + const govActionBuilder = VotingProposalBuilder.new(); + try { + // Create new no confidence action + const noConfidenceAction = NoConfidenceAction.new(); + const noConfidenceGovAct = + GovernanceAction.new_no_confidence_action(noConfidenceAction); + // Create an anchor + const anchor = generateAnchor(url, hash); + + const rewardAddr = await getRewardAddress(); + if (!rewardAddr) throw new Error("Can not get reward address"); + + // Create voting proposal + const votingProposal = VotingProposal.new( + noConfidenceGovAct, + anchor, + rewardAddr, + BigNum.from_str(epochParams?.gov_action_deposit.toString()), + ); + govActionBuilder.add(votingProposal); + + return govActionBuilder; + } catch (err) { + console.error(err); + } + }, + [], + ); + // treasury action const buildTreasuryGovernanceAction = useCallback( async ({ hash, url, withdrawals }: TreasuryProps) => { @@ -1227,6 +1449,9 @@ const CardanoProvider = (props: Props) => { buildHardForkGovernanceAction, buildNewInfoGovernanceAction, buildProtocolParameterChangeGovernanceAction, + buildNoConfidenceGovernanceAction, + buildNewConstitutionGovernanceAction, + buildUpdateCommitteeGovernanceAction, buildSignSubmitConwayCertTx, buildStakeKeyRegCert, buildTreasuryGovernanceAction, @@ -1257,6 +1482,9 @@ const CardanoProvider = (props: Props) => { buildHardForkGovernanceAction, buildNewInfoGovernanceAction, buildProtocolParameterChangeGovernanceAction, + buildNoConfidenceGovernanceAction, + buildNewConstitutionGovernanceAction, + buildUpdateCommitteeGovernanceAction, buildSignSubmitConwayCertTx, buildStakeKeyRegCert, buildTreasuryGovernanceAction, diff --git a/govtool/frontend/src/types/governanceAction.ts b/govtool/frontend/src/types/governanceAction.ts index c150444dd..eb225ca24 100644 --- a/govtool/frontend/src/types/governanceAction.ts +++ b/govtool/frontend/src/types/governanceAction.ts @@ -41,6 +41,33 @@ export type TreasuryGovernanceActionFieldSchema = receivingAddress: FieldSchema; amount: FieldSchema; }>; +export type NoConfidenceActionFieldSchema = SharedGovernanceActionFieldSchema; +export type NewCommitteeActionFieldSchema = SharedGovernanceActionFieldSchema & + Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + numerator: FieldSchema; + denominator: FieldSchema; + newCommitteeMembers: FieldSchema[]; + removeCommitteeMembers: FieldSchema[]; + }>; +export type HardForkInitiationActionFieldSchema = + SharedGovernanceActionFieldSchema & + Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + major: FieldSchema; + minor: FieldSchema; + }>; +export type NewConstitutionActionFieldSchema = + SharedGovernanceActionFieldSchema & + Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + constitutionUrl: FieldSchema; + constitutionHash: FieldSchema; + scriptHash: FieldSchema; + }>; export type GovernanceActionFieldSchemas = | InfoGovernanceActionFieldSchema & TreasuryGovernanceActionFieldSchema; From b2a8233e79c22fcbebc2d0c7a6ceacc71ba0e5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 7 Feb 2025 11:23:57 +0100 Subject: [PATCH 4/6] feat(#2258): add support for submitting new governance actions inside wrapper --- .../CreateGovernanceActionForm.tsx | 6 + .../src/consts/governanceAction/fields.ts | 139 ++++++++++++++++++ govtool/frontend/src/context/wallet.tsx | 34 +++-- .../forms/useCreateGovernanceActionForm.ts | 63 +++++++- govtool/frontend/src/i18n/locales/en.json | 50 +++++++ .../frontend/src/types/governanceAction.ts | 74 +++++----- 6 files changed, 312 insertions(+), 54 deletions(-) diff --git a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx index d1cc18b0c..5f3e9b010 100644 --- a/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx +++ b/govtool/frontend/src/components/organisms/CreateGovernanceActionSteps/CreateGovernanceActionForm.tsx @@ -47,6 +47,9 @@ export const CreateGovernanceActionForm = ({ type! as | GovernanceActionType.InfoAction | GovernanceActionType.TreasuryWithdrawals + | GovernanceActionType.NewCommittee + | GovernanceActionType.NewConstitution + | GovernanceActionType.NoConfidence ], ).some( (field) => !watch(field as unknown as Parameters[0]), @@ -67,6 +70,9 @@ export const CreateGovernanceActionForm = ({ type! as | GovernanceActionType.InfoAction | GovernanceActionType.TreasuryWithdrawals + | GovernanceActionType.NewCommittee + | GovernanceActionType.NewConstitution + | GovernanceActionType.NoConfidence ], ).map(([key, field]) => { const fieldProps = { diff --git a/govtool/frontend/src/consts/governanceAction/fields.ts b/govtool/frontend/src/consts/governanceAction/fields.ts index 259a72396..0367b4799 100644 --- a/govtool/frontend/src/consts/governanceAction/fields.ts +++ b/govtool/frontend/src/consts/governanceAction/fields.ts @@ -97,6 +97,92 @@ export const sharedGovernanceActionFields: SharedGovernanceActionFieldSchema = { export const GOVERNANCE_ACTION_FIELDS: GovernanceActionFields = { [GovernanceActionType.InfoAction]: sharedGovernanceActionFields, + [GovernanceActionType.NoConfidence]: sharedGovernanceActionFields, + [GovernanceActionType.NewCommittee]: { + ...sharedGovernanceActionFields, + numerator: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.numerator.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.numerator.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + validate: numberValidation, + }, + }, + denominator: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.denominator.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.denominator.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + validate: numberValidation, + }, + }, + newCommitteeHash: { + component: GovernanceActionField.Input, + labelI18nKey: "createGovernanceAction.fields.declarations.members.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.members.placeholder", + tipI18nKey: "createGovernanceAction.fields.declarations.members.tip", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + maxLength: { + value: 500, + message: I18n.t( + "createGovernanceAction.fields.validations.maxLength", + { + maxLength: 500, + }, + ), + }, + }, + }, + newCommitteeExpiryEpoch: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.expiryEpoch.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.expiryEpoch.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + validate: numberValidation, + }, + }, + removeCommitteeHash: { + component: GovernanceActionField.Input, + labelI18nKey: "createGovernanceAction.fields.declarations.remove.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.remove.placeholder", + tipI18nKey: "createGovernanceAction.fields.declarations.remove.tip", + rules: { + maxLength: { + value: 500, + message: I18n.t( + "createGovernanceAction.fields.validations.maxLength", + { + maxLength: 500, + }, + ), + }, + }, + }, + }, [GovernanceActionType.TreasuryWithdrawals]: { ...sharedGovernanceActionFields, receivingAddress: { @@ -123,6 +209,59 @@ export const GOVERNANCE_ACTION_FIELDS: GovernanceActionFields = { }, }, }, + [GovernanceActionType.NewConstitution]: { + ...sharedGovernanceActionFields, + prevGovernanceActionHash: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionHash.placeholder", + }, + prevGovernanceActionIndex: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.prevGovernanceActionIndex.placeholder", + rules: { + validate: numberValidation, + }, + }, + constitutionUrl: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.constitutionUrl.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.constitutionUrl.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + }, + }, + constitutionHash: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.constitutionHash.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.constitutionHash.placeholder", + rules: { + required: { + value: true, + message: I18n.t("createGovernanceAction.fields.validations.required"), + }, + }, + }, + scriptHash: { + component: GovernanceActionField.Input, + labelI18nKey: + "createGovernanceAction.fields.declarations.scriptHash.label", + placeholderI18nKey: + "createGovernanceAction.fields.declarations.scriptHash.placeholder", + }, + }, } as const; export const GOVERNANCE_ACTION_CONTEXT = { diff --git a/govtool/frontend/src/context/wallet.tsx b/govtool/frontend/src/context/wallet.tsx index 4c6427b5c..1f31438dc 100644 --- a/govtool/frontend/src/context/wallet.tsx +++ b/govtool/frontend/src/context/wallet.tsx @@ -136,35 +136,35 @@ type ProtocolParameterChangeProps = { type HardForkInitiationProps = { prevGovernanceActionHash: string; - prevGovernanceActionIndex: number; - major: number; - minor: number; + prevGovernanceActionIndex: string; + major: string; + minor: string; } & VotingAnchor; type NewConstitutionProps = { - prevGovernanceActionHash: string; - prevGovernanceActionIndex: number; + prevGovernanceActionHash?: string; + prevGovernanceActionIndex?: string; constitutionUrl: string; constitutionHash: string; - scriptHash: string; + scriptHash?: string; } & VotingAnchor; type UpdateCommitteeProps = { prevGovernanceActionHash?: string; - prevGovernanceActionIndex?: number; + prevGovernanceActionIndex?: string; quorumThreshold: QuorumThreshold; newCommittee?: CommitteeToAdd[]; removeCommittee?: string[]; } & VotingAnchor; export type CommitteeToAdd = { - expiryEpoch: number; + expiryEpoch: string; committee: string; }; export type QuorumThreshold = { - numerator: number; - denominator: number; + numerator: string; + denominator: string; }; type ProtocolParamsUpdate = { @@ -1060,7 +1060,7 @@ const CardanoProvider = (props: Props) => { if (prevGovernanceActionHash && prevGovernanceActionIndex) { const prevGovernanceActionId = GovernanceActionId.new( TransactionHash.from_hex(prevGovernanceActionHash), - prevGovernanceActionIndex, + Number(prevGovernanceActionIndex), ); newConstitution = NewConstitutionAction.new_with_action_id( prevGovernanceActionId, @@ -1112,14 +1112,13 @@ const CardanoProvider = (props: Props) => { BigNum.from_str(quorumThreshold.numerator.toString()), BigNum.from_str(quorumThreshold.denominator.toString()), ); - const committeeToAdd = Committee.new(threshold); if (newCommittee) { newCommittee.forEach(async (member) => { const credential = await buildCredentialFromBech32Key( member.committee, ); - committeeToAdd.add_member(credential, member.expiryEpoch); + committeeToAdd.add_member(credential, Number(member.expiryEpoch)); }); } const committeeToRemoveCredentials = Credentials.new(); @@ -1134,7 +1133,7 @@ const CardanoProvider = (props: Props) => { if (prevGovernanceActionHash && prevGovernanceActionIndex) { const prevGovernanceActionId = GovernanceActionId.new( TransactionHash.from_hex(prevGovernanceActionHash), - prevGovernanceActionIndex, + Number(prevGovernanceActionIndex), ); updateCommitteeAction = UpdateCommitteeAction.new_with_action_id( prevGovernanceActionId, @@ -1393,13 +1392,16 @@ const CardanoProvider = (props: Props) => { }: HardForkInitiationProps) => { const govActionBuilder = VotingProposalBuilder.new(); try { - const newProtocolVersion = ProtocolVersion.new(major, minor); + const newProtocolVersion = ProtocolVersion.new( + Number(major), + Number(minor), + ); let hardForkInitiationAction; if (prevGovernanceActionHash && prevGovernanceActionIndex) { const prevGovernanceActionId = GovernanceActionId.new( TransactionHash.from_hex(prevGovernanceActionHash), - prevGovernanceActionIndex, + Number(prevGovernanceActionIndex), ); hardForkInitiationAction = HardForkInitiationAction.new_with_action_id( diff --git a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts index 0760b27cd..5e2a45454 100644 --- a/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts +++ b/govtool/frontend/src/hooks/forms/useCreateGovernanceActionForm.ts @@ -10,7 +10,7 @@ import { PATHS, storageInformationErrorModals, } from "@consts"; -import { useCardano, useModal, useAppContext } from "@context"; +import { useCardano, useModal, useAppContext, QuorumThreshold } from "@context"; import { correctAdaFormat, downloadJson, @@ -56,6 +56,9 @@ export const useCreateGovernanceActionForm = ( const { buildNewInfoGovernanceAction, buildTreasuryGovernanceAction, + buildNoConfidenceGovernanceAction, + buildNewConstitutionGovernanceAction, + buildUpdateCommitteeGovernanceAction, buildSignSubmitConwayCertTx, } = useCardano(); @@ -131,6 +134,64 @@ export const useCreateGovernanceActionForm = ( switch (govActionType) { case GovernanceActionType.InfoAction: return buildNewInfoGovernanceAction(commonGovActionDetails); + case GovernanceActionType.NoConfidence: + return buildNoConfidenceGovernanceAction(commonGovActionDetails); + case GovernanceActionType.NewConstitution: { + if ( + data.constitutionUrl === undefined || + data.constitutionHash === undefined + ) { + throw new Error( + t("errors.invalidNewCommitteeGovernanceActionType"), + ); + } + + return buildNewConstitutionGovernanceAction({ + ...commonGovActionDetails, + constitutionUrl: data.constitutionUrl, + constitutionHash: data.constitutionHash, + scriptHash: data.scriptHash, + prevGovernanceActionHash: data.prevGovernanceActionHash, + prevGovernanceActionIndex: data.prevGovernanceActionIndex, + }); + } + case GovernanceActionType.NewCommittee: { + if ( + data.newCommitteeHash === undefined || + data.newCommitteeExpiryEpoch === undefined + ) { + throw new Error( + t("errors.invalidUpdateCommitteeGovernanceActionType"), + ); + } + + let quorumThreshold: QuorumThreshold = { + numerator: "1", + denominator: "2", + }; + if (data.numerator !== undefined && data.denominator !== undefined) { + quorumThreshold = { + numerator: data.numerator, + denominator: data.denominator, + }; + } + + return buildUpdateCommitteeGovernanceAction({ + ...commonGovActionDetails, + newCommittee: [ + { + committee: data.newCommitteeHash, + expiryEpoch: data.newCommitteeExpiryEpoch, + }, + ], + removeCommittee: data.removeCommitteeHash + ? [data.removeCommitteeHash] + : [], + quorumThreshold, + prevGovernanceActionHash: data.prevGovernanceActionHash, + prevGovernanceActionIndex: data.prevGovernanceActionIndex, + }); + } case GovernanceActionType.TreasuryWithdrawals: { if ( data.amount === undefined || diff --git a/govtool/frontend/src/i18n/locales/en.json b/govtool/frontend/src/i18n/locales/en.json index 40e878484..09b478923 100644 --- a/govtool/frontend/src/i18n/locales/en.json +++ b/govtool/frontend/src/i18n/locales/en.json @@ -154,6 +154,56 @@ "title": { "label": "Title", "placeholder": "A name for this Action" + }, + "denominator": { + "label": "Denominator", + "placeholder": "Denominator", + "tip": "Denominator of the threshold" + }, + "numerator": { + "label": "Numerator", + "placeholder": "Numerator", + "tip": "Numerator of the threshold" + }, + "members": { + "label": "New committee member", + "placeholder": "Members to be added", + "tip": "Bech32 address of the new member" + }, + "expiryEpoch": { + "label": "Expiry Epoch", + "placeholder": "Expiry Epoch of the new Committee member", + "tip": "Epoch when the new committee will expire" + }, + "remove": { + "label": "Remove committee member", + "placeholder": "Members to be removed", + "tip": "Bech32 address of the member to be removed" + }, + "prevGovernanceActionIndex": { + "label": "Previous Governance Action ID", + "placeholder": "Previous Governance Action ID", + "tip": "Previous Governance Action ID" + }, + "prevGovernanceActionHash": { + "label": "Previous Governance Action Hash", + "placeholder": "Previous Governance Action Hash", + "tip": "Previous Governance Action Hash" + }, + "constitutionUrl": { + "label": "New Constitution URL", + "placeholder": "New Constitution URL", + "tip": "URL of the new constitution" + }, + "constitutionHash": { + "label": "New Constitution Hash", + "placeholder": "New Constitution Hash", + "tip": "Hash of the new constitution" + }, + "scriptHash": { + "label": "New Constitution Script Hash", + "placeholder": "New Constitution Script Hash", + "tip": "Script hash of the new constitution" } }, "validations": { diff --git a/govtool/frontend/src/types/governanceAction.ts b/govtool/frontend/src/types/governanceAction.ts index eb225ca24..77bad990a 100644 --- a/govtool/frontend/src/types/governanceAction.ts +++ b/govtool/frontend/src/types/governanceAction.ts @@ -21,7 +21,7 @@ export type FieldSchema = { labelI18nKey: NestedKeys; placeholderI18nKey: NestedKeys; tipI18nKey?: NestedKeys; - rules: Omit; + rules?: Omit; }; // Following properties are based on [CIP-108](https://github.com/Ryun1/CIPs/blob/governance-metadata-actions/CIP-0108/README.md) @@ -34,45 +34,45 @@ export type SharedGovernanceActionFieldSchema = { rationale: FieldSchema; }; -export type InfoGovernanceActionFieldSchema = SharedGovernanceActionFieldSchema; -export type TreasuryGovernanceActionFieldSchema = - SharedGovernanceActionFieldSchema & - Partial<{ - receivingAddress: FieldSchema; - amount: FieldSchema; - }>; -export type NoConfidenceActionFieldSchema = SharedGovernanceActionFieldSchema; -export type NewCommitteeActionFieldSchema = SharedGovernanceActionFieldSchema & - Partial<{ - prevGovernanceActionHash: FieldSchema; - prevGovernanceActionIndex: FieldSchema; - numerator: FieldSchema; - denominator: FieldSchema; - newCommitteeMembers: FieldSchema[]; - removeCommitteeMembers: FieldSchema[]; - }>; -export type HardForkInitiationActionFieldSchema = - SharedGovernanceActionFieldSchema & - Partial<{ - prevGovernanceActionHash: FieldSchema; - prevGovernanceActionIndex: FieldSchema; - major: FieldSchema; - minor: FieldSchema; - }>; -export type NewConstitutionActionFieldSchema = - SharedGovernanceActionFieldSchema & - Partial<{ - prevGovernanceActionHash: FieldSchema; - prevGovernanceActionIndex: FieldSchema; - constitutionUrl: FieldSchema; - constitutionHash: FieldSchema; - scriptHash: FieldSchema; - }>; +export type TreasuryGovernanceActionFieldSchema = Partial<{ + receivingAddress: FieldSchema; + amount: FieldSchema; +}>; +export type NewCommitteeActionFieldSchema = Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + numerator: FieldSchema; + denominator: FieldSchema; + newCommitteeHash: FieldSchema; + newCommitteeExpiryEpoch: FieldSchema; + removeCommitteeHash: FieldSchema; +}>; +export type HardForkInitiationActionFieldSchema = Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + major: FieldSchema; + minor: FieldSchema; +}>; +export type NewConstitutionActionFieldSchema = Partial<{ + prevGovernanceActionHash: FieldSchema; + prevGovernanceActionIndex: FieldSchema; + constitutionUrl: FieldSchema; + constitutionHash: FieldSchema; + scriptHash: FieldSchema; +}>; export type GovernanceActionFieldSchemas = - | InfoGovernanceActionFieldSchema & TreasuryGovernanceActionFieldSchema; + | SharedGovernanceActionFieldSchema & + TreasuryGovernanceActionFieldSchema & + NewCommitteeActionFieldSchema & + HardForkInitiationActionFieldSchema & + NewConstitutionActionFieldSchema; export type GovernanceActionFields = Record< - GovernanceActionType.InfoAction | GovernanceActionType.TreasuryWithdrawals, + | GovernanceActionType.InfoAction + | GovernanceActionType.TreasuryWithdrawals + | GovernanceActionType.NoConfidence + | GovernanceActionType.NewCommittee + | GovernanceActionType.NewConstitution, GovernanceActionFieldSchemas >; From 1019178cc0d27dd63a413d67c6f53f46001ba46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Tue, 11 Feb 2025 09:18:12 +0100 Subject: [PATCH 5/6] fix: ts error on outcomes pillar --- govtool/frontend/src/pages/GovernanceActionOutComes.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/govtool/frontend/src/pages/GovernanceActionOutComes.tsx b/govtool/frontend/src/pages/GovernanceActionOutComes.tsx index 5801cea32..a5b66289e 100644 --- a/govtool/frontend/src/pages/GovernanceActionOutComes.tsx +++ b/govtool/frontend/src/pages/GovernanceActionOutComes.tsx @@ -40,6 +40,9 @@ export const GovernanceActionOutComesPillar = () => { } > + {/* TODO: Remove this comments when tsc issue is resolved */} + {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} + {/* @ts-expect-error */} From 495648bb27562671028d458ae49556134f90c57b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Mon, 10 Feb 2025 21:04:49 +0100 Subject: [PATCH 6/6] chore: bump @intersect.mbo/pdf-ui to v0.6.0 --- CHANGELOG.md | 1 + govtool/frontend/package-lock.json | 10 ++--- govtool/frontend/package.json | 2 +- govtool/frontend/yarn.lock | 67 ++++++++++++++---------------- 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91ab52bbc..c660571e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ changes. - Change threshold visual representation in governance action votes - Resize governance action details columns +- Update @intersect.mbo/pdf-ui to v0.6.0 ### Removed diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index b2684379f..14051e68f 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -15,7 +15,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "1.0.0", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.5.11", + "@intersect.mbo/pdf-ui": "^0.6.0", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3397,13 +3397,13 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.11.tgz", - "integrity": "sha512-LchrkbU2cbNP3zajkVoFy/+ZcqBDAt9AnF9weYGQPU0qD2ryj93JNeKzUctsYsWfGLy5d7TslNdnpx0zGVcc9A==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.6.0.tgz", + "integrity": "sha512-4lNDqUp03UQEy5Fwu2kTewM8Jxfc5uNxk7h40wOWx4zNIIOos187kF1NsE8yW2/VXRSkklsxSbc1ckifEJJakw==", "dependencies": { "@emurgo/cardano-serialization-lib-asmjs": "^12.0.0-beta.2", "@fontsource/poppins": "^5.0.14", - "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", + "@intersect.mbo/intersectmbo.org-icons-set": "^1.1.0", "axios": "^1.7.2", "date-fns": "^3.6.0", "react-markdown": "^8.0.6", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 90dd255c8..f7b5d9175 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -29,7 +29,7 @@ "@hookform/resolvers": "^3.3.1", "@intersect.mbo/govtool-outcomes-pillar-ui": "1.0.0", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.5.11", + "@intersect.mbo/pdf-ui": "^0.6.0", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock index b5dd9c3ce..9dc9df1c6 100644 --- a/govtool/frontend/yarn.lock +++ b/govtool/frontend/yarn.lock @@ -1367,15 +1367,15 @@ resolved "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-asmjs/-/cardano-serialization-lib-asmjs-12.1.1.tgz" integrity sha512-K3f28QUfLDJ7seO6MtKfMYtRm5ccf36TQ5yxyTmZqX1TA85MkriEdxqpgV9KLiLEA95emwnlvU2/WmlHMRPg1A== -"@esbuild/linux-x64@0.21.5": +"@esbuild/darwin-arm64@0.21.5": version "0.21.5" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== -"@esbuild/linux-x64@0.24.2": +"@esbuild/darwin-arm64@0.24.2": version "0.24.2" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz" - integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz" + integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.1" @@ -1500,19 +1500,19 @@ buffer "^6.0.3" react-query "^3.39.3" -"@intersect.mbo/intersectmbo.org-icons-set@^1.0.8": +"@intersect.mbo/intersectmbo.org-icons-set@^1.0.8", "@intersect.mbo/intersectmbo.org-icons-set@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@intersect.mbo/intersectmbo.org-icons-set/-/intersectmbo.org-icons-set-1.1.0.tgz" integrity sha512-sjKEtnK9eLYH/8kCD0YRQCms3byFA/tnSsei9NHTZbBYX9sBpeX6ErfR0sKYjOSxQOxl4FumX9D0X+vHIqxo8g== -"@intersect.mbo/pdf-ui@^0.5.11": - version "0.5.11" - resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.5.11.tgz" - integrity sha512-LchrkbU2cbNP3zajkVoFy/+ZcqBDAt9AnF9weYGQPU0qD2ryj93JNeKzUctsYsWfGLy5d7TslNdnpx0zGVcc9A== +"@intersect.mbo/pdf-ui@^0.6.0": + version "0.6.0" + resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.6.0.tgz" + integrity sha512-4lNDqUp03UQEy5Fwu2kTewM8Jxfc5uNxk7h40wOWx4zNIIOos187kF1NsE8yW2/VXRSkklsxSbc1ckifEJJakw== dependencies: "@emurgo/cardano-serialization-lib-asmjs" "^12.0.0-beta.2" "@fontsource/poppins" "^5.0.14" - "@intersect.mbo/intersectmbo.org-icons-set" "^1.0.8" + "@intersect.mbo/intersectmbo.org-icons-set" "^1.1.0" axios "^1.7.2" date-fns "^3.6.0" react-markdown "^8.0.6" @@ -2166,15 +2166,10 @@ resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz" integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== -"@parcel/watcher-linux-x64-glibc@2.5.0": - version "2.5.0" - resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz" - integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw== - -"@parcel/watcher-linux-x64-musl@2.5.0": +"@parcel/watcher-darwin-arm64@2.5.0": version "2.5.0" - resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz" - integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA== + resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz" + integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw== "@parcel/watcher@^2.4.1": version "2.5.0" @@ -2287,15 +2282,10 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-linux-x64-gnu@4.27.4": - version "4.27.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz" - integrity sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q== - -"@rollup/rollup-linux-x64-musl@4.27.4": +"@rollup/rollup-darwin-arm64@4.27.4": version "4.27.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz" - integrity sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw== + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz" + integrity sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q== "@rtsao/scc@^1.1.0": version "1.1.0" @@ -2874,15 +2864,10 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" -"@swc/core-linux-x64-gnu@1.9.3": +"@swc/core-darwin-arm64@1.9.3": version "1.9.3" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.9.3.tgz" - integrity sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w== - -"@swc/core-linux-x64-musl@1.9.3": - version "1.9.3" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.9.3.tgz" - integrity sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg== + resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.9.3.tgz" + integrity sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w== "@swc/core@*", "@swc/core@^1.5.22", "@swc/core@^1.7.26": version "1.9.3" @@ -7188,6 +7173,16 @@ fs@^0.0.1-security: resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"