Skip to content

Commit 97e80d8

Browse files
committed
state: add error handling to all API requests
1 parent b825027 commit 97e80d8

File tree

6 files changed

+127
-102
lines changed

6 files changed

+127
-102
lines changed

app/src/components/loop/swap/SwapProcessing.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22
import { observer } from 'mobx-react-lite';
33
import loadingJson from 'assets/animations/loading.json';
44
import { usePrefixedTranslation } from 'hooks';
5-
import { useStore } from 'store';
65
import Animation from 'components/common/Animation';
76
import { HeaderFour } from 'components/common/text';
87
import { styled } from 'components/theme';
@@ -22,26 +21,18 @@ const Styled = {
2221
LoadingMessage: styled.div`
2322
text-align: center;
2423
`,
25-
ErrorMessage: styled.div`
26-
padding: 10px;
27-
color: red;
28-
`,
2924
};
3025

3126
const SwapProcessingStep: React.FC = () => {
3227
const { l } = usePrefixedTranslation('cmps.loop.swap.SwapProcessingStep');
33-
const { buildSwapStore } = useStore();
3428

35-
const { Wrapper, Loader, LoadingMessage, ErrorMessage } = Styled;
29+
const { Wrapper, Loader, LoadingMessage } = Styled;
3630
return (
3731
<Wrapper>
3832
<Loader animationData={loadingJson} loop />
3933
<LoadingMessage>
4034
<HeaderFour>{l('loadingMsg')}</HeaderFour>
4135
</LoadingMessage>
42-
{buildSwapStore.swapError && (
43-
<ErrorMessage>{buildSwapStore.swapError.message}</ErrorMessage>
44-
)}
4536
</Wrapper>
4637
);
4738
};

app/src/store/stores/buildSwapStore.ts

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ class BuildSwapStore {
4040
/** the reference to the timeout used to allow cancelling a swap */
4141
@observable processingTimeout?: NodeJS.Timeout;
4242

43-
/** the error error returned from LoopIn/LoopOut if any */
44-
@observable swapError?: Error;
45-
4643
constructor(store: Store) {
4744
this._store = store;
4845
}
@@ -227,28 +224,34 @@ class BuildSwapStore {
227224
@action.bound
228225
async getTerms(): Promise<void> {
229226
this._store.log.info(`fetching loop terms`);
230-
const inTerms = await this._store.api.loop.getLoopInTerms();
231-
const outTerms = await this._store.api.loop.getLoopOutTerms();
232-
runInAction(() => {
233-
this.terms = {
234-
in: {
235-
min: inTerms.minSwapAmount,
236-
max: inTerms.maxSwapAmount,
237-
},
238-
out: {
239-
min: outTerms.minSwapAmount,
240-
max: outTerms.maxSwapAmount,
241-
},
242-
};
243-
this._store.log.info('updated store.terms', toJS(this.terms));
244-
245-
// restrict the amount whenever the terms are updated
246-
const { min, max } = this.termsForDirection;
247-
if (this.amount < min || this.amount > max) {
248-
this.setAmount(Math.floor((min + max) / 2));
249-
this._store.log.info(`updated buildSwapStore.amount`, this.amount);
250-
}
251-
});
227+
try {
228+
const inTerms = await this._store.api.loop.getLoopInTerms();
229+
const outTerms = await this._store.api.loop.getLoopOutTerms();
230+
runInAction('getTermsContinuation', () => {
231+
this.terms = {
232+
in: {
233+
min: inTerms.minSwapAmount,
234+
max: inTerms.maxSwapAmount,
235+
},
236+
out: {
237+
min: outTerms.minSwapAmount,
238+
max: outTerms.maxSwapAmount,
239+
},
240+
};
241+
this._store.log.info('updated store.terms', toJS(this.terms));
242+
243+
// restrict the amount whenever the terms are updated
244+
const { min, max } = this.termsForDirection;
245+
if (this.amount < min || this.amount > max) {
246+
this.setAmount(Math.floor((min + max) / 2));
247+
this._store.log.info(`updated buildSwapStore.amount`, this.amount);
248+
}
249+
});
250+
} catch (error) {
251+
runInAction('getTermsError', () => {
252+
this._store.uiStore.notify(error.message, 'Unable to fetch Loop Terms');
253+
});
254+
}
252255
}
253256

254257
/**
@@ -259,19 +262,25 @@ class BuildSwapStore {
259262
const { amount, direction } = this;
260263
this._store.log.info(`fetching ${direction} quote for ${amount} sats`);
261264

262-
const quote =
263-
direction === SwapDirection.IN
264-
? await this._store.api.loop.getLoopInQuote(amount)
265-
: await this._store.api.loop.getLoopOutQuote(amount);
266-
267-
runInAction(() => {
268-
this.quote = {
269-
swapFee: quote.swapFee,
270-
minerFee: quote.minerFee,
271-
prepayAmount: quote.prepayAmt,
272-
};
273-
this._store.log.info('updated buildSwapStore.quote', toJS(this.quote));
274-
});
265+
try {
266+
const quote =
267+
direction === SwapDirection.IN
268+
? await this._store.api.loop.getLoopInQuote(amount)
269+
: await this._store.api.loop.getLoopOutQuote(amount);
270+
271+
runInAction('getQuoteContinuation', () => {
272+
this.quote = {
273+
swapFee: quote.swapFee,
274+
minerFee: quote.minerFee,
275+
prepayAmount: quote.prepayAmt,
276+
};
277+
this._store.log.info('updated buildSwapStore.quote', toJS(this.quote));
278+
});
279+
} catch (error) {
280+
runInAction('getQuoteError', () => {
281+
this._store.uiStore.notify(error.message, 'Unable to fetch Quote');
282+
});
283+
}
275284
}
276285

277286
/**
@@ -292,13 +301,17 @@ class BuildSwapStore {
292301
? await this._store.api.loop.loopIn(amount, quote)
293302
: await this._store.api.loop.loopOut(amount, quote);
294303
this._store.log.info('completed loop', toJS(res));
295-
// hide the swap UI after it is complete
296-
this.cancel();
297-
this._store.uiStore.toggleProcessingSwaps();
298-
this._store.swapStore.fetchSwaps();
304+
runInAction('requestSwapContinuation', () => {
305+
// hide the swap UI after it is complete
306+
this.cancel();
307+
this._store.uiStore.toggleProcessingSwaps();
308+
this._store.swapStore.fetchSwaps();
309+
});
299310
} catch (error) {
300-
this.swapError = error;
301-
this._store.log.error(`failed to perform ${direction}`, error);
311+
runInAction('requestSwapError', () => {
312+
this._store.uiStore.notify(error.message, `Unable to Perform ${direction}`);
313+
this.goToPrevStep();
314+
});
302315
}
303316
}, delay);
304317
}

app/src/store/stores/channelStore.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,34 @@ export default class ChannelStore {
5151
async fetchChannels() {
5252
this._store.log.info('fetching channels');
5353

54-
const { channelsList } = await this._store.api.lnd.listChannels();
55-
runInAction(() => {
56-
channelsList.forEach(lndChan => {
57-
// update existing channels or create new ones in state. using this
58-
// approach instead of overwriting the array will cause fewer state
59-
// mutations, resulting in better react rendering performance
60-
const existing = this.channels.get(lndChan.chanId);
61-
if (existing) {
62-
existing.update(lndChan);
63-
} else {
64-
this.channels.set(lndChan.chanId, new Channel(this._store, lndChan));
65-
}
66-
});
67-
// remove any channels in state that are not in the API response
68-
const serverIds = channelsList.map(c => c.chanId);
69-
const localIds = Object.keys(this.channels);
70-
localIds
71-
.filter(id => !serverIds.includes(id))
72-
.forEach(id => this.channels.delete(id));
54+
try {
55+
const { channelsList } = await this._store.api.lnd.listChannels();
56+
runInAction('fetchChannelsContinuation', () => {
57+
channelsList.forEach(lndChan => {
58+
// update existing channels or create new ones in state. using this
59+
// approach instead of overwriting the array will cause fewer state
60+
// mutations, resulting in better react rendering performance
61+
const existing = this.channels.get(lndChan.chanId);
62+
if (existing) {
63+
existing.update(lndChan);
64+
} else {
65+
this.channels.set(lndChan.chanId, new Channel(this._store, lndChan));
66+
}
67+
});
68+
// remove any channels in state that are not in the API response
69+
const serverIds = channelsList.map(c => c.chanId);
70+
const localIds = Object.keys(this.channels);
71+
localIds
72+
.filter(id => !serverIds.includes(id))
73+
.forEach(id => this.channels.delete(id));
7374

74-
this._store.log.info('updated channelStore.channels', toJS(this.channels));
75-
});
75+
this._store.log.info('updated channelStore.channels', toJS(this.channels));
76+
});
77+
} catch (error) {
78+
runInAction('fetchChannelsError', () => {
79+
this._store.uiStore.notify(error.message, 'Unable to fetch Channels');
80+
});
81+
}
7682
}
7783

7884
/** exports the sorted list of channels to CSV file */

app/src/store/stores/nodeStore.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ export default class NodeStore {
1818
@action.bound
1919
async fetchBalances() {
2020
this._store.log.info('fetching node balances');
21-
const offChain = await this._store.api.lnd.channelBalance();
22-
const onChain = await this._store.api.lnd.walletBalance();
23-
runInAction(() => {
24-
this.wallet.channelBalance = offChain.balance;
25-
this.wallet.walletBalance = onChain.totalBalance;
26-
this._store.log.info('updated nodeStore.wallet', toJS(this.wallet));
27-
});
21+
try {
22+
const offChain = await this._store.api.lnd.channelBalance();
23+
const onChain = await this._store.api.lnd.walletBalance();
24+
runInAction('fetchBalancesContinuation', () => {
25+
this.wallet.channelBalance = offChain.balance;
26+
this.wallet.walletBalance = onChain.totalBalance;
27+
this._store.log.info('updated nodeStore.wallet', toJS(this.wallet));
28+
});
29+
} catch (error) {
30+
runInAction('fetchBalancesError', () => {
31+
this._store.uiStore.notify(error.message, 'Unable to fetch balances');
32+
});
33+
}
2834
}
2935
}

app/src/store/stores/swapStore.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,26 +82,34 @@ export default class SwapStore {
8282
async fetchSwaps() {
8383
this._store.log.info('fetching swaps');
8484

85-
const { swapsList } = await this._store.api.loop.listSwaps();
86-
runInAction(() => {
87-
swapsList.forEach(loopSwap => {
88-
// update existing swaps or create new ones in state. using this
89-
// approach instead of overwriting the array will cause fewer state
90-
// mutations, resulting in better react rendering performance
91-
const existing = this.swaps.get(loopSwap.id);
92-
if (existing) {
93-
existing.update(loopSwap);
94-
} else {
95-
this.swaps.set(loopSwap.id, new Swap(loopSwap));
96-
}
85+
try {
86+
const { swapsList } = await this._store.api.loop.listSwaps();
87+
runInAction('fetchSwapsContinuation', () => {
88+
swapsList.forEach(loopSwap => {
89+
// update existing swaps or create new ones in state. using this
90+
// approach instead of overwriting the array will cause fewer state
91+
// mutations, resulting in better react rendering performance
92+
const existing = this.swaps.get(loopSwap.id);
93+
if (existing) {
94+
existing.update(loopSwap);
95+
} else {
96+
this.swaps.set(loopSwap.id, new Swap(loopSwap));
97+
}
98+
});
99+
// remove any swaps in state that are not in the API response
100+
const serverIds = swapsList.map(c => c.id);
101+
const localIds = Object.keys(this.swaps);
102+
localIds
103+
.filter(id => !serverIds.includes(id))
104+
.forEach(id => this.swaps.delete(id));
105+
106+
this._store.log.info('updated swapStore.swaps', toJS(this.swaps));
97107
});
98-
// remove any swaps in state that are not in the API response
99-
const serverIds = swapsList.map(c => c.id);
100-
const localIds = Object.keys(this.swaps);
101-
localIds.filter(id => !serverIds.includes(id)).forEach(id => this.swaps.delete(id));
102-
103-
this._store.log.info('updated swapStore.swaps', toJS(this.swaps));
104-
});
108+
} catch (error) {
109+
runInAction('fetchSwapsError', () => {
110+
this._store.uiStore.notify(error.message, 'Unable to fetch Swaps');
111+
});
112+
}
105113
}
106114

107115
@action.bound

app/src/store/stores/uiStore.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export default class UiStore {
6262
notify(message: string, title?: string) {
6363
const alert: Alert = { id: Date.now(), type: 'error', message, title };
6464
this.alerts.set(alert.id, alert);
65-
this._store.log.info('Added alert', message, toJS(this.alerts));
65+
this._store.log.info('Added alert', toJS(this.alerts));
66+
this._store.log.error(`[${title}] ${message}`);
6667
}
6768

6869
/** removes an existing alert */

0 commit comments

Comments
 (0)