Skip to content

Commit ed36f0a

Browse files
WIP: add base api-ts types
1 parent c7c2125 commit ed36f0a

File tree

8 files changed

+233
-126
lines changed

8 files changed

+233
-126
lines changed

cert.key

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCf49KqlyCwSPuS
3+
9g1lgarBY3yVAkeBdHxaoRHbdWSe3gq7OgkUD9bUnJyg8nZzXyYT3Dx+59J6kS4U
4+
i5eM/JcPMI6LHUWiwQWGg+LoFg+JY5DyRkiMrZrjbKt0N/nn7+MBIMMrZAJ8pWy+
5+
VmZBQ+LbKlnTQT6jdNh14MnSRc03QSfCjKnFPCuQ6elvuD2FT7syzegO5daZM1Bi
6+
F+omMSn9vb2wrGt3RxzJDNwIbx5SuBGqyiA0bWuPRYDVO/1caWbD4t17L0dqwwWP
7+
qLlOFv2xcTmGdB+PRcXM4ec4XgbTD8bcDxqtC4EzMnwnQ63fSrztYSUJ1AeFMEvN
8+
Afs/HkQVAgMBAAECggEAByEfOmSRPFMQxqmKiOFqhgOD4VgP7K2PQvJGK9E0+qF/
9+
fIA2ueqH44SVNlcBYZ0XQ1DxcJ4xJC53jcp4qDx2FuMNJBZazcpKDwiv9DXRnQhv
10+
xOHN59nw212z2nOJhOZNKrZ1hWiI9Npiei07k4LtqWSeyzzwSFUUNtNeZG4g26sN
11+
v5IDqKyIr+pKIQXGP9k2swqoMLKJeQR6ugjIpRERugJ4EJo92Bt5KmE/B5KcYX8g
12+
NvpsQAVlaPYit9sIKrupEsgSQW6/Y/Tt1KNagyd9ruabkmVOzC9Is8FRjPSc6WGg
13+
C31ZYPLDmzFSX1oPfRFkZchNS/NQttn2XreOvc4J+QKBgQDYfaF+6IagYFMAXuyh
14+
H4VI7VkrRxITcosDo2Q3nfVgvoKrZe2fuoL6VTetDKHQRXysZRoJetjnNt3dbe9g
15+
WTiZsGbGQIjoI1SS1I3QOGbUjP9VufEpkuRsj1CgnzVg8lQlfqK7SChG3aMrJmYF
16+
+ELtKqm5xUyjY0NJ3SzYLH+mTQKBgQC9EdKYrcfMol3rmcWyHNH0Rlg5WAv9Lwcc
17+
A5+OA7bSX24M4E1EHj3FNg7Vr/2UIBD0eSo11EO7ACl3u9vX7Lanljh6s+pCOHHy
18+
9HgsYraivu4zsXParRHhSSEdwDzUkjcBNxsht4d65uaV/33w3XhiqCIXbkMiJv3J
19+
Q29NInOI6QKBgDMADZ6HCsgXSRZqRlaCxXRzrbD7Ui/QqR0XTdGoXZkH6GKWZY9e
20+
ceKlVrNmqWwWIpO+UY7wKM73Zvb2IhFRk3rpSpzjsRz2zcK1Xh8yWk8yVCiO4FhJ
21+
6ZQFgxoDx6BqFharKYzzJ8HiDsFoj1pSrPmQNmG0MCTBiqWI/DqE6SF1AoGAM+oP
22+
5GJbKSIwHb/0W6q0L5mdIem+KP/fuN550hnM+ki/xANW0+xl05+7RQt02lZPsYEP
23+
iQZGrrMlr73CaLCTmsKRsYdzPEmZaDeeQ7m7IkbAyyrff9zjuvNEh5HAYjHfrpK9
24+
/W0SYznBeNBVeWymYJh/++UHw/nm13uPtSNPi/kCgYEAlRS9eEp+Y4Gx8mh/Dg3k
25+
mmrPvk+Fofxm52+BBmhPMREi3Xu/nc+oGoB2fe+1DLm4rg529ka4GfmjErsYJ1ip
26+
fg+TBM6j4D+W1pyPmPFTXjL16MGg0zYFcIcuaZBmD1WP1Ojz2uZt5WaPsapuXTi/
27+
rkA/bbzrGAE65dSaZDx58k0=
28+
-----END PRIVATE KEY-----

src/api.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ function masterExpressEnvConfig(): Partial<MasterExpressConfig> {
209209
timeout: Number(readEnvVar('BITGO_TIMEOUT')),
210210
keepAliveTimeout: Number(readEnvVar('BITGO_KEEP_ALIVE_TIMEOUT')),
211211
headersTimeout: Number(readEnvVar('BITGO_HEADERS_TIMEOUT')),
212-
// BitGo API settings
212+
// BitGo MasterExpressApi settings
213213
env: readEnvVar('BITGO_ENV') as EnvironmentName,
214214
customRootUri: readEnvVar('BITGO_CUSTOM_ROOT_URI'),
215215
enableSSL: readEnvVar('BITGO_ENABLE_SSL') !== 'false', // Default to true unless explicitly set to false

src/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export class EnclavedError extends Error {
1717
}
1818

1919
/**
20-
* Error for API responses
20+
* Error for MasterExpressApi responses
2121
*/
2222
export class ApiResponseError extends EnclavedError {
2323
public result: any;
Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
GenerateWalletOptions,
32
promiseProps,
43
RequestTracer,
54
SupplementGenerateWalletOptions,
@@ -8,42 +7,49 @@ import {
87
Wallet,
98
WalletWithKeychains,
109
AddKeychainOptions,
10+
BitGoBase,
11+
WalletData,
1112
} from '@bitgo/sdk-core';
1213
import { createEnclavedExpressClient } from './enclavedExpressClient';
13-
import _ from 'lodash';
14-
import { BitGoRequest } from '../types/request';
14+
import { BitGo } from 'bitgo';
15+
16+
export type GenerateWalletOnPremParams = {
17+
coin: string;
18+
label: string;
19+
enterprise?: string;
20+
multisigType?: string;
21+
isDistributedCustody?: boolean;
22+
};
1523

1624
/**
1725
* This route is used to generate a multisig wallet when enclaved express is enabled
1826
*/
19-
export async function handleGenerateWalletOnPrem(req: BitGoRequest) {
20-
const bitgo = req.bitgo;
21-
const baseCoin = bitgo.coin(req.params.coin);
22-
23-
const enclavedExpressClient = createEnclavedExpressClient(req.params.coin);
27+
export async function handleGenerateWalletOnPrem({
28+
bitGo,
29+
params,
30+
}: {
31+
bitGo: BitGo;
32+
params: GenerateWalletOnPremParams;
33+
}): Promise<WalletWithKeychains> {
34+
const baseCoin = bitGo.coin(params.coin);
35+
36+
const enclavedExpressClient = createEnclavedExpressClient(params.coin);
2437
if (!enclavedExpressClient) {
2538
throw new Error(
2639
'Enclaved express client not configured - enclaved express features will be disabled',
2740
);
2841
}
2942

30-
const params = req.body as GenerateWalletOptions;
3143
const reqId = new RequestTracer();
3244

3345
// Assign the default multiSig type value based on the coin
3446
if (!params.multisigType) {
3547
params.multisigType = baseCoin.getDefaultMultisigType();
3648
}
3749

38-
if (typeof params.label !== 'string') {
39-
throw new Error('missing required string parameter label');
40-
}
41-
42-
const { label, enterprise } = params;
43-
4450
// Create wallet parameters with type assertion to allow 'onprem' subtype
4551
const walletParams = {
46-
label: label,
52+
label: params.label,
4753
m: 2,
4854
n: 3,
4955
keys: [],
@@ -52,17 +58,10 @@ export async function handleGenerateWalletOnPrem(req: BitGoRequest) {
5258
multisigType: 'onchain',
5359
} as unknown as SupplementGenerateWalletOptions; // TODO: Add onprem to the SDK subType and remove "unknown" type casting
5460

55-
if (!_.isUndefined(enterprise)) {
56-
if (!_.isString(enterprise)) {
57-
throw new Error('invalid enterprise argument, expecting string');
58-
}
59-
walletParams.enterprise = enterprise;
60-
}
61-
6261
const userKeychainPromise = async (): Promise<Keychain> => {
6362
const userKeychain = await enclavedExpressClient.createIndependentKeychain({
6463
source: 'user',
65-
coin: req.params.coin,
64+
coin: params.coin,
6665
type: 'independent',
6766
});
6867
const userKeychainParams: AddKeychainOptions = {
@@ -73,13 +72,13 @@ export async function handleGenerateWalletOnPrem(req: BitGoRequest) {
7372
};
7473

7574
const newUserKeychain = await baseCoin.keychains().add(userKeychainParams);
76-
return _.extend({}, newUserKeychain, userKeychain);
75+
return { ...newUserKeychain, ...userKeychain };
7776
};
7877

7978
const backupKeychainPromise = async (): Promise<Keychain> => {
8079
const backupKeychain = await enclavedExpressClient.createIndependentKeychain({
8180
source: 'backup',
82-
coin: req.params.coin,
81+
coin: params.coin,
8382
type: 'independent',
8483
});
8584
const backupKeychainParams: AddKeychainOptions = {
@@ -90,7 +89,7 @@ export async function handleGenerateWalletOnPrem(req: BitGoRequest) {
9089
};
9190

9291
const newBackupKeychain = await baseCoin.keychains().add(backupKeychainParams);
93-
return _.extend({}, newBackupKeychain, backupKeychain);
92+
return { ...newBackupKeychain, ...backupKeychain };
9493
};
9594

9695
const { userKeychain, backupKeychain, bitgoKeychain }: KeychainsTriplet = await promiseProps({
@@ -113,16 +112,21 @@ export async function handleGenerateWalletOnPrem(req: BitGoRequest) {
113112

114113
const finalWalletParams = await baseCoin.supplementGenerateWallet(walletParams, keychains);
115114

116-
bitgo.setRequestTracer(reqId);
117-
const newWallet = await bitgo.post(baseCoin.url('/wallet/add')).send(finalWalletParams).result();
115+
bitGo.setRequestTracer(reqId);
116+
const wallet = await baseCoin.wallets().add({
117+
...finalWalletParams,
118+
enterprise: params.enterprise,
119+
reqId,
120+
isDistributedCustody: params.isDistributedCustody,
121+
});
118122

119-
const result: WalletWithKeychains = {
120-
wallet: new Wallet(bitgo, baseCoin, newWallet),
123+
const result = {
124+
wallet: wallet as WalletData,
121125
userKeychain: userKeychain,
122126
backupKeychain: backupKeychain,
123127
bitgoKeychain: bitgoKeychain,
124128
responseType: 'WalletWithKeychains',
125129
};
126130

127-
return { ...result, wallet: result.wallet.toJSON() };
131+
return result as unknown as WalletWithKeychains;
128132
}

src/masterExpressApi.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import * as t from 'io-ts';
2+
import * as h from '@api-ts/io-ts-http';
3+
4+
export const InternalErrorResponse = t.type({
5+
error: t.string,
6+
details: t.string,
7+
});
8+
9+
export const enclavedPingResponse = t.type({
10+
status: t.string,
11+
timeStamp: t.string,
12+
});
13+
export type EnclavedPingResponse = t.TypeOf<typeof enclavedPingResponse>;
14+
15+
export const PingEnclavedExpressRequest = h.httpRoute({
16+
path: '/ping/enclavedExpress',
17+
method: 'POST',
18+
request: h.httpRequest({}),
19+
response: {
20+
200: t.type({
21+
status: t.string,
22+
enclavedResponse: enclavedPingResponse,
23+
}),
24+
500: InternalErrorResponse,
25+
},
26+
});
27+
28+
// TODO: Fill out full response type
29+
export const WalletGenerateRequest = {
30+
label: t.string,
31+
enterprise: t.string,
32+
};
33+
34+
// TODO: Update response type
35+
export const WalletGenerateResponse = t.type({
36+
wallet: t.any,
37+
userKeychain: t.any,
38+
backupKeychain: t.any,
39+
bitgoKeychain: t.any,
40+
});
41+
42+
export const GenerateWalletRequest = h.httpRoute({
43+
path: '/api/{coin}/wallet/generate',
44+
method: 'POST',
45+
request: h.httpRequest({
46+
params: {
47+
coin: t.string,
48+
},
49+
headers: {
50+
authorization: t.union([t.string, t.undefined]),
51+
'user-agent': t.union([t.string, t.undefined]),
52+
},
53+
body: WalletGenerateRequest,
54+
}),
55+
response: {
56+
200: WalletGenerateResponse,
57+
400: InternalErrorResponse,
58+
500: InternalErrorResponse,
59+
},
60+
});
61+
62+
export const MasterExpressApi = h.apiSpec({
63+
'api.v1.pingEnclavedExpress': {
64+
post: PingEnclavedExpressRequest,
65+
},
66+
'api.v1.generateWallet': {
67+
post: GenerateWalletRequest,
68+
},
69+
});

0 commit comments

Comments
 (0)