OSDN Git Service

feat: support transfer for dapp
authormonky <monky@it709.com>
Sun, 6 Jan 2019 09:32:25 +0000 (17:32 +0800)
committermonky <monky@it709.com>
Sun, 6 Jan 2019 09:32:25 +0000 (17:32 +0800)
14 files changed:
src/assets/style.css
src/background.js
src/content.js
src/dapp.js [new file with mode: 0644]
src/inject.js
src/messages/event.js [new file with mode: 0644]
src/messages/internalTypes.js [deleted file]
src/messages/network.js
src/messages/networkTypes.js [deleted file]
src/messages/types.js [new file with mode: 0644]
src/prompt.js
src/views/home.vue
src/views/transfer.vue
src/views/transferConfirm.vue

index cede9a1..dad490c 100644 (file)
@@ -44,6 +44,7 @@ a {
   color: #fff;
   font-size: 18px;
   line-height: 25px;
+  height: 600px;
   overflow: hidden;
 }
 .warp {
@@ -187,7 +188,7 @@ hr {
 
 .mask {
   position: absolute;
-  height: 100%;
+  /* height: 100%; */
   width: 100%;
   z-index: 993;
   top: 0;
index da9f28a..4e844c8 100644 (file)
@@ -1,5 +1,6 @@
 import { LocalStream } from 'extension-streams'
 import InternalMessage from '@/messages/internal'
+import * as MsgTypes from './messages/types'
 
 export default class Background {
   constructor() {
@@ -17,36 +18,30 @@ export default class Background {
 
   dispatchMessage(sendResponse, message) {
     switch (message.type) {
-      case 'auth':
-        this.transfer()
+      case MsgTypes.TRANSFER:
+        this.transfer(sendResponse, message.payload)
         break
     }
   }
 
-  transfer(sendResponse) {
+  transfer(sendResponse, payload) {
     var promptURL = chrome.extension.getURL('pages/prompt.html')
-    console.log(promptURL)
-    chrome.tabs.query({ url: promptURL }, tabs => {
-      console.log(22, tabs)
-      chrome.windows.create(
-        {
-          url: `${promptURL}#transfer`,
-          type: 'popup',
-          width: 350,
-          height: 625,
-          left: 0
-        },
-        () => {
-          chrome.extension.sendMessage(
-            { cmd: '来自前台页面的主动调用' },
-            function(response) {
-              console.log(123, response)
-            }
-          ) //测试前台掉后台
-        }
-      )
-    })
+    var queryString = new URLSearchParams(payload).toString()
+    console.log(promptURL, queryString)
+    chrome.windows.create(
+      {
+        url: `${promptURL}#transfer?${queryString}`,
+        type: 'popup',
+        width: 350,
+        height: 623,
+        top: 0,
+        left: 0
+      },
+      () => {
+        sendResponse(true)
+      }
+    )
   }
 }
 
-const background = new Background()
+new Background()
index e6552d3..a78875d 100644 (file)
@@ -2,6 +2,8 @@ import { EncryptedStream, LocalStream } from 'extension-streams'
 import IdGenerator from '@/utils/IdGenerator'
 import NetworkMessage from '@/messages/network'
 import InternalMessage from '@/messages/internal'
+import * as MsgTypes from './messages/types'
+import * as EventNames from '@/messages/event'
 
 let stream = new WeakMap()
 let INJECTION_SCRIPT_FILENAME = 'js/inject.js'
@@ -9,11 +11,11 @@ let isReady = false
 
 class Content {
   constructor() {
-    this.setupInjectScript()
     this.setupEncryptedStream()
+    this.injectInteractionScript()
   }
 
-  setupInjectScript() {
+  injectInteractionScript() {
     let script = document.createElement('script')
     script.src = chrome.extension.getURL(INJECTION_SCRIPT_FILENAME)
     ;(document.head || document.documentElement).appendChild(script)
@@ -23,15 +25,20 @@ class Content {
   setupEncryptedStream() {
     console.log('stream listening...', IdGenerator.text(256))
 
-    stream = new EncryptedStream('bytom', IdGenerator.text(256))
+    stream = new EncryptedStream(EventNames.BYTOM, IdGenerator.text(256))
     stream.listenWith(msg => this.contentListener(msg))
 
     stream.onSync(() => {
       const version = this.getVersion()
       // const version = await this.getVersion();
       // const identity = await this.identityFromPermissions();
+
       // Pushing an instance of Scatterdapp to the web application
-      // stream.send(NetworkMessage.payload(NetworkMessageTypes.PUSH_SCATTER, {version, identity}), PairingTags.INJECTED);
+      stream.send(
+        NetworkMessage.payload(MsgTypes.PUSH_BYTOM, {}),
+        EventNames.INJECT
+      )
+
       // Dispatching the loaded event to the web application.
       isReady = true
 
@@ -39,10 +46,9 @@ class Content {
     })
   }
 
-  getVersion() {}
-
   contentListener(msg) {
-    console.log('event.data', msg)
+    console.log('content.stream.listen:', msg, stream.key)
+
     if (!isReady) return
     if (!msg) return
 
@@ -51,35 +57,38 @@ class Content {
       case 'sync':
         this.sync(msg)
         break
-      case 'auth':
-        this.authenticate(networkMessage)
+      case MsgTypes.TRANSFER:
+        this.transfer(networkMessage)
         break
-
       default:
+        stream.send(networkMessage.error('errtest'), EventNames.INJECT)
         break
     }
   }
 
+  getVersion() {}
+
   respond(message, payload) {
     if (!isReady) return
 
+    console.log(222, message, payload)
     const response =
       !payload || payload.hasOwnProperty('isError')
         ? message.error(payload)
         : message.respond(payload)
-    stream.send(response, 'injected')
+    stream.send(response, EventNames.INJECT)
   }
 
   sync(message) {
     stream.key = message.handshake.length ? message.handshake : null
-    stream.send({ type: 'sync' }, 'injected')
+    stream.send({ type: 'sync' }, EventNames.INJECT)
     stream.synced = true
   }
 
-  authenticate(message) {
+  transfer(message) {
     if (!isReady) return
 
-    InternalMessage.payload('auth', message.payload)
+    InternalMessage.payload(MsgTypes.TRANSFER, message.payload)
       .send()
       .then(res => this.respond(message, res))
   }
diff --git a/src/dapp.js b/src/dapp.js
new file mode 100644 (file)
index 0000000..6c01db9
--- /dev/null
@@ -0,0 +1,75 @@
+import NetworkMessage from '@/messages/network'
+import * as MsgTypes from './messages/types'
+import * as EventNames from '@/messages/event'
+import IdGenerator from '@/utils/IdGenerator'
+
+/***
+ * This is just a helper to manage resolving fake-async
+ * requests using browser messaging.
+ */
+class DanglingResolver {
+  constructor(_id, _resolve, _reject) {
+    this.id = _id
+    this.resolve = _resolve
+    this.reject = _reject
+  }
+}
+
+let stream = new WeakMap()
+let resolvers = new WeakMap()
+let currentVersion = new WeakMap()
+let requiredVersion = new WeakMap()
+
+/***
+ * Messages do not come back on the same thread.
+ * To accomplish a future promise structure this method
+ * catches all incoming messages and dispenses
+ * them to the open promises. */
+const _subscribe = () => {
+  stream.listenWith(msg => {
+    if (!msg || !msg.hasOwnProperty('type')) return false
+
+    for (let i = 0; i < resolvers.length; i++) {
+      if (resolvers[i].id === msg.resolver) {
+        if (msg.type === 'error') resolvers[i].reject(msg.payload)
+        else resolvers[i].resolve(msg.payload)
+        resolvers = resolvers.slice(i, 1)
+      }
+    }
+  })
+}
+
+/***
+ * Turns message sending between the application
+ * and the content script into async promises
+ * @param _type
+ * @param _payload
+ */
+const _send = (_type, _payload) => {
+  return new Promise((resolve, reject) => {
+    let id = IdGenerator.numeric(24)
+    let message = new NetworkMessage(_type, _payload, id)
+    resolvers.push(new DanglingResolver(id, resolve, reject))
+    stream.send(message, EventNames.BYTOM)
+  })
+}
+
+export default class Bytomdapp {
+  constructor(_stream, _options) {
+    currentVersion = parseFloat(_options.version)
+    // this.useIdentity(_options.identity)
+    stream = _stream
+    resolvers = []
+
+    // setupSigProviders(this)
+
+    _subscribe()
+  }
+
+  transfer(to, amount, fee) {
+    return _send(MsgTypes.TRANSFER, {
+      to: to,
+      amount: amount
+    })
+  }
+}
index b1dddf1..2590a91 100644 (file)
@@ -1,7 +1,8 @@
 import IdGenerator from '@/utils/IdGenerator'
 import { EncryptedStream } from 'extension-streams'
-// import * as PairingTags from './messages/PairingTags'
-// import * as NetworkMessageTypes from './messages/NetworkMessageTypes'
+import * as MsgTypes from './messages/types'
+import * as EventNames from '@/messages/event'
+import Bytomdapp from './dapp'
 
 /***
  * This is the javascript which gets injected into
@@ -11,19 +12,23 @@ import { EncryptedStream } from 'extension-streams'
 class Inject {
   constructor() {
     // Injecting an encrypted stream into the web application.
-    const stream = new EncryptedStream('inject', IdGenerator.text(64))
+    const stream = new EncryptedStream(EventNames.INJECT, IdGenerator.text(64))
 
     // Waiting for bytomExtension to push itself onto the application
     stream.listenWith(msg => {
-      console.log(1111, msg)
-      if (msg && msg.hasOwnProperty('type') && msg.type === 'scatter') {
+      console.log('inject.stream.listen:', msg)
+      if (
+        msg &&
+        msg.hasOwnProperty('type') &&
+        msg.type === MsgTypes.PUSH_BYTOM
+      ) {
+        window.bytom = new Bytomdapp(stream, msg.payload)
       }
-      // window.scatter = new Scatterdapp(stream, msg.payload)
     })
 
     // Syncing the streams between the extension and the web application
-    stream.sync('bytom', stream.key)
+    stream.sync(EventNames.BYTOM, stream.key)
   }
 }
 
-const inject = new Inject()
+new Inject()
diff --git a/src/messages/event.js b/src/messages/event.js
new file mode 100644 (file)
index 0000000..01cc7cb
--- /dev/null
@@ -0,0 +1,2 @@
+export const INJECT = 'bytom-inject-js'
+export const BYTOM = 'bytom-content-js'
diff --git a/src/messages/internalTypes.js b/src/messages/internalTypes.js
deleted file mode 100644 (file)
index 2247352..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export const AUTHENTICATE = 'authenticate'
index 3ce94ae..fb3f040 100644 (file)
@@ -1,4 +1,4 @@
-import * as NetworkMessageTypes from './NetworkTypes'
+import * as MessageTypes from './types'
 
 export default class NetworkMessage {
   constructor(_type = '', _payload = {}, _resolver = '', _domain = '') {
@@ -33,6 +33,6 @@ export default class NetworkMessage {
     return new NetworkMessage(this.type, payload, this.resolver)
   }
   error(payload) {
-    return new NetworkMessage(NetworkMessageTypes.ERROR, payload, this.resolver)
+    return new NetworkMessage(MessageTypes.ERROR, payload, this.resolver)
   }
 }
diff --git a/src/messages/networkTypes.js b/src/messages/networkTypes.js
deleted file mode 100644 (file)
index b96c264..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export const ERROR = 'error'
diff --git a/src/messages/types.js b/src/messages/types.js
new file mode 100644 (file)
index 0000000..3405e62
--- /dev/null
@@ -0,0 +1,5 @@
+export const ERROR = 'error'
+
+export const PUSH_BYTOM = 'pushBytom'
+export const AUTHENTICATE = 'authenticate'
+export const TRANSFER = 'transfer'
index 2614135..31e731e 100644 (file)
@@ -1,8 +1,11 @@
 import Vue from 'vue'
+import moment from 'moment'
 import VueI18n from 'vue-i18n'
 import VueRouter from 'vue-router'
 import Loading from 'vue-loading-overlay'
+import vuescroll from 'vuescroll/dist/vuescroll-native'
 import 'vue-loading-overlay/dist/vue-loading.css'
+import 'vuescroll/dist/vuescroll.css'
 
 import Routers from './router'
 import ViewBase from '@/views/viewBase'
@@ -18,10 +21,22 @@ const i18n = new VueI18n({
   messages
 })
 Vue.use(i18n)
+Vue.use(vuescroll)
 Vue.use(VueRouter)
 Vue.use(Loading)
 Vue.use(Dialog, i18n)
 Vue.component('v-select', vSelect)
+Vue.filter('moment', function(value, formatString) {
+  formatString = formatString || 'YYYY-MM-DD HH:mm:ss'
+  return moment(value * 1000).format(formatString)
+})
+Vue.prototype.$vuescrollConfig = {
+  mode: 'pure-native',
+  bar: {
+    keepShow: true,
+    background: '#c9c9c9'
+  }
+}
 
 const RouterConfig = {
   routes: Routers
index 2e97255..944ce03 100644 (file)
@@ -90,7 +90,8 @@
 }
 .transactions {
     font-size: 15px;
-    height: 275px;
+    height: 273px;
+    overflow: hidden;
 }
 .transactions .list {
     padding: 0 20px;
index ddd1fff..c2ceb51 100644 (file)
@@ -46,7 +46,7 @@
             <div class="balance">
                 <img src="@/assets/logo.png" class="token-icon">
                 <div class="token-amount">
-                    {{account.balance}}
+                    {{accountBalance}}
                     <span class="asset">BTM</span>
                 </div>
             </div>
@@ -124,14 +124,12 @@ export default {
             ],
             show: false,
             accounts: [],
-            unit: "",
             assets: {
                 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff: "BTM"
             },
             guid: null,
-            account: {
-                guid: ""
-            },
+            account: {},
+            accountBalance: 0.00,
             fee: this.$t("transfer.feeType"),
             feeTypeOptions: [this.$t("transfer.feeType")],
             transaction: {
@@ -143,6 +141,11 @@ export default {
             }
         };
     },
+    computed: {
+        unit() {
+            return this.assets[this.transaction.asset];
+        }
+    },
     watch: {
         selectAsset: function (val) {
             this.transaction.asset = val.assets;
@@ -152,6 +155,9 @@ export default {
                 this.transaction.cost = Number(ret.result.data.cny_price * newAmount).toFixed(2);
             });
         },
+        account: function (newAccount) {
+            this.guid = newAccount.guid;
+        },
         guid: function (newGuid) {
             this.accounts.forEach(account => {
                 if (account.guid == newGuid.guid) {
@@ -159,6 +165,12 @@ export default {
                     return;
                 }
             });
+
+            account.balance(newGuid).then(balance => {
+                this.accountBalance = balance;
+            }).catch(error => {
+                console.log(error);
+            });
         }
     },
     methods: {
@@ -200,17 +212,28 @@ export default {
             });
         }
     }, mounted() {
-        this.account = this.$route.params.account;
-        this.guid = this.account.guid;
-        this.unit = this.assets[this.transaction.asset];
+        if (this.$route.params.account != undefined) {
+            this.account = this.$route.params.account;
+        }
+
+        if (this.$route.query.to != undefined) {
+            this.transaction.to = this.$route.query.to
+        }
+        if (this.$route.query.amount != undefined) {
+            this.transaction.amount = this.$route.query.amount
+        }
 
+        account.setupNet(localStorage.bytomNet);
         account.list().then(accounts => {
             this.accounts = accounts;
             this.accounts.forEach(function (ele) {
                 ele.label = ele.alias
                 ele.value = ele.guid
             });
-            console.log(this.accounts)
+
+            if (Object.keys(this.account).length == 0) {
+                this.account = accounts[0]
+            }
         });
     }
 };
index 1354668..f69ad38 100644 (file)
@@ -13,6 +13,8 @@
 
 .content {
     padding: 25px 30px;
+    height: 480px;
+    overflow: hidden;
 }
 
 .ft {
@@ -91,7 +93,7 @@
                 <div class="col value">{{transaction.fee}}<span class="uint">BTM</span></div>
             </div>
 
-            <div class="divider" style="margin-top: 130px; margin-bottom: 10px;"></div>
+            <div class="divider" style="margin-top: 100px; margin-bottom: 10px;"></div>
             <div class="row" style="text-align: right;">
                 <div class="col label" style="line-height: 50px;">{{ $t('transfer.total') }}</div>
                 <div class="col value">