Skip to content

Commit d5f886c

Browse files
authored
Fix tests + schema for wallet/create endpoint (#5603)
1 parent 4596b89 commit d5f886c

File tree

3 files changed

+178
-58
lines changed

3 files changed

+178
-58
lines changed

ironfish/src/rpc/routes/wallet/create.test.slow.ts

Lines changed: 11 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { v4 as uuid } from 'uuid'
99
import { createRouteTest } from '../../../testUtilities/routeTest'
1010
import { RPC_ERROR_CODES } from '../../adapters'
1111
import { RpcRequestError } from '../../clients/errors'
12+
import { CreateAccountResponse } from './createAccount'
1213

13-
describe('Route wallet/createAccount', () => {
14+
describe('Route wallet/create', () => {
1415
jest.setTimeout(15000)
1516
const routeTest = createRouteTest()
1617

@@ -27,7 +28,8 @@ describe('Route wallet/createAccount', () => {
2728

2829
const name = uuid()
2930

30-
const response = await routeTest.client.wallet.createAccount({ name })
31+
const response = await routeTest.client.request(`wallet/create`, { name }).waitForEnd()
32+
3133
expect(response.status).toBe(200)
3234
expect(response.content).toMatchObject({
3335
name: name,
@@ -38,7 +40,7 @@ describe('Route wallet/createAccount', () => {
3840
const account = routeTest.node.wallet.getAccountByName(name)
3941
expect(account).toMatchObject({
4042
name: name,
41-
publicAddress: response.content.publicAddress,
43+
publicAddress: (response.content as CreateAccountResponse).publicAddress,
4244
createdAt: createdAtHead,
4345
})
4446
})
@@ -48,7 +50,8 @@ describe('Route wallet/createAccount', () => {
4850

4951
const name = uuid()
5052

51-
const response = await routeTest.client.wallet.createAccount({ name })
53+
const response = await routeTest.client.request(`wallet/create`, { name }).waitForEnd()
54+
5255
expect(response.content).toMatchObject({
5356
name: name,
5457
publicAddress: expect.any(String),
@@ -64,13 +67,13 @@ describe('Route wallet/createAccount', () => {
6467

6568
try {
6669
expect.assertions(2)
67-
await routeTest.client.wallet.createAccount({ name: name })
70+
await routeTest.client.request(`wallet/create`, { name }).waitForEnd()
6871
} catch (e: unknown) {
6972
if (!(e instanceof RpcRequestError)) {
7073
throw e
7174
}
7275
expect(e.status).toBe(400)
73-
expect(e.code).toBe(RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME)
76+
expect(e.code).toBe(RPC_ERROR_CODES.ACCOUNT_EXISTS)
7477
}
7578
})
7679

@@ -83,7 +86,8 @@ describe('Route wallet/createAccount', () => {
8386

8487
const name = uuid()
8588

86-
const response = await routeTest.client.wallet.createAccount({ name })
89+
const response = await routeTest.client.request(`wallet/create`, { name }).waitForEnd()
90+
8791
expect(response.status).toBe(200)
8892
expect(response.content).toMatchObject({
8993
name: name,
@@ -93,54 +97,4 @@ describe('Route wallet/createAccount', () => {
9397

9498
expect(scanSpy).toHaveBeenCalled()
9599
})
96-
97-
it('should set account createdAt if passed', async () => {
98-
const name = uuid()
99-
const createdAt = 10
100-
101-
const response = await routeTest.client.wallet.createAccount({
102-
name,
103-
createdAt,
104-
})
105-
106-
expect(response.status).toBe(200)
107-
expect(response.content).toMatchObject({
108-
name: name,
109-
publicAddress: expect.any(String),
110-
isDefaultAccount: true,
111-
})
112-
113-
const account = routeTest.node.wallet.getAccountByName(name)
114-
expect(account).toMatchObject({
115-
name: name,
116-
publicAddress: response.content.publicAddress,
117-
createdAt: {
118-
hash: Buffer.alloc(32, 0),
119-
sequence: 10,
120-
},
121-
})
122-
})
123-
124-
it('should set account createdAt to null', async () => {
125-
const name = uuid()
126-
127-
const response = await routeTest.client.wallet.createAccount({
128-
name,
129-
createdAt: null,
130-
})
131-
132-
expect(response.status).toBe(200)
133-
expect(response.content).toMatchObject({
134-
name: name,
135-
publicAddress: expect.any(String),
136-
isDefaultAccount: true,
137-
})
138-
139-
const account = routeTest.node.wallet.getAccountByName(name)
140-
expect(account).toMatchObject({
141-
name: name,
142-
publicAddress: response.content.publicAddress,
143-
createdAt: null,
144-
})
145-
})
146100
})

ironfish/src/rpc/routes/wallet/create.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,31 @@
88
* is the verbObject naming convention. For example, `POST /wallet/burnAsset` burns an asset.
99
*/
1010

11+
import * as yup from 'yup'
1112
import { RPC_ERROR_CODES, RpcValidationError } from '../../adapters'
1213
import { ApiNamespace } from '../namespaces'
1314
import { routes } from '../router'
1415
import { AssertHasRpcContext } from '../rpcContext'
15-
import { CreateAccountRequestSchema, CreateAccountResponse } from '../wallet'
16+
17+
type CreateAccountRequest = {
18+
name: string
19+
default?: boolean
20+
createdAt?: number | null
21+
}
22+
23+
type CreateAccountResponse = {
24+
name: string
25+
publicAddress: string
26+
isDefaultAccount: boolean
27+
}
28+
29+
const CreateAccountRequestSchema: yup.ObjectSchema<CreateAccountRequest> = yup
30+
.object({
31+
name: yup.string().defined(),
32+
default: yup.boolean().optional(),
33+
createdAt: yup.number().optional().nullable(),
34+
})
35+
.defined()
1636

1737
routes.register<typeof CreateAccountRequestSchema, CreateAccountResponse>(
1838
`${ApiNamespace.wallet}/create`,
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4+
5+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
6+
/* eslint-disable @typescript-eslint/no-explicit-any */
7+
8+
import { v4 as uuid } from 'uuid'
9+
import { createRouteTest } from '../../../testUtilities/routeTest'
10+
import { RPC_ERROR_CODES } from '../../adapters'
11+
import { RpcRequestError } from '../../clients/errors'
12+
13+
describe('Route wallet/createAccount', () => {
14+
jest.setTimeout(15000)
15+
const routeTest = createRouteTest()
16+
17+
beforeEach(() => {
18+
jest.spyOn(routeTest.node.wallet, 'scan').mockReturnValue(Promise.resolve(null))
19+
})
20+
21+
it('should create an account', async () => {
22+
await routeTest.node.wallet.createAccount('existingAccount', { setDefault: true })
23+
const createdAtHead = {
24+
hash: routeTest.node.chain.head.hash,
25+
sequence: routeTest.node.chain.head.sequence,
26+
}
27+
28+
const name = uuid()
29+
30+
const response = await routeTest.client.wallet.createAccount({ name })
31+
expect(response.status).toBe(200)
32+
expect(response.content).toMatchObject({
33+
name: name,
34+
publicAddress: expect.any(String),
35+
isDefaultAccount: false,
36+
})
37+
38+
const account = routeTest.node.wallet.getAccountByName(name)
39+
expect(account).toMatchObject({
40+
name: name,
41+
publicAddress: response.content.publicAddress,
42+
createdAt: createdAtHead,
43+
})
44+
})
45+
46+
it('should set the account as default', async () => {
47+
await routeTest.node.wallet.setDefaultAccount(null)
48+
49+
const name = uuid()
50+
51+
const response = await routeTest.client.wallet.createAccount({ name })
52+
expect(response.content).toMatchObject({
53+
name: name,
54+
publicAddress: expect.any(String),
55+
isDefaultAccount: true,
56+
})
57+
expect(routeTest.node.wallet.getDefaultAccount()?.name).toBe(name)
58+
})
59+
60+
it('should fail if name already exists', async () => {
61+
const name = uuid()
62+
63+
await routeTest.node.wallet.createAccount(name)
64+
65+
try {
66+
expect.assertions(2)
67+
await routeTest.client.wallet.createAccount({ name: name })
68+
} catch (e: unknown) {
69+
if (!(e instanceof RpcRequestError)) {
70+
throw e
71+
}
72+
expect(e.status).toBe(400)
73+
expect(e.code).toBe(RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME)
74+
}
75+
})
76+
77+
it('should start scanning transactions for the new account', async () => {
78+
const scanSpy = jest
79+
.spyOn(routeTest.node.wallet, 'scan')
80+
.mockReturnValue(Promise.resolve(null))
81+
82+
await routeTest.node.wallet.createAccount('existingAccount', { setDefault: true })
83+
84+
const name = uuid()
85+
86+
const response = await routeTest.client.wallet.createAccount({ name })
87+
expect(response.status).toBe(200)
88+
expect(response.content).toMatchObject({
89+
name: name,
90+
publicAddress: expect.any(String),
91+
isDefaultAccount: false,
92+
})
93+
94+
expect(scanSpy).toHaveBeenCalled()
95+
})
96+
97+
it('should set account createdAt if passed', async () => {
98+
const name = uuid()
99+
const createdAt = 10
100+
101+
const response = await routeTest.client.wallet.createAccount({
102+
name,
103+
createdAt,
104+
})
105+
106+
expect(response.status).toBe(200)
107+
expect(response.content).toMatchObject({
108+
name: name,
109+
publicAddress: expect.any(String),
110+
isDefaultAccount: true,
111+
})
112+
113+
const account = routeTest.node.wallet.getAccountByName(name)
114+
expect(account).toMatchObject({
115+
name: name,
116+
publicAddress: response.content.publicAddress,
117+
createdAt: {
118+
hash: Buffer.alloc(32, 0),
119+
sequence: 10,
120+
},
121+
})
122+
})
123+
124+
it('should set account createdAt to null', async () => {
125+
const name = uuid()
126+
127+
const response = await routeTest.client.wallet.createAccount({
128+
name,
129+
createdAt: null,
130+
})
131+
132+
expect(response.status).toBe(200)
133+
expect(response.content).toMatchObject({
134+
name: name,
135+
publicAddress: expect.any(String),
136+
isDefaultAccount: true,
137+
})
138+
139+
const account = routeTest.node.wallet.getAccountByName(name)
140+
expect(account).toMatchObject({
141+
name: name,
142+
publicAddress: response.content.publicAddress,
143+
createdAt: null,
144+
})
145+
})
146+
})

0 commit comments

Comments
 (0)