Skip to content

Commit 6c9cab6

Browse files
authored
fix(express): simpleCreateV1 type codec
2 parents e9cadcd + 3f0faf7 commit 6c9cab6

File tree

2 files changed

+102
-32
lines changed

2 files changed

+102
-32
lines changed

modules/express/src/typedRoutes/api/v1/simpleCreate.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ export const SimpleCreateRequestBody = {
1919
disableKRSEmail: optional(t.boolean),
2020
};
2121

22+
export const SimpleCreateResponse = t.intersection([
23+
t.type({
24+
/** newly created wallet model object */
25+
wallet: t.UnknownRecord,
26+
/** the newly created user keychain, which has an encrypted xprv stored on BitGo */
27+
userKeychain: t.UnknownRecord,
28+
/** the newly created backup keychain */
29+
backupKeychain: t.UnknownRecord,
30+
/** the BitGo-managed keychain */
31+
bitgoKeychain: t.UnknownRecord,
32+
}),
33+
t.partial({
34+
/** warning message when backup keychain has xprv */
35+
warning: t.string,
36+
}),
37+
]);
38+
2239
/**
2340
* Create Wallet with Keychain
2441
* Create a new 2-of-3 wallet and it's associated keychains.
@@ -41,14 +58,7 @@ export const PostSimpleCreate = httpRoute({
4158
body: SimpleCreateRequestBody,
4259
}),
4360
response: {
44-
200: t.type({
45-
/** newly created wallet model object */
46-
wallet: t.string,
47-
/** the newly created user keychain, which has an encrypted xprv stored on BitGo */
48-
userKeychain: t.string,
49-
/** the newly created backup keychain */
50-
backupKeychain: t.string,
51-
}),
61+
200: SimpleCreateResponse,
5262
400: BitgoExpressError,
5363
},
5464
});

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

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as assert from 'assert';
22
import * as t from 'io-ts';
3-
import { SimpleCreateRequestBody, PostSimpleCreate } from '../../../src/typedRoutes/api/v1/simpleCreate';
3+
import {
4+
SimpleCreateRequestBody,
5+
SimpleCreateResponse,
6+
PostSimpleCreate,
7+
} from '../../../src/typedRoutes/api/v1/simpleCreate';
48
import { assertDecode } from './common';
59
import 'should';
610
import 'should-http';
@@ -68,37 +72,77 @@ describe('SimpleCreate codec tests', function () {
6872
});
6973

7074
describe('SimpleCreateResponse', function () {
71-
const SimpleCreateResponse = PostSimpleCreate.response[200];
75+
it('should validate response with all required fields as objects', function () {
76+
const validResponse = {
77+
wallet: {
78+
id: 'wallet_id_123',
79+
label: 'My Wallet',
80+
m: 2,
81+
n: 3,
82+
},
83+
userKeychain: {
84+
xpub: 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8',
85+
encryptedXprv: 'encrypted_xprv_data',
86+
},
87+
backupKeychain: {
88+
xpub: 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB',
89+
},
90+
bitgoKeychain: {
91+
xpub: 'xpub661MyMwAqRbcGU7FnXMKSHMwbWxARxYJUpKD1CoMJP6vonLT9bZZaWYq7A7tKPXmDFFXTKigT7VHMnbtEnjCmxQ1E93ZJe6HDKwxWD28M6f',
92+
isBitGo: true,
93+
},
94+
};
7295

73-
it('should validate response with all required fields', function () {
96+
const decoded = assertDecode(SimpleCreateResponse, validResponse);
97+
assert.deepStrictEqual(decoded.wallet, validResponse.wallet);
98+
assert.deepStrictEqual(decoded.userKeychain, validResponse.userKeychain);
99+
assert.deepStrictEqual(decoded.backupKeychain, validResponse.backupKeychain);
100+
assert.deepStrictEqual(decoded.bitgoKeychain, validResponse.bitgoKeychain);
101+
});
102+
103+
it('should validate response with optional warning field', function () {
74104
const validResponse = {
75-
wallet: 'wallet_id_123',
76-
userKeychain: 'user_keychain_123',
77-
backupKeychain: 'backup_keychain_123',
105+
wallet: { id: 'wallet_id_123' },
106+
userKeychain: { xpub: 'xpub123' },
107+
backupKeychain: { xpub: 'xpub456', xprv: 'xprv789' },
108+
bitgoKeychain: { xpub: 'xpub789' },
109+
warning: 'Be sure to backup the backup keychain -- it is not stored anywhere else!',
78110
};
79111

80112
const decoded = assertDecode(SimpleCreateResponse, validResponse);
81-
assert.strictEqual(decoded.wallet, validResponse.wallet);
82-
assert.strictEqual(decoded.userKeychain, validResponse.userKeychain);
83-
assert.strictEqual(decoded.backupKeychain, validResponse.backupKeychain);
113+
assert.strictEqual(decoded.warning, validResponse.warning);
84114
});
85115

86116
it('should reject response with missing wallet field', function () {
87117
const invalidResponse = {
88-
userKeychain: 'user_keychain_123',
89-
backupKeychain: 'backup_keychain_123',
118+
userKeychain: { xpub: 'xpub123' },
119+
backupKeychain: { xpub: 'xpub456' },
120+
bitgoKeychain: { xpub: 'xpub789' },
121+
};
122+
123+
assert.throws(() => {
124+
assertDecode(SimpleCreateResponse, invalidResponse);
125+
});
126+
});
127+
128+
it('should reject response with missing bitgoKeychain field', function () {
129+
const invalidResponse = {
130+
wallet: { id: 'wallet_id_123' },
131+
userKeychain: { xpub: 'xpub123' },
132+
backupKeychain: { xpub: 'xpub456' },
90133
};
91134

92135
assert.throws(() => {
93136
assertDecode(SimpleCreateResponse, invalidResponse);
94137
});
95138
});
96139

97-
it('should reject response with non-string fields', function () {
140+
it('should reject response with non-object fields', function () {
98141
const invalidResponse = {
99-
wallet: 123,
100-
userKeychain: 'user_keychain_123',
101-
backupKeychain: 'backup_keychain_123',
142+
wallet: 'not_an_object',
143+
userKeychain: { xpub: 'xpub123' },
144+
backupKeychain: { xpub: 'xpub456' },
145+
bitgoKeychain: { xpub: 'xpub789' },
102146
};
103147

104148
assert.throws(() => {
@@ -130,9 +174,24 @@ describe('SimpleCreate codec tests', function () {
130174
const agent = setupAgent();
131175

132176
const mockCreateWalletResponse = {
133-
wallet: 'wallet_id_123',
134-
userKeychain: 'user_keychain_123',
135-
backupKeychain: 'backup_keychain_123',
177+
wallet: {
178+
id: 'wallet_id_123',
179+
label: 'My Test Wallet',
180+
m: 2,
181+
n: 3,
182+
keychains: [{ xpub: 'xpub_user' }, { xpub: 'xpub_backup' }, { xpub: 'xpub_bitgo' }],
183+
},
184+
userKeychain: {
185+
xpub: 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8',
186+
encryptedXprv: 'encrypted_user_xprv',
187+
},
188+
backupKeychain: {
189+
xpub: 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB',
190+
},
191+
bitgoKeychain: {
192+
xpub: 'xpub661MyMwAqRbcGU7FnXMKSHMwbWxARxYJUpKD1CoMJP6vonLT9bZZaWYq7A7tKPXmDFFXTKigT7VHMnbtEnjCmxQ1E93ZJe6HDKwxWD28M6f',
193+
isBitGo: true,
194+
},
136195
};
137196

138197
afterEach(function () {
@@ -161,10 +220,11 @@ describe('SimpleCreate codec tests', function () {
161220
result.body.should.have.property('wallet');
162221
result.body.should.have.property('userKeychain');
163222
result.body.should.have.property('backupKeychain');
164-
assert.strictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
223+
result.body.should.have.property('bitgoKeychain');
224+
assert.deepStrictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
165225

166-
const decodedResponse = assertDecode(PostSimpleCreate.response[200], result.body);
167-
assert.strictEqual(decodedResponse.wallet, mockCreateWalletResponse.wallet);
226+
const decodedResponse = assertDecode(SimpleCreateResponse, result.body);
227+
assert.deepStrictEqual(decodedResponse.wallet, mockCreateWalletResponse.wallet);
168228

169229
sinon.assert.calledOnce(createWalletStub);
170230
sinon.assert.calledWith(createWalletStub, requestBody);
@@ -194,9 +254,9 @@ describe('SimpleCreate codec tests', function () {
194254
.send(requestBody);
195255

196256
assert.strictEqual(result.status, 200);
197-
assert.strictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
257+
assert.deepStrictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
198258

199-
const decodedResponse = assertDecode(PostSimpleCreate.response[200], result.body);
259+
const decodedResponse = assertDecode(SimpleCreateResponse, result.body);
200260
assert.ok(decodedResponse);
201261

202262
sinon.assert.calledOnce(createWalletStub);
@@ -224,7 +284,7 @@ describe('SimpleCreate codec tests', function () {
224284
.send(requestBody);
225285

226286
assert.strictEqual(result.status, 200);
227-
assert.strictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
287+
assert.deepStrictEqual(result.body.wallet, mockCreateWalletResponse.wallet);
228288

229289
sinon.assert.calledOnce(createWalletStub);
230290
sinon.assert.calledWith(createWalletStub, requestBody);

0 commit comments

Comments
 (0)