22import Button from " $lib/components/ui/Button.svelte"
33import Card from " $lib/components/ui/Card.svelte"
44import Tabs from " $lib/components/ui/Tabs.svelte"
5+ import { runPromiseExit$ } from " $lib/runtime"
6+ import { DESTINATION_CHANNEL_ID } from " $lib/stake/config"
7+ import { predictProxy } from " $lib/stake/instantiate2"
8+ import { wallets as WalletStore } from " $lib/stores/wallets.svelte"
59import { Utils } from " @unionlabs/sdk"
10+ import { Cosmos } from " @unionlabs/sdk-cosmos"
11+ import { EU_LST } from " @unionlabs/sdk/Constants"
612import type { Chain , Token } from " @unionlabs/sdk/schema"
7- import { BigDecimal , pipe } from " effect"
13+ import { Array , BigDecimal , Effect , Exit , pipe } from " effect"
814import * as O from " effect/Option"
15+ import ProxyDustRecovery from " ./ProxyDustRecovery.svelte"
16+ import StakingRewardsDisplay from " ./StakingRewardsDisplay.svelte"
917import TokenBalanceRow from " ./TokenBalanceRow.svelte"
1018
1119interface Props {
@@ -15,6 +23,8 @@ interface Props {
1523 uOnEvmBalance: O .Option <bigint >
1624 eUOnEvmBalance: O .Option <bigint >
1725 purchaseRate: O .Option <BigDecimal .BigDecimal >
26+ redemptionRate: O .Option <BigDecimal .BigDecimal >
27+ stakingHistory? : O .Option <Array .NonEmptyReadonlyArray <any >>
1828}
1929
2030let {
2434 uOnEvmBalance,
2535 eUOnEvmBalance,
2636 purchaseRate,
37+ redemptionRate,
38+ stakingHistory = O .none (),
2739}: Props = $props ()
2840
2941// Calculate eU value of U balance
@@ -53,25 +65,75 @@ const eUBalanceInU = $derived<O.Option<BigDecimal.BigDecimal>>(
5365 ),
5466)
5567
56- type BalanceTab = " balances" | " rewards"
68+ type BalanceTab = " balances" | " rewards" | " dust "
5769let selectedTab = $state <BalanceTab >(" balances" )
70+
71+ // Query proxy balance for dust
72+ const proxyDustData = runPromiseExit$ (() => {
73+ void WalletStore .evmAddress
74+
75+ return pipe (
76+ WalletStore .evmAddress ,
77+ O .match ({
78+ onNone : () => Effect .succeed ({ euDust: BigDecimal .make (0n , 18 ), proxyAddress: " " }),
79+ onSome : (address ) =>
80+ Effect .gen (function * () {
81+ const proxy = yield * predictProxy ({
82+ path: 0n ,
83+ channel: DESTINATION_CHANNEL_ID ,
84+ sender: address ,
85+ })
86+
87+ // Query eU balance on proxy
88+ const euBalanceResponse = yield * pipe (
89+ Cosmos .queryContract (EU_LST , {
90+ balance: { address: proxy .address },
91+ }),
92+ Effect .map (resp => resp as { balance: string }),
93+ Effect .catchAll (() => Effect .succeed ({ balance: " 0" })),
94+ )
95+
96+ // Convert the raw balance string (with 18 decimals) to BigDecimal
97+ const euDustRaw = BigInt (euBalanceResponse .balance )
98+ const euDust = BigDecimal .make (euDustRaw , 18 ) // 18 decimals for eU
99+
100+ return { euDust , proxyAddress: proxy .address }
101+ }),
102+ }),
103+ Effect .provide (Cosmos .Client .Live (" https://rpc.union.build" )),
104+ Effect .catchAll (() => Effect .succeed ({ euDust: BigDecimal .make (0n , 18 ), proxyAddress: " " })),
105+ )
106+ })
107+
108+ const proxyEuDust = $derived (
109+ O .isSome (proxyDustData .current ) && Exit .isSuccess (proxyDustData .current .value )
110+ ? O .some (proxyDustData .current .value .value .euDust )
111+ : O .none (),
112+ )
113+
114+ const proxyAddress = $derived (
115+ O .isSome (proxyDustData .current ) && Exit .isSuccess (proxyDustData .current .value )
116+ ? O .some (proxyDustData .current .value .value .proxyAddress )
117+ : O .none (),
118+ )
58119 </script >
59120
60121<Card divided >
61122 <div class =" px-4 py-2.5 border-b border-zinc-800" >
62123 <Tabs
63124 items ={[
64125 { id: " balances" , label: " Balances" },
65- // { id: "rewards", label: "Rewards" },
126+ { id: " rewards" , label: " Rewards" },
127+ { id: " dust" , label: " Dust" },
66128 ]}
67129 activeId ={selectedTab }
68130 onTabChange ={(id ) => selectedTab = id as BalanceTab }
69131 />
70132 </div >
71133
72- <div class =" p-4" >
134+ <div class =" p-4 min-h-[250px] flex flex-col " >
73135 {#if selectedTab === " balances" }
74- <div class =" flex flex-col gap-3" >
136+ <div class =" flex flex-col gap-3 flex-1 " >
75137 <!-- U Balance Card -->
76138 <TokenBalanceRow
77139 chain ={evmChain }
@@ -115,18 +177,35 @@ let selectedTab = $state<BalanceTab>("balances")
115177 )}
116178 />
117179
180+ <div class =" flex-1" ></div >
181+
118182 <!-- Transfer U Button -->
119183 <Button
120184 variant =" primary"
121185 href =" /transfer?source=union-1& destination=1& asset=0x6175"
122- class =" w-full h-9 text-sm font-semibold mt-1 "
186+ class =" w-full"
123187 >
124188 Transfer U →
125189 </Button >
126190 </div >
127- {:else }
128- <div class =" text-center py-8 text-zinc-500" >
129- Rewards coming soon...
191+ {:else if selectedTab === " rewards" }
192+ <div class =" flex-1" >
193+ <StakingRewardsDisplay
194+ eUBalance ={eUOnEvmBalance }
195+ {redemptionRate }
196+ {stakingHistory }
197+ {proxyEuDust }
198+ />
199+ </div >
200+ {:else if selectedTab === " dust" }
201+ <div class =" flex-1" >
202+ <ProxyDustRecovery
203+ {evmChain }
204+ {eUOnEvmToken }
205+ {redemptionRate }
206+ {proxyEuDust }
207+ {proxyAddress }
208+ />
130209 </div >
131210 {/if }
132211 </div >
0 commit comments