Skip to content

Commit 685ae3c

Browse files
committed
feat(express): migrate init wallet to typed routes
TICKET: WP-5444
1 parent 5ec3ddd commit 685ae3c

File tree

5 files changed

+40
-30
lines changed

5 files changed

+40
-30
lines changed

modules/express/src/clientRoutes.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,7 @@ export function setupAPIRoutes(app: express.Application, config: Config): void {
15661566
router.post('express.decrypt', [prepareBitGo(config), typedPromiseWrapper(handleDecrypt)]);
15671567
router.post('express.encrypt', [prepareBitGo(config), typedPromiseWrapper(handleEncrypt)]);
15681568
router.post('express.verifyaddress', [prepareBitGo(config), typedPromiseWrapper(handleVerifyAddress)]);
1569+
router.post('express.lightning.initWallet', [prepareBitGo(config), typedPromiseWrapper(handleInitLightningWallet)]);
15691570
app.post(
15701571
'/api/v[12]/calculateminerfeeinfo',
15711572
parseBody,
@@ -1790,12 +1791,6 @@ export function setupEnclavedExpressRoutes(app: express.Application, config: Con
17901791
}
17911792

17921793
export function setupLightningSignerNodeRoutes(app: express.Application, config: Config): void {
1793-
app.post(
1794-
'/api/v2/:coin/wallet/:id/initwallet',
1795-
parseBody,
1796-
prepareBitGo(config),
1797-
promiseWrapper(handleInitLightningWallet)
1798-
);
17991794
app.post(
18001795
'/api/v2/:coin/wallet/:id/signermacaroon',
18011796
parseBody,

modules/express/src/lightning/lightningSignerRoutes.ts

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,10 @@ import {
1414
import * as utxolib from '@bitgo/utxo-lib';
1515
import { Buffer } from 'buffer';
1616

17-
import {
18-
CreateSignerMacaroonRequest,
19-
GetWalletStateResponse,
20-
InitLightningWalletRequest,
21-
UnlockLightningWalletRequest,
22-
} from './codecs';
17+
import { CreateSignerMacaroonRequest, GetWalletStateResponse, UnlockLightningWalletRequest } from './codecs';
2318
import { LndSignerClient } from './lndSignerClient';
2419
import { ApiResponseError } from '../errors';
20+
import { ExpressApiRouteRequest } from '../typedRoutes/api';
2521

2622
type Decrypt = (params: { input: string; password: string }) => string;
2723

@@ -61,29 +57,16 @@ function getMacaroonRootKey(passphrase: string, nodeAuthEncryptedPrv: string, de
6157
/**
6258
* Handle the request to initialise remote signer LND for a wallet.
6359
*/
64-
export async function handleInitLightningWallet(req: express.Request): Promise<unknown> {
60+
export async function handleInitLightningWallet(
61+
req: ExpressApiRouteRequest<'express.lightning.initWallet', 'post'>
62+
): Promise<unknown> {
6563
const bitgo = req.bitgo;
66-
const coinName = req.params.coin;
64+
const { coin: coinName, walletId, passphrase, expressHost } = req.decoded as any;
6765
if (!isLightningCoinName(coinName)) {
6866
throw new ApiResponseError(`Invalid coin ${coinName}. This is not a lightning coin.`, 400);
6967
}
7068
const coin = bitgo.coin(coinName);
7169

72-
const walletId = req.params.id;
73-
if (typeof walletId !== 'string') {
74-
throw new ApiResponseError(`Invalid wallet id: ${walletId}`, 400);
75-
}
76-
77-
const { passphrase, expressHost } = decodeOrElse(
78-
InitLightningWalletRequest.name,
79-
InitLightningWalletRequest,
80-
req.body,
81-
(_) => {
82-
// DON'T throw errors from decodeOrElse. It could leak sensitive information.
83-
throw new ApiResponseError('Invalid request body to initialize lightning wallet', 400);
84-
}
85-
);
86-
8770
const wallet = await coin.wallets().get({ id: walletId, includeBalance: false });
8871
if (wallet.subType() !== 'lightningSelfCustody') {
8972
throw new ApiResponseError(`not a self custodial lighting wallet ${walletId}`, 400);

modules/express/src/typedRoutes/api/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { PostAcceptShare } from './v1/acceptShare';
1212
import { PostSimpleCreate } from './v1/simpleCreate';
1313
import { PutPendingApproval } from './v1/pendingApproval';
1414
import { PostSignTransaction } from './v1/signTransaction';
15+
import { PostLightningInitWallet } from './v2/lightningInitWallet';
1516

1617
export const ExpressApi = apiSpec({
1718
'express.ping': {
@@ -44,6 +45,9 @@ export const ExpressApi = apiSpec({
4445
'express.v1.wallet.signTransaction': {
4546
post: PostSignTransaction,
4647
},
48+
'express.lightning.initWallet': {
49+
post: PostLightningInitWallet,
50+
},
4751
});
4852

4953
export type ExpressApi = typeof ExpressApi;

modules/express/test/unit/clientRoutes/lightning/lightningSignerRoutes.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ describe('Lightning signer routes', () => {
7474
config: {
7575
lightningSignerFileSystemPath: 'lightningSignerFileSystemPath',
7676
},
77-
} as unknown as express.Request;
77+
decoded: {
78+
coin: 'tlnbtc',
79+
walletId: apiData.wallet.id,
80+
passphrase: apiData.initWalletRequestBody.passphrase,
81+
...(includingOptionalFields ? { expressHost: apiData.initWalletRequestBody.expressHost } : {}),
82+
},
83+
} as unknown as express.Request & { decoded: any };
7884

7985
await handleInitLightningWallet(req);
8086

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { EncryptRequestBody } from '../../../src/typedRoutes/api/common/encrypt'
55
import { LoginRequest } from '../../../src/typedRoutes/api/common/login';
66
import { VerifyAddressBody } from '../../../src/typedRoutes/api/common/verifyAddress';
77
import { SimpleCreateRequestBody } from '../../../src/typedRoutes/api/v1/simpleCreate';
8+
import {
9+
LightningInitWalletBody,
10+
LightningInitWalletParams,
11+
} from '../../../src/typedRoutes/api/v2/lightningInitWallet';
812

913
export function assertDecode<T>(codec: t.Type<T, unknown>, input: unknown): T {
1014
const result = codec.decode(input);
@@ -100,4 +104,22 @@ describe('io-ts decode tests', function () {
100104
passphrase: 'pass',
101105
});
102106
});
107+
it('express.lightning.initWallet params', function () {
108+
// missing walletId
109+
assert.throws(() => assertDecode(t.type(LightningInitWalletParams), { coin: 'ltc' }));
110+
// valid
111+
assertDecode(t.type(LightningInitWalletParams), { coin: 'ltc', walletId: 'wallet123' });
112+
});
113+
it('express.lightning.initWallet body', function () {
114+
// missing passphrase
115+
assert.throws(() => assertDecode(t.type(LightningInitWalletBody), {}));
116+
// passphrase must be string
117+
assert.throws(() => assertDecode(t.type(LightningInitWalletBody), { passphrase: 123 }));
118+
// expressHost optional and must be string if provided
119+
assert.throws(() => assertDecode(t.type(LightningInitWalletBody), { passphrase: 'p', expressHost: 99 }));
120+
// valid minimal
121+
assertDecode(t.type(LightningInitWalletBody), { passphrase: 'p' });
122+
// valid with expressHost
123+
assertDecode(t.type(LightningInitWalletBody), { passphrase: 'p', expressHost: 'host.example' });
124+
});
103125
});

0 commit comments

Comments
 (0)