UNPKG

copay-crown

Version:

A Secure Crown Wallet

269 lines (234 loc) 9.25 kB
import { Component } from "@angular/core"; import { TranslateService } from '@ngx-translate/core'; import { Events, NavController, NavParams } from 'ionic-angular'; import * as _ from "lodash"; import { Logger } from '../../providers/logger/logger'; // Providers import { AddressBookProvider } from '../../providers/address-book/address-book'; import { ConfigProvider } from '../../providers/config/config'; import { ExternalLinkProvider } from '../../providers/external-link/external-link'; import { OnGoingProcessProvider } from "../../providers/on-going-process/on-going-process"; import { PopupProvider } from '../../providers/popup/popup'; import { ProfileProvider } from '../../providers/profile/profile'; import { TxConfirmNotificationProvider } from '../../providers/tx-confirm-notification/tx-confirm-notification'; import { TxFormatProvider } from '../../providers/tx-format/tx-format'; import { WalletProvider } from '../../providers/wallet/wallet'; @Component({ selector: 'page-tx-details', templateUrl: 'tx-details.html' }) export class TxDetailsPage { private txId: string; private config: any; private blockexplorerUrl: string; public wallet: any; public btx: any; public actionList: any[]; public isShared: boolean; public title: string; public alternativeIsoCode: string; public rateDate: any; public rate: any; public txNotification: any; public color: string; public copayerId: string; public txsUnsubscribedForNotifications: boolean; public toName: string; constructor( private addressBookProvider: AddressBookProvider, private configProvider: ConfigProvider, private events: Events, private externalLinkProvider: ExternalLinkProvider, private logger: Logger, private navCtrl: NavController, private navParams: NavParams, private onGoingProcess: OnGoingProcessProvider, private popupProvider: PopupProvider, private profileProvider: ProfileProvider, private txConfirmNotificationProvider: TxConfirmNotificationProvider, private txFormatProvider: TxFormatProvider, private walletProvider: WalletProvider, private translate: TranslateService ) { this.config = this.configProvider.get(); this.txId = this.navParams.data.txid; this.title = this.translate.instant('Transaction'); this.wallet = this.profileProvider.getWallet(this.navParams.data.walletId); this.color = this.wallet.color; this.copayerId = this.wallet.credentials.copayerId; this.isShared = this.wallet.credentials.n > 1; this.txsUnsubscribedForNotifications = this.config.confirmedTxsNotifications ? !this.config.confirmedTxsNotifications.enabled : true; let defaults = this.configProvider.getDefaults(); this.blockexplorerUrl = this.wallet.coin === 'bch' ? defaults.blockExplorerUrl.bch : defaults.blockExplorerUrl.btc; this.txConfirmNotificationProvider.checkIfEnabled(this.txId).then((res: any) => { this.txNotification = { value: res }; }); this.updateTx(); } ionViewWillEnter() { this.events.subscribe('bwsEvent', (walletId: string, type: string, n: any) => { if (type == 'NewBlock' && n && n.data && n.data.network == 'livenet') this.updateTxDebounced({ hideLoading: true }); }); } public readMore(): void { let url = 'https://support.bitpay.com/hc/en-us/articles/115004497783-What-does-the-BitPay-wallet-s-warning-amount-too-low-to-spend-mean-'; let optIn = true; let title = null; let message = this.translate.instant('Read more in our support page'); let okText = this.translate.instant('Open'); let cancelText = this.translate.instant('Go Back'); this.externalLinkProvider.open(url, optIn, title, message, okText, cancelText); } private updateMemo(): void { this.walletProvider.getTxNote(this.wallet, this.btx.txid).then((note: any) => { if (!note || note.body == "") return; this.btx.note = note; }).catch((err: any) => { this.logger.warn('Could not fetch transaction note: ' + err); return; }); } private initActionList(): void { this.actionList = []; if (this.btx.action != 'sent' && this.btx.action != 'moved' || !this.isShared) return; let actionDescriptions = { created: this.translate.instant('Proposal Created'), accept: this.translate.instant('Accepted'), reject: this.translate.instant('Rejected'), broadcasted: this.translate.instant('Broadcasted') }; this.actionList.push({ type: 'created', time: this.btx.createdOn, description: actionDescriptions.created, by: this.btx.creatorName }); _.each(this.btx.actions, (action: any) => { this.actionList.push({ type: action.type, time: action.createdOn, description: actionDescriptions[action.type], by: action.copayerName }); }); this.actionList.push({ type: 'broadcasted', time: this.btx.time, description: actionDescriptions.broadcasted, }); setTimeout(() => { this.actionList.reverse(); }, 10); } private updateTxDebounced = _.debounce(this.updateTx, 1000); private updateTx(opts?: any): void { opts = opts ? opts : {}; if (!opts.hideLoading) this.onGoingProcess.set('loadingTxInfo'); this.walletProvider.getTx(this.wallet, this.txId).then((tx: any) => { if (!opts.hideLoading) this.onGoingProcess.clear(); this.btx = this.txFormatProvider.processTx(this.wallet.coin, tx, this.walletProvider.useLegacyAddress()); let v: string = this.txFormatProvider.formatAlternativeStr(this.wallet.coin, tx.fees); this.btx.feeFiatStr = v; this.btx.feeRateStr = (this.btx.fees / (this.btx.amount + this.btx.fees) * 100).toFixed(2) + '%'; if (this.btx.action != 'invalid') { if (this.btx.action == 'sent') this.title = this.translate.instant('Sent Funds'); if (this.btx.action == 'received') this.title = this.translate.instant('Received Funds'); if (this.btx.action == 'moved') this.title = this.translate.instant('Moved Funds'); } this.updateMemo(); this.initActionList(); this.getFiatRate(); this.contact(); this.walletProvider.getLowAmount(this.wallet).then((amount: number) => { this.btx.lowAmount = tx.amount < amount; }).catch((err: any) => { this.logger.warn('Error getting low amounts: ' + err); return; }); }).catch((err: any) => { if (!opts.hideLoading) this.onGoingProcess.clear(); this.logger.warn('Error getting transaction: ' + err); this.navCtrl.pop(); return this.popupProvider.ionicAlert('Error', this.translate.instant('Transaction not available at this time')); }); } public showCommentPopup(): void { let opts: any = {}; if (this.btx.message) { opts.defaultText = this.btx.message; } if (this.btx.note && this.btx.note.body) opts.defaultText = this.btx.note.body; this.popupProvider.ionicPrompt(this.wallet.name, this.translate.instant('Memo'), opts).then((text: string) => { if (text == null) return; this.btx.note = { body: text }; this.logger.debug('Saving memo'); let args = { txid: this.btx.txid, body: text }; this.walletProvider.editTxNote(this.wallet, args).then((res: any) => { this.logger.info('Tx Note edited'); }).catch((err: any) => { this.logger.debug('Could not save tx comment ' + err); }); }); } public viewOnBlockchain(): void { let btx = this.btx; let url = 'https://' + (this.getShortNetworkName() == 'test' ? 'test-' : '') + this.blockexplorerUrl + '/tx/' + btx.txid; let optIn = true; let title = null; let message = this.translate.instant('View Transaction on Insight'); let okText = this.translate.instant('Open Insight'); let cancelText = this.translate.instant('Go Back'); this.externalLinkProvider.open(url, optIn, title, message, okText, cancelText); } public getShortNetworkName(): string { let n: string = this.wallet.credentials.network; return n.substring(0, 4); } private getFiatRate(): void { this.alternativeIsoCode = this.wallet.status.alternativeIsoCode; this.wallet.getFiatRate({ code: this.alternativeIsoCode, ts: this.btx.time * 1000 }, (err, res) => { if (err) { this.logger.debug('Could not get historic rate'); return; } if (res && res.rate) { this.rateDate = res.fetchedOn; this.rate = res.rate; } }); } public txConfirmNotificationChange(): void { if (this.txNotification.value) { this.txConfirmNotificationProvider.subscribe(this.wallet, { txid: this.txId }); } else { this.txConfirmNotificationProvider.unsubscribe(this.wallet, this.txId); } } private contact(): void { let addr = this.btx.addressTo; this.addressBookProvider.get(addr).then((ab: any) => { if (ab) { let name = _.isObject(ab) ? ab.name : ab; this.toName = name; } else { this.toName = addr; } }).catch((err: any) => { this.logger.warn(err); }); } }