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'
10 import Error from './utils/errors/Error'
11 import { BTM, camelize } from './utils/constants'
15 export default class Background {
17 this.setupInternalMessaging()
20 setupInternalMessaging() {
21 LocalStream.watch((request, sendResponse) => {
23 const message = InternalMessage.fromJson(request)
24 this.dispatchMessage(sendResponse, message)
28 dispatchMessage(sendResponse, message) {
29 switch (message.type) {
30 case MsgTypes.SETCHAIN:
31 Background.setChain(sendResponse, message.payload)
33 case MsgTypes.TRANSFER:
34 this.transfer(sendResponse, message.payload)
36 case MsgTypes.ADVTRANSFER:
37 this.advancedTransfer(sendResponse, message.payload)
40 this.send(sendResponse, message.payload)
42 case MsgTypes.SIGNTRANSACTION:
43 this.signTransaction(sendResponse, message.payload)
45 case MsgTypes.SIGNMESSAGE:
46 this.signMessage(sendResponse, message.payload)
48 case MsgTypes.REQUEST_CURRENT_ACCOUNT:
49 this.requestCurrentAccount(sendResponse, message.payload)
51 case MsgTypes.REQUEST_CURRENT_NETWORK:
52 this.requestCurrentNetwork(sendResponse)
54 case MsgTypes.REQUEST_CURRENT_CHAIN_TYPE:
55 this.requestCurrentChain(sendResponse)
58 Background.authenticate(sendResponse, message.payload)
60 case MsgTypes.SET_PROMPT:
61 Background.setPrompt(sendResponse, message.payload);
63 case MsgTypes.GET_PROMPT:
64 Background.getPrompt(sendResponse);
67 Background.load(sendResponse);
70 Background.update(sendResponse, message.payload);
75 static setPrompt(sendResponse, notification){
76 prompt = notification;
80 static getPrompt(sendResponse){
84 signMessage(sendResponse, payload) {
85 if(payload.address === undefined){
86 sendResponse(Error.typeMissed('address'));
89 if(payload.message === undefined){
90 sendResponse(Error.typeMissed('message'));
94 NotificationService.open(new Prompt(PromptTypes.REQUEST_SIGN, '', payload ,approved => {
95 sendResponse(camelize(approved));
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)
106 if(requestBody.from === undefined){
107 sendResponse(Error.typeMissed('from'));
110 if(requestBody.to === undefined){
111 sendResponse(Error.typeMissed('to'));
114 if(requestBody.asset === undefined){
115 sendResponse(Error.typeMissed('asset'));
118 if(requestBody.amount === undefined){
119 sendResponse(Error.typeMissed('amount'));
123 // NotificationService.open(new Prompt(PromptTypes.REQUEST_TRANSFER, '', payload ,approved => {
124 // sendResponse(approved);
127 chrome.windows.create(
129 url: `${promptURL}#transfer?${queryString}`,
137 chrome.runtime.onMessage.addListener(function(request, sender) {
138 if(sender.tab.windowId === window.id){
139 switch (request.method){
141 if (request.action === 'success'){
142 sendResponse(camelize(request.message));
144 } else if (request.action === 'reject'){
145 sendResponse(request.message);
152 chrome.windows.onRemoved.addListener(function(windowId){
153 if(windowId === window.id) {
154 sendResponse(Error.promptClosedWithoutAction());
162 advancedTransfer(sendResponse, payload) {
164 if(payload.input === undefined){
165 sendResponse(Error.typeMissed('input'));
168 if(payload.output === undefined){
169 sendResponse(Error.typeMissed('output'));
172 if(payload.gas === undefined){
173 sendResponse(Error.typeMissed('gas'));
177 NotificationService.open(new Prompt(PromptTypes.REQUEST_ADVANCED_TRANSFER, '', payload ,approved => {
178 sendResponse(camelize(approved));
183 signTransaction(sendResponse, payload) {
184 NotificationService.open(new Prompt(PromptTypes.REQUEST_SIGN_TRANSACTION, '', payload ,approved => {
185 sendResponse(camelize(approved));
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
195 if(bytom.settings.netType === 'vapor'){
197 const votes = currentAccount.votes
198 if(votes && votes.length >0 ){
199 vote = _.sumBy(votes,'total')
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}
211 address: currentAccount.vpAddress,
212 alias:currentAccount.alias,
213 balances: balances|| [],
214 accountId: currentAccount.guid,
215 rootXPub: currentAccount.rootXPub
218 let balances = currentAccount.balances ||[]
219 balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => keepAttrs)
222 address: currentAccount.address,
223 alias:currentAccount.alias,
224 balances: balances|| [],
225 accountId: currentAccount.guid,
226 rootXPub: currentAccount.rootXPub
230 sendResponse(account)
239 requestCurrentNetwork(sendResponse){
240 Background.load(bytom => {
241 sendResponse(bytom.settings.network);
245 requestCurrentChain(sendResponse){
246 Background.load(bytom => {
247 const chain = bytom.settings.netType ==='vapor'?'vapor':'bytom'
252 send(sendResponse, payload) {
253 const action = payload.action
257 case 'listAllAccount':
258 promise = accountAction.list()
271 * Returns the saved instance of Bytom from the storage
272 * @param sendResponse - Delegating response handler
275 static load(sendResponse){
276 StorageService.get().then(bytom => {
282 * Updates the Scatter instance inside persistent storage
283 * @param sendResponse - Delegating response handler
284 * @param bytom - The updated cleartext Scatter instance
287 static update(sendResponse, bytom){
288 StorageService.save(bytom).then(saved => {
293 static setChain(sendResponse, newNetType) {
294 Background.load(bytom => {
295 const currentNet = bytom.settings.netType
297 if( newNetType !== currentNet){
298 bytom.settings.netType = newNetType;
299 this.update(() => sendResponse({status:'success'}), bytom);
301 sendResponse(Error.duplicate(newNetType));
306 static authenticate(sendResponse, payload){
307 Background.load(bytom => {
308 const domain = payload.domain;
309 const currentAccount = bytom.currentAccount
312 if(bytom.settings.netType === 'vapor'){
314 const votes = currentAccount.votes
315 if(votes && votes.length >0 ){
316 vote = _.sumBy(votes,'total')
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}
328 address: currentAccount.vpAddress,
329 alias:currentAccount.alias,
330 balances: balances || [],
331 accountId: currentAccount.guid,
332 rootXPub: currentAccount.rootXPub
336 let balances = currentAccount.balances ||[]
337 balances = balances.map(({ in_btc, in_cny, in_usd, name, ...keepAttrs}) => keepAttrs)
340 address: currentAccount.address,
341 alias:currentAccount.alias,
342 balances: balances|| [],
343 accountId: currentAccount.guid,
344 rootXPub: currentAccount.rootXPub
348 if(bytom.settings.domains.find(_domain => _domain === domain)) {
349 sendResponse(account);
351 NotificationService.open(new Prompt(PromptTypes.REQUEST_AUTH, payload.domain, {}, approved => {
352 if(approved === false || approved.hasOwnProperty('isError')) sendResponse(approved);
354 bytom.settings.domains.unshift(domain);
355 if(approved === true){
356 this.update(() => sendResponse(account), bytom);
358 this.update(() => sendResponse(approved), bytom);