Skip to content

Commit

Permalink
Merge pull request #507 from SiaFoundation/02-23-fix_explorer_proof_o…
Browse files Browse the repository at this point in the history
…utput_labels

fix: explorer proof output labels
  • Loading branch information
n8maninger authored Feb 26, 2024
2 parents 805f32e + 4ed4099 commit 30783a1
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-fishes-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'explorer': patch
---

Add detailed labels to contract proof outputs explaining what each output is for.
5 changes: 5 additions & 0 deletions .changeset/weak-tips-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siafoundation/design-system': patch
---

Fix flex layout and add a title tooltip to EntityListItem.
195 changes: 171 additions & 24 deletions apps/explorer/components/Contract/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BigNumber from 'bignumber.js'
import {
SiaCentralContract,
SiaCentralExchangeRates,
SiaCentralPartialSiacoinOutput,
} from '@siafoundation/sia-central'
import { humanBytes, humanDate, humanSiacoin } from '@siafoundation/units'
import { EntityList, EntityListItemProps } from '@siafoundation/design-system'
Expand Down Expand Up @@ -148,34 +149,90 @@ export function Contract({ contract, rates, renewedFrom, renewedTo }: Props) {
] as DatumProps[]
}, [contract, exchange])

const missedProofOutputs = useMemo(() => {
if (!contract) {
return []
const validProofOutputs = useMemo(() => {
if (isProperlyFormedNewContract(contract)) {
const { renterPayoutValid, hostPayoutValid } =
getNewContractFormattedOutputs(contract)
return [
{
label: 'renter payout: remaining renter allowance',
initials: 'r',
sc: new BigNumber(renterPayoutValid.value),
hash: renterPayoutValid.output_id,
},
{
label: 'host payout',
initials: 'h',
sc: new BigNumber(hostPayoutValid.value),
hash: hostPayoutValid.output_id,
},
] as EntityListItemProps[]
}
if (isProperlyFormedRenewedContract(contract)) {
const { renterPayoutValid, hostPayoutValid } =
getRenewedContractFormattedOutputs(contract)
return [
{
label: 'renter payout: remaining renter allowance',
initials: 'r',
sc: new BigNumber(renterPayoutValid.value),
hash: renterPayoutValid.output_id,
},
{
label: 'host payout',
initials: 'h',
sc: new BigNumber(hostPayoutValid.value),
hash: hostPayoutValid.output_id,
},
] as EntityListItemProps[]
}
const list: EntityListItemProps[] = []
contract.missed_proof_outputs?.forEach((o) => {
list.push({
label: o.source ? o.source.replace(/_/g, ' ') : 'output',
sc: new BigNumber(o.value),
hash: o.output_id,
})
})
return list
return contract?.valid_proof_outputs?.map(genericOutputListItem) || []
}, [contract])

const validProofOutputs = useMemo(() => {
if (!contract) {
return []
const missedProofOutputs = useMemo(() => {
if (isProperlyFormedNewContract(contract)) {
const { renterPayoutMissed, hostPayoutMissed, hostBurned } =
getNewContractFormattedOutputs(contract)
return [
{
label: 'renter payout: remaining renter allowance',
initials: 'r',
sc: new BigNumber(renterPayoutMissed.value),
hash: renterPayoutMissed.output_id,
},
{
label: `host payout: payout minus risked collateral and storage revenue`,
initials: 'h',
sc: new BigNumber(hostPayoutMissed.value),
hash: hostPayoutMissed.output_id,
},
{
label: 'host burn: host revenue plus risked collateral',
initials: 'b',
sc: new BigNumber(hostBurned.value),
hash: hostBurned.output_id,
},
] as EntityListItemProps[]
}
if (isProperlyFormedRenewedContract(contract)) {
const { renterPayoutMissed, hostPayoutMissed } =
getRenewedContractFormattedOutputs(contract)
return [
{
label: 'renter payout: remaining renter allowance',
initials: 'r',
sc: new BigNumber(renterPayoutMissed.value),
hash: renterPayoutMissed.output_id,
},
{
label: `host payout: payout minus risked collateral and storage revenue`,
initials: 'h',
sc: new BigNumber(hostPayoutMissed.value),
hash: hostPayoutMissed.output_id,
},
] as EntityListItemProps[]
}
const list: EntityListItemProps[] = []
contract.valid_proof_outputs?.forEach((o) => {
list.push({
label: o.source ? o.source.replace(/_/g, ' ') : 'output',
sc: new BigNumber(o.value),
hash: o.output_id,
})
})
return list
return contract?.missed_proof_outputs?.map(genericOutputListItem) || []
}, [contract])

return (
Expand Down Expand Up @@ -216,3 +273,93 @@ export function Contract({ contract, rates, renewedFrom, renewedTo }: Props) {
</ContentLayout>
)
}

function isProperlyFormedNewContract(contract: SiaCentralContract) {
// renter payout, host payout
if (contract.valid_proof_outputs?.length !== 2) {
return false
}
// renter payout, host payout, and host burned
if (contract.missed_proof_outputs?.length !== 3) {
return false
}

const { renterPayoutValid, renterPayoutMissed } =
getNewContractFormattedOutputs(contract)

// renter payout valid and missed should be the same
if (renterPayoutValid.value !== renterPayoutMissed.value) {
return false
}

// math.MaxUint64 with lost precision
const mathMaxUint64 = 18446744073709552000
if (contract.revision_number >= mathMaxUint64) {
return false
}
return true
}

function isProperlyFormedRenewedContract(contract: SiaCentralContract) {
// renter payout, host payout
if (contract.valid_proof_outputs?.length !== 2) {
return false
}
// renter payout, host payout
if (contract.missed_proof_outputs?.length !== 2) {
return false
}

const {
renterPayoutValid,
renterPayoutMissed,
hostPayoutValid,
hostPayoutMissed,
} = getRenewedContractFormattedOutputs(contract)

// renter payout valid and missed should be the same
if (renterPayoutValid.value !== renterPayoutMissed.value) {
return false
}

// host payout valid and missed should be the same
if (hostPayoutValid.value !== hostPayoutMissed.value) {
return false
}

// math.MaxUint64 with lost precision
const mathMaxUint64 = 18446744073709552000
if (contract.revision_number !== mathMaxUint64) {
return false
}
return true
}

function getNewContractFormattedOutputs(contract: SiaCentralContract) {
return {
renterPayoutValid: contract.valid_proof_outputs[0],
renterPayoutMissed: contract.missed_proof_outputs[0],
hostPayoutValid: contract.valid_proof_outputs[1],
hostPayoutMissed: contract.missed_proof_outputs[1],
hostBurned: contract.missed_proof_outputs[2],
}
}

function getRenewedContractFormattedOutputs(contract: SiaCentralContract) {
return {
renterPayoutValid: contract.valid_proof_outputs[0],
renterPayoutMissed: contract.missed_proof_outputs[0],
hostPayoutValid: contract.valid_proof_outputs[1],
hostPayoutMissed: contract.missed_proof_outputs[1],
}
}

function genericOutputListItem(
o: SiaCentralPartialSiacoinOutput
): EntityListItemProps {
return {
label: o.source ? o.source.replace(/_/g, ' ') : 'output',
sc: new BigNumber(o.value),
hash: o.output_id,
}
}
2 changes: 1 addition & 1 deletion apps/explorer/components/ExplorerDatum.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function ExplorerDatum({
comment,
}: DatumProps) {
return (
<div className="flex flex-wrap gap-x-12 gap-y-4 items-baseline py-1.5 overflow-hidden">
<div className="flex flex-wrap gap-x-12 gap-y-4 items-baseline py-1.5">
<Text color="subtle" scaleSize="14" ellipsis className="flex-1">
{upperFirst(label)}
</Text>
Expand Down
23 changes: 18 additions & 5 deletions libs/design-system/src/components/EntityListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import BigNumber from 'bignumber.js'
import { DotMark16 } from '@siafoundation/react-icons'
import { EntityListItemLayout } from './EntityListItemLayout'
import { ValueScFiat } from './ValueScFiat'
import { Tooltip } from '../core/Tooltip'

export type EntityListItemProps = {
label?: string
Expand Down Expand Up @@ -62,21 +63,33 @@ export function EntityListItem(entity: EntityListItemProps) {
const title = isValidUrl(label) ? label : upperFirst(label)
return (
<EntityListItemLayout {...entity}>
<div className="flex flex-col items-center gap-1 w-full">
<div className="flex flex-col items-center gap-1 w-full min-w-0">
<div className="flex gap-2 items-center w-full">
<div className="flex gap-2 items-center">
<div className="flex gap-2 items-center min-w-0">
{entity.height && entity.blockHref && (
<Text color="subtle" weight="semibold">
<Link href={entity.blockHref} underline="none">
{humanNumber(entity.height)}
</Link>
</Text>
)}
<Text weight="medium">{title || truncHashEl}</Text>
{title ? (
<Tooltip content={title}>
<Text ellipsis weight="medium">
{title}
</Text>
</Tooltip>
) : (
<Text ellipsis weight="medium">
{truncHashEl}
</Text>
)}
</div>
<div className="flex-1" />
{!!sc && <ValueScFiat variant={entity.scVariant} value={sc} />}
{!!sf && <ValueSf variant={entity.sfVariant} value={sf} />}
<div className="flex items-center">
{!!sc && <ValueScFiat variant={entity.scVariant} value={sc} />}
{!!sf && <ValueSf variant={entity.sfVariant} value={sf} />}
</div>
</div>
<div className="flex justify-between w-full">
<div className="flex gap-1">{!!title && truncHashEl}</div>
Expand Down

0 comments on commit 30783a1

Please sign in to comment.