diff --git a/packages/app/src/components/Contract.vue b/packages/app/src/components/Contract.vue
index 6c5edf2d5a..c8bf8a58b4 100644
--- a/packages/app/src/components/Contract.vue
+++ b/packages/app/src/components/Contract.vue
@@ -7,6 +7,7 @@
v-if="contract?.address && !pending"
:title="contractName ?? t('contract.title')"
:value="contractName ? undefined : contract?.address"
+ :is-verified="contract?.verificationInfo != null"
/>
@@ -78,6 +79,8 @@
import { computed, type PropType } from "vue";
import { useI18n } from "vue-i18n";
+import { CheckCircleIcon } from "@heroicons/vue/solid";
+
import SearchForm from "@/components/SearchForm.vue";
import BalanceTable from "@/components/balances/Table.vue";
import Breadcrumbs from "@/components/common/Breadcrumbs.vue";
@@ -118,7 +121,11 @@ const props = defineProps({
const tabs = computed(() => [
{ title: t("tabs.transactions"), hash: "#transactions" },
{ title: t("tabs.transfers"), hash: "#transfers" },
- { title: t("tabs.contract"), hash: "#contract" },
+ {
+ title: t("tabs.contract"),
+ hash: "#contract",
+ icon: props.contract?.verificationInfo ? CheckCircleIcon : null,
+ },
{ title: t("tabs.events"), hash: "#events" },
]);
const breadcrumbItems = computed((): BreadcrumbItem[] | [] => {
diff --git a/packages/app/src/components/common/Tabs.vue b/packages/app/src/components/common/Tabs.vue
index 16524e921e..8ef40b5d31 100644
--- a/packages/app/src/components/common/Tabs.vue
+++ b/packages/app/src/components/common/Tabs.vue
@@ -15,9 +15,13 @@
v-else
class="tab-btn"
:class="{ active: currentTabHash === tab.hash && tabs.length > 1 }"
- v-html="tab.title"
@click="setTab(tab)"
- >
+ >
+
+
+
+
+
@@ -35,9 +39,12 @@
import { type PropType, ref, watchEffect } from "vue";
import { useRoute, useRouter } from "vue-router";
+import type { FunctionalComponent } from "vue";
+
export type Tab = {
title: string;
hash: string | null;
+ icon?: FunctionalComponent | null;
};
const props = defineProps({
@@ -76,7 +83,7 @@ watchEffect(() => {
@apply flex border-b md:flex-row;
}
.tab-btn {
- @apply px-4 py-3.5 text-sm text-gray-400 outline-0 sm:text-base;
+ @apply px-4 py-3.5 text-sm text-gray-400 outline-0 sm:text-base flex;
}
.tab-content {
@apply rounded-b-lg;
@@ -84,5 +91,8 @@ watchEffect(() => {
.active {
@apply border-b-2 border-primary-600 font-bold text-primary-600;
}
+ .tab-icon {
+ @apply ml-0.5 w-5 text-green-500;
+ }
}
diff --git a/packages/app/src/components/common/Title.vue b/packages/app/src/components/common/Title.vue
index 696315da59..2bbc85757b 100644
--- a/packages/app/src/components/common/Title.vue
+++ b/packages/app/src/components/common/Title.vue
@@ -5,9 +5,16 @@
{{ shortValue(value) }}
+
+ {{ t("contract.verified") }}
+
diff --git a/packages/app/src/locales/en.json b/packages/app/src/locales/en.json
index d07cc2f19d..095751e95c 100644
--- a/packages/app/src/locales/en.json
+++ b/packages/app/src/locales/en.json
@@ -326,6 +326,8 @@
"infoTableError": "An Error Occurred",
"balanceTableTitle": "Balances",
"notFound": "Not Found",
+ "verified": "Source Code",
+ "verifiedTooltip": "The contract's source code has been verified to match its on-chain Bytecode. Source code verification does not imply the contract is safe to interact with.",
"transactionTable": {
"error": "Something went wrong",
"notFound": {
diff --git a/packages/app/src/locales/uk.json b/packages/app/src/locales/uk.json
index e04fecae3c..6f580a38be 100644
--- a/packages/app/src/locales/uk.json
+++ b/packages/app/src/locales/uk.json
@@ -188,6 +188,8 @@
"infoTableError": "Виникла помилка",
"balanceTableTitle": "Мої кошти",
"notFound": "Не знайдено",
+ "verified": "вихідний код",
+ "verifiedTooltip": "Вихідний код контракту було перевірено на відповідність його байт-коду в мережі. Перевірений вихідний код не означає, що контракт безпечний для взаємодії.",
"transactionTable": {
"error": "Щось пішло не так",
"notFound": {
diff --git a/packages/app/tests/components/Contract.spec.ts b/packages/app/tests/components/Contract.spec.ts
index 0ccd2c5cf4..6b9a345391 100644
--- a/packages/app/tests/components/Contract.spec.ts
+++ b/packages/app/tests/components/Contract.spec.ts
@@ -88,6 +88,7 @@ describe("Contract:", () => {
stubs: ["router-link"],
},
});
- expect(container.querySelector(".title-container")?.textContent?.trim()).toBe("DARA2");
+ expect(container.querySelector(".title-container")?.textContent?.trim()).toContain("DARA2");
+ expect(container.querySelector(".title-container")?.textContent?.trim()).toContain("Source Code");
});
});
diff --git a/packages/app/tests/e2e/src/pages/contract.page.ts b/packages/app/tests/e2e/src/pages/contract.page.ts
index 4ed032d106..267a619ba8 100644
--- a/packages/app/tests/e2e/src/pages/contract.page.ts
+++ b/packages/app/tests/e2e/src/pages/contract.page.ts
@@ -19,11 +19,11 @@ export class ContractPage extends BasePage {
super(world);
}
get transactionsTab() {
- return "//button[text()='Transactions']/..";
+ return "//button[contains(.,'Transactions')]/..";
}
get contractTab() {
- return "//button[text()='Contract']/..";
+ return "//button[contains(.,'Contract')]/..";
}
get contractVerificationBtn() {
diff --git a/packages/app/tests/e2e/src/pages/transaction.page.ts b/packages/app/tests/e2e/src/pages/transaction.page.ts
index bfec33015b..9a2939f8a3 100644
--- a/packages/app/tests/e2e/src/pages/transaction.page.ts
+++ b/packages/app/tests/e2e/src/pages/transaction.page.ts
@@ -23,11 +23,11 @@ export class TransactionPage extends BasePage {
}
get generalInfoTab() {
- return "//button[contains(text(),'General Info')]/..";
+ return "//button[contains(.,'General Info')]/..";
}
get logsTab() {
- return "//button[contains(text(),'Logs')]/..";
+ return "//button[contains(.,'Logs')]/..";
}
get badgeContent() {