1 <style lang="scss" scoped>
12 justify-content: center;
15 color: rgba(0, 0, 0, 0.88);
25 border: 1px solid #EBEBEB;
29 word-break: break-all;
33 color: rgba(0, 0, 0, 0.64);
39 letter-spacing: 0.2px;
75 justify-content: space-between;
85 -webkit-border-radius: 16px;
86 -moz-border-radius: 16px;
91 justify-content: center;
93 text-transform: uppercase;
108 text-overflow: ellipsis;
119 .iconfont.icon_arrow_2 {
120 transform: rotate(90deg);
128 justify-content: space-between;
139 word-break: break-all;
140 white-space: pre-wrap;
141 white-space: -moz-pre-wrap;
142 white-space: -pre-wrap;
143 white-space: -o-pre-wrap;
144 word-wrap: break-word;
156 <section class="header">
157 <h1 v-if="prompt.data && prompt.data.type ==='signTransaction'" >{{ $t('transfer.signComfirm') }}</h1>
158 <h1 v-else-if="prompt.data && prompt.data.type ==='message'" >{{ $t('transfer.signMessage') }}</h1>
159 <h1 v-else>{{ $t('transfer.confirmTransaction') }}</h1>
162 <section v-if="dataReady">
163 <div class="tab-group">
164 <a :class="{'color-black font-bold': tab === 'details'}" v-on:click="tab = 'details'">{{ $t('transfer.detail')
166 <a :class="{'color-black font-bold': tab === 'inout'}" v-on:click="tab = 'inout'">{{ $t('transfer.requestDetail')
170 <div v-if="tab ==='details'" class="content">
175 <img class="logo" src="@/assets/logo.png" alt="">
177 <div class="col value">
178 <div v-if="currentWallet && currentWallet.alias" class="wallet color-black">{{currentWallet.alias}}</div>
179 <div>{{shortAddress}}</div>
184 <i class="iconfont icon_arrow_2"></i>
186 <div class="col divider"></div>
191 <img v-if="prompt.domain && domainsMeta[prompt.domain] && domainsMeta[prompt.domain].icon" class="logo"
192 :src="domainsMeta[prompt.domain].icon" alt="">
193 <div v-else-if="initial" class="logo">
198 <div class="col value">
199 <span class="color-black"
200 v-if="prompt.domain && domainsMeta[prompt.domain] && domainsMeta[prompt.domain].title ">{{domainsMeta[prompt.domain].title }}</span>
201 <span class="color-black" v-else-if="prompt.domain ">{{prompt.domain }}</span>
203 <div v-if="transaction.to">{{short(transaction.to)}}</div>
208 <!--transaction types-->
209 <div v-if="prompt.data && prompt.data.type ==='signTransaction'" class="amount-list">
210 <div >{{ $t('transfer.types') }}</div>
211 <div class="color-black font-bold">{{transaction.types}}</div>
215 <div v-if="prompt.data && prompt.data.type ==='message'" class="amount-list">
216 <div style="min-width: 78px;" >{{ $t('signMessage.message') }}</div>
217 <div class="color-black font-bold">{{transaction.message}}</div>
221 <div v-if="prompt.data && prompt.data.type ==='transfer'" class="amount-list">
222 <div>{{ $t('transfer.amount') }}</div>
223 <div class="color-black font-bold">{{transaction.amount}}<span class="uint uppercase">{{unit || short(transaction.asset) }}</span>
226 <div v-else v-for="(amountInput, index) in transaction.amounts" :key="index" class="amount-list">
227 <div>{{index ==0 && $t('transfer.amount') }}</div>
228 <div class="color-black font-bold">{{amountInput.amount}}<span class="uint uppercase">{{amountInput.alias || short(amountInput.asset) }}</span>
233 <div v-if="transaction.fee" class="amount-list">
234 <div>{{ $t('transfer.fee') }}</div>
235 <div class="color-black font-bold">{{transaction.fee}}<span class="uint">BTM</span></div>
239 <div v-if="tab ==='inout'" class="content content-black">
240 <pre>{{detail}}</pre>
244 <div class="form-item">
245 <div class="form-item-content">
246 <input type="password" :placeholder="$t('transfer.password')" v-model="password" ref="password" autofocus>
251 <div class="btn btn-primary btn-round float-right" @click="transfer"><i class="iconfont icon-right-arrow"></i></div>
266 import transaction from "@/models/transaction";
267 import getLang from "@/assets/language/sdk";
268 import {apis} from '@/utils/BrowserApis';
269 import NotificationService from '../../services/NotificationService'
270 import {mapActions, mapGetters, mapState} from 'vuex'
271 import _ from 'lodash';
272 import account from "@/models/account";
273 import add from "@/utils/address";
274 import { camelize, removeFromArray } from "@/utils/utils";
275 import bytomjslib from 'bytomjs-lib'
294 if (this.prompt && this.prompt.data && this.prompt.data.title) {
295 return this.prompt.data.title.substring(0, 1)
296 } else if (this.prompt && this.prompt.domain) {
297 return this.prompt.domain.substring(0, 1)
300 address: function () {
301 if (this.netType === 'vapor') {
302 return this.currentAccount.vpAddress
304 return this.currentAccount.address
307 shortAddress: function () {
308 if(this.prompt.data && this.prompt.data.type ==='transfer') {
309 return add.short(this.transaction.from);
310 }else if(this.prompt.data && this.prompt.data.type ==='message'){
311 return add.short(this.transaction.address);
313 if (this.netType === 'vapor') {
314 return add.short(this.currentAccount.vpAddress);
316 return add.short(this.currentAccount.address);
321 if(this.prompt.data && this.prompt.data.type ==='signTransaction'){
322 const param = this.prompt.data[0] || this.prompt.data
323 const _tx = camelize(param)
324 const { rawTransaction, signingInstructions } = _tx
326 tx: this.transaction,
330 return JSON.stringify(obj, null, 2);
331 }else if(this.prompt.data && this.prompt.data.type ==='message'){
332 const {confirmations, ...Attr} = this.transaction
333 return JSON.stringify(Attr, null, 2);
335 return JSON.stringify(this.transaction, null, 2);
339 if(this.prompt.data && this.prompt.data.type ==='transfer'){
340 return this.bytom.keychain.findByAddress(this.transaction.from);
341 }else if(this.prompt.data && this.prompt.data.type ==='message'){
342 return this.bytom.keychain.findByAddress(this.transaction.address);
344 return this.currentAccount
360 return add.short(address)
362 transfer: function () {
365 this.$t('error.BTM0008')
367 this.$refs.password.focus();
370 let loader = this.$loading.show({
371 // Optional parameters
374 onCancel: this.onCancel
377 if(this.prompt.data.type ==='advTransfer'){
378 transaction.buildTransaction(this.address, this.transaction.input, this.transaction.output, this.transaction.fee, this.transaction.confirmations).then(async (result) => {
381 if (this.transaction.args) {
382 arrayData = await transaction.convertArgument(this.transaction.args)
385 return transaction.advancedTransfer(this.address, result[0], this.password, arrayData, this)
388 this.prompt.responder(resp);
390 this.$t("transfer.success")
392 NotificationService.close();
401 getLang(error.message) || error.message || error
404 } else if(this.prompt.data.type ==='transfer'){
405 transaction.transfer(this.transaction, this.password, this.address, this).then(result => {
407 this.prompt.responder(result);
409 this.$t("transfer.success")
411 NotificationService.close();
416 getLang(error.message) || error.message || error
419 } else if(this.prompt.data.type ==='signTransaction'){
420 const data = this.prompt.data.value
422 if(Array.isArray(data)){
423 Promise.all(data.map( (rawdata) => transaction.signTransaction(this.address, rawdata, this.password, this)))
426 this.prompt.responder(result);
427 this.$toast.success(this.$t("transfer.success"));
428 NotificationService.close();
433 getLang(error.message) || error.message || error
437 transaction.signTransaction(this.address, data, this.password, this).then( (result) => {
439 this.prompt.responder(result);
440 this.$toast.success(this.$t("transfer.success"));
442 NotificationService.close();
447 getLang(error.message) || error.message || error
452 } else if(this.prompt.data.type ==='message'){
453 transaction.signMessage(this.transaction.message, this.password, this.address, this).then((resp) => {
455 this.prompt.responder(resp);
457 this.$t("transfer.success")
459 NotificationService.close();
463 this.$toast.error( getLang(error.message));
474 queryAsset: function (assetID) {
475 return transaction.asset(assetID)
478 this.prompt = window.data || apis.extension.getBackgroundPage().notification || null;
479 console.log(this.prompt)
481 const params = this.prompt.data
482 if (params !== undefined) {
483 const data = params.value
487 if (inout.input !== undefined) {
488 this.transaction.input = inout.input
490 if (inout.output !== undefined) {
491 this.transaction.output = inout.output
493 if (inout.args !== undefined) {
494 this.transaction.args = inout.args
496 if (inout.gas !== undefined) {
497 this.transaction.fee = inout.gas
499 if (inout.confirmations !== undefined) {
500 this.transaction.confirmations = inout.confirmations
503 const array = inout.input.filter(action => action.type === 'spend_wallet')
505 if (array.length > 0) {
506 account.setupNet(`${this.net}${this.netType}`)
510 .map((objs, key) => {
511 return this.queryAsset(key).then(resp => {
514 'alias': resp.symbol,
515 'amount': _.sumBy(objs, 'amount')
521 Promise.all(promise).then(function (output) {
522 that.transaction.amounts = output
523 this.dataReady = true
525 this.dataReady = true
532 if (data.from != undefined) {
533 this.transaction.from = data.from
535 if (data.asset != undefined) {
536 this.transaction.asset= data.asset
538 if (data.to != undefined) {
539 this.transaction.to = data.to
541 if (data.amount != undefined) {
542 this.transaction.amount = data.amount
545 if(data.confirmations != undefined) {
546 this.transaction.confirmations = data.confirmations
549 const asset_amounts ={}
550 asset_amounts[data.asset] = data.amount
552 transaction.estimateFee( data.from, asset_amounts).then( (resp) =>{
553 this.transaction.fee = resp.fee
554 this.queryAsset(data.asset).then(resp => {
555 this.unit = resp.symbol
556 this.dataReady = true
562 this.dataReady = true
566 case "signTransaction":{
567 const param = data[0] || data
568 const _tx = camelize(param)
569 const rawTransaction = _tx.rawTransaction
571 const tx = this.netType === 'vapor'?
572 bytomjslib.vapor.Transaction.decodeRawTransaction(rawTransaction):
573 bytomjslib.bytom.Transaction.decodeRawTransaction(rawTransaction)
575 this.transaction.fee = tx.fee/100000000
576 this.transaction.input = tx.inputs
577 this.transaction.output = tx.outputs
579 const inputs = tx.inputs.filter(i => i.address === this.address)
580 const outputs = tx.outputs.filter(i => i.address === this.address)
581 const inputAsset = inputs.map(i => i.assetID);
582 const outputAsset = outputs.map(i => i.assetID);
584 const asset = _.union(inputAsset, outputAsset)
586 let types = ["transfer"]
590 return this.queryAsset(assetId).then(resp =>{
591 const assetInput = inputs.filter(i => i.assetID ===assetId)
592 const assetOutput = outputs.filter(o => o.assetID ===assetId)
593 const inputAmount = new BigNumber(_.sumBy(assetInput, 'amount'))
594 const outputAmount = new BigNumber(_.sumBy(assetOutput, 'amount'))
596 const decimals = decimalsMap[this.net][assetId]
597 const amount = inputAmount.minus(outputAmount).shiftedBy(-decimals)
601 'alias': resp.symbol,
602 'amount': amount.toString()
608 const inputType = inputs.map(i => i.type);
609 const outputType = outputs.map(o => o.type);
610 types = _.union(inputType, outputType, types);
612 const remove = ['spend','control'];
613 types = removeFromArray(types, remove);
614 types = types.map(ty => this.$t(`common.${ty}`)).join(', ');
616 this.transaction.types = types
618 Promise.all(promise).then(function(output) {
619 that.transaction.amounts = output
620 that.dataReady = true
622 that.dataReady = true
629 if(data.address !== undefined){
630 this.transaction.address = data.address;
632 if(data.message !== undefined){
633 this.transaction.message = data.message
636 this.dataReady = true