fix: Add audit badge and contract addresses prominently on landing (#147)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
723476d4f6
commit
ef65cf6146
2 changed files with 190 additions and 1 deletions
187
landing/src/components/SecurityInfo.vue
Normal file
187
landing/src/components/SecurityInfo.vue
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
<template>
|
||||
<section class="security-info">
|
||||
<div class="security-info__badge">
|
||||
<div class="security-info__badge-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="security-info__badge-text">
|
||||
<span class="security-info__badge-label">Unaudited</span>
|
||||
<span class="security-info__badge-sub">Third-party audit planned for Q3 2026</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="security-info__contracts" v-if="krkAddress || stakeAddress">
|
||||
<h3 class="security-info__heading">Contract Addresses</h3>
|
||||
<div class="security-info__address-list">
|
||||
<div v-if="krkAddress" class="security-info__address-row">
|
||||
<span class="security-info__address-label">KRK Token</span>
|
||||
<span class="security-info__address-value">
|
||||
<a :href="`https://basescan.org/address/${krkAddress}`" target="_blank" rel="noopener noreferrer">{{ krkAddress }}</a>
|
||||
<button class="security-info__copy-btn" @click="copyAddress(krkAddress, 'krk')" :title="copied === 'krk' ? 'Copied!' : 'Copy address'" :aria-label="copied === 'krk' ? 'Copied!' : 'Copy KRK token address'">
|
||||
<svg v-if="copied !== 'krk'" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
||||
<svg v-else width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#4ade80" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="stakeAddress" class="security-info__address-row">
|
||||
<span class="security-info__address-label">Stake</span>
|
||||
<span class="security-info__address-value">
|
||||
<a :href="`https://basescan.org/address/${stakeAddress}`" target="_blank" rel="noopener noreferrer">{{ stakeAddress }}</a>
|
||||
<button class="security-info__copy-btn" @click="copyAddress(stakeAddress, 'stake')" :title="copied === 'stake' ? 'Copied!' : 'Copy address'" :aria-label="copied === 'stake' ? 'Copied!' : 'Copy Stake contract address'">
|
||||
<svg v-if="copied !== 'stake'" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
||||
<svg v-else width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#4ade80" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="security-info__links">
|
||||
<a href="https://codeberg.org/johba/harb" target="_blank" rel="noopener noreferrer" class="security-info__link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>
|
||||
Source Code
|
||||
</a>
|
||||
<a v-if="krkAddress" :href="`https://basescan.org/address/${krkAddress}#code`" target="_blank" rel="noopener noreferrer" class="security-info__link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
|
||||
Basescan Verification
|
||||
</a>
|
||||
<a href="https://codeberg.org/johba/harb/wiki" target="_blank" rel="noopener noreferrer" class="security-info__link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
|
||||
Documentation
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
const krkAddress = import.meta.env.VITE_KRAIKEN_ADDRESS || '';
|
||||
const stakeAddress = import.meta.env.VITE_STAKE_ADDRESS || '';
|
||||
const copied = ref('');
|
||||
|
||||
function copyAddress(addr: string, key: string) {
|
||||
navigator.clipboard.writeText(addr);
|
||||
copied.value = key;
|
||||
setTimeout(() => { copied.value = ''; }, 1500);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.security-info
|
||||
margin-top: 88px
|
||||
padding: 32px 24px
|
||||
background: rgba(255, 255, 255, 0.03)
|
||||
border: 1px solid rgba(255, 255, 255, 0.08)
|
||||
border-radius: 16px
|
||||
text-align: center
|
||||
@media (min-width: 768px)
|
||||
padding: 48px 40px
|
||||
|
||||
.security-info__badge
|
||||
display: inline-flex
|
||||
align-items: center
|
||||
gap: 12px
|
||||
padding: 10px 20px
|
||||
border: 1px solid rgba(234, 179, 8, 0.4)
|
||||
background: rgba(234, 179, 8, 0.08)
|
||||
border-radius: 8px
|
||||
margin-bottom: 32px
|
||||
|
||||
.security-info__badge-icon
|
||||
color: #eab308
|
||||
display: flex
|
||||
align-items: center
|
||||
|
||||
.security-info__badge-text
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: flex-start
|
||||
gap: 2px
|
||||
|
||||
.security-info__badge-label
|
||||
font-weight: 600
|
||||
font-size: 15px
|
||||
color: #eab308
|
||||
|
||||
.security-info__badge-sub
|
||||
font-size: 12px
|
||||
color: rgba(234, 179, 8, 0.7)
|
||||
|
||||
.security-info__heading
|
||||
font-size: 13px
|
||||
font-weight: 600
|
||||
text-transform: uppercase
|
||||
letter-spacing: 1px
|
||||
color: #9A9898
|
||||
margin-bottom: 16px
|
||||
|
||||
.security-info__address-list
|
||||
display: flex
|
||||
flex-direction: column
|
||||
gap: 12px
|
||||
margin-bottom: 28px
|
||||
|
||||
.security-info__address-row
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
gap: 12px
|
||||
flex-wrap: wrap
|
||||
|
||||
.security-info__address-label
|
||||
font-weight: 500
|
||||
font-size: 14px
|
||||
color: rgba(240, 240, 240, 0.7)
|
||||
min-width: 80px
|
||||
text-align: right
|
||||
|
||||
.security-info__address-value
|
||||
display: inline-flex
|
||||
align-items: center
|
||||
gap: 6px
|
||||
a
|
||||
font-family: monospace
|
||||
font-size: 13px
|
||||
color: #7550AE
|
||||
text-decoration: none
|
||||
word-break: break-all
|
||||
&:hover
|
||||
text-decoration: underline
|
||||
@media (max-width: 767px)
|
||||
font-size: 11px
|
||||
|
||||
.security-info__copy-btn
|
||||
background: none
|
||||
border: none
|
||||
cursor: pointer
|
||||
padding: 2px
|
||||
color: #9A9898
|
||||
display: inline-flex
|
||||
align-items: center
|
||||
&:hover
|
||||
color: #c084fc
|
||||
|
||||
.security-info__links
|
||||
display: flex
|
||||
justify-content: center
|
||||
gap: 24px
|
||||
flex-wrap: wrap
|
||||
|
||||
.security-info__link
|
||||
display: inline-flex
|
||||
align-items: center
|
||||
gap: 6px
|
||||
font-size: 14px
|
||||
color: rgba(240, 240, 240, 0.7)
|
||||
text-decoration: none
|
||||
padding: 8px 16px
|
||||
border: 1px solid rgba(255, 255, 255, 0.1)
|
||||
border-radius: 8px
|
||||
transition: border-color 0.2s, color 0.2s
|
||||
&:hover
|
||||
color: #c084fc
|
||||
border-color: rgba(150, 103, 190, 0.4)
|
||||
</style>
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
<WalletCard />
|
||||
<LiveStats />
|
||||
<div class="k-container">
|
||||
<SecurityInfo />
|
||||
<section class="how-it-works-section">
|
||||
<h2>How It Works</h2>
|
||||
<div class="cards-grid">
|
||||
|
|
@ -75,7 +76,7 @@
|
|||
</section>
|
||||
<section class="trust-section">
|
||||
<h2>Verified On-Chain</h2>
|
||||
<p>Deployed on Base. Verified and auditable on-chain.</p>
|
||||
<p>Deployed on Base. All contracts immutable and verified. Inspect every transaction yourself.</p>
|
||||
<div class="trust-links">
|
||||
<KButton outlined @click="router.push('/docs/code')">Source Code</KButton>
|
||||
<KButton outlined @click="router.push('/docs')">Documentation</KButton>
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
import KButton from '@/components/KButton.vue';
|
||||
import LeftRightComponent from '@/components/LeftRightComponent.vue';
|
||||
import LiveStats from '@/components/LiveStats.vue';
|
||||
import SecurityInfo from '@/components/SecurityInfo.vue';
|
||||
import WalletCard from '@/components/WalletCard.vue';
|
||||
import { useMobile } from '@/composables/useMobile';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue