Skip to content

Commit 3cb0dc2

Browse files
feat(mbe): use generated client for type safety
Ticket: WP-000000
1 parent d09b586 commit 3cb0dc2

File tree

13 files changed

+313
-211
lines changed

13 files changed

+313
-211
lines changed

masterBitgoExpress.json

Lines changed: 107 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,23 @@
264264
}
265265
},
266266
"/ping": {
267+
"post": {
268+
"parameters": [],
269+
"responses": {
270+
"200": {
271+
"description": "OK",
272+
"content": {
273+
"application/json": {
274+
"schema": {
275+
"$ref": "#/components/schemas/PingResponseType"
276+
}
277+
}
278+
}
279+
}
280+
}
281+
}
282+
},
283+
"/ping/enclavedExpress": {
267284
"post": {
268285
"parameters": [],
269286
"responses": {
@@ -277,13 +294,35 @@
277294
"status": {
278295
"type": "string"
279296
},
280-
"timestamp": {
281-
"type": "string"
297+
"enclavedResponse": {
298+
"$ref": "#/components/schemas/PingResponseType"
282299
}
283300
},
284301
"required": [
285302
"status",
286-
"timestamp"
303+
"enclavedResponse"
304+
]
305+
}
306+
}
307+
}
308+
},
309+
"500": {
310+
"description": "Internal Server Error",
311+
"content": {
312+
"application/json": {
313+
"schema": {
314+
"type": "object",
315+
"properties": {
316+
"error": {
317+
"type": "string"
318+
},
319+
"details": {
320+
"type": "string"
321+
}
322+
},
323+
"required": [
324+
"error",
325+
"details"
287326
]
288327
}
289328
}
@@ -298,21 +337,48 @@
298337
"responses": {
299338
"200": {
300339
"description": "OK",
340+
"content": {
341+
"application/json": {
342+
"schema": {
343+
"$ref": "#/components/schemas/VersionResponseType"
344+
}
345+
}
346+
}
347+
}
348+
}
349+
}
350+
},
351+
"/version/enclavedExpress": {
352+
"get": {
353+
"parameters": [],
354+
"responses": {
355+
"200": {
356+
"description": "OK",
357+
"content": {
358+
"application/json": {
359+
"schema": {
360+
"$ref": "#/components/schemas/VersionResponseType"
361+
}
362+
}
363+
}
364+
},
365+
"500": {
366+
"description": "Internal Server Error",
301367
"content": {
302368
"application/json": {
303369
"schema": {
304370
"type": "object",
305371
"properties": {
306-
"version": {
372+
"error": {
307373
"type": "string"
308374
},
309-
"name": {
375+
"details": {
310376
"type": "string"
311377
}
312378
},
313379
"required": [
314-
"version",
315-
"name"
380+
"error",
381+
"details"
316382
]
317383
}
318384
}
@@ -323,6 +389,39 @@
323389
}
324390
},
325391
"components": {
326-
"schemas": {}
392+
"schemas": {
393+
"VersionResponseType": {
394+
"title": "VersionResponseType",
395+
"type": "object",
396+
"properties": {
397+
"version": {
398+
"type": "string"
399+
},
400+
"name": {
401+
"type": "string"
402+
}
403+
},
404+
"required": [
405+
"version",
406+
"name"
407+
]
408+
},
409+
"PingResponseType": {
410+
"title": "PingResponseType",
411+
"type": "object",
412+
"properties": {
413+
"status": {
414+
"type": "string"
415+
},
416+
"timestamp": {
417+
"type": "string"
418+
}
419+
},
420+
"required": [
421+
"status",
422+
"timestamp"
423+
]
424+
}
425+
}
327426
}
328427
}

src/__tests__/masterBitgoExpress/generateWallet.test.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import nock from 'nock';
55
import { app as expressApp } from '../../masterExpressApp';
66
import { AppMode, MasterExpressConfig, TlsMode } from '../../types';
77
import { Environments } from '@bitgo/sdk-core';
8+
import assert from 'assert';
89

910
describe('POST /api/:coin/wallet/generate', () => {
1011
let agent: request.SuperAgentTest;
@@ -45,8 +46,6 @@ describe('POST /api/:coin/wallet/generate', () => {
4546
const userKeychainNock = nock(enclavedExpressUrl)
4647
.post(`/api/${coin}/key/independent`, {
4748
source: 'user',
48-
coin: coin,
49-
type: 'independent',
5049
})
5150
.reply(200, {
5251
pub: 'xpub_user',
@@ -57,8 +56,6 @@ describe('POST /api/:coin/wallet/generate', () => {
5756
const backupKeychainNock = nock(enclavedExpressUrl)
5857
.post(`/api/${coin}/key/independent`, {
5958
source: 'backup',
60-
coin: coin,
61-
type: 'independent',
6259
})
6360
.reply(200, {
6461
pub: 'xpub_backup',
@@ -155,18 +152,11 @@ describe('POST /api/:coin/wallet/generate', () => {
155152
allowSelfSigned: true,
156153
};
157154

158-
const app = expressApp(invalidConfig as MasterExpressConfig);
159-
const testAgent = request.agent(app);
160-
161-
const response = await testAgent
162-
.post(`/api/${coin}/wallet/generate`)
163-
.set('Authorization', `Bearer ${accessToken}`)
164-
.send({
165-
label: 'test-wallet',
166-
});
167-
168-
response.status.should.equal(500);
169-
response.body.should.have.property('error');
170-
response.body.error.should.equal('Please configure enclaved express configs.');
155+
try {
156+
expressApp(invalidConfig as MasterExpressConfig);
157+
assert(false, 'Expected error to be thrown when enclaved express client is not configured');
158+
} catch (e) {
159+
(e as Error).message.should.equal('enclavedExpressUrl and enclavedExpressCert are required');
160+
}
171161
});
172162
});

src/__tests__/masterBitgoExpress/sendMany.test.ts

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { app as expressApp } from '../../masterExpressApp';
77
import { AppMode, MasterExpressConfig, TlsMode } from '../../types';
88
import { Environments, Wallet } from '@bitgo/sdk-core';
99
import { Coin } from 'bitgo';
10+
import assert from 'assert';
1011

1112
describe('POST /api/:coin/wallet/:walletId/sendmany', () => {
1213
let agent: request.SuperAgentTest;
@@ -277,26 +278,14 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => {
277278
allowSelfSigned: true,
278279
};
279280

280-
const app = expressApp(invalidConfig as MasterExpressConfig);
281-
const testAgent = request.agent(app);
282-
283-
const response = await testAgent
284-
.post(`/api/${coin}/wallet/${walletId}/sendMany`)
285-
.set('Authorization', `Bearer ${accessToken}`)
286-
.send({
287-
recipients: [
288-
{
289-
address: 'tb1qtest1',
290-
amount: '100000',
291-
},
292-
],
293-
source: 'user',
294-
pubkey: 'xpub_user',
295-
});
296-
297-
response.status.should.equal(500);
298-
response.body.should.have.property('error');
299-
response.body.error.should.equal('Please configure enclaved express configs.');
281+
try {
282+
expressApp(invalidConfig as MasterExpressConfig);
283+
assert(false, 'Expected error to be thrown when enclaved express client is not configured');
284+
} catch (error) {
285+
(error as Error).message.should.equal(
286+
'enclavedExpressUrl and enclavedExpressCert are required',
287+
);
288+
}
300289
});
301290

302291
it('should fail when transaction verification returns false', async () => {

src/enclavedBitgoExpress/routers/enclavedApiSpec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export const EnclavedAPiSpec = apiSpec({
8484
'v1.multisig.sign': {
8585
post: httpRoute({
8686
method: 'POST',
87-
path: '/{coin}/multisig/sign',
87+
path: '/api/{coin}/multisig/sign',
8888
request: httpRequest({
8989
params: {
9090
coin: t.string,
@@ -98,7 +98,7 @@ export const EnclavedAPiSpec = apiSpec({
9898
'v1.multisig.recovery': {
9999
post: httpRoute({
100100
method: 'POST',
101-
path: '/{coin}/multisig/recovery',
101+
path: '/api/{coin}/multisig/recovery',
102102
request: httpRequest({
103103
params: {
104104
coin: t.string,
@@ -112,7 +112,7 @@ export const EnclavedAPiSpec = apiSpec({
112112
'v1.key.independent': {
113113
post: httpRoute({
114114
method: 'POST',
115-
path: '/{coin}/key/independent',
115+
path: '/api/{coin}/key/independent',
116116
request: httpRequest({
117117
params: {
118118
coin: t.string,

src/enclavedBitgoExpress/routers/healthCheck.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
1-
import * as t from 'io-ts';
21
import { apiSpec, httpRoute, httpRequest, HttpResponse } from '@api-ts/io-ts-http';
32
import { createRouter, type WrappedRouter } from '@api-ts/typed-express-router';
43
import { Response } from '@api-ts/response';
54
import pjson from '../../../package.json';
65
import { responseHandler } from '../../shared/middleware';
6+
import { PingResponseType, VersionResponseType } from '../../types/health';
77

8-
// Response type for /ping endpoint
8+
// API Response types
99
const PingResponse: HttpResponse = {
10-
200: t.type({
11-
status: t.string,
12-
timestamp: t.string,
13-
}),
10+
200: PingResponseType,
1411
};
1512

16-
// Response type for /version endpoint
1713
const VersionResponse: HttpResponse = {
18-
200: t.type({
19-
version: t.string,
20-
name: t.string,
21-
}),
14+
200: VersionResponseType,
2215
};
2316

2417
// API Specification
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { EnclavedAPiSpec as ApiSpec } from './enclavedApiSpec';
2+
import { HealthCheckApiSpec } from './healthCheck';
3+
4+
export const EnclavedApiSpec = {
5+
...HealthCheckApiSpec,
6+
...ApiSpec,
7+
};
8+
export type EnclavedApiSpec = typeof EnclavedApiSpec;

0 commit comments

Comments
 (0)