Skip to content

Commit 44b48eb

Browse files
committed
refactor: handleUpdateLightningWalletCoinSpecific to work with api-ts
TICKET: WP-5416
1 parent c47d741 commit 44b48eb

File tree

3 files changed

+66
-72
lines changed

3 files changed

+66
-72
lines changed
Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
1-
import * as express from 'express';
2-
import { ApiResponseError } from '../errors';
3-
import { UpdateLightningWalletClientRequest, updateWalletCoinSpecific } from '@bitgo/abstract-lightning';
4-
import { decodeOrElse } from '@bitgo/sdk-core';
1+
import { updateWalletCoinSpecific } from '@bitgo/abstract-lightning';
2+
import { ExpressApiRouteRequest } from '../typedRoutes/api';
53

6-
export async function handleUpdateLightningWalletCoinSpecific(req: express.Request): Promise<unknown> {
4+
export async function handleUpdateLightningWalletCoinSpecific(
5+
req: ExpressApiRouteRequest<'express.wallet.update', 'put'>
6+
): Promise<unknown> {
77
const bitgo = req.bitgo;
88

9-
const params = decodeOrElse(
10-
'UpdateLightningWalletClientRequest',
11-
UpdateLightningWalletClientRequest,
12-
req.body,
13-
(_) => {
14-
// DON'T throw errors from decodeOrElse. It could leak sensitive information.
15-
throw new ApiResponseError('Invalid request body to update lightning wallet coin specific', 400);
16-
}
17-
);
9+
const coin = bitgo.coin(req.decoded.coin);
10+
const wallet = await coin.wallets().get({ id: req.decoded.id, includeBalance: false });
1811

19-
const coin = bitgo.coin(req.params.coin);
20-
const wallet = await coin.wallets().get({ id: req.params.id, includeBalance: false });
21-
22-
return await updateWalletCoinSpecific(wallet, params);
12+
return await updateWalletCoinSpecific(wallet, req.decoded);
2313
}
Lines changed: 8 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
import * as sinon from 'sinon';
22
import should from 'should';
3-
import * as express from 'express';
4-
import { handleUpdateLightningWalletCoinSpecific } from '../../../src/lightning/lightningWalletRoutes';
53
import { BitGo } from 'bitgo';
6-
import { ApiResponseError } from '../../../src/errors';
4+
import { ExpressApiRouteRequest } from '../../../src/typedRoutes/api';
75

86
describe('Lightning Wallet Routes', () => {
97
let bitgo;
108
const coin = 'tlnbtc';
119

12-
const mockRequestObject = (params: { body?: any; params?: any; query?: any; bitgo?: any }) => {
13-
const req: Partial<express.Request> = {};
14-
req.body = params.body || {};
15-
req.params = params.params || {};
16-
req.query = params.query || {};
17-
req.bitgo = params.bitgo;
18-
return req as express.Request;
19-
};
20-
2110
beforeEach(() => {
2211
const walletStub = {};
2312
const coinStub = {
@@ -53,11 +42,16 @@ describe('Lightning Wallet Routes', () => {
5342
},
5443
});
5544

56-
const req = mockRequestObject({
45+
const req = {
5746
params: { id: 'testWalletId', coin },
5847
body: inputParams,
48+
decoded: {
49+
id: 'testWalletId',
50+
coin,
51+
...inputParams,
52+
},
5953
bitgo,
60-
});
54+
} as unknown as ExpressApiRouteRequest<'express.wallet.update', 'put'>;
6155

6256
const result = await lightningRoutes.handleUpdateLightningWalletCoinSpecific(req);
6357

@@ -70,45 +64,5 @@ describe('Lightning Wallet Routes', () => {
7064
should(secondArg).have.property('signerHost', 'signer.example.com');
7165
should(secondArg).have.property('passphrase', 'wallet-password-123');
7266
});
73-
74-
it('should throw error when passphrase is missing', async () => {
75-
const invalidParams = {
76-
signerMacaroon: 'encrypted-data',
77-
signerHost: 'signer.example.com',
78-
};
79-
80-
const req = mockRequestObject({
81-
params: { id: 'testWalletId', coin },
82-
body: invalidParams,
83-
bitgo,
84-
});
85-
86-
await should(handleUpdateLightningWalletCoinSpecific(req))
87-
.be.rejectedWith(ApiResponseError)
88-
.then((error) => {
89-
should(error.status).equal(400);
90-
should(error.message).equal('Invalid request body to update lightning wallet coin specific');
91-
});
92-
});
93-
94-
it('should handle invalid request body', async () => {
95-
const invalidParams = {
96-
signerHost: 12345, // invalid type
97-
passphrase: 'valid-pass',
98-
};
99-
100-
const req = mockRequestObject({
101-
params: { id: 'testWalletId', coin },
102-
body: invalidParams,
103-
bitgo,
104-
});
105-
106-
await should(handleUpdateLightningWalletCoinSpecific(req))
107-
.be.rejectedWith(ApiResponseError)
108-
.then((error) => {
109-
should(error.status).equal(400);
110-
should(error.message).equal('Invalid request body to update lightning wallet coin specific');
111-
});
112-
});
11367
});
11468
});

modules/express/test/unit/typedRoutes/decode.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import {
1515
import { UnlockLightningWalletBody, UnlockLightningWalletParams } from '../../../src/typedRoutes/api/v2/unlockWallet';
1616
import { OfcSignPayloadBody } from '../../../src/typedRoutes/api/v2/ofcSignPayload';
1717
import { CreateAddressBody, CreateAddressParams } from '../../../src/typedRoutes/api/v2/createAddress';
18+
import {
19+
ExpressWalletUpdateBody,
20+
ExpressWalletUpdateParams,
21+
} from '../../../src/typedRoutes/api/v2/expressWalletUpdate';
1822

1923
export function assertDecode<T>(codec: t.Type<T, unknown>, input: unknown): T {
2024
const result = codec.decode(input);
@@ -243,4 +247,50 @@ describe('io-ts decode tests', function () {
243247
assertDecode(t.type(CreateAddressBody), { eip1559: { maxFeePerGas: 1, maxPriorityFeePerGas: 1 } });
244248
assertDecode(t.type(CreateAddressBody), {});
245249
});
250+
it('express.wallet.update', function () {
251+
// missing coin
252+
assert.throws(() => assertDecode(t.type(ExpressWalletUpdateParams), { id: 'wallet123' }));
253+
// missing id
254+
assert.throws(() => assertDecode(t.type(ExpressWalletUpdateParams), { coin: 'tlnbtc' }));
255+
// missing required fields
256+
assert.throws(() => assertDecode(t.type(ExpressWalletUpdateBody), {}));
257+
// signerHost must be string
258+
assert.throws(() =>
259+
assertDecode(t.type(ExpressWalletUpdateBody), {
260+
signerHost: 123,
261+
signerTlsCert: 'cert',
262+
passphrase: 'p',
263+
})
264+
);
265+
// signerTlsCert must be string
266+
assert.throws(() =>
267+
assertDecode(t.type(ExpressWalletUpdateBody), {
268+
signerHost: 'host.example',
269+
signerTlsCert: 456,
270+
passphrase: 'p',
271+
})
272+
);
273+
// passphrase must be string and required
274+
assert.throws(() =>
275+
assertDecode(t.type(ExpressWalletUpdateBody), {
276+
signerHost: 'host.example',
277+
signerTlsCert: 'cert',
278+
})
279+
);
280+
// valid minimal
281+
assertDecode(t.type(ExpressWalletUpdateBody), {
282+
signerHost: 'host.example',
283+
signerTlsCert: 'cert',
284+
passphrase: 'p',
285+
});
286+
// valid
287+
assertDecode(t.type(ExpressWalletUpdateParams), { coin: 'tlnbtc', id: 'wallet123' });
288+
// valid with optional signerMacaroon
289+
assertDecode(t.type(ExpressWalletUpdateBody), {
290+
signerHost: 'host.example',
291+
signerTlsCert: 'cert',
292+
passphrase: 'p',
293+
signerMacaroon: 'mac',
294+
});
295+
});
246296
});

0 commit comments

Comments
 (0)