Skip to content

Commit 8cb0f2a

Browse files
feat(express): migrate getlightningstate to typed routes
2 parents e190bc0 + 6f89e61 commit 8cb0f2a

File tree

6 files changed

+71
-9
lines changed

6 files changed

+71
-9
lines changed

modules/express/src/clientRoutes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,7 @@ export function setupAPIRoutes(app: express.Application, config: Config): void {
15861586
);
15871587

15881588
router.post('express.v1.wallet.signTransaction', [prepareBitGo(config), typedPromiseWrapper(handleSignTransaction)]);
1589+
router.get('express.lightning.getState', [prepareBitGo(config), typedPromiseWrapper(handleGetLightningWalletState)]);
15891590

15901591
app.post('/api/v1/wallet/:id/simpleshare', parseBody, prepareBitGo(config), promiseWrapper(handleShareWallet));
15911592
router.post('express.v1.wallet.acceptShare', [prepareBitGo(config), typedPromiseWrapper(handleAcceptShare)]);
@@ -1787,5 +1788,4 @@ export function setupLightningSignerNodeRoutes(app: express.Application, config:
17871788
prepareBitGo(config),
17881789
promiseWrapper(handleCreateSignerMacaroon)
17891790
);
1790-
app.get('/api/v2/:coin/wallet/:id/state', prepareBitGo(config), promiseWrapper(handleGetLightningWalletState));
17911791
}

modules/express/src/lightning/lightningSignerRoutes.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,13 @@ export async function handleCreateSignerMacaroon(req: express.Request): Promise<
170170
/**
171171
* Handle the request to get the state of a wallet from the signer.
172172
*/
173-
export async function handleGetLightningWalletState(req: express.Request): Promise<GetWalletStateResponse> {
174-
const coinName = req.params.coin;
173+
export async function handleGetLightningWalletState(
174+
req: ExpressApiRouteRequest<'express.lightning.getState', 'get'>
175+
): Promise<GetWalletStateResponse> {
176+
const { coin: coinName, walletId } = req.decoded;
175177
if (!isLightningCoinName(coinName)) {
176178
throw new ApiResponseError(`Invalid coin to get lightning wallet state: ${coinName}`, 400);
177179
}
178-
const walletId = req.params.id;
179-
if (typeof walletId !== 'string') {
180-
throw new ApiResponseError(`Invalid wallet id: ${walletId}`, 400);
181-
}
182180

183181
const lndSignerClient = await LndSignerClient.create(walletId, req.config);
184182
return await lndSignerClient.getWalletState();

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { PostSimpleCreate } from './v1/simpleCreate';
1414
import { PutPendingApproval } from './v1/pendingApproval';
1515
import { PostSignTransaction } from './v1/signTransaction';
1616
import { PostKeychainLocal } from './v2/keychainLocal';
17+
import { GetLightningState } from './v2/lightningState';
1718
import { PostLightningInitWallet } from './v2/lightningInitWallet';
1819
import { PostUnlockLightningWallet } from './v2/unlockWallet';
1920
import { PostVerifyCoinAddress } from './v2/verifyAddress';
@@ -54,6 +55,9 @@ export const ExpressApi = apiSpec({
5455
'express.keychain.local': {
5556
post: PostKeychainLocal,
5657
},
58+
'express.lightning.getState': {
59+
get: GetLightningState,
60+
},
5761
'express.lightning.initWallet': {
5862
post: PostLightningInitWallet,
5963
},
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as t from 'io-ts';
2+
import { httpRoute, httpRequest } from '@api-ts/io-ts-http';
3+
import { BitgoExpressError } from '../../schemas/error';
4+
import { WalletState } from '../../../lightning/codecs';
5+
6+
/**
7+
* Path parameters for getting lightning node state
8+
*/
9+
export const LightningStateParams = {
10+
/** A lightning coin name (e.g., lnbtc or tlnbtc) */
11+
coin: t.string,
12+
/** The ID of the lightning self-custody wallet */
13+
walletId: t.string,
14+
} as const;
15+
16+
export const LightningStateResponse200 = t.type({
17+
state: WalletState,
18+
});
19+
20+
/**
21+
* Response for getting lightning node state
22+
*/
23+
export const LightningStateResponse = {
24+
/** Current Lightning wallet/node state('NON_EXISTING' | 'LOCKED' | 'UNLOCKED' | 'RPC_ACTIVE' | 'SERVER_ACTIVE' | 'WAITING_TO_START') */
25+
200: LightningStateResponse200,
26+
/** BitGo Express error payload when the request is invalid (e.g., invalid coin or wallet not a self-custody lightning wallet). */
27+
400: BitgoExpressError,
28+
} as const;
29+
30+
/**
31+
* Lightning - Get node state
32+
*
33+
* This is only used for self-custody lightning. Get the current state of the lightning node.
34+
*
35+
* @operationId express.lightning.getState
36+
*/
37+
export const GetLightningState = httpRoute({
38+
method: 'GET',
39+
path: '/api/v2/{coin}/wallet/{walletId}/state',
40+
request: httpRequest({
41+
params: LightningStateParams,
42+
}),
43+
response: LightningStateResponse,
44+
});

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from '../../../../src/lightning/lightningSignerRoutes';
1717
import { ExpressApiRouteRequest } from '../../../../src/typedRoutes/api';
1818
import { PostLightningInitWallet } from '../../../../src/typedRoutes/api/v2/lightningInitWallet';
19+
import { LightningStateResponse } from '../../../../src/typedRoutes/api/v2/lightningState';
1920

2021
describe('Lightning signer routes', () => {
2122
let bitgo: TestBitGoAPI;
@@ -165,13 +166,21 @@ describe('Lightning signer routes', () => {
165166
params: {
166167
coin: 'tlnbtc',
167168
id: apiData.wallet.id,
169+
walletId: apiData.wallet.id,
170+
},
171+
decoded: {
172+
coin: 'tlnbtc',
173+
walletId: apiData.wallet.id,
168174
},
169175
config: {
170176
lightningSignerFileSystemPath: 'lightningSignerFileSystemPath',
171177
},
172-
} as unknown as express.Request;
178+
} as unknown as ExpressApiRouteRequest<'express.lightning.getState', 'get'>;
173179

174-
await handleGetLightningWalletState(req);
180+
const res = await handleGetLightningWalletState(req);
181+
decodeOrElse('LightningStateResponse200', LightningStateResponse[200], res, () => {
182+
throw new Error('Response did not match expected codec');
183+
});
175184

176185
walletStateNock.done();
177186
readFileStub.calledOnceWith('lightningSignerFileSystemPath').should.be.true();

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { VerifyAddressBody } from '../../../src/typedRoutes/api/common/verifyAdd
77
import { VerifyAddressV2Body, VerifyAddressV2Params } from '../../../src/typedRoutes/api/v2/verifyAddress';
88
import { SimpleCreateRequestBody } from '../../../src/typedRoutes/api/v1/simpleCreate';
99
import { KeychainLocalRequestParams } from '../../../src/typedRoutes/api/v2/keychainLocal';
10+
import { LightningStateParams } from '../../../src/typedRoutes/api/v2/lightningState';
1011
import {
1112
LightningInitWalletBody,
1213
LightningInitWalletParams,
@@ -157,6 +158,12 @@ describe('io-ts decode tests', function () {
157158
coin: 'tbtc',
158159
});
159160
});
161+
it('express.lightning.getState params valid', function () {
162+
assertDecode(t.type(LightningStateParams), { coin: 'lnbtc', walletId: 'wallet123' });
163+
});
164+
it('express.lightning.getState params invalid', function () {
165+
assert.throws(() => assertDecode(t.type(LightningStateParams), { coin: 'lnbtc' }));
166+
});
160167
it('express.lightning.initWallet params', function () {
161168
// missing walletId
162169
assert.throws(() => assertDecode(t.type(LightningInitWalletParams), { coin: 'ltc' }));

0 commit comments

Comments
 (0)