Skip to content

Commit a63ee52

Browse files
committed
refactor: boltz query handling
1 parent 828e267 commit a63ee52

File tree

6 files changed

+272
-147
lines changed

6 files changed

+272
-147
lines changed

src/client/src/views/swap/SwapStatus.tsx

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Fragment, useEffect, useState } from 'react';
2-
import { Trash } from 'react-feather';
2+
import { RefreshCw, Trash } from 'react-feather';
33
import { Tooltip as ReactTooltip } from 'react-tooltip';
44
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
55
import { getTransactionLink } from '../../components/generic/helpers';
@@ -11,7 +11,7 @@ import {
1111
SubTitle,
1212
} from '../../components/generic/Styled';
1313
import Modal from '../../components/modal/ReactModal';
14-
import { useGetBoltzSwapStatusLazyQuery } from '../../graphql/queries/__generated__/getBoltzSwapStatus.generated';
14+
import { useGetBoltzSwapStatusQuery } from '../../graphql/queries/__generated__/getBoltzSwapStatus.generated';
1515
import { chartColors, themeColors } from '../../styles/Themes';
1616
import styled from 'styled-components';
1717
import { SwapClaim } from './SwapClaim';
@@ -192,20 +192,14 @@ export const SwapStatus = () => {
192192

193193
const [enriched, setEnriched] = useState<EnrichedSwap[]>([]);
194194

195-
const [getStatus, { data, loading }] = useGetBoltzSwapStatusLazyQuery({
196-
pollInterval: 2000,
195+
const { data, refetch, networkStatus } = useGetBoltzSwapStatusQuery({
196+
notifyOnNetworkStatusChange: true,
197+
variables: { ids: swaps.map((s: { id: string }) => s.id).filter(Boolean) },
197198
fetchPolicy: 'network-only',
199+
skip: !swaps.length,
198200
});
199201

200-
useEffect(() => {
201-
if (swaps.length) {
202-
getStatus({
203-
variables: {
204-
ids: swaps.map((s: { id: string }) => s.id).filter(Boolean),
205-
},
206-
});
207-
}
208-
}, [swaps, getStatus]);
202+
const loading = [1, 2, 3, 4, 6].includes(networkStatus);
209203

210204
useEffect(() => {
211205
if (loading || !data?.getBoltzSwapStatus) return;
@@ -232,7 +226,19 @@ export const SwapStatus = () => {
232226
dispatch({ type: 'cleanup', swaps: cleaned });
233227
};
234228

235-
if (!swaps.length || !data?.getBoltzSwapStatus || loading) {
229+
if (loading) {
230+
return (
231+
<>
232+
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
233+
<SubTitle>Swap History</SubTitle>
234+
<Separation />
235+
<DarkSubTitle>Loading swap statuses...</DarkSubTitle>
236+
</Card>
237+
</>
238+
);
239+
}
240+
241+
if (!swaps.length || !data?.getBoltzSwapStatus) {
236242
return (
237243
<>
238244
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
@@ -249,11 +255,20 @@ export const SwapStatus = () => {
249255
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
250256
<SingleLine>
251257
<SubTitle>Swap History</SubTitle>
252-
<div data-tip data-for={`cleanup`}>
253-
<ColorButton disabled={loading} onClick={handleCleanup}>
254-
<Trash size={18} />
258+
<SingleLine>
259+
<ColorButton
260+
disabled={loading}
261+
onClick={() => refetch()}
262+
withMargin="0 4px 0 0"
263+
>
264+
<RefreshCw size={18} />
255265
</ColorButton>
256-
</div>
266+
<div data-tip data-for={`cleanup`}>
267+
<ColorButton disabled={loading} onClick={handleCleanup}>
268+
<Trash size={18} />
269+
</ColorButton>
270+
</div>
271+
</SingleLine>
257272
</SingleLine>
258273
<Separation />
259274
{enriched.map((swap, index) => (

src/server/modules/api/boltz/boltz.module.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,13 @@ import { FetchModule } from '../../fetch/fetch.module';
33
import { NodeModule } from '../../node/node.module';
44
import {
55
BoltzResolver,
6-
BoltzSwapResolver,
76
CreateBoltzReverseSwapTypeResolver,
87
} from './boltz.resolver';
98
import { BoltzService } from './boltz.service';
109

1110
@Module({
1211
imports: [NodeModule, FetchModule],
13-
providers: [
14-
BoltzService,
15-
BoltzSwapResolver,
16-
CreateBoltzReverseSwapTypeResolver,
17-
BoltzResolver,
18-
],
12+
providers: [BoltzService, CreateBoltzReverseSwapTypeResolver, BoltzResolver],
1913
exports: [BoltzService],
2014
})
2115
export class BoltzModule {}

src/server/modules/api/boltz/boltz.resolver.ts

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,53 +32,18 @@ import {
3232
BoltzInfoType,
3333
BoltzSwap,
3434
CreateBoltzReverseSwapType,
35+
isBoltzError,
3536
} from './boltz.types';
3637
import { getPreimageAndHash } from 'src/server/utils/crypto';
3738
import { CurrentUser } from '../../security/security.decorators';
3839
import { UserId } from '../../security/security.types';
3940
import { toWithError } from 'src/server/utils/async';
4041
import { ECPairAPI, ECPairFactory } from 'ecpair';
4142
import * as ecc from 'tiny-secp256k1';
43+
import { mapSeries } from 'async';
4244

4345
const ECPair: ECPairAPI = ECPairFactory(ecc);
4446

45-
@Resolver(BoltzSwap)
46-
export class BoltzSwapResolver {
47-
constructor(
48-
private boltzService: BoltzService,
49-
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger
50-
) {}
51-
52-
@ResolveField()
53-
async id(@Parent() parent: string) {
54-
return parent;
55-
}
56-
57-
@ResolveField()
58-
async boltz(@Parent() parent: string) {
59-
const [info, error] = await toWithError(
60-
this.boltzService.getSwapStatus(parent)
61-
);
62-
63-
if (error || info?.error) {
64-
this.logger.error(`Error getting status for swap with id: ${parent}`, {
65-
error: error || info.error,
66-
});
67-
return null;
68-
}
69-
70-
if (!info?.status) {
71-
this.logger.debug(
72-
`No status in Boltz response for swap with id: ${parent}`,
73-
{ info }
74-
);
75-
return null;
76-
}
77-
78-
return info;
79-
}
80-
}
81-
8247
@Resolver(CreateBoltzReverseSwapType)
8348
export class CreateBoltzReverseSwapTypeResolver {
8449
constructor(private nodeService: NodeService) {}
@@ -110,13 +75,14 @@ export class BoltzResolver {
11075

11176
@Query(() => BoltzInfoType)
11277
async getBoltzInfo() {
113-
const info = await this.boltzService.getPairs();
78+
const [info, error] = await toWithError(this.boltzService.getPairs());
11479

115-
if (info?.error) {
80+
if (error || isBoltzError(info)) {
11681
this.logger.error('Error getting swap information from Boltz', {
117-
error: info.error,
82+
error,
83+
boltzError: info,
11884
});
119-
throw new Error(info.error);
85+
throw new GraphQLError('Error getting swap informaion from Boltz');
12086
}
12187

12288
const btcPair = info?.BTC?.BTC;
@@ -137,7 +103,29 @@ export class BoltzResolver {
137103
async getBoltzSwapStatus(
138104
@Args('ids', { type: () => [String] }) ids: string[]
139105
) {
140-
return ids;
106+
return mapSeries(ids, async (id: string) => {
107+
const [info, error] = await toWithError(
108+
this.boltzService.getSwapStatus(id)
109+
);
110+
111+
if (error || isBoltzError(info)) {
112+
this.logger.error(`Error getting status for swap with id: ${id}`, {
113+
error,
114+
boltzError: info,
115+
});
116+
return { id };
117+
}
118+
119+
if (!info.status) {
120+
this.logger.debug(
121+
`No status in Boltz response for swap with id: ${id}`,
122+
{ info }
123+
);
124+
return { id };
125+
}
126+
127+
return { id, boltz: info };
128+
});
141129
}
142130

143131
@Mutation(() => String)
@@ -289,15 +277,16 @@ export class BoltzResolver {
289277
publicKey,
290278
});
291279

292-
const info = await this.boltzService.createReverseSwap(
293-
amount,
294-
hash,
295-
publicKey
280+
const [info, error] = await toWithError(
281+
this.boltzService.createReverseSwap(amount, hash, publicKey)
296282
);
297283

298-
if (info?.error) {
299-
this.logger.error('Error creating reverse swap with Boltz', info.error);
300-
throw new Error(info.error);
284+
if (error || isBoltzError(info)) {
285+
this.logger.error('Error creating reverse swap with Boltz', {
286+
error,
287+
boltzError: info,
288+
});
289+
throw new GraphQLError('Error creating reverse swap with Boltz');
301290
}
302291

303292
const finalInfo = {
@@ -327,17 +316,23 @@ export class BoltzResolver {
327316
private broadcastTransaction = async (finalTransaction: Transaction) => {
328317
this.logger.debug('Final transaction', { finalTransaction });
329318

330-
const response = await this.boltzService.broadcastTransaction(
331-
finalTransaction.toHex()
319+
const [info, error] = await toWithError(
320+
this.boltzService.broadcastTransaction(finalTransaction.toHex())
332321
);
333322

334-
this.logger.debug('Response from Boltz', { response });
323+
if (error || isBoltzError(info)) {
324+
this.logger.error('Error broadcasting transaction through Boltz', {
325+
error,
326+
boltzError: info,
327+
});
328+
throw new GraphQLError('Error broadcasting transaction through Boltz');
329+
}
335330

336-
if (!response?.id) {
331+
if (!info.id) {
337332
this.logger.error('Did not receive a transaction id from Boltz');
338333
throw new Error('NoTransactionIdFromBoltz');
339334
}
340335

341-
return response.id;
336+
return info.id;
342337
};
343338
}

0 commit comments

Comments
 (0)