Skip to content

Commit bf59521

Browse files
committed
feat: tx info
1 parent 45663f9 commit bf59521

File tree

8 files changed

+245
-7
lines changed

8 files changed

+245
-7
lines changed

apps/enterprise/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@mui/icons-material": "^5.10.2",
4141
"@mui/material": "^5.10.2",
4242
"@popperjs/core": "^2.11.6",
43+
"@terra-money/log-finder-ruleset": "^3.0.2",
4344
"@terra-money/terra.js": "^3.1.6",
4445
"@terra-money/wallet-provider": "^3.11.1",
4546
"@terra.kitchen/utils": "^1.0.7",
@@ -127,4 +128,4 @@
127128
"parser": "typescript"
128129
}
129130
}
130-
}
131+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { reportError } from 'errors/errorMonitoring';
2+
import { ComponentWithChildrenProps } from 'lib/shared/props';
3+
import React, { Component, ReactNode } from 'react';
4+
5+
interface ErrorBoundaryProps extends ComponentWithChildrenProps {
6+
fallback?: ReactNode;
7+
}
8+
9+
interface State {
10+
hasError: boolean;
11+
}
12+
13+
export class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
14+
constructor(props: ErrorBoundaryProps) {
15+
super(props);
16+
this.state = {
17+
hasError: false,
18+
};
19+
}
20+
21+
static getDerivedStateFromError(_: Error): State {
22+
return { hasError: true };
23+
}
24+
25+
componentDidCatch(error: Error): void {
26+
reportError(error)
27+
}
28+
29+
render(): React.ReactNode {
30+
if (this.state.hasError) {
31+
return this.props.fallback || null
32+
}
33+
34+
return this.props.children
35+
}
36+
}
37+

apps/enterprise/src/lib/ui/Tag.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ComponentProps, ReactNode } from 'react'
2+
import styled from 'styled-components'
3+
import { HSLA } from 'lib/ui/colors/HSLA'
4+
import { Text } from 'lib/ui/Text'
5+
6+
type Props = ComponentProps<typeof Text> & {
7+
color: HSLA
8+
children: ReactNode
9+
}
10+
11+
const Container = styled(Text) <{ $color: HSLA }>`
12+
padding: 4px 8px;
13+
border-radius: 8px;
14+
color: ${({ $color }) => $color.toCssValue()};
15+
background: ${({ $color }) =>
16+
$color.getVariant({ a: () => 0.14 }).toCssValue()};
17+
`
18+
19+
export const Tag = ({ color, children, ...rest }: Props) => {
20+
return (
21+
<Container as="span" $color={color} {...rest}>
22+
{children}
23+
</Container>
24+
)
25+
}

apps/enterprise/src/pages/dao/staking/TokenStaking.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { SameWidthChildrenRow } from 'lib/ui/Layout/SameWidthChildrenRow';
2626
import { OverlayOpener } from 'lib/ui/OverlayOpener';
2727
import { StakeTokenOverlay } from './StakeTokenOverlay';
2828
import { PrimaryButton } from 'lib/ui/buttons/rect/PrimaryButton';
29-
import { RewardsPanel } from './RewardsPanel';
3029

3130
const useTokenData = (daoAddress: string, tokenAddress: string) => {
3231
const { data: token } = useCW20TokenInfoQuery(tokenAddress);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { demicrofy, formatAmount } from "@terra-money/apps/libs/formatting"
2+
import { isDenom } from "@terra.kitchen/utils"
3+
import { AssetType } from "chain"
4+
import { useAssetInfoQuery } from "chain/queries/useAssetInfoQuery"
5+
import { Spinner } from "lib/ui/Spinner"
6+
import { Text } from "lib/ui/Text"
7+
8+
interface TxAssetProps {
9+
id: string
10+
amount: string
11+
}
12+
13+
export const TxAsset = ({ id, amount }: TxAssetProps) => {
14+
const type: AssetType = isDenom(id) ? 'native' : 'cw20'
15+
16+
const { data, isLoading } = useAssetInfoQuery({ id, type })
17+
18+
if (data) {
19+
const { symbol, decimals } = data
20+
return (
21+
<Text weight="semibold" color="regular">
22+
{formatAmount(demicrofy(amount, decimals))} {symbol}
23+
</Text>
24+
)
25+
}
26+
27+
if (isLoading) {
28+
return <Spinner />
29+
}
30+
31+
return <>🤷‍♂️</>
32+
}

apps/enterprise/src/pages/dao/treasury/TxItem.tsx

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useWallet } from '@terra-money/wallet-provider';
2-
import { getFinderUrl, truncateAddress } from '@terra-money/apps/utils';
2+
import { assertDefined, getFinderUrl, getLast, truncateAddress } from '@terra-money/apps/utils';
33
import { TxEvent, TxResponse } from '@terra-money/apps/types';
44
import { Container } from '@terra-money/apps/components';
55
import { ExpandablePanel } from 'lib/ui/Panel/ExpandablePanel';
@@ -8,6 +8,17 @@ import { Text } from 'lib/ui/Text';
88
import { ShyTextButton } from 'lib/ui/buttons/ShyTextButton';
99
import { HStack } from 'lib/ui/Stack';
1010
import { TimeAgo } from 'lib/ui/TimeAgo';
11+
import {
12+
createActionRuleSet,
13+
createLogMatcherForActions,
14+
getTxCanonicalMsgs,
15+
} from "@terra-money/log-finder-ruleset"
16+
import { ErrorBoundary } from 'errors/components/ErrorBoundary';
17+
import { useTheme } from 'styled-components';
18+
import { Tag } from 'lib/ui/Tag';
19+
import { capitalizeFirstLetter } from 'lib/shared/utils/capitalizeFirstLetter';
20+
import { TxMessage } from './TxMessage';
21+
import { useCurrentDao } from 'dao/components/CurrentDaoProvider';
1122

1223
interface TxItemProps {
1324
tx: TxResponse;
@@ -17,17 +28,54 @@ export const TxItem = (props: TxItemProps) => {
1728
const { tx } = props;
1829
const { txhash, timestamp, logs } = tx;
1930
const { network } = useWallet();
20-
console.log(timestamp)
31+
32+
const { address } = useCurrentDao()
2133

2234
const events: TxEvent[] = logs ? logs[0].events : [];
2335

2436
const attributes = events?.flatMap(event => event.attributes);
2537

38+
const ruleset = createActionRuleSet(network.name)
39+
const logMatcher = createLogMatcherForActions(ruleset)
40+
const getCanonicalMsgs = (txInfo: TxResponse) => {
41+
const matchedMsg = getTxCanonicalMsgs(txInfo, logMatcher)
42+
return matchedMsg
43+
? matchedMsg
44+
.map((matchedLog) => matchedLog.map(({ transformed }) => transformed))
45+
.flat(2)
46+
: []
47+
}
48+
49+
const isSuccess = tx.code === 0
50+
51+
const { colors } = useTheme()
52+
2653
const header = (
2754
<HStack fullWidth gap={20} wrap="wrap" justifyContent="space-between">
28-
<ExternalLink to={getFinderUrl(network.name, txhash)}>
29-
<ShyTextButton as="div" text={truncateAddress(txhash)} />
30-
</ExternalLink>
55+
<HStack alignItems="center" gap={16}>
56+
<ExternalLink to={getFinderUrl(network.name, txhash)}>
57+
<ShyTextButton as="div" text={truncateAddress(txhash)} />
58+
</ExternalLink>
59+
<ErrorBoundary>
60+
{getCanonicalMsgs(tx).filter(msg => msg).map(
61+
(msg, index) => {
62+
const { msgType, canonicalMsg } = assertDefined(msg)
63+
const type = getLast(msgType.split("/"))
64+
65+
return (
66+
<HStack alignItems="center" gap={8}>
67+
<Tag color={isSuccess ? colors.success : colors.alert}>
68+
{capitalizeFirstLetter(type)}
69+
</Tag>
70+
{canonicalMsg.map((text, index) => (
71+
<TxMessage targetAddress={address} text={text} key={index} />
72+
))}
73+
</HStack>
74+
)
75+
}
76+
)}
77+
</ErrorBoundary>
78+
</HStack>
3179
<Text color="supporting" size={14}>
3280
<TimeAgo value={new Date(timestamp)} />
3381
</Text>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { capitalizeFirstLetter, truncateAddress } from "@terra-money/apps/utils"
2+
import { AccAddress, Coin, Coins, } from "@terra-money/terra.js"
3+
import { useWallet } from "@terra-money/wallet-provider"
4+
import { isDenom } from "@terra.kitchen/utils"
5+
import { ExternalLink } from "lib/navigation/Link/ExternalLink"
6+
import { ShyTextButton } from "lib/ui/buttons/ShyTextButton"
7+
import { HStack } from "lib/ui/Stack"
8+
import { Text } from "lib/ui/Text"
9+
import { ReactNode } from "react"
10+
import { TxAsset } from "./TxAsset"
11+
12+
interface TxMessageProps {
13+
text: string
14+
targetAddress: string
15+
}
16+
17+
const validateTokens = (tokens: any) => {
18+
const validate = ({ denom }: Coin) =>
19+
isDenom(denom) || AccAddress.validate(denom)
20+
21+
try {
22+
const coins = new Coins(tokens)
23+
return coins.toArray().every(validate)
24+
} catch {
25+
return false
26+
}
27+
}
28+
29+
export const TxMessage = ({ text, targetAddress }: TxMessageProps) => {
30+
const { network } = useWallet()
31+
32+
const parse = (word: string, index: number): ReactNode => {
33+
if (!word) return null
34+
if (word === targetAddress) return 'treasury'
35+
36+
if (word.endsWith(",")) return <>{parse(word.slice(0, -1), index)},</>
37+
38+
if (validateTokens(word)) {
39+
const list = new Coins(word).toArray()
40+
41+
return (
42+
<span style={{ color: 'purple' }}>
43+
{list.length > 1 ? 'multiple tokens' : list.map((coin, index) => {
44+
// todo: style address
45+
const denom = coin.toData().denom
46+
const [amount] = word.split(denom)
47+
return <TxAsset amount={amount} id={denom} />
48+
})}
49+
50+
</span>
51+
)
52+
}
53+
54+
if (AccAddress.validate(word)) {
55+
return (
56+
<ExternalLink to={`https://terrasco.pe/${network.name}/address/${word}`}>
57+
<ShyTextButton text={truncateAddress(word)} as="div" />
58+
</ExternalLink>
59+
)
60+
}
61+
62+
if (index === 0) {
63+
return capitalizeFirstLetter(word)
64+
}
65+
66+
return <span>{word}</span>
67+
}
68+
return (
69+
<Text as="div" style={{ textAlign: 'start' }} color="supporting">
70+
<HStack alignItems="center" gap={4}>
71+
{text.split(' ').map((word, index) => {
72+
const parsed = parse(word, index)
73+
74+
return <span key={index}>{parsed}</span>
75+
})}
76+
</HStack>
77+
</Text>
78+
)
79+
}

yarn.lock

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3981,6 +3981,7 @@ __metadata:
39813981
"@mui/icons-material": ^5.10.2
39823982
"@mui/material": ^5.10.2
39833983
"@popperjs/core": ^2.11.6
3984+
"@terra-money/log-finder-ruleset": ^3.0.2
39843985
"@terra-money/terra.js": ^3.1.6
39853986
"@terra-money/wallet-provider": ^3.11.1
39863987
"@terra.kitchen/utils": ^1.0.7
@@ -5238,6 +5239,22 @@ __metadata:
52385239
languageName: node
52395240
linkType: hard
52405241

5242+
"@terra-money/log-finder-ruleset@npm:^3.0.2":
5243+
version: 3.0.2
5244+
resolution: "@terra-money/log-finder-ruleset@npm:3.0.2"
5245+
dependencies:
5246+
"@terra-money/log-finder": ^1.1.6
5247+
checksum: 71ecf5645ab1baa94aa600d24f09cb3ef88666b83580c789e6059dc5ccecdec57cecf85c0d230f2f34f6ee714e49837e65ac72257c05e2508003c446369774d5
5248+
languageName: node
5249+
linkType: hard
5250+
5251+
"@terra-money/log-finder@npm:^1.1.6":
5252+
version: 1.1.6
5253+
resolution: "@terra-money/log-finder@npm:1.1.6"
5254+
checksum: 68519c37109f8d5788ca14028031b50e00059cf275d6d1c5127e311790fb2ffc3df1088ad001eee6c1f31c9f1be2bd29ba6320ef178330c3c3567a1624f9bca8
5255+
languageName: node
5256+
linkType: hard
5257+
52415258
"@terra-money/terra.js@npm:^3.1.3":
52425259
version: 3.1.3
52435260
resolution: "@terra-money/terra.js@npm:3.1.3"

0 commit comments

Comments
 (0)