color: #fff;
font-size: 18px;
line-height: 25px;
+ height: 600px;
overflow: hidden;
}
.warp {
.mask {
position: absolute;
- height: 100%;
+ /* height: 100%; */
width: 100%;
z-index: 993;
top: 0;
import { LocalStream } from 'extension-streams'
import InternalMessage from '@/messages/internal'
+import * as MsgTypes from './messages/types'
export default class Background {
constructor() {
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()
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'
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)
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
})
}
- getVersion() {}
-
contentListener(msg) {
- console.log('event.data', msg)
+ console.log('content.stream.listen:', msg, stream.key)
+
if (!isReady) return
if (!msg) return
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))
}
--- /dev/null
+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
+ })
+ }
+}
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
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()
--- /dev/null
+export const INJECT = 'bytom-inject-js'
+export const BYTOM = 'bytom-content-js'
+++ /dev/null
-export const AUTHENTICATE = 'authenticate'
-import * as NetworkMessageTypes from './NetworkTypes'
+import * as MessageTypes from './types'
export default class NetworkMessage {
constructor(_type = '', _payload = {}, _resolver = '', _domain = '') {
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)
}
}
+++ /dev/null
-export const ERROR = 'error'
--- /dev/null
+export const ERROR = 'error'
+
+export const PUSH_BYTOM = 'pushBytom'
+export const AUTHENTICATE = 'authenticate'
+export const TRANSFER = 'transfer'
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'
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
}
.transactions {
font-size: 15px;
- height: 275px;
+ height: 273px;
+ overflow: hidden;
}
.transactions .list {
padding: 0 20px;
<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>
],
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: {
}
};
},
+ computed: {
+ unit() {
+ return this.assets[this.transaction.asset];
+ }
+ },
watch: {
selectAsset: function (val) {
this.transaction.asset = val.assets;
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) {
return;
}
});
+
+ account.balance(newGuid).then(balance => {
+ this.accountBalance = balance;
+ }).catch(error => {
+ console.log(error);
+ });
}
},
methods: {
});
}
}, 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]
+ }
});
}
};
.content {
padding: 25px 30px;
+ height: 480px;
+ overflow: hidden;
}
.ft {
<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">