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

staking #164

Merged
merged 12 commits into from
Nov 7, 2024
Merged
21 changes: 21 additions & 0 deletions src/lib/components/elements/tokencard.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { TokenBalance } from '@wharfkit/common';
interface Props {
token?: TokenBalance;
title: string;
description: string;
}

const { token, title, description }: Props = $props();
</script>

<div class="relative h-[103px] rounded-lg bg-[#303338]">
<div class="absolute left-4 top-3">
<img src={token?.metadata.logo} class="size-6" alt="token icon" />
</div>
<div class="absolute right-3 top-3 text-xl font-bold">{title}</div>
<div class="absolute bottom-2 right-3">
<h5 class="h5 text-right">{token?.asset}</h5>
<p>{description}</p>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import AssetText from '$lib/components/elements/asset.svelte';
import { Card } from '$lib/components/layout';
import Button from '$lib/components/button/button.svelte';
import type { UnstakingRecord } from './utils';
import type { UnstakingRecord } from '$lib/utils/staking';

interface Props extends HTMLAttributes<HTMLDivElement> {
href?: string;
Expand All @@ -15,7 +15,7 @@
const { href, records = [], ...props }: Props = $props();
</script>

<Card {...props} title="Unstaking Balances">
<Card {...props} title="Unstaking Balances" class="auto-rows-max">
<table class="table-styles">
<thead class="border-b-2 border-shark-100/10">
<tr class="caption font-medium">
Expand All @@ -24,23 +24,27 @@
</tr>
</thead>
<tbody>
{#each records as record}
{#if !record.savings}
<tr>
<td><AssetText value={record.balance} /></td>
<td class="text-right">
{record.date
? record.date.toLocaleDateString(undefined, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})
: '--'}
</td>
</tr>
{/if}
{/each}
{#if records.filter((r) => !r.savings).length > 0}
{#each records as record}
{#if !record.savings}
<tr>
<td><AssetText value={record.balance} /></td>
<td class="text-right">
{record.date
? record.date.toLocaleDateString(undefined, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})
: '--'}
</td>
</tr>
{/if}
{/each}
{:else}
<tr><td class="caption">No staking in progress</td></tr>
{/if}
</tbody>
</table>
{#if href}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/layout/box/card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
const {
class: className = '',
title = '',
titleTag = 'h3',
titleTag = 'h4',
children,
...props
}: Props = $props();
</script>

<div class={`card ${className}`} {...props}>
{#if title}
<svelte:element this={titleTag} class="card-title h3">
<svelte:element this={titleTag} class="card-title h4">
{title}
</svelte:element>
{/if}
Expand Down
File renamed without changes.
46 changes: 24 additions & 22 deletions src/routes/[network]/(account)/(staking)/staking/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
<script lang="ts">
import { Stack } from '$lib/components/layout';
import PageHeader from '$lib/components/pageheader.svelte';
import PillGroup from '$lib/components/navigation/pillgroup.svelte';
import { page } from '$app/stores';
import { Stack } from '$lib/components/layout';
import Pageheader from '$lib/components/pageheader.svelte';
import { i18n } from '$lib/i18n';

const { children, data } = $props();

const tabOptions = $derived.by(() => {
const network = String(data.network);
return [
{ href: `/${network}/staking`, text: 'Overview' },
{ href: `/${network}/staking/stake`, text: 'Stake' },
{ href: `/${network}/staking/unstake`, text: 'Unstake' },
{ href: `/${network}/staking/withdraw`, text: 'Withdraw' }
];
const locale = i18n.getLanguageFromUrl($page.url);

let currentTab = $derived($page.url.pathname.split('/')[4] || 'overview');

const subtitle = $derived.by(() => {
switch (currentTab) {
case 'stake':
return 'Select amount to stake';
case 'unstake':
return 'Select amount to unstake';
case 'withdraw':
return 'Withdraw';
default:
return 'Overview';
}
});

let currentTab = $derived($page.url.pathname.split('/').pop());
let options = $derived(
tabOptions.map((option) => ({
...option,
active: option.href.split('/').pop() === currentTab
}))
let backPath = $derived(
currentTab === 'overview' ? undefined : `/${locale}/${data.network.shortname}/staking`
);
</script>

<Stack>
<PageHeader title="Staking" />
<PillGroup {options} class="mb-6" />
</Stack>
<Stack class="gap-6">
<Pageheader title="Staking" {subtitle} {backPath} />

{@render children()}
{@render children()}
</Stack>
114 changes: 83 additions & 31 deletions src/routes/[network]/(account)/(staking)/staking/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
import { Asset } from '@wharfkit/antelope';
import { getContext } from 'svelte';

import type { UnstakingRecord } from './utils';
import { getStakedBalance, getUnstakingBalances, getAPY } from './utils';
import UnstakingBalances from './unstaking.svelte';
import type { UnstakingRecord } from '$lib/utils/staking';
import {
getClaimableBalance,
getWithdrawableBalance,
getStakedBalance,
getUnstakingBalances,
getAPY
} from '$lib/utils/staking';
import UnstakingBalances from '$lib/components/elements/unstaking.svelte';
import StakingCalculator from './stakingcalculator.svelte';

const context = getContext<UnicoveContext>('state');
const { data } = $props();
Expand All @@ -18,44 +25,89 @@
let unstaking: Array<UnstakingRecord> = $derived(
getUnstakingBalances(data.network, context.account)
);
let claimable: Asset = $derived(getClaimableBalance(data.network, context.account, unstaking));
let withdrawable: Asset = $derived(getWithdrawableBalance(data.network, context.account));
let totalWithdraw: Asset = $derived(
Asset.fromUnits(
claimable.units.adding(withdrawable.units),
data.network.chain.systemToken!.symbol
)
);

let apy = $derived(getAPY(data.network));
let usdValue = $derived(
Asset.from(
staked.value * (data.network.tokenprice ? data.network.tokenprice.value : 0),
'4,USD'
'2,USD'
)
);
</script>

<Stack class="mx-auto max-w-5xl gap-8">
<Switcher threshold="40rem" class="items-start justify-center">
<Card class="gap-5">
<Stack class="gap-0">
<p class="caption">
Staked Balance - {apy}% APY
</p>
<p class="h3">
<AssetText value={staked} />
</p>
<p class="mt-1.5 self-start rounded bg-shark-800/60 px-2">
$<AssetText value={usdValue} />
</p>
</Stack>
<Switcher threshold="64rem" class="place-content-between">
<Stack class="max-w-lg gap-9">
<Card class="gap-5" title="Staked - {apy}% APY">
<Switcher threshold="20rem">
<Stack class="text-md gap-0">
<p class="caption">Currently Staked</p>
<p class="mt-1.5 self-start rounded bg-shark-800/60 px-2 text-white">
<AssetText class="text-white" variant="full" value={staked} />
</p>
</Stack>
<Stack class="text-md gap-0">
<p class="caption">USD Value</p>
<p class="mt-1.5 self-start rounded bg-shark-800/60 px-2 text-white">
$<AssetText variant="value" value={usdValue} />
</p>
</Stack>
</Switcher>
<Switcher threshold="20rem">
<Button href="/{networkName}/staking/stake" variant="secondary" class="text-skyBlue-500"
>Stake</Button
<Button
href="/{networkName}/staking/stake"
variant="outline"
class="bg-blue-500 hover:bg-blue-600">Stake</Button
>
<Button href="/{networkName}/staking/unstake" variant="secondary" class="text-skyBlue-500"
>Unstake</Button
<Button
href="/{networkName}/staking/unstake"
variant="outline"
class="bg-blue-500 hover:bg-blue-600">Unstake</Button
>
</Switcher>
</Card>
<UnstakingBalances href="/{networkName}/staking/withdraw" records={unstaking} />
</Switcher>
<Card class="gap-5">
<Stack class="gap-0">
<p class="caption">Staking yield history</p>
<p class="h3">0.0 EOS</p>
</Stack>
</Card>
</Stack>
<UnstakingBalances records={unstaking} />
<Card class="gap-5" title="Withdrawable">
<Stack class="text-md gap-0">
<p class="caption">Currently Withdrawable</p>
<p class="mt-1.5 self-start rounded bg-shark-800/60 px-2 text-white">
<AssetText class="text-white" variant="full" value={totalWithdraw} />
</p>
</Stack>
<Button
href="/{networkName}/staking/withdraw"
variant="outline"
class="bg-blue-500 hover:bg-blue-600">Withdraw</Button
>
</Card>
</Stack>
<Stack class="max-w-lg gap-4">
<StakingCalculator
{apy}
network={data.network}
tokenprice={data.network.tokenprice || Asset.from(0, '2,USD')}
/>
<Card class="gap-5" title="About staking">
<Stack class="gap-5">
<p class="caption">
The APY is an estimate, and may fluctuate based on how many and much others are staking.
Your 21 day lockup period starts when you unstake your EOS.
</p>
<p class="caption">You will never get back less EOS.</p>

<p class="caption">
Unstaking balances will still accrue rewards until they are claimed. However, any
operation you do (staking more for instance) will automatically claim your fully unstaked
positions.
</p>
</Stack>
</Card>
</Stack>
</Switcher>
Loading
Loading