[V4] FEAT: Success modal

This commit is contained in:
Gabriel Bazán 2018-01-05 11:22:46 -03:00
parent 5f0e875768
commit 4b64f035c5
27 changed files with 358 additions and 410 deletions

View File

@ -52,6 +52,7 @@ import { WalletDetailsPage } from '../pages/wallet-details/wallet-details';
import { TxDetailsPage } from '../pages/tx-details/tx-details';
import { TxpDetailsPage } from '../pages/txp-details/txp-details';
import { SendFeedbackPage } from '../pages/feedback/send-feedback/send-feedback';
import { SuccessModalPage } from '../pages/success/success';
// Integrations: Amazon
import { AmazonCardDetailsPage } from '../pages/integrations/amazon/amazon-card-details/amazon-card-details';
@ -275,6 +276,7 @@ let pages: any = [
FeePolicyPage,
SessionLogPage,
SendFeedbackPage,
SuccessModalPage,
TourPage,
TabsPage,
TxpDetailsPage,

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="158px" height="157px" viewBox="0 0 158 157" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
<title>Group 3</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Onboarding" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="0.2.4---Wallet-Created" transform="translate(-109.000000, -169.000000)">
<g id="Overlay/Success" transform="translate(-1.000000, 0.000000)">
<g id="Group-3" transform="translate(111.592000, 170.431784)">
<g id="ios-checkmark-outline" transform="translate(49.261333, 54.161919)"></g>
<polyline id="Line" stroke="#FFFFFF" stroke-width="3" stroke-linecap="square" points="49.764 82.7473763 67.3573333 100.801349 114.608 54.6634183"></polyline>
<path d="M77.4106667,154.461769 C120.163397,154.461769 154.821333,119.884324 154.821333,77.2308846 C154.821333,34.5774448 120.163397,0 77.4106667,0 C34.657936,0 0,34.5774448 0,77.2308846 C0,119.884324 34.657936,154.461769 77.4106667,154.461769 Z" id="Oval-1" stroke="#FFFFFF" stroke-width="2"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -238,8 +238,8 @@ export class HomePage {
this.logger.error(err);
});
}, 2000, {
'leading': true
});
'leading': true
});
private updateAllWallets(): void {
let wallets: Array<any> = [];

View File

@ -53,7 +53,7 @@ export class WalletSelectorPage {
}
}
public backdropDismiss() {
public backdropDismiss(): void {
this.events.publish('selectWalletEvent');
this.showSlideEffect = false;
setTimeout(() => {

View File

@ -1,7 +1,7 @@
<ion-header>
<ion-navbar>
<ion-title>Buy</ion-title>
<ion-title>{{'Buy' | translate}}</ion-title>
</ion-navbar>
</ion-header>
@ -26,10 +26,10 @@
<button ion-item (click)="showWallets()" class="wallets-list">
<div translate>From</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg" class="icon-wallet"
/>
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
@ -40,19 +40,24 @@
<ion-item>
<span translate>Gift Card</span>
<ion-note item-end>
{{amount | currency:'$ ':2}}<span *ngIf="amount"> {{currencyIsoCode}}</span>
{{amount | currency:'$ ':2}}
<span *ngIf="amount"> {{currencyIsoCode}}</span>
</ion-note>
</ion-item>
<ion-item>
<span translate>Network Cost</span>
<ion-note item-end>
<span>{{invoiceFee | currency:'$ ':2}}<span *ngIf="invoiceFee"> {{currencyIsoCode}}</span></span>
<span>{{invoiceFee | currency:'$ ':2}}
<span *ngIf="invoiceFee"> {{currencyIsoCode}}</span>
</span>
</ion-note>
</ion-item>
<ion-item>
<span translate>Miner Fee</span>
<ion-note item-end>
<span>{{networkFee | currency:'$ ':2}}<span *ngIf="networkFee"> {{currencyIsoCode}}</span></span>
<span>{{networkFee | currency:'$ ':2}}
<span *ngIf="networkFee"> {{currencyIsoCode}}</span>
</span>
</ion-note>
</ion-item>
<ion-item>
@ -65,33 +70,19 @@
</div>
<ion-item-divider color="light"></ion-item-divider>
<ion-item class="amazon-info">
* <a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> is not a sponsor of this promotion. Except as
required by law, <a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> Gift Cards ("GCs") cannot be transferred
for value or redeemed for cash. GCs may be used only for purchases of eligible goods at <a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> or certain of its affiliated websites. For complete terms and conditions, see
<a (click)="openExternalLink('https://www.amazon.com/gc-legal')">www.amazon.com/gc-legal</a>. GCs are issued by ACI
Gift Cards, Inc., a Washington corporation. All Amazon &reg;, &trade; &amp; &copy; are IP of <a (click)="openExternalLink('http://amazon.com')">Amazon.com</a>,
Inc. or its affiliates. No expiration date or service fees.
*
<a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> is not a sponsor of this promotion. Except as required by law,
<a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> Gift Cards ("GCs") cannot be transferred for value or redeemed for cash. GCs may be used only for
purchases of eligible goods at
<a (click)="openExternalLink('http://amazon.com')">Amazon.com</a> or certain of its affiliated websites. For complete terms and conditions, see
<a (click)="openExternalLink('https://www.amazon.com/gc-legal')">www.amazon.com/gc-legal</a>. GCs are issued by ACI Gift Cards, Inc., a Washington corporation. All Amazon &reg;,
&trade; &amp; &copy; are IP of
<a (click)="openExternalLink('http://amazon.com')">Amazon.com</a>, Inc. or its affiliates. No expiration date or service fees.
</ion-item>
</ion-item-group>
</ion-list>
</ion-content>
<ion-footer *ngIf="!amazonGiftCard">
<ion-footer>
<button ion-button block class="button-footer" (click)="buyConfirm()" [disabled]="!(wallet && totalAmountStr)" translate>Confirm purchase</button>
</ion-footer>
<ion-footer *ngIf="amazonGiftCard">
<span *ngIf="amazonGiftCard.status == 'FAILURE'" translate>
Your purchase could not be completed
</span>
<span *ngIf="amazonGiftCard.status == 'PENDING'" translate>
Your purchase was added to the list of pending
</span>
<span *ngIf="amazonGiftCard.status == 'SUCCESS'" translate>
Bought {{amountUnitStr}}
</span>
<div *ngIf="amazonGiftCard.status == 'SUCCESS'" translate>
Gift card generated and ready to use.
</div>
<button ion-button block class="button-footer" (click)="goBackHome()" [disabled]="!(wallet && totalAmountStr)" translate>Accept and back home</button>
</ion-footer>

View File

@ -7,6 +7,7 @@ import * as moment from 'moment';
// Pages
import { FeeWarningPage } from '../../../../pages/send/fee-warning/fee-warning';
import { AmazonCardsPage } from '../../../../pages/integrations/amazon/amazon-cards/amazon-cards';
import { SuccessModalPage } from '../../../success/success';
// Provider
import { AmazonProvider } from '../../../../providers/amazon/amazon';
@ -42,7 +43,6 @@ export class BuyAmazonPage {
public invoiceFee: number;
public networkFee: number;
public totalAmount: number;
public sendStatus: string;
public amazonGiftCard: any;
public amountUnitStr: string;
public limitPerDayMessage: string;
@ -123,7 +123,6 @@ export class BuyAmazonPage {
private showErrorAndBack(title: string, msg: any) {
title = title ? title : 'Error'; // TODO: gettextCatalog
this.sendStatus = '';
this.logger.error(msg);
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
this.popupProvider.ionicAlert(title, msg).then(() => {
@ -134,7 +133,6 @@ export class BuyAmazonPage {
private showError = function (title: string, msg: any): Promise<any> {
return new Promise((resolve, reject) => {
title = title || 'Error'; // TODO: gettextCatalog
this.sendStatus = '';
this.logger.error(msg);
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
this.popupProvider.ionicAlert(title, msg).then(() => {
@ -143,7 +141,7 @@ export class BuyAmazonPage {
});
}
private publishAndSign(wallet: any, txp: any, onSendStatusChange: any): Promise<any> {
private publishAndSign(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
let err = 'No signing proposal: No private key'; // TODO: gettextCatalog
@ -151,7 +149,7 @@ export class BuyAmazonPage {
return reject(err);
}
this.walletProvider.publishAndSign(wallet, txp, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
return resolve(txp);
}).catch((err: any) => {
return reject(err);
@ -159,16 +157,6 @@ export class BuyAmazonPage {
});
}
private statusChangeHandler(processName: string, isOn: boolean) {
let showName = this.onGoingProcessProvider.getShowName(processName);
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'buyingGiftCard' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private satToFiat(sat: number): Promise<any> {
return new Promise((resolve, reject) => {
this.txFormatProvider.toFiat(this.coin, sat, this.currencyIsoCode).then((value: string) => {
@ -281,7 +269,6 @@ export class BuyAmazonPage {
this.logger.debug("creating gift card " + count);
if (err) {
this.onGoingProcessProvider.set('buyingGiftCard', false);
this.statusChangeHandler('buyingGiftCard', false);
giftCard = giftCard || {};
giftCard['status'] = 'FAILURE';
}
@ -302,7 +289,6 @@ export class BuyAmazonPage {
}, (err: any) => {
this.logger.error(err);
this.onGoingProcessProvider.set('buyingGiftCard', false);
this.statusChangeHandler('buyingGiftCard', false);
this.showError(null, 'Gift card expired'); // TODO: gettextCatalog
});
return;
@ -319,7 +305,6 @@ export class BuyAmazonPage {
this.amazonProvider.savePendingGiftCard(newData, null, (err: any) => {
this.onGoingProcessProvider.set('buyingGiftCard', false);
this.statusChangeHandler('buyingGiftCard', false);
this.logger.debug("Saved new gift card with status: " + newData.status);
this.amazonGiftCard = newData;
});
@ -397,13 +382,11 @@ export class BuyAmazonPage {
var cancelText = 'Cancel'; // TODO: gettextCatalog
this.popupProvider.ionicConfirm(title, this.message, okText, cancelText).then((ok) => {
if (!ok) {
this.sendStatus = '';
return;
}
this.publishAndSign(this.wallet, this.createdTx, function () { }).then((txSent) => {
this.publishAndSign(this.wallet, this.createdTx).then((txSent) => {
this.onGoingProcessProvider.set('buyingGiftCard', true);
this.statusChangeHandler('buyingGiftCard', true);
this.checkTransaction(1, this.createdTx.giftData);
}).catch((err: any) => {
this._resetValues();
@ -418,13 +401,6 @@ export class BuyAmazonPage {
this.initialize(wallet);
}
public goBackHome(): void {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(AmazonCardsPage, { invoiceId: this.invoiceId });
}
public showWallets(): void {
let id = this.wallet ? this.wallet.credentials.walletId : null;
this.events.publish('showWalletsSelectorEvent', this.wallets, id, 'Buy from');
@ -434,4 +410,28 @@ export class BuyAmazonPage {
});
}
public openSuccessModal(): void {
let successComment: string;
if (this.amazonGiftCard.status == 'FAILURE') {
successComment = 'Bitcoin purchase completed. Coinbase has queued the transfer to your selected wallet';
}
if (this.amazonGiftCard.status == 'PENDING') {
successComment = 'Your purchase was added to the list of pending'
}
if (this.amazonGiftCard.status == 'SUCCESS') {
successComment = 'Bought ' + this.amountUnitStr;
}
if (this.amazonGiftCard.status == 'SUCCESS') {
successComment = 'Gift card generated and ready to use.';
}
let successText = '';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(AmazonCardsPage, { invoiceId: this.invoiceId });
});
}
}

View File

@ -5,14 +5,6 @@
</ion-header>
<ion-content padding>
<ion-card *ngIf="sendStatus === 'success'">
<ion-card-header>
Bought
</ion-card-header>
<ion-card-content>
Bitcoin purchase completed. Coinbase has queued the transfer to your selected wallet
</ion-card-content>
</ion-card>
<ion-list *ngIf="buyRequestInfo">
<ion-item>
<div class="sending-label">
@ -22,8 +14,7 @@
<div class="amount-label">
<div class="amount">{{amountUnitStr}}</div>
<div class="alternative" *ngIf="buyPrice">
<span ng-show="isFiat">{{buyRequestInfo.amount.amount}} {{buyRequestInfo.amount.currency}}</span> @ ${{buyPrice.amount}}
per BTC
<span ng-show="isFiat">{{buyRequestInfo.amount.amount}} {{buyRequestInfo.amount.currency}}</span> @ ${{buyPrice.amount}} per BTC
</div>
</div>
</ion-item>
@ -39,9 +30,9 @@
<div>Receive in</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg" class="icon-wallet"
/>
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg"
class="icon-wallet" />
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
@ -70,10 +61,6 @@
</ion-list>
</ion-content>
<ion-footer *ngIf="sendStatus != 'success'">
<ion-footer>
<button ion-button block class="button-footer" (click)="buyConfirm()" [disabled]="!wallet || !buyRequestInfo || !selectedPaymentMethodId">Confirm purchase</button>
</ion-footer>
<ion-footer *ngIf="sendStatus === 'success'">
<button ion-button block class="button-footer" (click)="goBackHome()">Accept and back home</button>
</ion-footer>

View File

@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { NavController, NavParams, Events } from 'ionic-angular';
import { NavController, NavParams, Events, ModalController } from 'ionic-angular';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
@ -14,7 +14,7 @@ import { ProfileProvider } from '../../../../providers/profile/profile';
//pages
import { CoinbasePage } from '../coinbase';
import { SuccessModalPage } from '../../../success/success';
@Component({
selector: 'page-buy-coinbase',
@ -27,7 +27,6 @@ export class BuyCoinbasePage {
private coin: string;
private wallets: any;
public sendStatus: string;
public paymentMethods: Array<any>;
public selectedPaymentMethodId: any;
public buyPrice: string;
@ -50,7 +49,8 @@ export class BuyCoinbasePage {
private navParams: NavParams,
private walletProvider: WalletProvider,
private txFormatProvider: TxFormatProvider,
private profileProvider: ProfileProvider
private profileProvider: ProfileProvider,
private modalCtrl: ModalController
) {
this.coin = 'btc';
this.isFiat = this.navParams.data.currency != 'BTC' ? true : false;
@ -78,7 +78,6 @@ export class BuyCoinbasePage {
}
private showErrorAndBack(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err).then(() => {
@ -87,22 +86,11 @@ export class BuyCoinbasePage {
}
private showError(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err);
}
private statusChangeHandler(processName: string, isOn: boolean): void {
let showName = this.onGoingProcessProvider.getShowName(processName);
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'buyingBitcoin' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private processPaymentInfo(): void {
this.onGoingProcessProvider.set('connectingCoinbase', true);
this.coinbaseProvider.init((err: any, res: any) => {
@ -191,11 +179,9 @@ export class BuyCoinbasePage {
if (!ok) return;
this.onGoingProcessProvider.set('buyingBitcoin', true);
this.statusChangeHandler('buyingBitcoin', true);
this.coinbaseProvider.init((err: any, res: any) => {
if (err) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
return;
}
@ -210,7 +196,6 @@ export class BuyCoinbasePage {
this.coinbaseProvider.buyRequest(accessToken, accountId, dataSrc, (err: any, b: any) => {
if (err) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
return;
}
@ -231,7 +216,6 @@ export class BuyCoinbasePage {
private processBuyTx(tx: any): void {
if (!tx) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError('Transaction not found');
return;
}
@ -239,7 +223,6 @@ export class BuyCoinbasePage {
this.coinbaseProvider.getTransaction(this.accessToken, this.accountId, tx.id, (err: any, updatedTx: any) => {
if (err) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
return;
}
@ -251,12 +234,11 @@ export class BuyCoinbasePage {
this.logger.debug('Saving transaction to process later...');
this.coinbaseProvider.savePendingTransaction(updatedTx.data, {}, (err: any) => {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
if (err) this.logger.debug(err);
this.openSuccessModal();
});
}).catch((err) => {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
});
});
@ -266,7 +248,6 @@ export class BuyCoinbasePage {
this.coinbaseProvider.getBuyOrder(this.accessToken, this.accountId, b.data.id, (err: any, buyResp: any) => {
if (err) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
return;
}
@ -310,11 +291,16 @@ export class BuyCoinbasePage {
});
}
public goBackHome() {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(CoinbasePage, { coin: 'btc' });
public openSuccessModal(): void {
let successText = 'Bought';
let successComment = 'Bitcoin purchase completed. Coinbase has queued the transfer to your selected wallet';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(CoinbasePage, { coin: 'btc' });
});
}
}

View File

@ -5,15 +5,6 @@
</ion-header>
<ion-content padding>
<ion-card *ngIf="sendStatus === 'success'">
<ion-card-header>
Funds sent to Coinbase Account
</ion-card-header>
<ion-card-content>
The transaction is not yet confirmed, and will show as "Pending" in your Activity. The bitcoin sale will be completed automatically
once it is confirmed by Coinbase.
</ion-card-content>
</ion-card>
<ion-list *ngIf="sellRequestInfo">
<ion-item>
<div class="selling-label">
@ -23,22 +14,22 @@
<div class="amount-label">
<div class="amount">{{amountUnitStr}}</div>
<div class="alternative">
<span *ngIf="isFiat">{{sellRequestInfo.subtotal}} {{sellRequestInfo.currency}}</span> @ ${{sellPrice.amount}} per
BTC
<span *ngIf="isFiat">{{sellRequestInfo.subtotal}} {{sellRequestInfo.currency}}</span> @ ${{sellPrice.amount}} per BTC
</div>
</div>
</ion-item>
<ion-item-group class="info">
<button ion-item (click)="showWallets()" class="wallets-list">
<div>From</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet"/>
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg" class="icon-wallet"/>
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
<div>From</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg"
class="icon-wallet" />
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
<ion-item>
<ion-label stacked>Deposit into</ion-label>
@ -66,17 +57,15 @@
<div *ngIf="sellRequestInfo">
Estimated sale value:
<strong>
{{sellRequestInfo.total.amount | currency : '' : 2}}
{{sellRequestInfo.total.currency}}
</strong>
{{sellRequestInfo.total.amount | currency : '' : 2}} {{sellRequestInfo.total.currency}}
</strong>
</div>
<div *ngIf="sellRequestInfo">
Still sell if price fall until:
<strong>
{{(sellRequestInfo.total.amount -
(selectedPriceSensitivity.data.value / 100) * sellRequestInfo.total.amount) | currency : '' : 2}}
{{sellRequestInfo.total.currency}}
</strong>
{{(sellRequestInfo.total.amount - (selectedPriceSensitivity.data.value / 100) * sellRequestInfo.total.amount) | currency
: '' : 2}} {{sellRequestInfo.total.currency}}
</strong>
</div>
</ion-item>
@ -91,8 +80,8 @@
</ion-item>
<ion-item *ngFor="let fee of sellRequestInfo.fees">
<span>
{{fee.type}} fee
</span>
{{fee.type}} fee
</span>
<ion-note item-end>
<span *ngIf="fee.amount.amount != '0.00'">-</span> {{fee.amount.amount}} {{fee.amount.currency}}
</ion-note>
@ -108,10 +97,6 @@
</ion-list>
</ion-content>
<ion-footer *ngIf="sendStatus != 'success'">
<ion-footer>
<button ion-button block class="button-footer" (click)="sellConfirm()" [disabled]="!selectedPaymentMethodId || !sellRequestInfo || !wallet">Confirm sale</button>
</ion-footer>
<ion-footer *ngIf="sendStatus === 'success'">
<button ion-button block class="button-footer" (click)="goBackHome()">Accept and back home</button>
</ion-footer>

View File

@ -1,10 +1,11 @@
import { Component } from '@angular/core';
import { NavController, NavParams, Events } from 'ionic-angular';
import { NavController, NavParams, Events, ModalController } from 'ionic-angular';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
//pages
import { CoinbasePage } from '../coinbase';
import { SuccessModalPage } from '../../../success/success';
//providers
import { AppProvider } from '../../../../providers/app/app';
@ -28,7 +29,6 @@ export class SellCoinbasePage {
private currency: string;
private wallets: any;
public sendStatus: string;
public paymentMethods: Array<any>;
public selectedPaymentMethodId: any;
public selectedPriceSensitivity: any;
@ -54,7 +54,8 @@ export class SellCoinbasePage {
private onGoingProcessProvider: OnGoingProcessProvider,
private walletProvider: WalletProvider,
private txFormatProvider: TxFormatProvider,
private profileProvider: ProfileProvider
private profileProvider: ProfileProvider,
private modalCtrl: ModalController
) {
this.coin = 'btc';
this.isFiat = this.navParams.data.currency != 'BTC' ? true : false;
@ -86,7 +87,6 @@ export class SellCoinbasePage {
}
private showErrorAndBack(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err).then(() => {
@ -95,13 +95,12 @@ export class SellCoinbasePage {
}
private showError(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err);
}
private publishAndSign(wallet: any, txp: any, onSendStatusChange: any): Promise<any> {
private publishAndSign(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
let err = 'No signing proposal: No private key'; // TODO: gettextCatalog
@ -109,7 +108,7 @@ export class SellCoinbasePage {
return reject(err);
}
this.walletProvider.publishAndSign(wallet, txp, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
return resolve(txp);
}).catch((err: any) => {
return reject(err);
@ -217,7 +216,7 @@ export class SellCoinbasePage {
ctx.description = this.appProvider.info.nameCase + ' Wallet: ' + this.wallet.name;
this.coinbaseProvider.savePendingTransaction(ctx, null, (err: any) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.openSuccessModal();
if (err) this.logger.debug(this.coinbaseProvider.getErrorsAsString(err.errors));
});
return;
@ -230,7 +229,6 @@ export class SellCoinbasePage {
this.checkTransaction(count + 1, txp);
} else {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError('No transaction found');
return;
}
@ -242,16 +240,6 @@ export class SellCoinbasePage {
'leading': true
});
private statusChangeHandler(processName: string, isOn: boolean): void {
let showName = this.onGoingProcessProvider.getShowName(processName);
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'sellingBitcoin' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
public sellRequest(): void {
this.onGoingProcessProvider.set('connectingCoinbase', true);
this.coinbaseProvider.init((err: any, res: any) => {
@ -291,11 +279,9 @@ export class SellCoinbasePage {
if (!ok) return;
this.onGoingProcessProvider.set('sellingBitcoin', true);
this.statusChangeHandler('sellingBitcoin', true);
this.coinbaseProvider.init((err: any, res: any) => {
if (err) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(this.coinbaseProvider.getErrorsAsString(err.errors));
return;
}
@ -308,7 +294,6 @@ export class SellCoinbasePage {
this.coinbaseProvider.createAddress(accessToken, accountId, dataSrc, (err: any, data: any) => {
if (err) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(this.coinbaseProvider.getErrorsAsString(err.errors));
return;
}
@ -335,18 +320,16 @@ export class SellCoinbasePage {
this.walletProvider.createTx(this.wallet, txp).then((ctxp: any) => {
this.logger.debug('Transaction created.');
this.publishAndSign(this.wallet, ctxp, function () { }).then((txSent: any) => {
this.publishAndSign(this.wallet, ctxp).then((txSent: any) => {
this.logger.debug('Transaction broadcasted. Wait for Coinbase confirmation...');
this.checkTransaction(1, txSent);
}).catch((err: any) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
return;
});
}).catch((err: any) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
return;
});
@ -374,11 +357,16 @@ export class SellCoinbasePage {
this.processPaymentInfo();
}
public goBackHome() {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(CoinbasePage, { coin: 'btc' });
public openSuccessModal(): void {
let successText = 'Funds sent to Coinbase Account';
let successComment = 'The transaction is not yet confirmed, and will show as "Pending" in your Activity. The bitcoin sale will be completed automatically once it is confirmed by Coinbase';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(CoinbasePage, { coin: 'btc' });
});
}
}

View File

@ -4,14 +4,6 @@
</ion-header>
<ion-content>
<ion-card *ngIf="sendStatus === 'success'">
<ion-card-header>
Bought
</ion-card-header>
<ion-card-content>
A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business day
</ion-card-content>
</ion-card>
<ion-list *ngIf="buyInfo">
<ion-item>
<div class="buying-label">
@ -32,9 +24,9 @@
<div>Receive in</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg" class="icon-wallet"
/>
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg"
class="icon-wallet" />
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
@ -63,10 +55,6 @@
</ion-list>
</ion-content>
<ion-footer *ngIf="sendStatus != 'success'">
<ion-footer>
<button ion-button block class="button-footer" (click)="buyConfirm()" [disabled]="!wallet">Confirm purchase</button>
</ion-footer>
<ion-footer *ngIf="sendStatus === 'success'">
<button ion-button block class="button-footer" (click)="goBackHome()">Accept and back home</button>
</ion-footer>

View File

@ -1,7 +1,10 @@
import { Component } from '@angular/core';
import { NavController, NavParams, Events } from 'ionic-angular';
import { NavController, NavParams, Events, ModalController } from 'ionic-angular';
import { Logger } from '@nsalaun/ng-logger';
//pages
import { SuccessModalPage } from '../../../success/success';
//providers
import { PlatformProvider } from '../../../../providers/platform/platform';
import { PopupProvider } from '../../../../providers/popup/popup';
@ -20,7 +23,6 @@ import * as _ from 'lodash';
export class BuyGlideraPage {
public isCordova: boolean;
public sendStatus: string;
public token: string;
public isFiat: boolean;
public network: string;
@ -45,6 +47,7 @@ export class BuyGlideraPage {
private profileProvider: ProfileProvider,
private txFormatProvider: TxFormatProvider,
private walletProvider: WalletProvider,
private modalCtrl: ModalController
) {
this.coin = 'btc';
this.isCordova = this.platformProvider.isCordova;
@ -70,7 +73,6 @@ export class BuyGlideraPage {
}
private showErrorAndBack(err): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err || '';
this.popupProvider.ionicAlert('Error', err).then(() => {
@ -79,22 +81,11 @@ export class BuyGlideraPage {
}
private showError(err): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err);
}
private statusChangeHandler(processName: string, isOn: boolean): void {
let showName = this.onGoingProcessProvider.getShowName(processName);
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'buyingBitcoin' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private processPaymentInfo(): void {
this.onGoingProcessProvider.set('connectingGlidera', true);
this.glideraProvider.init((err, data) => {
@ -149,18 +140,15 @@ export class BuyGlideraPage {
this.popupProvider.ionicConfirm(null, message, okText, cancelText).then((ok) => {
if (!ok) return;
this.onGoingProcessProvider.set('buyingBitcoin', true);
this.statusChangeHandler('buyingBitcoin', true);
this.glideraProvider.get2faCode(this.token, (err, tfa) => {
if (err) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
return;
}
this.ask2FaCode(tfa.mode, (twoFaCode) => {
if (tfa.mode != 'NONE' && _.isEmpty(twoFaCode)) {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError('No code entered');
return;
}
@ -175,13 +163,12 @@ export class BuyGlideraPage {
};
this.glideraProvider.buy(this.token, twoFaCode, data, (err, data) => {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
if (err) return this.showError(err);
this.logger.info(data);
this.openSuccessModal();
});
}).catch(() => {
this.onGoingProcessProvider.set('buyingBitcoin', false);
this.statusChangeHandler('buyingBitcoin', false);
this.showError(err);
});
});
@ -211,10 +198,14 @@ export class BuyGlideraPage {
this.processPaymentInfo();
}
public goBackHome(): void {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
public openSuccessModal(): void {
let successText = 'Bought';
let successComment = 'A transfer has been initiated from your bank account. Your bitcoins should arrive to your wallet in 2-4 business day';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
})
}
}

View File

@ -5,15 +5,6 @@
</ion-header>
<ion-content>
<ion-card *ngIf="sendStatus === 'success'">
<ion-card-header>
Funds sent to Glidera Account
</ion-card-header>
<ion-card-content>
The transaction is not yet confirmed, and will show as "Pending" in your Activity. The bitcoin sale will be completed automatically
once it is confirmed by Glidera.
</ion-card-content>
</ion-card>
<ion-list *ngIf="sellInfo">
<ion-item>
<div class="selling-label">
@ -31,15 +22,15 @@
<ion-item-group class="info">
<button ion-item (click)="showWallets()" class="wallets-list">
<div>From</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
<div>From</div>
<div class="wallet">
<img *ngIf="network == 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet-testnet.svg"
class="icon-wallet" />
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg" class="icon-wallet"
/>
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
<img *ngIf="network != 'testnet'" [ngStyle]="{'background-color': wallet && wallet.color}" src="assets/img/icon-wallet.svg"
class="icon-wallet" />
<span>{{wallet ? wallet.name : '...'}}</span>
</div>
</button>
<ion-item-divider color="light">
Transaction details
</ion-item-divider>
@ -65,10 +56,6 @@
</ion-list>
</ion-content>
<ion-footer *ngIf="sendStatus != 'success'">
<ion-footer>
<button ion-button block class="button-footer" (click)="sellConfirm()" [disabled]="!wallet">Confirm sale</button>
</ion-footer>
<ion-footer *ngIf="sendStatus === 'success'">
<button ion-button block class="button-footer" (click)="goBackHome()">Accept and back home</button>
</ion-footer>

View File

@ -1,8 +1,11 @@
import { Component } from '@angular/core';
import { NavController, NavParams, Events } from 'ionic-angular';
import { NavController, NavParams, Events, ModalController } from 'ionic-angular';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
//pages
import { SuccessModalPage } from '../../../success/success';
//providers
import { PlatformProvider } from '../../../../providers/platform/platform';
import { PopupProvider } from '../../../../providers/popup/popup';
@ -20,7 +23,6 @@ import { ConfigProvider } from '../../../../providers/config/config';
export class SellGlideraPage {
public isCordova: boolean;
public sendStatus: string;
public token: string;
public isFiat: boolean;
public network: string;
@ -45,7 +47,8 @@ export class SellGlideraPage {
private txFormatProvider: TxFormatProvider,
private walletProvider: WalletProvider,
private configProvider: ConfigProvider,
private events: Events
private events: Events,
private modalCtrl: ModalController
) {
this.coin = 'btc';
this.isCordova = this.platformProvider.isCordova;
@ -74,7 +77,6 @@ export class SellGlideraPage {
}
private showErrorAndBack(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err).then(() => {
@ -83,22 +85,11 @@ export class SellGlideraPage {
}
private showError(err: any): void {
this.sendStatus = '';
this.logger.error(err);
err = err.errors ? err.errors[0].message : err;
this.popupProvider.ionicAlert('Error', err);
}
private statusChangeHandler(processName: string, isOn: boolean): void {
let showName = this.onGoingProcessProvider.getShowName(processName);
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'sellingBitcoin' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private processPaymentInfo(): void {
this.onGoingProcessProvider.set('connectingGlidera', true);
this.glideraProvider.init((err, data) => {
@ -153,18 +144,15 @@ export class SellGlideraPage {
this.popupProvider.ionicConfirm(null, message, okText, cancelText).then((ok) => {
if (!ok) return;
this.onGoingProcessProvider.set('sellingBitcoin', true);
this.statusChangeHandler('sellingBitcoin', true)
this.glideraProvider.get2faCode(this.token, (err, tfa) => {
if (err) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
return;
}
this.ask2FaCode(tfa.mode, (twoFaCode) => {
if (tfa.mode != 'NONE' && _.isEmpty(twoFaCode)) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError('No code entered');
return;
}
@ -177,14 +165,12 @@ export class SellGlideraPage {
this.walletProvider.getAddress(this.wallet, false).then((refundAddress) => {
if (!refundAddress) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError('Could not create address');
return;
}
this.glideraProvider.getSellAddress(this.token, (err, sellAddress) => {
if (!sellAddress || err) {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
return;
}
@ -228,13 +214,12 @@ export class SellGlideraPage {
};
this.glideraProvider.sell(this.token, twoFaCode, data, (err, data) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
if (err) return this.showError(err);
this.logger.info(data);
this.openSuccessModal();
});
}).catch((err) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
this.walletProvider.removeTx(this.wallet, publishedTxp).catch((err) => { // TODO in the original code use signedTxp on this function
if (err) this.logger.debug(err);
@ -242,17 +227,14 @@ export class SellGlideraPage {
});
}).catch((err) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
});
}).catch((err) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
});
}).catch((err) => {
this.onGoingProcessProvider.set('sellingBitcoin', false);
this.statusChangeHandler('sellingBitcoin', false);
this.showError(err);
});
});
@ -284,9 +266,15 @@ export class SellGlideraPage {
});
}
public goBackHome(): void {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
public openSuccessModal(): void {
let successText = 'Funds sent to Glidera Account';
let successComment = 'The transaction is not yet confirmed, and will show as "Pending" in your Activity. The bitcoin sale will be completed automatically once it is confirmed by Glidera';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
});
}
}

View File

@ -1,7 +1,7 @@
<ion-header>
<ion-navbar>
<ion-title>Buy</ion-title>
<ion-title>{{'Buy'|translate}}</ion-title>
</ion-navbar>
</ion-header>
@ -36,19 +36,24 @@
<ion-item>
<span translate>Gift Card</span>
<ion-note item-end>
{{amount | currency:'$ ':2}}<span *ngIf="amount"> {{currencyIsoCode}}</span>
{{amount | currency:'$ ':2}}
<span *ngIf="amount"> {{currencyIsoCode}}</span>
</ion-note>
</ion-item>
<ion-item>
<span translate>Network Cost</span>
<ion-note item-end>
<span>{{invoiceFee | currency:'$ ':2}}<span *ngIf="invoiceFee"> {{currencyIsoCode}}</span></span>
<span>{{invoiceFee | currency:'$ ':2}}
<span *ngIf="invoiceFee"> {{currencyIsoCode}}</span>
</span>
</ion-note>
</ion-item>
<ion-item>
<span translate>Miner Fee</span>
<ion-note item-end>
<span>{{networkFee | currency:'$ ':2}}<span *ngIf="networkFee"> {{currencyIsoCode}}</span></span>
<span>{{networkFee | currency:'$ ':2}}
<span *ngIf="networkFee"> {{currencyIsoCode}}</span>
</span>
</ion-note>
</ion-item>
<ion-item>
@ -63,22 +68,6 @@
</ion-list>
</ion-content>
<ion-footer *ngIf="!mlGiftCard">
<button ion-button block class="button-footer" (click)="buyConfirm()" [disabled]="!(wallet && totalAmountStr)" translate>Confirm purchase</button>
</ion-footer>
<ion-footer *ngIf="mlGiftCard">
<span *ngIf="mlGiftCard.status == 'FAILURE'" translate>
Sua compra não pôde ser concluída
</span>
<span *ngIf="mlGiftCard.status == 'PENDING'" translate>
Sua compra foi adicionada à lista de pendentes
</span>
<span *ngIf="mlGiftCard.status == 'SUCCESS' || mlGiftCard.status == 'active'" translate>
Comprou {{mlGiftCard.amount}} {{mlGiftCard.currency}}
</span>
<div *ngIf="mlGiftCard.status == 'SUCCESS' || mlGiftCard.cardStatus == 'active'" translate>
Vale-Presente gerado e pronto para usar
</div>
<button ion-button block class="button-footer" (click)="goBackHome()" [disabled]="!(wallet && totalAmountStr)" translate>Accept and back home</button>
<ion-footer>
<button ion-button block class="button-footer" (click)="buyConfirm()" [disabled]="!(wallet && totalAmountStr)">Confirmar a compra</button>
</ion-footer>

View File

@ -7,6 +7,7 @@ import * as moment from 'moment';
// Pages
import { FeeWarningPage } from '../../../../pages/send/fee-warning/fee-warning';
import { MercadoLibreCardsPage } from '../../../../pages/integrations/mercado-libre/mercado-libre-cards/mercado-libre-cards';
import { SuccessModalPage } from '../../../success/success';
// Provider
import { MercadoLibreProvider } from '../../../../providers/mercado-libre/mercado-libre';
@ -42,7 +43,6 @@ export class BuyMercadoLibrePage {
public invoiceFee: number;
public networkFee: number;
public totalAmount: number;
public sendStatus: string;
public mlGiftCard: any;
public amountUnitStr: string;
public limitPerDayMessage: string;
@ -118,7 +118,6 @@ export class BuyMercadoLibrePage {
private showErrorAndBack(title: string, msg: any) {
title = title ? title : 'Error'; // TODO: gettextCatalog
this.sendStatus = '';
this.logger.error(msg);
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
this.popupProvider.ionicAlert(title, msg).then(() => {
@ -129,7 +128,6 @@ export class BuyMercadoLibrePage {
private showError = function (title: string, msg: any): Promise<any> {
return new Promise((resolve, reject) => {
title = title || 'Error'; // TODO: gettextCatalog
this.sendStatus = '';
this.logger.error(msg);
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
this.popupProvider.ionicAlert(title, msg).then(() => {
@ -138,7 +136,7 @@ export class BuyMercadoLibrePage {
});
}
private publishAndSign(wallet: any, txp: any, onSendStatusChange: any): Promise<any> {
private publishAndSign(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
let err = 'No signing proposal: No private key'; // TODO: gettextCatalog
@ -146,7 +144,7 @@ export class BuyMercadoLibrePage {
return reject(err);
}
this.walletProvider.publishAndSign(wallet, txp, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
return resolve(txp);
}).catch((err: any) => {
return reject(err);
@ -154,15 +152,6 @@ export class BuyMercadoLibrePage {
});
}
private statusChangeHandler(processName: string, showName: string, isOn: boolean) {
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'buyingGiftCard' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private satToFiat(sat: number): Promise<any> {
return new Promise((resolve, reject) => {
this.txFormatProvider.toFiat(this.coin, sat, this.currencyIsoCode).then((value: string) => {
@ -274,15 +263,13 @@ export class BuyMercadoLibrePage {
this.mercadoLibreProvider.createGiftCard(dataSrc, (err, giftCard) => {
this.logger.debug("creating gift card " + count);
if (err) {
this.sendStatus = '';
this.onGoingProcessProvider.set('Comprando Vale-Presente', false, this.statusChangeHandler);
this.onGoingProcessProvider.set('Comprando Vale-Presente', false);
giftCard = giftCard || {};
giftCard['status'] = 'FAILURE';
}
if (giftCard && giftCard.cardStatus && (giftCard.cardStatus != 'active' && giftCard.cardStatus != 'inactive' && giftCard.cardStatus != 'expired')) {
this.sendStatus = '';
this.onGoingProcessProvider.set('Comprando Vale-Presente', false, this.statusChangeHandler);
this.onGoingProcessProvider.set('Comprando Vale-Presente', false);
giftCard = giftCard || {};
giftCard['status'] = 'FAILURE';
}
@ -308,9 +295,10 @@ export class BuyMercadoLibrePage {
}
this.mercadoLibreProvider.savePendingGiftCard(newData, null, (err: any) => {
this.onGoingProcessProvider.set('Comprando Vale-Presente', false, this.statusChangeHandler);
this.onGoingProcessProvider.set('Comprando Vale-Presente', false);
this.logger.debug("Saved new gift card with status: " + newData.status);
this.mlGiftCard = newData;
this.openSuccessModal();
});
});
}, 8000, {
@ -385,12 +373,11 @@ export class BuyMercadoLibrePage {
var cancelText = 'Cancel'; // TODO: gettextCatalog
this.popupProvider.ionicConfirm(title, this.message, okText, cancelText).then((ok) => {
if (!ok) {
this.sendStatus = '';
return;
}
this.publishAndSign(this.wallet, this.createdTx, function () { }).then((txSent) => {
this.onGoingProcessProvider.set('Comprando Vale-Presente', true, this.statusChangeHandler);
this.publishAndSign(this.wallet, this.createdTx).then((txSent) => {
this.onGoingProcessProvider.set('Comprando Vale-Presente', true);
this.checkTransaction(1, this.createdTx.giftData);
}).catch((err: any) => {
this._resetValues();
@ -405,13 +392,6 @@ export class BuyMercadoLibrePage {
this.initialize(wallet);
}
public goBackHome(): void {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(MercadoLibreCardsPage, { invoiceId: this.invoiceId });
}
public showWallets(): void {
let id = this.wallet ? this.wallet.credentials.walletId : null;
this.events.publish('showWalletsSelectorEvent', this.wallets, id, 'Buy from');
@ -421,4 +401,25 @@ export class BuyMercadoLibrePage {
});
}
public openSuccessModal(): void {
let successComment: string;
if (this.mlGiftCard.status == 'FAILURE') {
successComment = 'Sua compra não pôde ser concluída';
}
if (this.mlGiftCard.status == 'PENDING') {
successComment = 'Sua compra foi adicionada à lista de pendentes';
}
if (this.mlGiftCard.status == 'SUCCESS' || this.mlGiftCard.cardStatus == 'active') {
successComment = 'Vale-Presente gerado e pronto para usar';
}
let successText = '';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText, successComment: successComment }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(MercadoLibreCardsPage, { invoiceId: this.invoiceId });
});
}
}

View File

@ -79,10 +79,4 @@
<button ion-button block class="button-footer" (click)="confirmTx()" [disabled]="!fromWallet || !totalAmountStr" translate>
Click to shift
</button>
</ion-footer>
<ion-footer *ngIf="sendStatus === 'success'">
<button ion-button block class="button-footer" (click)="goBackHome()" [disabled]="!(wallet && totalAmountStr)" translate>
Transaction Sent
</button>
</ion-footer>

View File

@ -6,6 +6,7 @@ import * as _ from 'lodash';
// Pages
import { ShapeshiftPage } from '../shapeshift';
import { SuccessModalPage } from '../../../success/success';
// Providers
import { BwcProvider } from '../../../../providers/bwc/bwc';
@ -19,6 +20,7 @@ import { ProfileProvider } from '../../../../providers/profile/profile';
import { ShapeshiftProvider } from '../../../../providers/shapeshift/shapeshift';
import { TxFormatProvider } from '../../../../providers/tx-format/tx-format';
import { WalletProvider } from '../../../../providers/wallet/wallet';
import { ModalController } from 'ionic-angular/components/modal/modal-controller';
@Component({
selector: 'page-shapeshift-confirm',
@ -39,7 +41,6 @@ export class ShapeshiftConfirmPage {
public currencyIsoCode: string;
public isCordova: boolean;
public sendStatus: string;
public toWallet: any;
public fromWallet: any;
public fiatWithdrawal: number;
@ -70,7 +71,8 @@ export class ShapeshiftConfirmPage {
private profileProvider: ProfileProvider,
private shapeshiftProvider: ShapeshiftProvider,
private txFormatProvider: TxFormatProvider,
private walletProvider: WalletProvider
private walletProvider: WalletProvider,
private modalCtrl: ModalController
) {
this.configWallet = this.configProvider.get().wallet;
this.currencyIsoCode = 'USD'; // Only USD
@ -124,7 +126,6 @@ export class ShapeshiftConfirmPage {
private showErrorAndBack(title: string, msg: any) {
title = title ? title : 'Error'; // TODO: gettextCatalog
this.sendStatus = '';
this.logger.error(msg);
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
this.popupProvider.ionicAlert(title, msg).then(() => {
@ -132,7 +133,7 @@ export class ShapeshiftConfirmPage {
});
};
private publishAndSign(wallet: any, txp: any, onSendStatusChange: any): Promise<any> {
private publishAndSign(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
let err = 'No signing proposal: No private key'; // TODO: gettextCatalog
@ -140,7 +141,7 @@ export class ShapeshiftConfirmPage {
return reject(err);
}
this.walletProvider.publishAndSign(wallet, txp, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
return resolve(txp);
}).catch((err: any) => {
return reject(err);
@ -148,15 +149,6 @@ export class ShapeshiftConfirmPage {
});
}
private statusChangeHandler(processName: string, showName: string, isOn: boolean) {
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (processName == 'sendingTx' && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
}
private satToFiat(coin: string, sat: number, isoCode: string): Promise<any> {
return new Promise((resolve, reject) => {
this.txFormatProvider.toFiat(coin, sat, isoCode).then((value: any) => {
@ -196,6 +188,7 @@ export class ShapeshiftConfirmPage {
this.shapeshiftProvider.saveShapeshift(newData, null, (err: any) => {
this.logger.debug("Saved shift with status: " + newData.status);
this.openSuccessModal();
});
});
}
@ -330,13 +323,12 @@ export class ShapeshiftConfirmPage {
let cancelText = 'Cancel'; // TODO: gettextCatalog
this.popupProvider.ionicConfirm(title, '', okText, cancelText).then((ok: any) => {
if (!ok) {
this.sendStatus = '';
return;
}
this.onGoingProcessProvider.set('sendingTx', true, this.statusChangeHandler);
this.publishAndSign(this.fromWallet, this.createdTx, function () { }).then((txSent: any) => {
this.onGoingProcessProvider.set('sendingTx', false, this.statusChangeHandler);
this.onGoingProcessProvider.set('sendingTx', true);
this.publishAndSign(this.fromWallet, this.createdTx).then((txSent: any) => {
this.onGoingProcessProvider.set('sendingTx', false);
this.txSent = txSent;
this.saveShapeshiftData();
}).catch((err: any) => {
@ -346,11 +338,15 @@ export class ShapeshiftConfirmPage {
});
};
public goBackHome() {
this.sendStatus = '';
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(ShapeshiftPage);
public openSuccessModal(): void {
let successText = 'Transaction Sent';
let modal = this.modalCtrl.create(SuccessModalPage, { successText: successText }, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.remove(3, 1);
this.navCtrl.pop();
this.navCtrl.push(ShapeshiftPage);
});
}
}

View File

@ -19,7 +19,8 @@
</ion-item>
<button ion-item class="item item-icon-right item-fee" (click)="chooseFeeLevel()">
{{'Fee:' | translate}} <strong>{{tx.feeLevelName | translate}}</strong>
{{'Fee:' | translate}}
<strong>{{tx.feeLevelName | translate}}</strong>
<div *ngIf="!wallet || !tx.txp[wallet.id]">
<span>...</span>
<ion-note>
@ -125,4 +126,4 @@
<ion-footer>
<button ion-button block class="button-footer" (click)="approve(tx, wallet, statusChangeHandler)" [disabled]="!wallet" translate>Click to send</button>
</ion-footer>
</ion-footer>

View File

@ -8,6 +8,7 @@ import { SendPage } from '../../send/send';
import { PayProPage } from '../../paypro/paypro';
import { ChooseFeeLevelPage } from '../choose-fee-level/choose-fee-level';
import { FeeWarningPage } from '../fee-warning/fee-warning';
import { SuccessModalPage } from '../../success/success';
// Providers
import { ConfigProvider } from '../../../providers/config/config';
@ -41,7 +42,6 @@ export class ConfirmPage {
public buttonText: string;
public paymentExpired: boolean;
public remainingTimeStr: string;
public sendStatus: string;
// Config Related values
public config: any;
@ -470,7 +470,6 @@ export class ConfirmPage {
}
private setSendError(msg: string) {
this.sendStatus = '';
this.popupProvider.ionicAlert('Error at confirm', this.bwcErrorProvider.msg(msg)); // TODO gettextCatalog
}
@ -494,18 +493,17 @@ export class ConfirmPage {
});
};
public approve(tx: any, wallet: any, onSendStatusChange: Function): void {
public approve(tx: any, wallet: any): void {
if (!tx || !wallet) return;
if (this.paymentExpired) {
this.popupProvider.ionicAlert(null, 'This bitcoin payment request has expired.'); // TODO gettextCatalog
this.sendStatus = '';
return;
}
this.onGoingProcessProvider.set('creatingTx', true, onSendStatusChange);
this.onGoingProcessProvider.set('creatingTx', true);
this.getTxp(_.clone(tx), wallet, false).then((txp: any) => {
this.onGoingProcessProvider.set('creatingTx', false, onSendStatusChange);
this.onGoingProcessProvider.set('creatingTx', false);
// confirm txs for more that 20usd, if not spending/touchid is enabled
let confirmTx = (): Promise<any> => {
@ -534,20 +532,20 @@ export class ConfirmPage {
let publishAndSign = (): void => {
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
this.logger.info('No signing proposal: No private key');
this.walletProvider.onlyPublish(wallet, txp, onSendStatusChange).catch((err: any) => {
this.walletProvider.onlyPublish(wallet, txp).catch((err: any) => {
this.setSendError(err);
});
this.onSuccessConfirm(); // TODO review this line
this.openSuccessModal();
return;
}
this.walletProvider.publishAndSign(wallet, txp, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(wallet, txp).then((txp: any) => {
if (this.config.confirmedTxsNotifications && this.config.confirmedTxsNotifications.enabled) {
this.txConfirmNotificationProvider.subscribe(wallet, {
txid: txp.txid
});
}
this.onSuccessConfirm(); // TODO review this line
this.openSuccessModal();
}).catch((err: any) => {
this.setSendError(err);
return;
@ -556,7 +554,6 @@ export class ConfirmPage {
confirmTx().then((nok: boolean) => {
if (nok) {
this.sendStatus = '';
return;
}
publishAndSign();
@ -570,27 +567,16 @@ export class ConfirmPage {
});
}
public statusChangeHandler(processName: string, showName: string, isOn: boolean): void {
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (
(
processName === 'broadcastingTx' ||
((processName === 'signingTx') && this.wallet.m > 1) ||
(processName == 'sendingTx' && !this.wallet.canSign() && !this.wallet.isPrivKeyExternal())
) && !isOn) {
this.sendStatus = 'success';
} else if (showName) {
this.sendStatus = showName;
}
public openSuccessModal() {
let modal = this.modalCtrl.create(SuccessModalPage, {}, { showBackdrop: true, enableBackdropDismiss: false });
modal.present();
modal.onDidDismiss(() => {
this.navCtrl.setRoot(SendPage);
this.navCtrl.popToRoot();
this.navCtrl.parent.select(0);
})
}
public onSuccessConfirm(): void {
this.sendStatus = '';
this.navCtrl.setRoot(SendPage);
this.navCtrl.popToRoot();
this.navCtrl.parent.select(0);
};
public openPPModal(): void {
this.modalCtrl.create(PayProPage, {}, {
showBackdrop: true,

View File

@ -0,0 +1,16 @@
<div class="container">
<div class="content">
<div class="success">
<img class="success-img" src="assets/img/onboarding-success.svg">
<div class="success-text">
{{successText}}
</div>
<div class="success-comment">
{{successComment}}
</div>
</div>
</div>
<div class="footer" (click)="close()">
OK
</div>
</div>

View File

@ -0,0 +1,44 @@
page-success{
.container {
background-color: #11D1A6;
height: 100%;
position: relative;
.content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.success {
margin-top: -20vh;
text-align: center;
&-img {
padding: 3rem;
}
&-text {
font-size: 2.8rem;
color: #ffffff;
}
&-comment {
padding: 2rem;
font-size: 2rem;
color: #ffffff;
}
}
}
.footer {
padding: 2rem;
margin: 0 1.75rem;
border-top: 0.1rem solid rgba(255, 255, 255, 0.45);
position: absolute;
bottom: 0rem;
left: 0rem;
right: 0rem;
text-align: center;
color: #ffffff;
font-size: 2rem;
letter-spacing: 2.86px;
font-weight: 600;
cursor: pointer;
}
}
}

View File

@ -0,0 +1,24 @@
import { Component } from '@angular/core';
import { ViewController, NavParams } from 'ionic-angular';
@Component({
selector: 'page-success',
templateUrl: 'success.html',
})
export class SuccessModalPage {
public successText: string;
public successComment: string;
constructor(
private viewCtrl: ViewController,
private navParams: NavParams
) {
this.successText = this.navParams.data.successText ? this.navParams.data.successText : 'Payment Sent';
this.successComment = this.navParams.data.successComment ? this.navParams.data.successComment : '';
}
public close(): void {
this.viewCtrl.dismiss();
}
}

View File

@ -32,7 +32,6 @@ export class TxpDetailsPage {
public actionList: Array<any>;
public paymentExpired: boolean;
public expires: string;
public sendStatus: string;
public currentSpendUnconfirmed: boolean;
public loading: boolean;
@ -106,8 +105,6 @@ export class TxpDetailsPage {
}
});
});
this.statusChangeHandler = this.statusChangeHandler;
}
private displayFeeValues(): void {
@ -211,11 +208,11 @@ export class TxpDetailsPage {
this.popupProvider.ionicAlert('Error', this.bwcError.msg(err, prefix)); //TODO gettextcatalog
}
public sign(onSendStatusChange?: any): void {
public sign(): void {
this.loading = true;
this.walletProvider.publishAndSign(this.wallet, this.tx, onSendStatusChange).then((txp: any) => {
this.walletProvider.publishAndSign(this.wallet, this.tx).then((txp: any) => {
this.events.publish('UpdateTx');
this.success();
//this.success(); TODO
}).catch((err: any) => {
this.setError(err, 'Could not send payment'); //TODO gettextcatalog
});
@ -300,19 +297,8 @@ export class TxpDetailsPage {
});
}
private statusChangeHandler(processName: string, showName: string, isOn: boolean): void {
this.logger.debug('statusChangeHandler: ', processName, showName, isOn);
if (showName) {
this.sendStatus = showName;
}
}
private success(): void {
this.sendStatus = 'success';
}
public onConfirm(): void {
this.sign(this.statusChangeHandler);
this.sign();
};
public onSuccessConfirm(): void {

View File

@ -41,8 +41,8 @@ export class GlideraProvider {
* Development: 'testnet'
* Production: 'livenet'
*/
this.credentials.NETWORK = 'livenet';
//this.credentials.NETWORK = 'testnet';
//this.credentials.NETWORK = 'livenet';
this.credentials.NETWORK = 'testnet';
if (this.credentials.NETWORK == 'testnet') {
this.credentials.HOST = glidera.sandbox.host;

View File

@ -66,7 +66,7 @@ export class OnGoingProcessProvider {
this.loading.dismiss();
};
public set(processName: string, isOn: boolean, customHandler?: any): string {
public set(processName: string, isOn: boolean): string {
this.logger.debug('ongoingProcess', processName, isOn);
let showName = this.processNames[processName];
if (!isOn) {

View File

@ -433,7 +433,7 @@ export class WalletProvider {
let LIMIT = 50;
let requestLimit = FIRST_LIMIT;
let walletId = wallet.credentials.walletId;
this.progressFn[walletId] = opts.progressFn || (() => {});
this.progressFn[walletId] = opts.progressFn || (() => { });
let foundLimitTx = [];
if (opts.feeLevels) {
@ -1119,12 +1119,12 @@ export class WalletProvider {
});
}
public onlyPublish(wallet: any, txp: any, customStatusHandler: any): Promise<any> {
public onlyPublish(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
this.ongoingProcess.set('sendingTx', true, customStatusHandler);
this.ongoingProcess.set('sendingTx', true);
this.publishTx(wallet, txp).then((publishedTxp) => {
this.invalidateCache(wallet);
this.ongoingProcess.set('sendingTx', false, customStatusHandler);
this.ongoingProcess.set('sendingTx', false);
this.events.publish('Local/TxAction', wallet.id);
return resolve();
}).catch((err) => {
@ -1147,17 +1147,17 @@ export class WalletProvider {
});
}
private signAndBroadcast(wallet: any, publishedTxp: any, password: any, customStatusHandler: any): Promise<any> {
private signAndBroadcast(wallet: any, publishedTxp: any, password: any): Promise<any> {
return new Promise((resolve, reject) => {
this.ongoingProcess.set('signingTx', true, customStatusHandler);
this.ongoingProcess.set('signingTx', true);
this.signTx(wallet, publishedTxp, password).then((signedTxp: any) => {
this.ongoingProcess.set('signingTx', false, customStatusHandler);
this.ongoingProcess.set('signingTx', false);
this.invalidateCache(wallet);
if (signedTxp.status == 'accepted') {
this.ongoingProcess.set('broadcastingTx', true, customStatusHandler);
this.ongoingProcess.set('broadcastingTx', true);
this.broadcastTx(wallet, signedTxp).then((broadcastedTxp: any) => {
this.ongoingProcess.set('broadcastingTx', false, customStatusHandler);
this.ongoingProcess.set('broadcastingTx', false);
this.events.publish('Local/TxAction', wallet.id);
return resolve(broadcastedTxp);
}).catch((err) => {
@ -1176,12 +1176,12 @@ export class WalletProvider {
});
}
public publishAndSign(wallet: any, txp: any, customStatusHandler: any): Promise<any> {
public publishAndSign(wallet: any, txp: any): Promise<any> {
return new Promise((resolve, reject) => {
// Already published?
if (txp.status == 'pending') {
this.prepare(wallet).then((password: string) => {
this.signAndBroadcast(wallet, txp, password, customStatusHandler).then((broadcastedTxp: any) => {
this.signAndBroadcast(wallet, txp, password).then((broadcastedTxp: any) => {
return resolve(broadcastedTxp);
}).catch((err) => {
return reject(err);
@ -1191,16 +1191,16 @@ export class WalletProvider {
});
} else {
this.prepare(wallet).then((password: string) => {
this.ongoingProcess.set('sendingTx', true, customStatusHandler);
this.ongoingProcess.set('sendingTx', true);
this.publishTx(wallet, txp).then((publishedTxp: any) => {
this.ongoingProcess.set('sendingTx', false, customStatusHandler);
this.signAndBroadcast(wallet, publishedTxp, password, customStatusHandler).then((broadcastedTxp: any) => {
this.ongoingProcess.set('sendingTx', false);
this.signAndBroadcast(wallet, publishedTxp, password).then((broadcastedTxp: any) => {
return resolve(broadcastedTxp);
}).catch((err) => {
return reject(err);
});
}).catch((err) => {
this.ongoingProcess.set('sendingTx', false, customStatusHandler);
this.ongoingProcess.set('sendingTx', false);
return reject(this.bwcErrorProvider.msg(err));
});
}).catch((err) => {