Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explorer: Improve Cardano Transaction Certification & Certificate Chain Validation UI #1569

Merged
merged 32 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
45bf3b7
Uniformise file naming and export of explorer components
Alenar Mar 7, 2024
7fe6258
Add link to cexplorer for certified transaction hashes
Alenar Mar 7, 2024
fd7cab7
Add the beacon at which the verications took place
Alenar Mar 8, 2024
4fea4d4
Make `CopyableHash` component more customizable
Alenar Mar 8, 2024
7634f95
Fix incorrect default aggregator capabilities
Alenar Mar 8, 2024
46d4001
use the mithril logo for certified tx in explorer
Alenar Mar 8, 2024
e790b3a
Fix explorer empty tab when the ctx tab and switching aggregator
Alenar Mar 11, 2024
f96e6c3
Use icons font instead of directly the svg for the mithril badge icon
Alenar Mar 11, 2024
6228f41
Extract ctx result table to a local component
Alenar Mar 11, 2024
814b46d
Add epoch to certificate verification modal
Alenar Mar 11, 2024
f327d83
Validate proof before the certificate chain in explorer
Alenar Mar 12, 2024
7907ae8
Explorer CertificateVerifier now take its client and cert as parameters
Alenar Mar 12, 2024
3d9286f
Enhance error handling for explorer CertificateVerifier
Alenar Mar 12, 2024
7edd09e
Enhance error handling for explorer ctx certifier when certificate is…
Alenar Mar 13, 2024
c7875e4
Reflect validation errors in tx certification breadbrumb
Alenar Mar 13, 2024
da88781
Refactor explorer CertificateVerifier to use a table
Alenar Mar 13, 2024
21aad25
Add default export for explorer CopyButton
Alenar Mar 13, 2024
a22e4ca
Show links underline on hover in Explorer
Alenar Mar 13, 2024
fcaadd2
Make certificate hashes of the explorer chain verifier clickable
Alenar Mar 13, 2024
32c0a88
Clicking on a certificate hash on tx certifier modal open certificate…
Alenar Mar 13, 2024
982438f
Reduce confusion with navigation buttons in registration page
Alenar Mar 13, 2024
a6ce776
Use the same icons & wording for valid checks in the tx certification…
Alenar Mar 13, 2024
9c7cc1d
Always show the cexplorer link for tx en explorer
Alenar Mar 13, 2024
bca4ba0
Use absolute import in Explorer
Alenar Mar 13, 2024
649d4bb
Display correctly certificate chain validation error
Alenar Mar 14, 2024
a444d74
Fix issues from self review
Alenar Mar 14, 2024
d93d288
Fix incorrect error handling of invalid proof
Alenar Mar 14, 2024
99cdfef
Add mithril logo to tx certification result alert heading
Alenar Mar 14, 2024
393cb9f
Add a note about unicode codepoints in explorer readme
Alenar Mar 14, 2024
36b547d
address PR review: better wording for ctx certification done step
Alenar Mar 14, 2024
ee5f846
Tidy up some imports and remove unused variables in explorer
Alenar Mar 15, 2024
e591c7e
Upgrade explorer version from `0.5.0` to `0.6.0`
Alenar Mar 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions mithril-explorer/.fantasticonrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/** @type {import("fantasticon").RunnerOptions} */
module.exports = {
inputDir: "./icons",
outputDir: "./public/fonts",
fontTypes: ["woff", "woff2"],
assetTypes: ["css"],
fontsUrl: "/explorer/fonts",
formatOptions: {},
name: "mithril-icons",
prefix: "mi",
templates: {
css: "./font.css.hbs",
},
pathOptions: {
css: "./src/app/mithril-icons.css",
},
codepoints: {
logo: 57344, // 0xe000 = start of unicode private use area
},
};
1 change: 1 addition & 0 deletions mithril-explorer/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
out
explorer
font.css.hbs
5 changes: 5 additions & 0 deletions mithril-explorer/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ dev: build
@echo "\033[1mServing dev build at: http://localhost:3000/explorer \033[0m"
npm run dev

icons-font:
npm run icons-font
npm exec -- prettier ./src/app/mithril-icons.css --write

test: package-lock.json
npm run test:ci

Expand Down Expand Up @@ -61,6 +65,7 @@ upgrade: clean install
@testing-library/react@latest \
eslint@latest \
eslint-config-next@latest \
fantasticon@latest \
jest@latest \
jest-environment-jsdom@latest \
next-router-mock@latest \
Expand Down
21 changes: 21 additions & 0 deletions mithril-explorer/README.md
jpraynaud marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,24 @@ make dev
```

Open [http://localhost:3000](http://localhost:3000/explorer) with your browser to see the result.

## Adding or updating an icon of the 'Mithril' font

In the `./icons` folder add or modify a svg.

If you add a new icon you need to reference and associate it with a codepoint in the `./fantasticonrc.js`
configuration file.
The codepoint must be part of the [unicode private use area](https://www.unicode.org/charts/PDF/UE000.pdf), as
such it must be an integer between 57344 and 63743 (hex: E000-F8FF).

Then rebuild the font:

```bash
make icons-font
```

You can then use the icon in the js, ie if your icon name is `shield`:

```jsx
<i className={`bi mi mi-shield`}></i>
```
6 changes: 3 additions & 3 deletions mithril-explorer/__tests__/AggregatorSetter.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import AggregatorSetter from "../src/components/AggregatorSetter";
import { initStore } from "./helpers";
import { Provider } from "react-redux";
import default_available_aggregators from "../src/aggregators-list";
import { settingsSlice } from "../src/store/settingsSlice";
import AggregatorSetter from "#/AggregatorSetter";
import default_available_aggregators from "@/aggregators-list";
import { settingsSlice } from "@/store/settingsSlice";

function renderAggregatorSetter(default_state = undefined) {
const store = initStore(default_state);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fireEvent, render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import CardanoTransactionsFormInput from "../src/components/CardanoTransactionsFormInput";
import CardanoTransactionsFormInput from "#/CardanoTransactionsFormInput";

function setup() {
const utils = [render(<CardanoTransactionsFormInput />)];
Expand Down
13 changes: 9 additions & 4 deletions mithril-explorer/__tests__/PoolTicker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import { initStore } from "./helpers";
import { Provider } from "react-redux";
import { poolsSlice } from "../src/store/poolsSlice";
import PoolTicker from "../src/components/PoolTicker";
import { getCExplorerUrlForPool } from "../src/utils";
import { settingsSlice } from "../src/store/settingsSlice";
import PoolTicker from "#/PoolTicker";
import { settingsSlice } from "@/store/settingsSlice";
import { poolsSlice } from "@/store/poolsSlice";
import { getCExplorerUrl } from "@/utils";

function renderPoolTickerComponent(partyId, default_state = undefined) {
const store = initStore(default_state);
Expand All @@ -19,6 +19,11 @@ function renderPoolTickerComponent(partyId, default_state = undefined) {
];
}

function getCExplorerUrlForPool(network, partyId) {
const cExplorerUrl = getCExplorerUrl(network);
return cExplorerUrl ? `${cExplorerUrl}/pool/${partyId}` : undefined;
}

describe("PoolTicker", () => {
it("Pool ticker not on the three main network doesn't show link to cexplorer", () => {
const partyId = "pool1zmtm8yef33z2n7x4nn0kvv9xpzjuj7725p9y9m5t960g5qy51ua";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import TransactionCertificationBreadcrumb from "#/CertifyCardanoTransactionsModal/TransactionCertificationBreadcrumb";
import { validationSteps } from "#/CertifyCardanoTransactionsModal";

function setup(currentStep, isProofValid, isCertificateChainValid) {
const utils = [
render(
<TransactionCertificationBreadcrumb
currentStep={currentStep}
isProofValid={isProofValid}
isCertificateChainValid={isCertificateChainValid}
/>,
),
];

const tabs = new Map();
tabs.set(validationSteps.fetchingProof, screen.getByText(/Fetching Transactions Proof/i));
tabs.set(validationSteps.validatingProof, screen.getByText(/Verifying Transactions Proof/i));
tabs.set(
validationSteps.validatingCertificateChain,
screen.getByText(/Validating Certificate Chain/i),
);
tabs.set(validationSteps.done, screen.getByText(/Finish/i));

return {
tabs: tabs,
...utils,
};
}

const classForVariant = (variant) => `list-group-item-${variant}`;

describe("TransactionCertificationBreadcrumb", () => {
it("The tab variant are light when default", () => {
const { tabs } = setup(validationSteps.ready, false, false);

for (const [_key, tab] of tabs) {
expect(tab).toHaveClass(classForVariant("light"));
}
});

it.each([
["fetchingProof", validationSteps.fetchingProof],
["validatingProof", validationSteps.validatingProof],
["validatingCertificateChain", validationSteps.validatingCertificateChain],
])("The tab variant is primary when current and checks are valid : %s", (stepName, stepIndex) => {
const { tabs } = setup(stepIndex, true, true);

expect(tabs.get(stepIndex)).toHaveClass(classForVariant("primary"));
});

it("Current step is done and checks are valid then tabs are light except done step tab that is success", () => {
const { tabs } = setup(validationSteps.done, true, true);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("light"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("success"));
});

it("Current step is done and proof check is invalid then tabs are danger except tabs before proof validation", () => {
const { tabs } = setup(validationSteps.done, false, true);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("danger"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("danger"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("danger"));
});

it("Current step is done and certificate chain check is invalid then tabs are danger except tabs before certificate chain validation", () => {
const { tabs } = setup(validationSteps.done, true, false);

expect(tabs.get(validationSteps.fetchingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingProof)).toHaveClass(classForVariant("light"));
expect(tabs.get(validationSteps.validatingCertificateChain)).toHaveClass(
classForVariant("danger"),
);
expect(tabs.get(validationSteps.done)).toHaveClass(classForVariant("danger"));
});
});
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/helpers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { saveToLocalStorage, storeBuilder } from "../src/store/store";
import { saveToLocalStorage, storeBuilder } from "@/store/store";
import * as mockRouter from "next-router-mock";

const baseLocation = "http://localhost";
Expand Down
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/partyIdFormat.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatPartyId } from "../src/utils";
import { formatPartyId } from "@/utils";

describe("Stake formatting", () => {
it.each([
Expand Down
2 changes: 1 addition & 1 deletion mithril-explorer/__tests__/stakeFormat.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatStake } from "../src/utils";
import { formatStake } from "@/utils";

const toLovelace = (ada) => ada * 1000000;

Expand Down
10 changes: 5 additions & 5 deletions mithril-explorer/__tests__/store.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import default_available_aggregators from "../src/aggregators-list";
import { signedEntityType } from "../src/constants";
import { poolsSlice } from "../src/store/poolsSlice";
import default_available_aggregators from "@/aggregators-list";
import { signedEntityType } from "@/constants";
import { poolsSlice } from "@/store/poolsSlice";
import {
removeSelectedAggregator,
selectAggregator,
settingsSlice,
setUpdateInterval,
toggleAutoUpdate,
} from "../src/store/settingsSlice";
import { saveToLocalStorage, storeBuilder } from "../src/store/store";
} from "@/store/settingsSlice";
import { saveToLocalStorage, storeBuilder } from "@/store/store";
import { waitFor } from "@testing-library/react";
import { initStore } from "./helpers";

Expand Down
28 changes: 28 additions & 0 deletions mithril-explorer/font.css.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* autogenerated file using `make icons-font` - don't modify manually */

@font-face {
font-display: block;
font-family: "{{ name }}";
src: {{{ fontSrc }}};
}

.{{ prefix }}::before,
[class^="{{ prefix }}-"]::before,
[class*=" {{ prefix }}-"]::before {
display: inline-block;
font-family: {{ name }} !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
vertical-align: -.125em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

{{# each codepoints }}
.{{ ../prefix }}-{{ @key }}::before {
content: "\\{{ codepoint this }}";
}
{{/ each }}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions mithril-explorer/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"#/*": ["./src/components/*"]
}
}
}
Loading
Loading