- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation. - Changed default base URL for Playwright tests and updated security headers to reflect the new branding. - Enhanced README and API documentation to include new authentication endpoints and product access details. This refactor aligns the project branding and improves clarity in the API documentation.
215 lines
12 KiB
TypeScript
215 lines
12 KiB
TypeScript
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.',
|
|
IeMoneyToken: 'Repo-native eMoney token methodology for issuance and redemption semantics.',
|
|
DeterministicStorageNamespace: 'Stable namespace for upgrade-aware policy, registry, and audit resolution.',
|
|
JurisdictionAndSupervisionMetadata: 'Governance, supervisory, disclosure, and reporting metadata required by the GRU operating model.',
|
|
}
|
|
|
|
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
|
|
? 'This looks like a wrapped transport asset, 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 transport activation beyond the token interface itself.',
|
|
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
|
|
? 'This version is marked forward-canonical, so it should be treated as the preferred successor surface even if older liquidity or transport versions still coexist.'
|
|
: profile.forwardCanonical === false
|
|
? 'This version is not forward-canonical, which usually means it is legacy, staged, or transport-only relative to the intended primary canonical surface.'
|
|
: 'Forward-canonical posture is not directly detectable on this contract, so rely on the transport overlay and deployment records before making promotion assumptions.',
|
|
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">
|
|
<EntityBadge label={profile.profileId} tone="info" className="normal-case tracking-normal" />
|
|
<EntityBadge
|
|
label={profile.wrappedTransport ? 'wrapped transport' : 'canonical GRU'}
|
|
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}
|
|
label={standard.detected ? `${standard.id} detected` : `${standard.id} missing`}
|
|
tone={standard.detected ? 'success' : 'warning'}
|
|
className="normal-case tracking-normal"
|
|
/>
|
|
))}
|
|
</DetailRow>
|
|
|
|
<DetailRow label="Transport Posture">
|
|
<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
|
|
? 'This contract presents itself like a wrapped public-transport asset instead of the canonical Chain 138 money surface.'
|
|
: 'This contract presents itself like the canonical Chain 138 GRU money surface instead of a wrapped transport mirror.'}
|
|
</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
|
|
? `Active liquidity/transport version: ${profile.activeVersion || 'unknown'}; preferred forward version: ${profile.forwardVersion || 'unknown'}.`
|
|
: '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">
|
|
<div className="font-medium text-gray-900 dark:text-white">{standard.id}</div>
|
|
<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>
|
|
<div>Canonical profile: <code className="rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800">{profile.profileId}</code></div>
|
|
<div>Repo standards matrix: <code className="rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800">docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md</code></div>
|
|
<div>Machine-readable profile: <code className="rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800">config/gru-standards-profile.json</code></div>
|
|
<div>Transport overlay: <code className="rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800">config/gru-transport-active.json</code></div>
|
|
<div>x402 support note: <code className="rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800">docs/04-configuration/CHAIN138_X402_TOKEN_SUPPORT.md</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">docs/04-configuration/GRU_V2_CHAIN138_READINESS.md</code></div>
|
|
</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>
|
|
)
|
|
}
|