Skip to content

Commit

Permalink
Merge pull request #51 from TalismanSociety/feat/sharable-tx-links
Browse files Browse the repository at this point in the history
[FEAT] - Sharable Transaction links
  • Loading branch information
UrbanWill authored Jun 26, 2024
2 parents e8fbf94 + e69cf43 commit fc69175
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 31 deletions.
22 changes: 20 additions & 2 deletions apps/multisig/src/components/TransactionSidesheet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Transaction, executingTransactionsState, useSelectedMultisig } from '@domains/multisig'
import { SideSheet } from '@talismn/ui'
import { Button, SideSheet } from '@talismn/ui'
import { TransactionSidesheetHeader } from './TransactionSidesheetHeader'
import { useCallback, useMemo, useState } from 'react'
import TransactionDetailsExpandable from '../../layouts/Overview/Transactions/TransactionDetailsExpandable'
Expand All @@ -16,6 +16,8 @@ import { useNavigate } from 'react-router-dom'
import { useToast } from '@components/ui/use-toast'
import { useRecoilState } from 'recoil'
import { TxMetadata } from '@domains/offchain-data'
import useCopied from '@hooks/useCopied'
import { Check, Link } from '@talismn/icons'

type TransactionSidesheetProps = {
onApproved?: (res: { result: SubmittableResult; executed: boolean }) => void
Expand Down Expand Up @@ -58,6 +60,7 @@ export const TransactionSidesheet: React.FC<TransactionSidesheetProps> = ({
)

const navigate = useNavigate()
const { copy, copied } = useCopied()
const { saveDraft, loading: savingDraft } = useSaveDraftMetadata()
const { deleteDraft, loading: deletingDraft } = useDeleteDraftMetadata()
const { cancelAsMulti, canCancel: canReject } = useCancelAsMulti(t)
Expand Down Expand Up @@ -217,7 +220,22 @@ export const TransactionSidesheet: React.FC<TransactionSidesheetProps> = ({
<div className="px-[32px] w-full flex flex-col flex-1 gap-[32px] overflow-auto pb-[24px]">
<TransactionSummaryRow t={t} />
<div className="w-full">
<h4 className="mb-[8px] text-[16px]">Details</h4>
<div className="flex justify-between items-end pb-[16px]">
<h4 className="mb-[8px] text-[16px]">Details</h4>
<Button
css={{
padding: '4px 12px',
}}
variant="outlined"
className="flex gap-[8px]"
onClick={() => copy(window.location.href, 'Copied transaction URL')}
>
<div className="flex items-center gap-[8px]">
<div className="mt-[4px]">Share</div>
{copied ? <Check size={16} /> : <Link size={16} />}
</div>
</Button>
</div>
<TransactionDetailsExpandable t={t} />
</div>
{!t.executedAt && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import {
combinedViewState,
toConfirmedTxUrl,
} from '@domains/multisig'
import { Contract, List, Send, Settings, Share2, Unknown, Vote, Zap } from '@talismn/icons'
import { Skeleton } from '@talismn/ui'
import { Contract, List, Send, Settings, Share2, Unknown, Vote, Zap, Check, Link } from '@talismn/icons'
import { Skeleton, Button } from '@talismn/ui'
import { balanceToFloat, formatUsd } from '@util/numbers'
import { useMemo } from 'react'
import { useRecoilValue, useRecoilValueLoadable } from 'recoil'
Expand All @@ -22,21 +22,28 @@ import { Tooltip } from '@components/ui/tooltip'
import { getExtrinsicErrorsFromEvents } from '@util/errors'
import { blockEventsSelector } from '@domains/chains/storage-getters'
import { cn } from '@util/tailwindcss'
import { clsx } from 'clsx'
import useCopied from '@hooks/useCopied'

const TransactionSummaryRow = ({
t,
onClick,
txURL = '',
showDraftBadge,
showShareButton,
onClick,
}: {
t: Transaction
onClick?: () => void
txURL?: string
showDraftBadge?: boolean
showShareButton?: boolean
onClick?: () => void
}) => {
const { contactByAddress } = useKnownAddresses(t.multisig.orgId)
const sumOutgoing: Balance[] = useMemo(() => calcSumOutgoing(t), [t])
const combinedView = useRecoilValue(combinedViewState)
const tokenPrices = useRecoilValueLoadable(tokenPricesState(sumOutgoing.map(b => b.token)))
const { threshold } = t.multisig
const { copy, copied } = useCopied()
const sumPriceUsd: number | undefined = useMemo(() => {
if (tokenPrices.state === 'hasValue') {
return sumOutgoing.reduce((acc, b) => {
Expand Down Expand Up @@ -91,7 +98,7 @@ const TransactionSummaryRow = ({

const tokenBreakdown = sumOutgoing.map(b => `${balanceToFloat(b)} ${b.token.symbol}`).join(' + ')
return (
<div onClick={onClick} className="flex items-center justify-between w-full gap-[16px]">
<div onClick={onClick} className="group flex items-center justify-between w-full gap-[16px]">
<div className="flex items-center justify-start gap-[8px] w-full overflow-x-hidden">
<div className="flex items-center justify-center min-w-[36px] w-[36px] h-[36px] bg-gray-500 [&>svg]:h-[15px] [&>svg]:w-[15px] rounded-full text-signet-primary">
{txIcon}
Expand Down Expand Up @@ -160,7 +167,33 @@ const TransactionSummaryRow = ({

<div className="flex items-center justify-end">
<div className="flex flex-col items-end">
<p className="text-right text-offWhite leading-[16px] whitespace-nowrap">{tokenBreakdown}</p>
<div className="flex items-center">
<p
className={clsx('text-right text-offWhite leading-[16px] whitespace-nowrap', {
'group-hover:hidden': showShareButton,
})}
>
{tokenBreakdown}
</p>
<Button
css={{
padding: '4px 12px',
display: 'none',
}}
variant="outlined"
className={clsx('gap-8px', { 'group-hover:flex': showShareButton })}
onClick={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault()
e.stopPropagation()
copy(txURL, 'Copied transaction URL')
}}
>
<div className="flex items-center gap-[8px]">
<div className="mt-[4px]">Share</div>
{copied ? <Check size={16} /> : <Link size={16} />}
</div>
</Button>
</div>
<div className="text-right text-[14px]">
{tokenBreakdown.length === 0 ? null : sumPriceUsd !== undefined ? (
priceUnavailable ? null : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,30 +108,31 @@ export const TransactionsList = ({
<div className="gap-[20px] w-full flex flex-col flex-1">
{transactions.length > 0 && (
<div className="flex flex-col gap-[12px] mt-[4px] w-full">
{transactions.map(t => (
<motion.div
key={
t.draft?.id ??
(t.executedAt
? makeTransactionID(t.multisig.chain, t.executedAt.block, t.executedAt.index)
: t.id)
}
whileHover={{ scale: 1.015 }}
className="cursor-pointer"
>
<TransactionSummaryRow
onClick={() =>
navigate(
`/overview/${value}-tx/${t.draft?.id ?? t.hash}?tab=${value}&teamId=${multisig.id}${
window.location.hash
}`
)
{transactions.map(t => {
const txPath = `/overview/${value}-tx/${t.draft?.id ?? t.hash}?tab=${value}&teamId=${multisig.id}${
window.location.hash
}`
return (
<motion.div
key={
t.draft?.id ??
(t.executedAt
? makeTransactionID(t.multisig.chain, t.executedAt.block, t.executedAt.index)
: t.id)
}
t={t}
showDraftBadge
/>
</motion.div>
))}
whileHover={{ scale: 1.015 }}
className="cursor-pointer"
>
<TransactionSummaryRow
t={t}
txURL={`${window.origin}${txPath}`}
showDraftBadge
showShareButton
onClick={() => navigate(txPath)}
/>
</motion.div>
)
})}
</div>
)}
{transactions.length === 0 && <div>All caught up 🏖️</div>}
Expand Down

0 comments on commit fc69175

Please sign in to comment.