11import { A , useNavigate } from "@solidjs/router" ;
2- import { Shuffle , Users } from "lucide-solid" ;
3- import { createMemo , Match , Show , Suspense , Switch } from "solid-js" ;
2+ import { Plus , Shuffle , Trash , Users } from "lucide-solid" ;
3+ import {
4+ createMemo ,
5+ createResource ,
6+ createSignal ,
7+ Match ,
8+ Show ,
9+ Suspense ,
10+ Switch
11+ } from "solid-js" ;
412
513import {
614 AmountFiat ,
@@ -11,6 +19,7 @@ import {
1119 InfoBox ,
1220 MediumHeader ,
1321 NiceP ,
22+ SubtleButton ,
1423 VStack
1524} from "~/components" ;
1625import { useI18n } from "~/i18n/context" ;
@@ -47,10 +56,14 @@ const STYLE =
4756 "px-2 py-1 rounded-xl text-sm flex gap-2 items-center font-semibold" ;
4857
4958export function BalanceBox ( props : { loading ?: boolean ; small ?: boolean } ) {
50- const [ state , _actions ] = useMegaStore ( ) ;
59+ const [ state , _actions , sw ] = useMegaStore ( ) ;
5160 const navigate = useNavigate ( ) ;
5261 const i18n = useI18n ( ) ;
5362
63+ const [ nodeManagerLoading , setNodeManagerLoading ] = createSignal ( false ) ;
64+
65+ const lightningBalance = ( ) => state . balance ?. lightning || 0n ;
66+
5467 const totalOnchain = createMemo (
5568 ( ) =>
5669 ( state . balance ?. confirmed || 0n ) +
@@ -64,6 +77,35 @@ export function BalanceBox(props: { loading?: boolean; small?: boolean }) {
6477 ( state . balance ?. unconfirmed || 0n )
6578 ) ;
6679
80+ const [ hasSelfCustody , { refetch } ] = createResource ( async ( ) => {
81+ // short circuit if we have a balance
82+ if ( totalOnchain ( ) > 0 || state . balance ?. lightning || 0n > 0n ) {
83+ return true ;
84+ }
85+
86+ // otherwise check if we have created a node
87+ const nodes : string [ ] = await sw . list_nodes ( ) ;
88+ return nodes . length > 0 ;
89+ } ) ;
90+
91+ const createNodeManager = async ( ) => {
92+ if ( confirm ( "Pass this test:" ) ) {
93+ setNodeManagerLoading ( true ) ;
94+ await sw . create_node_manager_if_needed ( ) ;
95+ await refetch ( ) ;
96+ setNodeManagerLoading ( false ) ;
97+ }
98+ } ;
99+
100+ const removeNodeManager = async ( ) => {
101+ if ( confirm ( "Are you sure:" ) ) {
102+ setNodeManagerLoading ( true ) ;
103+ await sw . remove_node_manager ( ) ;
104+ await refetch ( ) ;
105+ setNodeManagerLoading ( false ) ;
106+ }
107+ } ;
108+
67109 return (
68110 < VStack >
69111 < Switch >
@@ -131,81 +173,123 @@ export function BalanceBox(props: { loading?: boolean; small?: boolean }) {
131173 </ Match >
132174 </ Switch >
133175 < MediumHeader > { i18n . t ( "profile.self_custody" ) } </ MediumHeader >
134- < FancyCard >
135- < Show when = { ! props . loading } fallback = { < LoadingShimmer /> } >
136- < Switch >
137- < Match when = { state . safe_mode } >
138- < div class = "flex flex-col gap-1" >
139- < InfoBox accent = "red" >
140- { i18n . t ( "common.error_safe_mode" ) }
141- </ InfoBox >
142- </ div >
143- </ Match >
144- < Match when = { true } >
145- < div class = "flex flex-col gap-1" >
146- < div class = "text-2xl" >
147- < AmountSats
148- amountSats = {
149- state . balance ?. lightning || 0
150- }
151- icon = "lightning"
152- denominationSize = "lg"
153- />
154- </ div >
155- < div class = "text-lg text-white/70" >
156- < Suspense >
157- < AmountFiat
158- amountSats = {
159- state . balance ?. lightning || 0
160- }
161- denominationSize = "sm"
162- />
163- </ Suspense >
164- </ div >
165- </ div >
166- </ Match >
167- </ Switch >
168- </ Show >
169- < hr class = "my-2 border-m-grey-750" />
170- < Show when = { ! props . loading } fallback = { < LoadingShimmer /> } >
171- < div class = "flex justify-between" >
172- < div class = "flex flex-col gap-1" >
173- < div class = "text-2xl" >
174- < AmountSats
175- amountSats = { totalOnchain ( ) }
176- icon = "chain"
177- denominationSize = "lg"
178- />
179- </ div >
180- < div class = "text-lg text-white/70" >
181- < Suspense >
182- < AmountFiat
183- amountSats = { totalOnchain ( ) }
184- denominationSize = "sm"
185- />
186- </ Suspense >
187- </ div >
188- </ div >
189- < div class = "flex flex-col items-end justify-between gap-1" >
190- < Show when = { state . balance ?. unconfirmed != 0n } >
191- < Indicator >
192- { i18n . t ( "common.pending" ) }
193- </ Indicator >
194- </ Show >
195- < Show when = { state . balance ?. unconfirmed === 0n } >
196- < div />
176+ < Suspense >
177+ < Switch >
178+ < Match when = { hasSelfCustody ( ) } >
179+ < FancyCard >
180+ < Show
181+ when = { ! props . loading }
182+ fallback = { < LoadingShimmer /> }
183+ >
184+ < Switch >
185+ < Match when = { state . safe_mode } >
186+ < div class = "flex flex-col gap-1" >
187+ < InfoBox accent = "red" >
188+ { i18n . t (
189+ "common.error_safe_mode"
190+ ) }
191+ </ InfoBox >
192+ </ div >
193+ </ Match >
194+ < Match when = { true } >
195+ < div class = "flex flex-col gap-1" >
196+ < div class = "text-2xl" >
197+ < AmountSats
198+ amountSats = { lightningBalance ( ) }
199+ icon = "lightning"
200+ denominationSize = "lg"
201+ />
202+ </ div >
203+ < div class = "text-lg text-white/70" >
204+ < Suspense >
205+ < AmountFiat
206+ amountSats = { lightningBalance ( ) }
207+ denominationSize = "sm"
208+ />
209+ </ Suspense >
210+ </ div >
211+ </ div >
212+ </ Match >
213+ </ Switch >
197214 </ Show >
198- < Show when = { usableOnchain ( ) > 0n } >
199- < div class = "self-end justify-self-end" >
200- < A href = "/swap" class = { STYLE } >
201- < Shuffle class = "h-6 w-6" />
202- </ A >
215+ < hr class = "my-2 border-m-grey-750" />
216+ < Show
217+ when = { ! props . loading }
218+ fallback = { < LoadingShimmer /> }
219+ >
220+ < div class = "flex justify-between" >
221+ < div class = "flex flex-col gap-1" >
222+ < div class = "text-2xl" >
223+ < AmountSats
224+ amountSats = { totalOnchain ( ) }
225+ icon = "chain"
226+ denominationSize = "lg"
227+ />
228+ </ div >
229+ < div class = "text-lg text-white/70" >
230+ < Suspense >
231+ < AmountFiat
232+ amountSats = { totalOnchain ( ) }
233+ denominationSize = "sm"
234+ />
235+ </ Suspense >
236+ </ div >
237+ </ div >
238+ < div class = "flex flex-col items-end justify-between gap-1" >
239+ < Show
240+ when = {
241+ state . balance ?. unconfirmed != 0n
242+ }
243+ >
244+ < Indicator >
245+ { i18n . t ( "common.pending" ) }
246+ </ Indicator >
247+ </ Show >
248+ < Show
249+ when = {
250+ state . balance ?. unconfirmed ===
251+ 0n
252+ }
253+ >
254+ < div />
255+ </ Show >
256+ < Show when = { usableOnchain ( ) > 0n } >
257+ < div class = "self-end justify-self-end" >
258+ < A href = "/swap" class = { STYLE } >
259+ < Shuffle class = "h-6 w-6" />
260+ </ A >
261+ </ div >
262+ </ Show >
263+ </ div >
203264 </ div >
265+ < Show
266+ when = {
267+ totalOnchain ( ) === 0n &&
268+ lightningBalance ( ) === 0n &&
269+ state . federations &&
270+ state . federations . length
271+ }
272+ >
273+ < SubtleButton
274+ onClick = { removeNodeManager }
275+ loading = { nodeManagerLoading ( ) }
276+ >
277+ < Trash class = "h-4 w-4" />
278+ </ SubtleButton >
279+ </ Show >
204280 </ Show >
205- </ div >
206- </ div >
207- </ Show >
208- </ FancyCard >
281+ </ FancyCard >
282+ </ Match >
283+ < Match when = { true } >
284+ < SubtleButton
285+ onClick = { createNodeManager }
286+ loading = { nodeManagerLoading ( ) }
287+ >
288+ < Plus class = "h-4 w-4" />
289+ </ SubtleButton >
290+ </ Match >
291+ </ Switch >
292+ </ Suspense >
209293 </ VStack >
210294 ) ;
211295}
0 commit comments