Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions src/components/known-label-highlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

import { type ReactNode } from 'react';
import { Badge } from '@/components/ui/badge';
import { KnownLabelEntry } from '@/lib/labels';
import { KnownLabelEntry, type TransactionLabelCategory } from '@/lib/labels';
import { cn } from '@/lib/utils';

type KnownLabelCategory = 'script' | 'address' | 'signer';

type CategoryTheme = {
title: string;
containerClass: string;
Expand All @@ -17,7 +15,7 @@ type CategoryTheme = {
linkClass: string;
};

const CATEGORY_THEMES: Record<KnownLabelCategory, CategoryTheme> = {
const CATEGORY_THEMES: Record<TransactionLabelCategory, CategoryTheme> = {
script: {
title: 'Known Script',
containerClass: 'border-emerald-200 bg-emerald-50 dark:border-emerald-800 dark:bg-emerald-950/40',
Expand All @@ -34,18 +32,50 @@ const CATEGORY_THEMES: Record<KnownLabelCategory, CategoryTheme> = {
descriptionClass: 'text-blue-700/80 dark:text-blue-200/80',
linkClass: 'text-blue-700 hover:text-blue-800 dark:text-blue-200 dark:hover:text-blue-100',
},
signer: {
title: 'Known Signer',
'payment-cred': {
title: 'Known Payment Key',
containerClass: 'border-purple-200 bg-purple-50 dark:border-purple-800 dark:bg-purple-950/40',
badgeClass: 'bg-purple-600/10 text-purple-700 hover:bg-purple-500/20 dark:bg-purple-500/10 dark:text-purple-200',
nameClass: 'text-purple-800 dark:text-purple-100',
descriptionClass: 'text-purple-700/80 dark:text-purple-200/80',
linkClass: 'text-purple-700 hover:text-purple-800 dark:text-purple-200 dark:hover:text-purple-100',
},
'stake-cred': {
title: 'Known Stake Key',
containerClass: 'border-sky-200 bg-sky-50 dark:border-sky-800 dark:bg-sky-950/40',
badgeClass: 'bg-sky-600/10 text-sky-700 hover:bg-sky-500/20 dark:bg-sky-500/10 dark:text-sky-200',
nameClass: 'text-sky-800 dark:text-sky-100',
descriptionClass: 'text-sky-700/80 dark:text-sky-200/80',
linkClass: 'text-sky-700 hover:text-sky-800 dark:text-sky-200 dark:hover:text-sky-100',
},
drep: {
title: 'Known DRep',
containerClass: 'border-amber-200 bg-amber-50 dark:border-amber-800 dark:bg-amber-950/40',
badgeClass: 'bg-amber-600/10 text-amber-700 hover:bg-amber-500/20 dark:bg-amber-500/10 dark:text-amber-200',
nameClass: 'text-amber-800 dark:text-amber-100',
descriptionClass: 'text-amber-700/80 dark:text-amber-200/80',
linkClass: 'text-amber-700 hover:text-amber-800 dark:text-amber-200 dark:hover:text-amber-100',
},
cc: {
title: 'Known Committee',
containerClass: 'border-rose-200 bg-rose-50 dark:border-rose-800 dark:bg-rose-950/40',
badgeClass: 'bg-rose-600/10 text-rose-700 hover:bg-rose-500/20 dark:bg-rose-500/10 dark:text-rose-200',
nameClass: 'text-rose-800 dark:text-rose-100',
descriptionClass: 'text-rose-700/80 dark:text-rose-200/80',
linkClass: 'text-rose-700 hover:text-rose-800 dark:text-rose-200 dark:hover:text-rose-100',
},
pool: {
title: 'Known Pool',
containerClass: 'border-indigo-200 bg-indigo-50 dark:border-indigo-800 dark:bg-indigo-950/40',
badgeClass: 'bg-indigo-600/10 text-indigo-700 hover:bg-indigo-500/20 dark:bg-indigo-500/10 dark:text-indigo-200',
nameClass: 'text-indigo-800 dark:text-indigo-100',
descriptionClass: 'text-indigo-700/80 dark:text-indigo-200/80',
linkClass: 'text-indigo-700 hover:text-indigo-800 dark:text-indigo-200 dark:hover:text-indigo-100',
},
};

type KnownLabelHighlightProps = {
category: KnownLabelCategory;
category: TransactionLabelCategory;
label: KnownLabelEntry;
className?: string;
children?: ReactNode;
Expand Down Expand Up @@ -94,4 +124,3 @@ export function KnownLabelHighlight({ category, label, className, children }: Kn
</div>
);
}

102 changes: 35 additions & 67 deletions src/data/known-labels.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,73 +9,41 @@
},
"addresses": {
"addr1xxzc8pt7fgf0lc0x7eq6z7z6puhsxmzktna7dluahrj6g6v9swzhujsjlls7dajp59u95re0qdk9vh8mumlemw89535s4ecqxj": {
"name": "Intersect 2025 TRC"
}
},
"signerKeyHashes": {
"4e72b1facdc7eea745767b8daca40bf73d75eb0e88dcee80d57eec5d":{
"name": "Intersect Leadership 1 - Primary"
},
"1c732c072364a2afd42a03228f3816fec37e73f64b61f4c12bab55ee":{
"name": "Intersect Leadership 1 - Secondary"
},
"91f5b1d436080c1beca93fbbb96596312d8f615b0ad9e94470af2224":{
"name": "Intersect Leadership 2 - Primary"
},
"a1ebdcc53ad3907461d92204f9789ddb640dcdcb0d9fce786a55eaf4":{
"name": "Intersect Leadership 2 - Secondary"
},
"1be0008bf2994524c0eaf0efdae4431e4a61ef7d974804fa794110b7":{
"name": "Intersect Admin 1 - Primary"
},
"27194940fae07315f4dc7a0394535dea7795dab2f232ee40f4457e8f":{
"name": "Intersect Admin 1 - Secondary"
},
"a664de561ccd2ca9a07c060d4dd7cea4dc68ba89d4bf04b21ff0726f":{
"name": "Intersect Admin 2 - Primary"
},
"821dbb013b85872e91f59e5c3c566390c866aea114a13b1b68f064bc":{
"name": "Intersect Admin 2 - Secondary"
},
"c236d8dc9441605238a5fe9cc7e6c1a79903289a4249c33122bf9627":{
"name": "Intersect Admin 3 - Primary"
},
"1b5850270f7a77ea9ef570a83fb4b120bf814ec94aa0dba0c9c28844":{
"name": "Intersect Admin 3 - Secondary"
"name": "Intersect 2025 Treasury Contract"
},
"ac3de68e8e1f9af3e00b299e7858bc44e126b33e130d06223d799d5d":{
"name": "Cardano Foundation - Primary"
},
"c9f2966a1b357718b45a006954106ba1f7ae9fea16e9826f3486ddd6":{
"name": "Cardano Foundation - Secondary"
},
"1880102b04725318eb7a6f9f481815c82473c2f50cfe9932c85a3bf8":{
"name": "Sundae Labs - Primary"
},
"7a827787c47a4e74f102330cc8566ed9845047903121025911163b9d":{
"name": "Sundae Labs - Secondary"
},
"a7f06cf4e9c03c6b7eac317d5533d573a9be3018fb7b9d95dd778d39":{
"name": "Xerberus - Primary"
},
"d8261e2c334b58072042130182de4fb945a46dd1b1974e1df755fe96":{
"name": "Xerberus - Secondary"
},
"8349f8b41d8337b617947ace444ef95b2b80ff2605cadf969914cf95":{
"name": "NMKR - Primary"
},
"cd820bac2773f2df622c567aa547894177a818593bdae996dd0881e3":{
"name": "NMKR - Secondary"
},
"679ad28e567eb42ddb30a5cf6b5f066b2defbce393f19968d711f658":{
"name": "DQuadrant - Primary"
},
"36e0cf1e52e05ef92e52c7bc2a04493d6bae481b8acbab12ec4300d7":{
"name": "DQuadrant - Secondary"
},
"03ccae794affbe27a5f5f74da6266002db11daa6ae446aea783b972d":{
"name": "Ryan testnet DRep key"
"addr1xxyzewehw7dh78ea62mkgdnzmcdlcxqt4u39a7pqc0v0at5g9janwaum0u0nm54hvsmx9hsmlsvqhteztmuzps7cl6hq7d35th": {
"name": "Intersect 2025 Vendor Contract"
}

},
"credentials": {
"payment": {
"4e72b1facdc7eea745767b8daca40bf73d75eb0e88dcee80d57eec5d": { "name": "Intersect 2025 Leadership 1 - Primary" },
"1c732c072364a2afd42a03228f3816fec37e73f64b61f4c12bab55ee": { "name": "Intersect 2025 Leadership 1 - Secondary" },
"91f5b1d436080c1beca93fbbb96596312d8f615b0ad9e94470af2224": { "name": "Intersect 2025 Leadership 2 - Primary" },
"a1ebdcc53ad3907461d92204f9789ddb640dcdcb0d9fce786a55eaf4": { "name": "Intersect 2025 Leadership 2 - Secondary" },
"1be0008bf2994524c0eaf0efdae4431e4a61ef7d974804fa794110b7": { "name": "Intersect 2025 Admin 1 - Primary" },
"27194940fae07315f4dc7a0394535dea7795dab2f232ee40f4457e8f": { "name": "Intersect 2025 Admin 1 - Secondary" },
"a664de561ccd2ca9a07c060d4dd7cea4dc68ba89d4bf04b21ff0726f": { "name": "Intersect 2025 Admin 2 - Primary" },
"821dbb013b85872e91f59e5c3c566390c866aea114a13b1b68f064bc": { "name": "Intersect 2025 Admin 2 - Secondary" },
"c236d8dc9441605238a5fe9cc7e6c1a79903289a4249c33122bf9627": { "name": "Intersect 2025 Admin 3 - Primary" },
"1b5850270f7a77ea9ef570a83fb4b120bf814ec94aa0dba0c9c28844": { "name": "Intersect 2025 Admin 3 - Secondary" },
"ac3de68e8e1f9af3e00b299e7858bc44e126b33e130d06223d799d5d": { "name": "Cardano Foundation - Primary" },
"c9f2966a1b357718b45a006954106ba1f7ae9fea16e9826f3486ddd6": { "name": "Cardano Foundation - Secondary" },
"1880102b04725318eb7a6f9f481815c82473c2f50cfe9932c85a3bf8": { "name": "Sundae Labs - Primary" },
"7a827787c47a4e74f102330cc8566ed9845047903121025911163b9d": { "name": "Sundae Labs - Secondary" },
"a7f06cf4e9c03c6b7eac317d5533d573a9be3018fb7b9d95dd778d39": { "name": "Xerberus - Primary" },
"d8261e2c334b58072042130182de4fb945a46dd1b1974e1df755fe96": { "name": "Xerberus - Secondary" },
"8349f8b41d8337b617947ace444ef95b2b80ff2605cadf969914cf95": { "name": "NMKR - Primary" },
"cd820bac2773f2df622c567aa547894177a818593bdae996dd0881e3": { "name": "NMKR - Secondary" },
"679ad28e567eb42ddb30a5cf6b5f066b2defbce393f19968d711f658": { "name": "DQuadrant - Primary" },
"36e0cf1e52e05ef92e52c7bc2a04493d6bae481b8acbab12ec4300d7": { "name": "DQuadrant - Secondary" }
},
"stake": {
"stake1uxzc8pt7fgf0lc0x7eq6z7z6puhsxmzktna7dluahrj6g6g7lgq9rl": { "name": "Intersect 2025 TRC" }},
"drep": {
"03ccae794affbe27a5f5f74da6266002db11daa6ae446aea783b972d": { "name": "Ryan testnet DRep key" }
},
"cc": {},
"pool": {}
}
}
}
18 changes: 11 additions & 7 deletions src/domain/tx.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// src/domain/tx.ts
export type AddressCredInfo = { kind: 'key' | 'script'; hash: string };
export type AddressCreds = { paymentCred?: AddressCredInfo; stakeCred?: AddressCredInfo };

export type DomainTx = {
id: string;
sizeBytes: number;
Expand All @@ -8,31 +11,32 @@ export type DomainTx = {
slot?: number | null;
validity: { start?: number | null; end?: number | null };
inputs: Array<{
txId: string;
index: number;
txId: string;
index: number;
isCollateral: boolean;
resolved?: { address?: string; value?: ValueSummary } // optional future lookup
resolved?: { address?: string; addressCreds?: AddressCreds; value?: ValueSummary } // optional future lookup
}>;
outputs: Array<{
address: string;
addressCreds?: AddressCreds;
ada: bigint;
assets: Array<{ policyId: string; assetName: string; quantity: bigint }>;
datum?: { inline?: boolean | string; hash?: string; ref?: boolean; type?: string; content?: unknown; size?: number };
scriptRef?: { type: "PlutusV1"|"PlutusV2"|"PlutusV3"|"Native"; bytes: string };
}>;
mint?: Array<{ policyId: string; assetName: string; quantity: bigint }>;
certs?: Array<CertificateVM>; // normalized, labeled
withdrawals?: Array<{ stakeAddr: string; amount: bigint }>;
withdrawals?: Array<{ stakeAddr: string; addressCreds?: AddressCreds; amount: bigint }>;
governance?: GovernanceVM | null; // Conway actions, drep votes, etc.
metadata?: Array<{ label: string; json?: unknown; cbor?: string }>;
scripts?: Array<{ type: string; hash: string; bytesLen: number; bytes?: string; address?: string }>;
scripts?: Array<{ type: string; hash: string; bytesLen: number; bytes?: string; address?: string; addressCreds?: AddressCreds }>;
redeemers?: Array<{ purpose: string; index: number; exUnits?: { mem: number; steps: number }; data?: string; scriptHash?: string }>;
witnesses: { vkeyCount: number; nativeCount: number; plutusCount: number };
vkeyWitnesses?: Array<{ vkey: string; signature: string; hash: string }>;
signers?: Array<{ type: 'vkey' | 'native' | 'plutus'; hash: string; address?: string; isWitness?: boolean; isRequired?: boolean }>;
signers?: Array<{ type: 'vkey' | 'native' | 'plutus'; hash: string; address?: string; addressCreds?: AddressCreds; isWitness?: boolean; isRequired?: boolean }>;
scriptDataHash?: string;
totalCollateral?: bigint;
collateralReturn?: { address: string; ada: bigint; assets: Array<{ policyId: string; assetName: string; quantity: bigint }> };
collateralReturn?: { address: string; addressCreds?: AddressCreds; ada: bigint; assets: Array<{ policyId: string; assetName: string; quantity: bigint }> };
referenceInputs?: Array<{ txId: string; index: number }>;
warnings: string[];
};
Expand Down
15 changes: 9 additions & 6 deletions src/features/inspector/tabs/ContentsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { formatLovelace, formatAda, formatAssetQuantity } from '@/lib/utils/ada'
import { encodeStakeAddress } from '@/lib/utils/stake-address';
import { toast } from 'sonner';
import { BlockExplorerLink } from '@/components/block-explorer-link';
import { getKnownAddressLabel, getKnownSignerLabel } from '@/lib/labels';
import { getKnownCredLabel, resolveAddressLabel } from '@/lib/labels';
import { KnownLabelHighlight } from '@/components/known-label-highlight';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { useAppStore } from '@/lib/store';
Expand Down Expand Up @@ -2736,8 +2736,11 @@ export function ContentsTab({ tx }: ContentsTabProps) {
These signers must provide signatures for the transaction to be valid.
</p>
{requiredSigners.map((signer, index) => {
const signerLabel = getKnownSignerLabel(signer.hash);
const signerAddressLabel = getKnownAddressLabel(signer.address);
const signerLabel = getKnownCredLabel(signer.hash, 'payment', network);
const signerAddressLabel = resolveAddressLabel(
{ address: signer.address, addressCreds: signer.addressCreds },
network,
);
const hasMatchingWitness = witnessHashes.has(signer.hash.toLowerCase());

return (
Expand Down Expand Up @@ -2776,7 +2779,7 @@ export function ContentsTab({ tx }: ContentsTabProps) {
</div>
</div>
{signerLabel && (
<KnownLabelHighlight category="signer" label={signerLabel} />
<KnownLabelHighlight category="payment-cred" label={signerLabel} />
)}
{hasMatchingWitness && (
<div className="flex items-center gap-2 text-sm text-green-600">
Expand Down Expand Up @@ -2871,9 +2874,9 @@ export function ContentsTab({ tx }: ContentsTabProps) {
<div className="text-xs font-medium text-muted-foreground mb-1 flex items-center gap-2">
Blake2b-224 Hash
{(() => {
const hashLabel = getKnownSignerLabel(witness.hash);
const hashLabel = getKnownCredLabel(witness.hash, 'payment', network);
return hashLabel ? (
<KnownLabelHighlight category="signer" label={hashLabel} />
<KnownLabelHighlight category="payment-cred" label={hashLabel} />
) : null;
})()}
</div>
Expand Down
24 changes: 19 additions & 5 deletions src/features/inspector/tabs/IoValueTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { Copy, ArrowRight, Coins, Shield, ArrowDownRight, ArrowUpRight } from 'l
import { Button } from '@/components/ui/button';
import { toast } from 'sonner';
import { BlockExplorerLink } from '@/components/block-explorer-link';
import { getKnownAddressLabel } from '@/lib/labels';
import { resolveAddressLabel } from '@/lib/labels';
import { KnownLabelHighlight } from '@/components/known-label-highlight';
import { useTokenRegistry } from '@/hooks/use-token-registry';
import { useAppStore } from '@/lib/store';
import { AssetDisplay } from '@/components/asset-display';

interface IoValueTabProps {
Expand All @@ -30,6 +31,7 @@ function truncateAddress(address: string, startLength: number = 15, endLength: n

export function IoValueTab({ tx }: IoValueTabProps) {
const { getMetadata } = useTokenRegistry(tx);
const network = useAppStore((s) => s.network);

const copyToClipboard = async (text: string, label: string) => {
try {
Expand Down Expand Up @@ -58,7 +60,10 @@ export function IoValueTab({ tx }: IoValueTabProps) {
{tx.inputs
.filter(input => !input.isCollateral)
.map((input, index) => {
const resolvedLabel = getKnownAddressLabel(input.resolved?.address);
const resolvedLabel = resolveAddressLabel(
{ address: input.resolved?.address, addressCreds: input.resolved?.addressCreds },
network,
);

return (
<div key={index} className="border rounded-lg p-3 space-y-2">
Expand Down Expand Up @@ -165,7 +170,10 @@ export function IoValueTab({ tx }: IoValueTabProps) {
{tx.inputs
.filter(input => input.isCollateral)
.map((input, index) => {
const collateralLabel = getKnownAddressLabel(input.resolved?.address);
const collateralLabel = resolveAddressLabel(
{ address: input.resolved?.address, addressCreds: input.resolved?.addressCreds },
network,
);

return (
<div key={index} className="border rounded-lg p-3 space-y-2 bg-orange-50 dark:bg-orange-950/20">
Expand Down Expand Up @@ -273,7 +281,10 @@ export function IoValueTab({ tx }: IoValueTabProps) {
) : (
<div className="space-y-3">
{tx.outputs.map((output, index) => {
const outputLabel = getKnownAddressLabel(output.address);
const outputLabel = resolveAddressLabel(
{ address: output.address, addressCreds: output.addressCreds },
network,
);

return (
<div key={index} className="border rounded-lg p-3 space-y-2">
Expand Down Expand Up @@ -530,7 +541,10 @@ export function IoValueTab({ tx }: IoValueTabProps) {
The collateral return output specifies where any unused collateral should be returned after script execution.
</p>
{(() => {
const collateralReturnLabel = getKnownAddressLabel(tx.collateralReturn.address);
const collateralReturnLabel = resolveAddressLabel(
{ address: tx.collateralReturn.address, addressCreds: tx.collateralReturn.addressCreds },
network,
);

return (
<div className="border rounded-lg p-3 space-y-2">
Expand Down
14 changes: 11 additions & 3 deletions src/features/inspector/tabs/OverviewTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ interface OverviewTabProps {

export function OverviewTab({ tx }: OverviewTabProps) {
const { network, isDetectingNetwork, networkDetected, isOnChain, onChainMeta, setNetwork } = useAppStore();
const transactionLabels = collectTransactionLabels(tx);
const transactionLabels = collectTransactionLabels(tx, network);

const getNetworkDisplayName = (net: string) => {
switch (net) {
Expand Down Expand Up @@ -103,8 +103,16 @@ export function OverviewTab({ tx }: OverviewTabProps) {
return 'Script';
case 'address':
return 'Address';
case 'signer':
return 'Signer';
case 'payment-cred':
return 'Payment Key';
case 'stake-cred':
return 'Stake Key';
case 'drep':
return 'DRep';
case 'cc':
return 'Committee';
case 'pool':
return 'Pool';
default:
return 'Label';
}
Expand Down
Loading
Loading