OSDN Git Service

update the dapp development guide to v1.4.0
[bytom/Byone.git] / src / background.js
1 import { LocalStream } from 'extension-streams'
2 import InternalMessage from '@/messages/internal'
3 import * as MsgTypes from './messages/types'
4 import NotificationService from './services/NotificationService'
5 import StorageService from './services/StorageService'
6 import Prompt from './prompts/Prompt';
7 import * as PromptTypes from './prompts/PromptTypes'
8
9 import _ from 'lodash'
10 import Error from './utils/errors/Error'
11 import { BTM, camelize } from './utils/constants'
12
13 let prompt = null;
14
15 export default class Background {
16   constructor() {
17     this.setupInternalMessaging()
18   }
19
20   setupInternalMessaging() {
21     LocalStream.watch((request, sendResponse) => {
22       console.log(request)
23       const message = InternalMessage.fromJson(request)
24       this.dispatchMessage(sendResponse, message)
25     })
26   }
27
28   dispatchMessage(sendResponse, message) {
29     switch (message.type) {
30       case MsgTypes.SETCHAIN:
31         Background.setChain(sendResponse, message.payload)
32         break
33       case MsgTypes.TRANSFER:
34         this.transfer(sendResponse, message.payload)
35         break
36       case MsgTypes.ADVTRANSFER:
37         this.advancedTransfer(sendResponse, message.payload)
38         break
39       case MsgTypes.SEND:
40         this.send(sendResponse, message.payload)
41         break
42       case MsgTypes.SIGNTRANSACTION:
43         this.signTransaction(sendResponse, message.payload)
44         break
45       case MsgTypes.SIGNMESSAGE:
46         this.signMessage(sendResponse, message.payload)
47         break
48       case MsgTypes.REQUEST_CURRENT_ACCOUNT:
49         this.requestCurrentAccount(sendResponse, message.payload)
50         break
51       case MsgTypes.REQUEST_CURRENT_NETWORK:
52         this.requestCurrentNetwork(sendResponse)
53         break
54       case MsgTypes.REQUEST_CURRENT_CHAIN_TYPE:
55         this.requestCurrentChain(sendResponse)
56         break
57       case MsgTypes.ENABLE:
58         Background.authenticate(sendResponse, message.payload)
59         break
60       case MsgTypes.SET_PROMPT:
61         Background.setPrompt(sendResponse, message.payload);
62         break;
63       case MsgTypes.GET_PROMPT:
64         Background.getPrompt(sendResponse);
65         break;
66       case MsgTypes.LOAD:
67         Background.load(sendResponse);
68         break;
69       case MsgTypes.UPDATE:
70         Background.update(sendResponse, message.payload);
71         break;
72     }
73   }
74
75   static setPrompt(sendResponse, notification){
76     prompt = notification;
77     sendResponse(true);
78   }
79
80   static getPrompt(sendResponse){
81     sendResponse(prompt);
82   }
83
84   signMessage(sendResponse, payload) {
85     if(payload.address === undefined){
86       sendResponse(Error.typeMissed('address'));
87       return false;
88     }
89     if(payload.message === undefined){
90       sendResponse(Error.typeMissed('message'));
91       return false;
92     }
93
94     NotificationService.open(new Prompt(PromptTypes.REQUEST_SIGN, '', payload ,approved => {
95      sendResponse(camelize(approved));
96     }));
97   }
98
99   transfer(sendResponse, payload) {
100     var promptURL = chrome.extension.getURL('pages/prompt.html')
101     var requestBody = payload
102     requestBody.type = "popup"
103     var queryString = new URLSearchParams(requestBody).toString()
104     console.log(promptURL, queryString)
105
106     if(requestBody.from === undefined){
107       sendResponse(Error.typeMissed('from'));
108       return false;
109     }
110     if(requestBody.to === undefined){
111       sendResponse(Error.typeMissed('to'));
112       return false;
113     }
114     if(requestBody.asset === undefined){
115       sendResponse(Error.typeMissed('asset'));
116       return false;
117     }
118     if(requestBody.amount === undefined){
119       sendResponse(Error.typeMissed('amount'));
120       return false;
121     }
122
123     // NotificationService.open(new Prompt(PromptTypes.REQUEST_TRANSFER, '', payload ,approved => {
124     //   sendResponse(approved);
125     // }));
126
127       chrome.windows.create(
128       {
129         url: `${promptURL}#transfer?${queryString}`,
130         type: 'popup',
131         width: 360,
132         height: 623,
133         top: 0,
134         left: 0
135       },
136       (window) => {
137         chrome.runtime.onMessage.addListener(function(request, sender) {
138           if(sender.tab.windowId === window.id){
139             switch (request.method){
140               case 'transfer':
141                 if (request.action === 'success'){
142                   sendResponse(camelize(request.message));
143                   return true;
144                 } else if (request.action === 'reject'){
145                   sendResponse(request.message);
146                   return false;
147                 }
148             }
149           }
150         });
151
152         chrome.windows.onRemoved.addListener(function(windowId){
153           if(windowId === window.id) {
154             sendResponse(Error.promptClosedWithoutAction());
155             return false;
156           }
157         });
158       }
159     )
160   }
161
162   advancedTransfer(sendResponse, payload) {
163
164     if(payload.input === undefined){
165       sendResponse(Error.typeMissed('input'));
166       return false;
167     }
168     if(payload.output === undefined){
169       sendResponse(Error.typeMissed('output'));
170       return false;
171     }
172     if(payload.gas === undefined){
173       sendResponse(Error.typeMissed('gas'));
174       return false;
175     }
176
177     NotificationService.open(new Prompt(PromptTypes.REQUEST_ADVANCED_TRANSFER, '', payload ,approved => {
178       sendResponse(camelize(approved));
179     }));
180
181   }
182
183   signTransaction(sendResponse, payload) {
184     NotificationService.open(new Prompt(PromptTypes.REQUEST_SIGN_TRANSACTION, '', payload ,approved => {
185       sendResponse(camelize(approved));
186     }));
187   }
188
189   requestCurrentAccount(sendResponse, payload){
190     Background.load(bytom => {
191       const domain = payload.domain;
192       if(bytom.settings.domains.find(_domain => _domain === domain)) {
193         const currentAccount =  bytom.currentAccount
194         let account
195         if(bytom.settings.netType === 'vapor'){
196           let vote
197           const votes = currentAccount.votes
198           if(votes && votes.length >0 ){
199             vote = _.sumBy(votes,'total')
200           }
201
202           let balances = currentAccount.vpBalances ||[]
203           balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => {
204             if(keepAttrs.asset === BTM)
205               return {availableBalance: (keepAttrs.balance-vote),...keepAttrs}
206               else
207                 return keepAttrs
208           })
209
210           account = {
211             address: currentAccount.vpAddress,
212             alias:currentAccount.alias,
213             balances: balances|| [],
214             accountId: currentAccount.guid,
215             rootXPub: currentAccount.rootXPub
216           };
217         }else{
218           let balances = currentAccount.balances ||[]
219           balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => keepAttrs)
220
221           account ={
222             address: currentAccount.address,
223             alias:currentAccount.alias,
224             balances: balances|| [],
225             accountId: currentAccount.guid,
226             rootXPub: currentAccount.rootXPub
227           };
228         }
229
230         sendResponse(account)
231       } else{
232         sendResponse(null);
233         return false;
234       }
235     })
236
237   }
238
239   requestCurrentNetwork(sendResponse){
240     Background.load(bytom => {
241         sendResponse(bytom.settings.network);
242     })
243   }
244
245   requestCurrentChain(sendResponse){
246     Background.load(bytom => {
247       const chain = bytom.settings.netType ==='vapor'?'vapor':'bytom'
248       sendResponse(chain);
249     })
250   }
251
252   send(sendResponse, payload) {
253     const action = payload.action
254     if(action){
255       let promise
256       switch (action){
257         case 'listAllAccount':
258           promise = accountAction.list()
259           break
260       }
261       if(promise){
262         promise.then(resp =>
263         {
264           sendResponse(resp)
265         })
266       }
267     }
268   }
269
270   /***
271    * Returns the saved instance of Bytom from the storage
272    * @param sendResponse - Delegating response handler
273    * @returns {Bytom}
274    */
275   static load(sendResponse){
276     StorageService.get().then(bytom => {
277       sendResponse(bytom)
278     })
279   }
280
281   /***
282    * Updates the Scatter instance inside persistent storage
283    * @param sendResponse - Delegating response handler
284    * @param bytom - The updated cleartext Scatter instance
285    * @returns {boolean}
286    */
287   static update(sendResponse, bytom){
288     StorageService.save(bytom).then(saved => {
289       sendResponse(bytom)
290     })
291   }
292
293   static setChain(sendResponse, newNetType) {
294     Background.load(bytom => {
295       const currentNet = bytom.settings.netType
296
297       if( newNetType !== currentNet){
298         bytom.settings.netType = newNetType;
299         this.update(() => sendResponse({status:'success'}), bytom);
300       }else{
301         sendResponse(Error.duplicate(newNetType));
302       }
303     })
304   }
305
306   static authenticate(sendResponse, payload){
307     Background.load(bytom => {
308       const domain = payload.domain;
309       const currentAccount =  bytom.currentAccount
310
311       let account
312       if(bytom.settings.netType === 'vapor'){
313         let vote = 0
314         const votes = currentAccount.votes
315         if(votes && votes.length >0 ){
316           vote = _.sumBy(votes,'total')
317         }
318
319         let balances = currentAccount.vpBalances ||[]
320         balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => {
321           if(keepAttrs.asset === BTM)
322             return {availableBalance: (keepAttrs.balance-vote),...keepAttrs}
323           else
324             return keepAttrs
325         })
326
327         account ={
328           address: currentAccount.vpAddress,
329           alias:currentAccount.alias,
330           balances: balances || [],
331           accountId: currentAccount.guid,
332           rootXPub: currentAccount.rootXPub
333         };
334
335       }else{
336         let balances = currentAccount.balances ||[]
337         balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => keepAttrs)
338
339         account ={
340           address: currentAccount.address,
341           alias:currentAccount.alias,
342           balances: balances|| [],
343           accountId: currentAccount.guid,
344           rootXPub: currentAccount.rootXPub
345         };
346       }
347
348       if(bytom.settings.domains.find(_domain => _domain === domain)) {
349         sendResponse(account);
350       } else{
351         NotificationService.open(new Prompt(PromptTypes.REQUEST_AUTH, payload.domain, {}, approved => {
352           if(approved === false || approved.hasOwnProperty('isError')) sendResponse(approved);
353           else {
354             bytom.settings.domains.unshift(domain);
355             if(approved === true){
356               this.update(() => sendResponse(account), bytom);
357             }else{
358               this.update(() => sendResponse(approved), bytom);
359             }
360           }
361         }));
362       }
363     })
364   }
365
366
367 }
368
369 new Background()