copay-crown
Version:
A Secure Crown Wallet
307 lines (277 loc) • 9.97 kB
text/typescript
import { Component } from '@angular/core';
import { Events, ModalController, NavController, NavParams } from 'ionic-angular';
import * as _ from 'lodash';
import { Logger } from '../../../../providers/logger/logger';
// providers
import { CoinbaseProvider } from '../../../../providers/coinbase/coinbase';
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 { TxFormatProvider } from '../../../../providers/tx-format/tx-format';
import { WalletProvider } from '../../../../providers/wallet/wallet';
// pages
import { FinishModalPage } from '../../../finish/finish';
import { CoinbasePage } from '../coinbase';
export class BuyCoinbasePage {
private amount: string;
private currency: string;
private coin: string;
private wallets: any;
public paymentMethods: any[];
public selectedPaymentMethodId: any;
public buyPrice: string;
public buyRequestInfo: any;
public amountUnitStr: string;
public accessToken: string;
public accountId: string;
public wallet: any;
public network: string;
public isFiat: boolean;
constructor(
private coinbaseProvider: CoinbaseProvider,
private logger: Logger,
private popupProvider: PopupProvider,
private navCtrl: NavController,
private events: Events,
private externalLinkProvider: ExternalLinkProvider,
private onGoingProcessProvider: OnGoingProcessProvider,
private navParams: NavParams,
private walletProvider: WalletProvider,
private txFormatProvider: TxFormatProvider,
private profileProvider: ProfileProvider,
private modalCtrl: ModalController
) {
this.coin = 'btc';
this.isFiat = this.navParams.data.currency != 'BTC' ? true : false;
this.amount = this.navParams.data.amount;
this.currency = this.navParams.data.currency;
this.network = this.coinbaseProvider.getNetwork();
}
ionViewDidLoad() {
this.logger.info('ionViewDidLoad BuyCoinbasePage');
}
ionViewWillEnter() {
this.wallets = this.profileProvider.getWallets({
onlyComplete: true,
network: this.network,
coin: this.coin
});
if (_.isEmpty(this.wallets)) {
this.showErrorAndBack('No wallets available');
return;
}
this.onWalletSelect(this.wallets[0]); // Default first wallet
}
private showErrorAndBack(err: any): void {
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err).then(() => {
this.navCtrl.pop();
});
}
private showError(err: any): void {
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err);
}
private processPaymentInfo(): void {
this.onGoingProcessProvider.set('connectingCoinbase');
this.coinbaseProvider.init((err: any, res: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showErrorAndBack(err);
return;
}
let accessToken = res.accessToken;
this.coinbaseProvider.buyPrice(accessToken, this.coinbaseProvider.getAvailableCurrency(), (err: any, b: any) => {
this.buyPrice = b.data || null;
});
this.paymentMethods = [];
this.selectedPaymentMethodId = null;
this.coinbaseProvider.getPaymentMethods(accessToken, (err: any, p: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showErrorAndBack(err);
return;
}
let hasPrimary;
let pm;
for (let i = 0; i < p.data.length; i++) {
pm = p.data[i];
if (pm.allow_buy) {
this.paymentMethods.push(pm);
}
if (pm.allow_buy && pm.primary_buy) {
hasPrimary = true;
this.selectedPaymentMethodId = pm.id;
}
}
if (_.isEmpty(this.paymentMethods)) {
this.onGoingProcessProvider.clear();
let url = 'https://support.coinbase.com/customer/portal/articles/1148716-payment-methods-for-us-customers';
let msg = 'No payment method available to buy';
let okText = 'More info';
let cancelText = 'Go Back';
this.popupProvider.ionicConfirm(null, msg, okText, cancelText).then((res) => {
if (res) this.externalLinkProvider.open(url);
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
});
return;
}
if (!hasPrimary) this.selectedPaymentMethodId = this.paymentMethods[0].id;
this.buyRequest();
});
});
}
public buyRequest(): void {
this.coinbaseProvider.init((err, res) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showErrorAndBack(err);
return;
}
let accessToken = res.accessToken;
let accountId = res.accountId;
let dataSrc = {
amount: this.amount,
currency: this.currency,
payment_method: this.selectedPaymentMethodId,
quote: true
};
this.coinbaseProvider.buyRequest(accessToken, accountId, dataSrc, (err: any, data: any) => {
this.onGoingProcessProvider.clear();
if (err) {
this.showErrorAndBack(err);
return;
}
this.buyRequestInfo = data.data;
});
});
}
public buyConfirm() {
let message = 'Buy bitcoin for ' + this.amountUnitStr;
let okText = 'Confirm';
let cancelText = 'Cancel';
this.popupProvider.ionicConfirm(null, message, okText, cancelText).then((ok: boolean) => {
if (!ok) return;
this.onGoingProcessProvider.set('buyingBitcoin');
this.coinbaseProvider.init((err: any, res: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showError(err);
return;
}
let accessToken = res.accessToken;
let accountId = res.accountId;
let dataSrc = {
amount: this.amount,
currency: this.currency,
payment_method: this.selectedPaymentMethodId,
commit: true
};
this.coinbaseProvider.buyRequest(accessToken, accountId, dataSrc, (err: any, b: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showError(err);
return;
}
setTimeout(() => {
let tx = b.data ? b.data.transaction : null;
if (tx && tx.id) {
this.processBuyTx(tx);
}
else {
this._processBuyOrder(b);
}
}, 8000);
});
});
});
};
private processBuyTx(tx: any): void {
if (!tx) {
this.onGoingProcessProvider.clear();
this.showError('Transaction not found');
return;
}
this.coinbaseProvider.getTransaction(this.accessToken, this.accountId, tx.id, (err: any, updatedTx: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showError(err);
return;
}
this.walletProvider.getAddress(this.wallet, false).then((walletAddr: string) => {
updatedTx.data['toAddr'] = walletAddr;
updatedTx.data['status'] = 'pending'; // Forcing "pending" status to process later
this.logger.debug('Saving transaction to process later...');
this.coinbaseProvider.savePendingTransaction(updatedTx.data, {}, (err: any) => {
this.onGoingProcessProvider.clear();
if (err) this.logger.debug(err);
this.openFinishModal();
});
}).catch((err) => {
this.onGoingProcessProvider.clear();
this.showError(err);
});
});
}
private _processBuyOrder(b: any): void {
this.coinbaseProvider.getBuyOrder(this.accessToken, this.accountId, b.data.id, (err: any, buyResp: any) => {
if (err) {
this.onGoingProcessProvider.clear();
this.showError(err);
return;
}
let tx = buyResp.data ? buyResp.data.transaction : null;
if (tx && tx.id) {
this.processBuyTx(tx);
} else {
setTimeout(() => {
this._processBuyOrder(b);
}, 5000);
}
});
}
public showWallets(): void {
let id = this.wallet ? this.wallet.credentials.walletId : null;
this.events.publish('showWalletsSelectorEvent', this.wallets, id, 'Receive in');
this.events.subscribe('selectWalletEvent', (wallet: any) => {
if (!_.isEmpty(wallet)) this.onWalletSelect(wallet);
this.events.unsubscribe('selectWalletEvent');
});
}
public onWalletSelect(wallet: any) {
this.wallet = wallet;
let parsedAmount = this.txFormatProvider.parseAmount(this.coin, this.amount, this.currency);
// Buy always in BTC
this.amount = (parsedAmount.amountSat / 100000000).toFixed(8);
this.currency = 'BTC';
this.amountUnitStr = parsedAmount.amountUnitStr;
this.onGoingProcessProvider.set('calculatingFee');
this.coinbaseProvider.checkEnoughFundsForFee(this.amount, (err: any) => {
this.onGoingProcessProvider.clear();
if (err) {
this.showErrorAndBack(err);
return;
}
this.processPaymentInfo();
});
}
private openFinishModal(): void {
let finishText = 'Bought';
let finishComment = 'Bitcoin purchase completed. Coinbase has queued the transfer to your selected wallet';
let modal = this.modalCtrl.create(FinishModalPage, { finishText, finishComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(CoinbasePage, { coin: 'btc' });
});
}
}