2026-04-10 12:52:17 -07:00
import { Card } from '@/libs/frontend-ui-primitives'
import { DetailRow } from '@/components/common/DetailRow'
import EntityBadge from '@/components/common/EntityBadge'
import type { GruStandardsProfile } from '@/services/api/gru'
import Link from 'next/link'
const STANDARD_EXPLANATIONS : Record < string , string > = {
'ERC-20' : 'Base fungible-token surface for wallets, DEXs, explorers, and accounting systems.' ,
AccessControl : 'Role-governed administration for mint, burn, pause, and supervised operations.' ,
Pausable : 'Emergency intervention surface for freezing activity during incidents or policy actions.' ,
'EIP-712' : 'Typed signing domain for structured off-chain approvals and payment flows.' ,
'ERC-2612' : 'Permit support for signature-based approvals without a separate on-chain approve transaction.' ,
'ERC-3009' : 'Authorization-based transfer model for signed payment flows without prior allowances.' ,
'ERC-5267' : 'Discoverable EIP-712 domain introspection so wallets and relayers can inspect the signing domain cleanly.' ,
2026-04-30 03:06:49 -07:00
CashElectronicMoneyInterface : 'Repo-native GRU instrument methodology for issuance and redemption semantics.' ,
2026-04-10 12:52:17 -07:00
DeterministicStorageNamespace : 'Stable namespace for upgrade-aware policy, registry, and audit resolution.' ,
JurisdictionAndSupervisionMetadata : 'Governance, supervisory, disclosure, and reporting metadata required by the GRU operating model.' ,
}
2026-04-30 03:06:49 -07:00
const STANDARD_DISPLAY_LABELS : Record < string , string > = {
CashElectronicMoneyInterface : 'Cash electronic-money interface' ,
DeterministicStorageNamespace : 'Deterministic storage namespace' ,
JurisdictionAndSupervisionMetadata : 'Jurisdiction and supervision metadata' ,
}
function formatStandardLabel ( id : string ) : string {
return STANDARD_DISPLAY_LABELS [ id ] || id
}
function formatProfileLabel ( id : string ) : string {
if ( id === 'gru-c-star-v2-public-network-and-payment' ) return 'GRU C* v2 payment profile'
return id
}
2026-04-10 12:52:17 -07:00
function formatDuration ( seconds : number | null ) : string | null {
if ( seconds == null || ! Number . isFinite ( seconds ) || seconds <= 0 ) return null
const units = [
{ label : 'day' , value : 86400 } ,
{ label : 'hour' , value : 3600 } ,
{ label : 'minute' , value : 60 } ,
]
const parts : string [ ] = [ ]
let remaining = Math . floor ( seconds )
for ( const unit of units ) {
if ( remaining >= unit . value ) {
const count = Math . floor ( remaining / unit . value )
remaining -= count * unit . value
parts . push ( ` ${ count } ${ unit . label } ${ count === 1 ? '' : 's' } ` )
}
if ( parts . length === 2 ) break
}
if ( parts . length === 0 ) {
return ` ${ remaining } second ${ remaining === 1 ? '' : 's' } `
}
return parts . join ( ' ' )
}
export default function GruStandardsCard ( {
profile ,
title = 'GRU v2 Standards' ,
} : {
profile : GruStandardsProfile
title? : string
} ) {
const detectedCount = profile . standards . filter ( ( standard ) = > standard . detected ) . length
const requiredCount = profile . standards . filter ( ( standard ) = > standard . required ) . length
const missingRequired = profile . standards . filter ( ( standard ) = > standard . required && ! standard . detected )
const noticePeriod = formatDuration ( profile . minimumUpgradeNoticePeriodSeconds )
const recommendations = [
missingRequired . length > 0
? ` Review the live contract ABI and deployment against the GRU v2 base-token matrix before treating this asset as fully canonical. `
: ` The live contract exposes the full required GRU v2 base-token surface currently checked by the explorer. ` ,
profile . wrappedTransport
2026-04-30 03:06:49 -07:00
? 'This looks like a cW public-network representation, so confirm the corresponding bridge lane and reserve-verifier posture in addition to the token ABI.'
: 'This looks like a canonical GRU asset, so the next meaningful checks are reserve, governance, and bridge activation beyond the token interface itself.' ,
2026-04-10 12:52:17 -07:00
profile . x402Ready
? 'This contract appears ready for x402-style payment flows because the explorer can see the required signature and domain surfaces.'
: 'This contract does not currently look x402-ready from the live explorer surface; verify EIP-712, ERC-5267, and permit or authorization flow exposure before using it as a payment rail.' ,
profile . forwardCanonical === true
2026-04-30 03:06:49 -07:00
? 'This version is marked forward-canonical, so it should be treated as the preferred successor surface even if older liquidity or bridge versions still coexist.'
2026-04-10 12:52:17 -07:00
: profile . forwardCanonical === false
2026-04-30 03:06:49 -07:00
? 'This version is not forward-canonical, which usually means it is legacy, staged, or bridge-only relative to the intended primary canonical surface.'
: 'Forward-canonical posture is not directly detectable on this contract, so rely on the bridge overlay and deployment records before making promotion assumptions.' ,
2026-04-10 12:52:17 -07:00
profile . legacyAliasSupport
? 'Legacy alias support is exposed, which is useful during version cutovers and explorer/search reconciliation.'
: 'Legacy alias support is not visible from the current explorer contract surface, so name/version migration may need registry or deployment-record cross-checks.' ,
'Use the repo standards references to reconcile any missing surface with the intended GRU profile and rollout phase.' ,
]
return (
< Card title = { title } >
< dl className = "space-y-4" >
< DetailRow label = "Profile" >
< div className = "space-y-2" >
< div className = "flex flex-wrap gap-2" >
2026-04-30 03:06:49 -07:00
< EntityBadge label = { formatProfileLabel ( profile . profileId ) } tone = "info" className = "normal-case tracking-normal" / >
2026-04-10 12:52:17 -07:00
< EntityBadge
2026-04-30 03:06:49 -07:00
label = { profile . wrappedTransport ? 'cW public-network' : 'canonical GRU' }
2026-04-10 12:52:17 -07:00
tone = { profile . wrappedTransport ? 'warning' : 'success' }
/ >
< / div >
< div className = "text-sm text-gray-600 dark:text-gray-400" >
{ detectedCount } of { requiredCount } required base - token standards are currently detectable from the live contract surface .
< / div >
< / div >
< / DetailRow >
< DetailRow label = "Standards" valueClassName = "flex flex-wrap gap-2" >
{ profile . standards . map ( ( standard ) = > (
< EntityBadge
key = { standard . id }
2026-04-30 03:06:49 -07:00
label = { standard . detected ? ` ${ formatStandardLabel ( standard . id ) } detected ` : ` ${ formatStandardLabel ( standard . id ) } missing ` }
2026-04-10 12:52:17 -07:00
tone = { standard . detected ? 'success' : 'warning' }
className = "normal-case tracking-normal"
/ >
) ) }
< / DetailRow >
2026-04-30 03:06:49 -07:00
< DetailRow label = "Bridge Posture" >
2026-04-10 12:52:17 -07:00
< div className = "space-y-3" >
< div className = "flex flex-wrap gap-2" >
< EntityBadge
label = { profile . x402Ready ? 'x402 ready' : 'x402 not ready' }
tone = { profile . x402Ready ? 'success' : 'warning' }
/ >
< EntityBadge
label = {
profile . forwardCanonical === true
? 'forward canonical'
: profile . forwardCanonical === false
? 'not forward canonical'
: 'forward canonical unknown'
}
tone = {
profile . forwardCanonical === true
? 'success'
: profile . forwardCanonical === false
? 'warning'
: 'info'
}
/ >
< EntityBadge
label = { profile . legacyAliasSupport ? 'legacy aliases exposed' : 'no alias surface' }
tone = { profile . legacyAliasSupport ? 'info' : 'warning' }
/ >
< / div >
< div className = "grid gap-3 md:grid-cols-2" >
< div className = "rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40" >
< div className = "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400" > Settlement posture < / div >
< div className = "mt-2 text-gray-900 dark:text-white" >
{ profile . wrappedTransport
2026-04-30 03:06:49 -07:00
? 'This contract presents itself like a cW public-network representation instead of the canonical Chain 138 GRU surface.'
: 'This contract presents itself like the canonical Chain 138 GRU surface instead of a cW public-network representation.' }
2026-04-10 12:52:17 -07:00
< / div >
< / div >
< div className = "rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40" >
< div className = "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400" > Upgrade notice < / div >
< div className = "mt-2 text-gray-900 dark:text-white" >
{ noticePeriod
? ` ${ noticePeriod } ( ${ profile . minimumUpgradeNoticePeriodSeconds } seconds) `
: 'No readable minimum upgrade notice period was detected from the current explorer surface.' }
< / div >
< / div >
< div className = "rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40" >
< div className = "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400" > Version posture < / div >
< div className = "mt-2 text-gray-900 dark:text-white" >
{ profile . activeVersion || profile . forwardVersion
2026-04-30 03:06:49 -07:00
? ` Active liquidity/bridge version: ${ profile . activeVersion || 'unknown' } ; preferred forward version: ${ profile . forwardVersion || 'unknown' } . `
2026-04-10 12:52:17 -07:00
: 'No explicit active-versus-forward version posture is available from the local GRU catalog yet.' }
< / div >
< / div >
< / div >
< / div >
< / DetailRow >
< DetailRow label = "Interpretation" >
< div className = "space-y-3" >
{ profile . standards . map ( ( standard ) = > (
< div key = { ` ${ standard . id } -explanation ` } className = "rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40" >
< div className = "flex flex-wrap items-center gap-2" >
2026-04-30 03:06:49 -07:00
< div className = "font-medium text-gray-900 dark:text-white" > { formatStandardLabel ( standard . id ) } < / div >
2026-04-10 12:52:17 -07:00
< EntityBadge label = { standard . detected ? 'detected' : 'missing' } tone = { standard . detected ? 'success' : 'warning' } / >
< / div >
< div className = "mt-2 text-gray-600 dark:text-gray-400" >
{ STANDARD_EXPLANATIONS [ standard . id ] || 'GRU-specific standard surfaced by the repo standards profile.' }
< / div >
< / div >
) ) }
< / div >
< / DetailRow >
{ profile . metadata . length > 0 ? (
< DetailRow label = "Metadata" >
< div className = "space-y-3" >
{ profile . metadata . map ( ( field ) = > (
< div key = { field . label } className = "rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40" >
< div className = "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400" > { field . label } < / div >
< div className = "mt-2 break-all text-gray-900 dark:text-white" > { field . value } < / div >
< / div >
) ) }
< / div >
< / DetailRow >
) : null }
< DetailRow label = "References" >
< div className = "space-y-2 text-sm text-gray-600 dark:text-gray-400" >
< div > < Link href = "/docs/gru" className = "text-primary-600 hover:underline" > Explorer GRU guide < / Link > < / div >
2026-04-30 03:06:49 -07:00
< div > Canonical profile : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > { formatProfileLabel ( profile . profileId ) } < / code > < / div >
< div > Standards matrix : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > GRU C * v2 implementation plan < / code > < / div >
< div > Machine - readable profile : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > GRU standards profile < / code > < / div >
< div > Public - network overlay : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > GRU cW representation registry < / code > < / div >
< div > x402 support note : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > Chain 138 x402 token support < / code > < / div >
< div > Chain 138 readiness guide : < code className = "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800" > GRU v2 Chain 138 readiness < / code > < / div >
2026-04-10 12:52:17 -07:00
< / div >
< / DetailRow >
< DetailRow label = "Recommendations" >
< div className = "space-y-2 text-sm text-gray-600 dark:text-gray-400" >
{ recommendations . map ( ( item ) = > (
< div key = { item } className = "rounded-xl border border-gray-200 bg-gray-50 p-3 dark:border-gray-700 dark:bg-gray-900/40" >
{ item }
< / div >
) ) }
< / div >
< / DetailRow >
< / dl >
< / Card >
)
}