Skip to content

Commit 82c29fa

Browse files
authored
Assets controller (#18)
* assets controller tokens * Update PreferencesController no more tokens responsability * Update AssetsController handling collectibles * Update tests according to new AssetsController * Fix some lines on AssetsController * AssetsController using preferences selected address and assets getter * AssetsController tokens object with selected address as keys * AssetsController test tokens per account * AssetsController tokens by selected address respective test * AssetsController update new tokens when adding token * AssetsController add and remove collectibles per account * AssetsController assets per account and network * AssetsCOntroller minor documentation additions * AssetsController clean up * AssetsController clean up * AssetsController test update for private methods
1 parent 2a79085 commit 82c29fa

10 files changed

+600
-83
lines changed

package-lock.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"dependencies": {
7171
"await-semaphore": "^0.1.3",
7272
"eth-block-tracker": "git://github.com/metamask/eth-block-tracker.git#3.0.1-subscription-fix",
73+
"eth-contract-metadata": "github:estebanmino/eth-contract-metadata#master",
7374
"eth-json-rpc-infura": "^3.1.2",
7475
"eth-keyring-controller": "^4.0.0",
7576
"eth-phishing-detect": "^1.1.13",

src/AssetsController.test.ts

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import { stub } from 'sinon';
2+
import AssetsController from './AssetsController';
3+
import ComposableController from './ComposableController';
4+
import PreferencesController from './PreferencesController';
5+
import { NetworkController } from './NetworkController';
6+
7+
const TOKENS = [{ address: '0xfoO', symbol: 'bar', decimals: 2 }];
8+
const COLLECTIBLES = [{ address: '0xfoO', image: 'url', name: 'name', tokenId: 1234 }];
9+
10+
describe('AssetsController', () => {
11+
let assetsController: AssetsController;
12+
beforeEach(() => {
13+
assetsController = new AssetsController();
14+
});
15+
16+
it('should set default state', () => {
17+
expect(assetsController.state).toEqual({
18+
allCollectibles: {},
19+
allTokens: {},
20+
collectibles: [],
21+
tokens: []
22+
});
23+
});
24+
25+
it('should add token', () => {
26+
assetsController.addToken('foo', 'bar', 2);
27+
expect(assetsController.state.tokens[0]).toEqual({
28+
address: '0xfoO',
29+
decimals: 2,
30+
symbol: 'bar'
31+
});
32+
assetsController.addToken('foo', 'baz', 2);
33+
expect(assetsController.state.tokens[0]).toEqual({
34+
address: '0xfoO',
35+
decimals: 2,
36+
symbol: 'baz'
37+
});
38+
});
39+
40+
it('should add token by selected address', () => {
41+
const preferences = new PreferencesController();
42+
const network = new NetworkController();
43+
const firstAddress = '0x123';
44+
const secondAddress = '0x321';
45+
/* tslint:disable-next-line:no-unused-expression */
46+
new ComposableController([assetsController, network, preferences]);
47+
preferences.update({ selectedAddress: firstAddress });
48+
assetsController.addToken('foo', 'bar', 2);
49+
preferences.update({ selectedAddress: secondAddress });
50+
expect(assetsController.state.tokens.length).toEqual(0);
51+
preferences.update({ selectedAddress: firstAddress });
52+
expect(assetsController.state.tokens[0]).toEqual({
53+
address: '0xfoO',
54+
decimals: 2,
55+
symbol: 'bar'
56+
});
57+
});
58+
59+
it('should add token by provider type', () => {
60+
const preferences = new PreferencesController();
61+
const network = new NetworkController();
62+
const firstNetworkType = 'rinkeby';
63+
const secondNetworkType = 'ropsten';
64+
/* tslint:disable-next-line:no-unused-expression */
65+
new ComposableController([assetsController, network, preferences]);
66+
network.update({ provider: { type: firstNetworkType } });
67+
assetsController.addToken('foo', 'bar', 2);
68+
network.update({ provider: { type: secondNetworkType } });
69+
expect(assetsController.state.tokens.length).toEqual(0);
70+
network.update({ provider: { type: firstNetworkType } });
71+
expect(assetsController.state.tokens[0]).toEqual({
72+
address: '0xfoO',
73+
decimals: 2,
74+
symbol: 'bar'
75+
});
76+
});
77+
78+
it('should remove token', () => {
79+
assetsController.addToken('foo', 'bar', 2);
80+
assetsController.removeToken('0xfoO');
81+
expect(assetsController.state.tokens.length).toBe(0);
82+
});
83+
84+
it('should remove token by selected address', () => {
85+
const preferences = new PreferencesController();
86+
const network = new NetworkController();
87+
const firstAddress = '0x123';
88+
const secondAddress = '0x321';
89+
/* tslint:disable-next-line:no-unused-expression */
90+
new ComposableController([assetsController, network, preferences]);
91+
preferences.update({ selectedAddress: firstAddress });
92+
assetsController.addToken('fou', 'baz', 2);
93+
preferences.update({ selectedAddress: secondAddress });
94+
assetsController.addToken('foo', 'bar', 2);
95+
assetsController.removeToken('0xfoO');
96+
expect(assetsController.state.tokens.length).toEqual(0);
97+
preferences.update({ selectedAddress: firstAddress });
98+
expect(assetsController.state.tokens[0]).toEqual({
99+
address: '0xFOu',
100+
decimals: 2,
101+
symbol: 'baz'
102+
});
103+
});
104+
105+
it('should remove token by provider type', () => {
106+
const preferences = new PreferencesController();
107+
const network = new NetworkController();
108+
const firstNetworkType = 'rinkeby';
109+
const secondNetworkType = 'ropsten';
110+
/* tslint:disable-next-line:no-unused-expression */
111+
new ComposableController([assetsController, network, preferences]);
112+
network.update({ provider: { type: firstNetworkType } });
113+
assetsController.addToken('fou', 'baz', 2);
114+
network.update({ provider: { type: secondNetworkType } });
115+
assetsController.addToken('foo', 'bar', 2);
116+
assetsController.removeToken('0xfoO');
117+
expect(assetsController.state.tokens.length).toEqual(0);
118+
network.update({ provider: { type: firstNetworkType } });
119+
expect(assetsController.state.tokens[0]).toEqual({
120+
address: '0xFOu',
121+
decimals: 2,
122+
symbol: 'baz'
123+
});
124+
});
125+
126+
it('should add collectible', async () => {
127+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
128+
await assetsController.addCollectible('foo', 1234);
129+
expect(assetsController.state.collectibles[0]).toEqual({
130+
address: '0xfoO',
131+
image: 'url',
132+
name: 'name',
133+
tokenId: 1234
134+
});
135+
});
136+
137+
it('should add collectible by selected address', async () => {
138+
const preferences = new PreferencesController();
139+
const network = new NetworkController();
140+
const firstAddress = '0x123';
141+
const secondAddress = '0x321';
142+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
143+
/* tslint:disable-next-line:no-unused-expression */
144+
new ComposableController([assetsController, network, preferences]);
145+
preferences.update({ selectedAddress: firstAddress });
146+
await assetsController.addCollectible('foo', 1234);
147+
preferences.update({ selectedAddress: secondAddress });
148+
await assetsController.addCollectible('fou', 4321);
149+
preferences.update({ selectedAddress: firstAddress });
150+
expect(assetsController.state.collectibles[0]).toEqual({
151+
address: '0xfoO',
152+
image: 'url',
153+
name: 'name',
154+
tokenId: 1234
155+
});
156+
});
157+
158+
it('should add collectible by provider type', async () => {
159+
const preferences = new PreferencesController();
160+
const network = new NetworkController();
161+
const firstNetworkType = 'rinkeby';
162+
const secondNetworkType = 'ropsten';
163+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
164+
/* tslint:disable-next-line:no-unused-expression */
165+
new ComposableController([assetsController, network, preferences]);
166+
network.update({ provider: { type: firstNetworkType } });
167+
await assetsController.addCollectible('foo', 1234);
168+
network.update({ provider: { type: secondNetworkType } });
169+
expect(assetsController.state.collectibles.length).toEqual(0);
170+
network.update({ provider: { type: firstNetworkType } });
171+
expect(assetsController.state.collectibles[0]).toEqual({
172+
address: '0xfoO',
173+
image: 'url',
174+
name: 'name',
175+
tokenId: 1234
176+
});
177+
});
178+
179+
it('should remove collectible', () => {
180+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
181+
assetsController.addCollectible('0xfoO', 1234);
182+
assetsController.removeCollectible('0xfoO', 1234);
183+
expect(assetsController.state.collectibles.length).toBe(0);
184+
});
185+
186+
it('should remove collectible by selected address', async () => {
187+
const preferences = new PreferencesController();
188+
const network = new NetworkController();
189+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
190+
const firstAddress = '0x123';
191+
const secondAddress = '0x321';
192+
/* tslint:disable-next-line:no-unused-expression */
193+
new ComposableController([assetsController, network, preferences]);
194+
preferences.update({ selectedAddress: firstAddress });
195+
await assetsController.addCollectible('fou', 4321);
196+
preferences.update({ selectedAddress: secondAddress });
197+
await assetsController.addCollectible('foo', 1234);
198+
assetsController.removeCollectible('0xfoO', 1234);
199+
expect(assetsController.state.collectibles.length).toEqual(0);
200+
preferences.update({ selectedAddress: firstAddress });
201+
expect(assetsController.state.collectibles[0]).toEqual({
202+
address: '0xFOu',
203+
image: 'url',
204+
name: 'name',
205+
tokenId: 4321
206+
});
207+
});
208+
209+
it('should remove collectible by provider type', async () => {
210+
const preferences = new PreferencesController();
211+
const network = new NetworkController();
212+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
213+
const firstNetworkType = 'rinkeby';
214+
const secondNetworkType = 'ropsten';
215+
/* tslint:disable-next-line:no-unused-expression */
216+
new ComposableController([assetsController, network, preferences]);
217+
network.update({ provider: { type: firstNetworkType } });
218+
await assetsController.addCollectible('fou', 4321);
219+
network.update({ provider: { type: secondNetworkType } });
220+
await assetsController.addCollectible('foo', 1234);
221+
assetsController.removeToken('0xfoO');
222+
assetsController.removeCollectible('0xfoO', 1234);
223+
expect(assetsController.state.collectibles.length).toEqual(0);
224+
network.update({ provider: { type: firstNetworkType } });
225+
expect(assetsController.state.collectibles[0]).toEqual({
226+
address: '0xFOu',
227+
image: 'url',
228+
name: 'name',
229+
tokenId: 4321
230+
});
231+
});
232+
233+
it('should not add duplicated collectible', async () => {
234+
const func = stub(assetsController, 'requestNFTCustomInformation' as any).returns({
235+
image: 'url',
236+
name: 'name'
237+
});
238+
await assetsController.addCollectible('foo', 1234);
239+
await assetsController.addCollectible('foo', 1234);
240+
expect(assetsController.state.collectibles.length).toEqual(1);
241+
func.restore();
242+
});
243+
244+
it('should request collectible default data and handle on adding collectible', async () => {
245+
await assetsController.addCollectible('0x06012c8cf97BEaD5deAe237070F9587f8E7A266d', 740632);
246+
expect(assetsController.state.collectibles[0]).not.toEqual({
247+
address: '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d',
248+
image: '',
249+
name: '',
250+
tokenId: 740632
251+
});
252+
await assetsController.addCollectible('foo', 1);
253+
expect(assetsController.state.collectibles[1]).toEqual({
254+
address: '0xfoO',
255+
image: '',
256+
name: '',
257+
tokenId: 1
258+
});
259+
});
260+
261+
it('should subscribe to new sibling preference controllers', async () => {
262+
const preferences = new PreferencesController();
263+
const network = new NetworkController();
264+
const networkType = 'rinkeby';
265+
const address = '0x123';
266+
/* tslint:disable-next-line:no-unused-expression */
267+
new ComposableController([assetsController, network, preferences]);
268+
preferences.update({ selectedAddress: address });
269+
expect(assetsController.context.PreferencesController.state.selectedAddress).toEqual(address);
270+
network.update({ provider: { type: networkType } });
271+
expect(assetsController.context.NetworkController.state.provider.type).toEqual(networkType);
272+
});
273+
274+
it('should return correct assets state', async () => {
275+
stub(assetsController, 'requestNFTCustomInformation' as any).returns({ name: 'name', image: 'url' });
276+
await assetsController.addCollectible('foo', 1234);
277+
assetsController.addToken('foo', 'bar', 2);
278+
expect(assetsController.state.tokens).toEqual(TOKENS);
279+
expect(assetsController.state.collectibles).toEqual(COLLECTIBLES);
280+
});
281+
});

0 commit comments

Comments
 (0)