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() {