Merge pull request #7025 from gabrielbazan7/feat/getAddrTest

Ref Receive view
This commit is contained in:
Javier Donadío 2017-11-03 09:47:32 -03:00 committed by GitHub
commit 094a6837f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 315 additions and 14 deletions

View File

@ -27,6 +27,7 @@ import { CopayApp } from './app.component';
import { TabsPage } from '../pages/tabs/tabs';
import { AddPage } from '../pages/add/add';
import { CreateWalletPage } from '../pages/add/create-wallet/create-wallet';
import { CopayersPage } from '../pages/copayers/copayers';
import { ImportWalletPage } from '../pages/add/import-wallet/import-wallet';
import { JoinWalletPage } from '../pages/add/join-wallet/join-wallet';
import { BackupRequestPage } from '../pages/onboarding/backup-request/backup-request';
@ -89,6 +90,7 @@ export function createTranslateLoader(http: Http) {
let pages: any = [
AddPage,
CreateWalletPage,
CopayersPage,
ImportWalletPage,
JoinWalletPage,
BackupWarningPage,
@ -178,7 +180,7 @@ export function providersComponents() {
@NgModule({
declarations: declarationsComponents(),
imports: [
IonicModule.forRoot(CopayApp, {
IonicModule.forRoot(CopayApp, {
tabsHideOnSubPages: true,
modalEnter: 'modal-slide-in',
modalLeave: 'modal-slide-out',

View File

@ -0,0 +1,8 @@
<ion-header>
<ion-navbar>
</ion-navbar>
</ion-header>
<ion-content padding>
</ion-content>

View File

View File

@ -0,0 +1,13 @@
import { Component } from '@angular/core';
@Component({
selector: 'page-copayers',
templateUrl: 'copayers.html',
})
export class CopayersPage {
constructor(
) {
}
}

View File

@ -1,27 +1,52 @@
<ion-header>
<ion-navbar>
<ion-title>{{ "Receive" | translate }}</ion-title>
<ion-title>{{'Receive'|translate}}</ion-title>
<ion-buttons *ngIf="showShareButton" (click)="shareAddress()" end>
<ion-icon name="share"></ion-icon>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<div *ngIf="wallet" class="qr-container">
<ion-content>
<div ng-if="wallet && wallet.isComplete() && wallet.needsBackup" (click)="openBackupNeededModal()" class="needs-backup-container">
<div class="backup">
<ion-icon name="alert"></ion-icon>
<span translate>Wallet not backed up</span>
<ion-icon name="arrow-forward"></ion-icon>
</div>
</div>
<div *ngIf="wallet && wallet.isComplete()" class="qr-container">
<qr-code *ngIf="address" [value]="qrAddress" [level]="M" [size]="220" [foreground]="'#334'"></qr-code>
<div>
<span>{{ address }}</span>
</div>
<div>
<button [hidden]="!address" class="button-request" (click)="requestSpecificAmount()">
<span translate>Request Specific amount</span>
<ion-icon name="arrow-forward"></ion-icon>
</button>
<span translate>Request Specific amount</span>
<ion-icon name="arrow-forward"></ion-icon>
</button>
</div>
<div>
<button [hidden]="!address" class="button-address" (click)="setAddress(true)">
<span translate>Generate new address</span>
<span translate>Generate new address</span>
</button>
</div>
</div>
<div *ngIf="wallet && !wallet.isComplete()" class="incomplete-wallet-container">
<div class="title">
<span translate>Incomplete wallet</span>
</div>
<div class="subtitle">
<span translate>All signing devices must be added to this multisig wallet before bitcoin addresses can be created.</span>
</div>
<button ion-button (click)="goCopayers()" translate>Open wallet</button>
</div>
<div *ngIf="wallets" class="wallets-container" (click)="showWallets()">
<img src="assets/img/icon-wallet.svg" class="icon-wallet">
<div class="wallet-text">
<div>{{wallet.name}}</div>
</div>
</div>
<div *ngIf="!wallet">
<ion-card>
<ion-item>

View File

@ -1,5 +1,27 @@
page-receive {
$v-text-accent-color: #1abb9b;
.incomplete-wallet-container {
.title {
padding-top: 10%;
font-size: 25px;
color: #444;
text-align: center;
}
.subtitle {
padding: 20px;
color: #444;
margin-top: 10%;
text-align: center;
}
}
.needs-backup-container {
.backup {
cursor: pointer;
background-color: orange;
color: #fff;
padding: 5px 0;
}
}
.qr-container {
text-align: center;
margin: auto;
@ -22,4 +44,47 @@ page-receive {
color: $v-text-accent-color;
}
}
.wallets-container {
position: absolute;
bottom: 0rem;
width: 100%;
border-top: solid 1px rgb(242, 242, 242);
min-height: 78px;
display: flex;
align-items: center;
cursor: pointer;
img.icon-wallet {
width: 35px !important;
background-color: #647ce8;
}
.wallet-text {
padding-left: 1rem;
}
}
}
@mixin wallets-list {
height: 4rem;
width: 4rem;
content: " ";
position: absolute;
border-radius: 3px;
box-shadow: 0px 6px 12px 0px rgba(0, 0, 0, 0.3);
}
.wallets::before {
@include wallets-list;
background: #647ce8 url('../assets/img/icon-wallet.svg') no-repeat 0px 0px;
}
.action-sheet-container {
.action-sheet-button {
display: flex;
justify-content: baseline;
align-items: center;
padding: 2.5rem;
.button-inner {
padding-left: 5rem;
}
}
}

View File

@ -1,8 +1,18 @@
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { NavController, NavParams, Events, ActionSheetController, ModalController } from 'ionic-angular';
//native
import { SocialSharing } from '@ionic-native/social-sharing';
//pages
import { AmountPage } from '../send/amount/amount';
import { CopayersPage } from '../copayers/copayers';
import { BackupWarningModalPage } from '../backup/backup-warning-modal/backup-warning-modal';
//providers
import { WalletProvider } from '../../providers/wallet/wallet';
import { ProfileProvider } from '../../providers/profile/profile';
import { PopupProvider } from '../../providers/popup/popup';
import { PlatformProvider } from '../../providers/platform/platform';
import * as _ from 'lodash';
@ -17,12 +27,19 @@ export class ReceivePage {
public qrAddress: string;
public wallets: any;
public wallet: any;
public showShareButton: boolean;
constructor(
private navCtrl: NavController,
private navParams: NavParams,
private profileProvider: ProfileProvider,
private walletProvider: WalletProvider
private walletProvider: WalletProvider,
private popupProvider: PopupProvider,
private platformProvider: PlatformProvider,
private events: Events,
private actionSheetCtrl: ActionSheetController,
private socialSharing: SocialSharing,
private modalCtrl: ModalController
) {
}
@ -34,6 +51,15 @@ export class ReceivePage {
this.wallets = this.profileProvider.getWallets();
this.updateQrAddress();
this.onSelect(this.checkSelectedWallet(this.wallet, this.wallets));
this.showShareButton = this.platformProvider.isCordova;
this.events.subscribe('bwsEvent', (e, walletId, type, n) => {
// Update current address
if (this.wallet && walletId == this.wallet.id && type == 'NewIncomingTx') this.setAddress(true);
});
}
ionViewWillLeave() {
this.events.unsubscribe('bwsEvent');
}
private onSelect(wallet: any): any {
@ -45,7 +71,7 @@ export class ReceivePage {
}
private setProtocolHandler(): void {
this.protocolHandler = this.walletProvider.getProtocolHandler(this.wallet);
this.protocolHandler = this.walletProvider.getProtocolHandler(this.wallet.coin);
}
private checkSelectedWallet(wallet: any, wallets: any): any {
@ -62,11 +88,14 @@ export class ReceivePage {
}
private setAddress(newAddr?: boolean): void {
this.walletProvider.getAddress(this.wallet, newAddr).then((addr) => {
this.address = addr;
this.updateQrAddress();
}).catch((err) => {
console.log(err);
if (err) {
this.popupProvider.ionicAlert(err);
}
});
}
@ -74,4 +103,46 @@ export class ReceivePage {
this.qrAddress = this.protocolHandler + ":" + this.address;
}
public shareAddress(): void {
let protocol = 'bitcoin';
if (this.wallet.coin == 'bch') protocol += 'cash';
this.socialSharing.share(protocol + ':' + this.address);
}
public showWallets(): void {
let buttons: Array<any> = [];
let coinClass: string = "wallets";
this.wallets.forEach((wallet, index) => {
let walletButton: Object = {
text: wallet.credentials.walletName,
cssClass: coinClass,
handler: () => {
this.onSelect(wallet);
}
}
buttons.push(walletButton);
});
const actionSheet = this.actionSheetCtrl.create({
title: 'Select a wallet',
buttons: buttons
});
actionSheet.present();
}
public goCopayers(): void {
this.navCtrl.push(CopayersPage, { walletId: this.wallet.credentials.walletId });
};
public openBackupNeededModal(): void {
const myModal = this.modalCtrl.create(BackupWarningModalPage, {}, {
showBackdrop: true,
enableBackdropDismiss: true,
});
myModal.present();
}
}

View File

@ -0,0 +1,117 @@
import { TestBed, async } from '@angular/core/testing';
import { HttpModule } from '@angular/http';
import { ConfigProvider } from '../config/config';
import { WalletProvider } from './wallet';
import { Logger, Level as LoggerLevel } from '@nsalaun/ng-logger';
import { BwcProvider } from '../bwc/bwc';
import { TxFormatProvider } from '../tx-format/tx-format';
import { PersistenceProvider } from '../persistence/persistence';
import { BwcErrorProvider } from '../bwc-error/bwc-error';
import { RateProvider } from '../rate/rate';
import { Filter } from '../filter/filter';
import { PopupProvider } from '../popup/popup';
import { OnGoingProcess } from '../on-going-process/on-going-process';
import { TouchIdProvider } from '../touchid/touchid';
describe('Provider: Wallet Provider', () => {
let walletProvider: WalletProvider;
class BwcProviderMock {
constructor() {
};
getErrors() {
return "error";
}
}
class PersistenceProviderMock {
constructor() {
};
getLastAddress(walletId: any) {
return Promise.resolve('storedAddress');
}
storeLastAddress(walletId: any, address: any) {
return Promise.resolve(address);
}
}
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [
WalletProvider,
{ provide: ConfigProvider },
{ provide: PersistenceProvider, useClass: PersistenceProviderMock },
{ provide: Logger, useValue: new Logger(LoggerLevel.DEBUG) },
{ provide: TxFormatProvider },
{ provide: BwcProvider, useClass: BwcProviderMock },
{ provide: BwcErrorProvider },
{ provide: RateProvider },
{ provide: Filter },
{ provide: PopupProvider },
{ provide: OnGoingProcess },
{ provide: TouchIdProvider },
],
});
walletProvider = TestBed.get(WalletProvider);
});
describe('Function: Get Address Function', () => {
it('should get the last address stored', () => {
let wallet = {
isComplete: function () {
return true;
}
};
let force = false;
walletProvider.getAddress(wallet, force).then((address) => {
expect(address).toEqual('storedAddress');
});
})
it('should reject to generate new address if wallet is not complete', () => {
let wallet = {
isComplete: function () {
return false;
}
};
let force = true;
walletProvider.getAddress(wallet, force).catch((err) => {
expect(err).toEqual('WALLET_NOT_COMPLETE');
});
})
it('should force to generate new address', () => {
let wallet = {
isComplete: function () {
return true;
},
createAddress: function ({ }, cb) {
return cb(null, { address: 'newAddress' });
}
};
let force = true;
walletProvider.getAddress(wallet, force).then((address) => {
expect(address).toEqual('newAddress');
});
})
});
describe('Function: Get Protocol Handler Function', () => {
it('should return bitcoincash if coin is bch', () => {
let coin = 'bch';
let protocol = walletProvider.getProtocolHandler(coin);
expect(protocol).toEqual('bitcoincash');
})
it('should return bitcoin if coin is btc', () => {
let coin = 'btc';
let protocol = walletProvider.getProtocolHandler(coin);
expect(protocol).toEqual('bitcoin');
})
});
});

View File

@ -1252,8 +1252,8 @@ export class WalletProvider {
});
};
public getProtocolHandler(wallet: any): string {
if (wallet.coin == 'bch') return 'bitcoincash';
public getProtocolHandler(coin: string): string {
if (coin == 'bch') return 'bitcoincash';
else return 'bitcoin';
}