Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix claiming for timelocked activity #5849

Merged
merged 10 commits into from Feb 23, 2023
7 changes: 5 additions & 2 deletions packages/shared/components/atoms/tiles/ActivityTile.svelte
Expand Up @@ -21,6 +21,7 @@
NftActivityTileContent,
GovernanceActivityTileContent,
} from 'shared/components'
import { time } from '@core/app'

export let activity: Activity

Expand All @@ -30,6 +31,8 @@
activity.type === ActivityType.Basic || activity.type === ActivityType.Foundry
? getAssetFromPersistedAssets(activity.assetId)
: undefined)
$: isTimelocked = activity?.asyncData?.timelockDate > $time
$: shouldShowAsyncFooter = activity.asyncData && activity.asyncData.asyncStatus !== ActivityAsyncStatus.Claimed

function handleTransactionClick(): void {
if (asset?.verification?.status === NotVerifiedStatus.New) {
Expand Down Expand Up @@ -70,9 +73,9 @@
<FoundryActivityTileContent {activity} />
{/if}
</tile-content>
{#if activity.asyncData?.asyncStatus === ActivityAsyncStatus.Timelocked}
{#if isTimelocked}
<TimelockActivityTileFooter {activity} />
{:else if activity.asyncData}
{:else if shouldShowAsyncFooter}
<AsyncActivityTileFooter {activity} />
{/if}
</activity-tile>
Expand Down
Expand Up @@ -30,9 +30,9 @@
(activity.direction === ActivityDirection.Incoming ||
activity.direction === ActivityDirection.SelfTransaction) &&
activity.asyncData?.asyncStatus === ActivityAsyncStatus.Unclaimed
$: shouldShowAsyncFooter = activity.asyncData?.asyncStatus !== ActivityAsyncStatus.Claimed

$: timeDiff = getTimeDiff(activity)
$: hasExpirationTime = !!activity.asyncData?.expirationDate

function handleRejectClick(): void {
openPopup({
Expand Down Expand Up @@ -68,45 +68,49 @@
return getTimeDifference(expirationDate, $time)
}
}
return localize('general.none')
return undefined
}
</script>

{#if shouldShowAsyncFooter}
<TileFooter>
<svelte:fragment slot="left">
<TileFooter>
<svelte:fragment slot="left">
{#if timeDiff}
<TooltipIcon
icon={IconEnum.ExpirationTime}
icon={hasExpirationTime ? IconEnum.ExpirationTime : IconEnum.Timelock}
iconClasses="text-gray-600 dark:text-gray-200"
title={localize('general.expirationTime')}
text={localize(`tooltips.transactionDetails.${activity.direction}.expirationTime`)}
title={localize(`general.${hasExpirationTime ? 'expirationTime' : 'timelockDate'}`)}
text={localize(
`tooltips.transactionDetails.${activity.direction}.${
hasExpirationTime ? 'expirationTime' : 'timelockDate'
}`
)}
position={Position.Top}
/>
<Text fontSize="13" color="gray-600" fontWeight={FontWeight.semibold}>{timeDiff}</Text>
</svelte:fragment>
<svelte:fragment slot="right">
{#if shouldShowActions}
<Button
onClick={handleRejectClick}
disabled={activity.asyncData?.isClaiming || activity.asyncData?.isRejected}
inlineStyle="min-width: 4rem;"
size={ButtonSize.Small}
outline
>
{localize('actions.reject')}
</Button>
<Button
onClick={handleClaimClick}
disabled={activity.asyncData?.isClaiming}
isBusy={activity.asyncData?.isClaiming}
inlineStyle="min-width: 4rem;"
size={ButtonSize.Small}
>
{localize('actions.claim')}
</Button>
{:else}
<ActivityAsyncStatusPill asyncStatus={activity.asyncData?.asyncStatus} />
{/if}
</svelte:fragment>
</TileFooter>
{/if}
{/if}
</svelte:fragment>
<svelte:fragment slot="right">
{#if shouldShowActions}
<Button
onClick={handleRejectClick}
disabled={activity.asyncData?.isClaiming || activity.asyncData?.isRejected}
inlineStyle="min-width: 4rem;"
size={ButtonSize.Small}
outline
>
{localize('actions.reject')}
</Button>
<Button
onClick={handleClaimClick}
disabled={activity.asyncData?.isClaiming}
isBusy={activity.asyncData?.isClaiming}
inlineStyle="min-width: 4rem;"
size={ButtonSize.Small}
>
{localize('actions.claim')}
</Button>
{:else}
<ActivityAsyncStatusPill asyncStatus={activity.asyncData?.asyncStatus} />
{/if}
</svelte:fragment>
</TileFooter>
@@ -1,9 +1,9 @@
import { syncBalance } from '@core/account/actions/syncBalance'
import { Activity } from '@core/wallet/types'
import { updateNftInAllAccountNfts } from '@core/nfts'
import { ActivityAsyncStatus, ActivityDirection, ActivityType } from '@core/wallet/enums'
import { allAccountActivities } from '../../stores'
import { refreshAccountAssetsForActiveProfile } from '../refreshAccountAssetsForActiveProfile'
import { getAsyncStatus } from '@core/wallet/utils/generateActivity/helper'

export function setAsyncStatusOfAccountActivities(time: Date): void {
const balancesToUpdate: number[] = []
Expand All @@ -14,8 +14,13 @@ export function setAsyncStatusOfAccountActivities(time: Date): void {
if (oldAsyncStatus === ActivityAsyncStatus.Claimed || oldAsyncStatus === ActivityAsyncStatus.Expired) {
continue
}
activity.asyncData.asyncStatus = getAsyncStatus(activity, time)

activity.asyncData.asyncStatus = getAsyncStatus(
false,
activity.asyncData.expirationDate,
activity.asyncData.timelockDate,
!!activity.storageDeposit,
time.getTime()
)
if (oldAsyncStatus !== null && oldAsyncStatus !== activity.asyncData.asyncStatus) {
if (!balancesToUpdate.includes(accountIndex)) {
balancesToUpdate.push(accountIndex)
Expand All @@ -40,19 +45,3 @@ export function setAsyncStatusOfAccountActivities(time: Date): void {
void refreshAccountAssetsForActiveProfile()
}
}

function getAsyncStatus(activity: Activity, time: Date): ActivityAsyncStatus {
if (activity.asyncData?.timelockDate) {
if (activity.asyncData.timelockDate.getTime() > time.getTime()) {
return ActivityAsyncStatus.Timelocked
}
} else if (activity.asyncData) {
if (activity.asyncData.asyncStatus !== ActivityAsyncStatus.Claimed) {
if (time > activity.asyncData.expirationDate) {
return ActivityAsyncStatus.Expired
} else {
return ActivityAsyncStatus.Unclaimed
}
}
}
}
Expand Up @@ -6,4 +6,8 @@ export const UNLOCK_CONDITION_STATE_CONTROLLER_ADDRESS = 4
export const UNLOCK_CONDITION_GOVERNOR_ADDRESS = 5
export const UNLOCK_CONDITION_IMMUTABLE_ALIAS = 6

export const ASYNC_UNLOCK_CONDITION_TYPES = [UNLOCK_CONDITION_STORAGE_DEPOSIT_RETURN, UNLOCK_CONDITION_EXPIRATION]
export const ASYNC_UNLOCK_CONDITION_TYPES = [
UNLOCK_CONDITION_STORAGE_DEPOSIT_RETURN,
UNLOCK_CONDITION_EXPIRATION,
UNLOCK_CONDITION_TIMELOCK,
]
@@ -1,8 +1,10 @@
import { IAccountState } from '@core/account'
import { isActivityHiddenForAccountIndex, ActivityAsyncStatus, IClaimData, Output, AsyncData } from '@core/wallet'
import { isActivityHiddenForAccountIndex, IClaimData, Output, AsyncData } from '@core/wallet'
import { getExpirationDateFromOutput } from '../../outputs/getExpirationDateFromOutput'
import { getTimelockDateFromOutput } from './getTimelockDateFromOutput'
import { isOutputAsync } from '../../outputs/isOutputAsync'
import { getAsyncStatus } from './getAsyncStatus'
import { getStorageDepositFromOutput } from './getStorageDepositFromOutput'

export function getAsyncDataFromOutput(
output: Output,
Expand All @@ -19,19 +21,15 @@ export function getAsyncDataFromOutput(

const expirationDate = getExpirationDateFromOutput(output)
const timelockDate = getTimelockDateFromOutput(output)
const { storageDeposit } = getStorageDepositFromOutput(output)

let asyncStatus
if (claimingData) {
asyncStatus = ActivityAsyncStatus.Claimed
} else if (timelockDate) {
if (timelockDate.getTime() > Date.now()) {
asyncStatus = ActivityAsyncStatus.Timelocked
}
} else if (expirationDate && expirationDate.getTime() < Date.now()) {
asyncStatus = ActivityAsyncStatus.Expired
} else {
asyncStatus = ActivityAsyncStatus.Unclaimed
}
const asyncStatus = getAsyncStatus(
!!claimingTransactionId,
expirationDate,
timelockDate,
!!storageDeposit,
Date.now()
)

return {
asyncStatus,
Expand Down
@@ -0,0 +1,23 @@
import { ActivityAsyncStatus } from '@core/wallet/enums'

export function getAsyncStatus(
isClaimed: boolean,
expirationDate: Date,
timelockDate: Date,
hasStorageDeposit: boolean,
currentTimeStamp: number
): ActivityAsyncStatus {
if (isClaimed) {
return ActivityAsyncStatus.Claimed
} else if (timelockDate && timelockDate.getTime() > currentTimeStamp) {
return ActivityAsyncStatus.Timelocked
} else if (expirationDate && expirationDate.getTime() < currentTimeStamp) {
return ActivityAsyncStatus.Expired
} else if (hasStorageDeposit || expirationDate) {
return ActivityAsyncStatus.Unclaimed
} else if (timelockDate) {
return ActivityAsyncStatus.Claimed
} else {
return ActivityAsyncStatus.Unclaimed
}
}
@@ -1,5 +1,6 @@
export * from './getActivityTypeFromOutput'
export * from './getAsyncDataFromOutput'
export * from './getAsyncStatus'
export * from './getAmountFromOutput'
export * from './getSendingInformation'
export * from './getGovernanceInfo'
Expand Down
Expand Up @@ -22,6 +22,6 @@ export function getTimeDifference(lateDate: Date, earlyDate: Date): string {
} else if (seconds > 0) {
return '<1min'
} else {
return '-'
return undefined
}
}