mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #7230 from Gamboster/feat/createSharedWalletsV4
[V4] Feat: Create shared wallets
This commit is contained in:
commit
d1c90816b8
|
@ -29,7 +29,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 { CopayersPage } from '../pages/add/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';
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<ion-header>
|
||||
|
||||
<ion-navbar>
|
||||
<ion-title *ngIf="wallet">{{ wallet.name }}</ion-title>
|
||||
</ion-navbar>
|
||||
|
||||
</ion-header>
|
||||
|
||||
|
||||
<ion-content>
|
||||
<div *ngIf="wallet" [hidden]="wallet.notAuthorized">
|
||||
<ion-list class="copayers-secret">
|
||||
<ion-item>
|
||||
{{ 'Share this invitation with your copayers' | translate }}
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<div class="qr-code-container" copy-to-clipboard="{{ secret }}">
|
||||
<qr-code [level]="L" [size]="220" [foreground]="'#334'" [value]="secret"></qr-code>
|
||||
<div [hidden]="secret" class="spinner">
|
||||
<ion-spinner></ion-spinner>
|
||||
</div>
|
||||
<div class="secret">
|
||||
{{ secret || ('Loading...'|translate) }}
|
||||
</div>
|
||||
</div>
|
||||
<button ion-button type="button" *ngIf="secret" (click)="showDeletePopup()" translate>Cancel invitation</button>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<div [hidden]="!secret">
|
||||
<ion-card class="copayers-card">
|
||||
<ion-card-header>
|
||||
<span translate>Waiting for copayers</span>
|
||||
<span>
|
||||
[ <span translate>{{wallet.m}}-of-{{wallet.n}}</span> ]
|
||||
</span>
|
||||
</ion-card-header>
|
||||
<ion-card-content>
|
||||
<ion-item *ngFor="let copayer of copayers">
|
||||
<span [hidden]="copayer.id != wallet.copayerId">
|
||||
<ion-icon ios="ios-checkmark" md="md-checkmark"></ion-icon>
|
||||
{{'Me'|translate}}
|
||||
</span>
|
||||
<span [hidden]="copayer.id == wallet.copayerId">
|
||||
<ion-icon ios="ios-checkmark" md="md-checkmark"></ion-icon>
|
||||
{{copayer.name}}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item *ngIf="!wallet.isComplete()">
|
||||
<ion-icon ios="ios-repeat" md="md-repeat"></ion-icon> {{'Waiting...'|translate}}
|
||||
</ion-item>
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-card [hidden]="!wallet.notAuthorized" class="errors-card">
|
||||
<h1 translate>Wallet incomplete and broken</h1>
|
||||
<h4 translate>Delete it and create a new one</h4>
|
||||
</ion-card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ion-content>
|
|
@ -0,0 +1,23 @@
|
|||
page-copayers {
|
||||
.copayers-secret {
|
||||
ion-item {
|
||||
text-align: center;
|
||||
}
|
||||
.qr-code-container {
|
||||
cursor: pointer;
|
||||
.secret {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.copayers-card {
|
||||
ion-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.errors-card {
|
||||
color: red;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NavController, NavParams, Events } from 'ionic-angular';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
|
||||
// Pages
|
||||
import { HomePage } from '../../../pages/home/home';
|
||||
import { WalletDetailsPage } from '../../../pages/wallet-details/wallet-details';
|
||||
|
||||
// Providers
|
||||
import { AppProvider } from '../../../providers/app/app';
|
||||
import { BwcErrorProvider } from '../../../providers/bwc-error/bwc-error';
|
||||
import { OnGoingProcessProvider } from "../../../providers/on-going-process/on-going-process";
|
||||
import { PlatformProvider } from '../../../providers/platform/platform';
|
||||
import { PopupProvider } from '../../../providers/popup/popup';
|
||||
import { ProfileProvider } from '../../../providers/profile/profile';
|
||||
import { WalletProvider } from '../../../providers/wallet/wallet';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'page-copayers',
|
||||
templateUrl: 'copayers.html',
|
||||
})
|
||||
export class CopayersPage {
|
||||
|
||||
public appName: string = this.appProvider.info.userVisibleName;
|
||||
public appUrl: string = this.appProvider.info.url;
|
||||
public isCordova: boolean = this.platformProvider.isCordova;
|
||||
|
||||
public wallet: any;
|
||||
public copayers: any;
|
||||
public secret: any;
|
||||
|
||||
constructor(
|
||||
private appProvider: AppProvider,
|
||||
private bwcErrorProvider: BwcErrorProvider,
|
||||
private events: Events,
|
||||
private logger: Logger,
|
||||
private navCtrl: NavController,
|
||||
private navParams: NavParams,
|
||||
private platformProvider: PlatformProvider,
|
||||
private popupProvider: PopupProvider,
|
||||
private profileProvider: ProfileProvider,
|
||||
private onGoingProcessProvider: OnGoingProcessProvider,
|
||||
private walletProvider: WalletProvider
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ionViewDidLoad() {
|
||||
console.log('ionViewDidLoad CopayersPage');
|
||||
this.wallet = this.profileProvider.getWallet(this.navParams.data.walletId);
|
||||
this.updateWallet();
|
||||
|
||||
this.events.subscribe('bwsEvent', (walletId, type, n) => {
|
||||
if (this.wallet && walletId == this.wallet.id && type == ('NewCopayer' || 'WalletComplete')) {
|
||||
this.updateWallet();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ionViewWillLeave() {
|
||||
this.events.unsubscribe('bwsEvent');
|
||||
}
|
||||
|
||||
private updateWallet(): void {
|
||||
this.logger.debug('Updating wallet:' + this.wallet.name)
|
||||
this.walletProvider.getStatus(this.wallet, {}).then((status: any) => {
|
||||
this.wallet.status = status;
|
||||
this.copayers = this.wallet.status.wallet.copayers;
|
||||
this.secret = this.wallet.status.wallet.secret;
|
||||
if (status.wallet.status == 'complete') {
|
||||
this.wallet.openWallet((err: any, status: any) => {
|
||||
if (err)
|
||||
this.logger.error(err);
|
||||
|
||||
this.navCtrl.setRoot(HomePage);
|
||||
this.navCtrl.popToRoot();
|
||||
this.navCtrl.push(WalletDetailsPage, { walletId: this.wallet.credentials.walletId });
|
||||
});
|
||||
}
|
||||
}).catch((err: any) => {
|
||||
this.popupProvider.ionicAlert(this.bwcErrorProvider.msg(err, 'Could not update wallet')); // TODO: GetTextCatalog
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
public showDeletePopup(): void {
|
||||
let title = 'Confirm'; // TODO: GetTextCatalog
|
||||
let msg = 'Are you sure you want to cancel and delete this wallet?'; // TODO: GetTextCatalog
|
||||
this.popupProvider.ionicConfirm(title, msg, 'Ok', 'Cancel').then((res: any) => {
|
||||
if (res) this.deleteWallet();
|
||||
});
|
||||
}
|
||||
|
||||
private deleteWallet(): void {
|
||||
this.onGoingProcessProvider.set('deletingWallet', true);
|
||||
this.profileProvider.deleteWalletClient(this.wallet).then(() => {
|
||||
this.onGoingProcessProvider.set('deletingWallet', false);
|
||||
|
||||
// TODO: pushNotificationsService.unsubscribe(this.wallet);
|
||||
this.navCtrl.setRoot(HomePage);
|
||||
this.navCtrl.popToRoot();
|
||||
this.navCtrl.parent.select(0);
|
||||
}).catch((err: any) => {
|
||||
this.onGoingProcessProvider.set('deletingWallet', false);
|
||||
this.popupProvider.ionicAlert('Error', err.message || err); // TODO: GetTextCatalog
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import { Logger } from '@nsalaun/ng-logger';
|
|||
|
||||
// Pages
|
||||
import { HomePage } from '../../../pages/home/home';
|
||||
import { CopayersPage } from '../copayers/copayers';
|
||||
|
||||
// Providers
|
||||
import { AppProvider } from '../../../providers/app/app';
|
||||
|
@ -260,7 +261,7 @@ export class CreateWalletPage implements OnInit {
|
|||
if (!wallet.isComplete()) {
|
||||
this.navCtrl.setRoot(HomePage);
|
||||
this.navCtrl.popToRoot();
|
||||
// TODO: tabs.copayers (QR view when shared wallet is created)
|
||||
this.navCtrl.push(CopayersPage, { walletId: wallet.credentials.walletId });
|
||||
} else {
|
||||
this.navCtrl.setRoot(HomePage);
|
||||
this.navCtrl.popToRoot();
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
|
||||
</ion-content>
|
|
@ -1,13 +0,0 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'page-copayers',
|
||||
templateUrl: 'copayers.html',
|
||||
})
|
||||
export class CopayersPage {
|
||||
|
||||
constructor(
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +1,20 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { AddPage } from "../add/add";
|
||||
import { ProfileProvider } from '../../providers/profile/profile';
|
||||
import { ReleaseProvider } from '../../providers/release/release';
|
||||
import { WalletProvider } from '../../providers/wallet/wallet';
|
||||
import { BwcErrorProvider } from '../../providers/bwc-error/bwc-error';
|
||||
import { WalletDetailsPage } from '../wallet-details/wallet-details';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
import * as moment from 'moment';
|
||||
|
||||
// Pages
|
||||
import { AddPage } from "../add/add";
|
||||
import { CopayersPage } from '../add/copayers/copayers';
|
||||
import { WalletDetailsPage } from '../wallet-details/wallet-details';
|
||||
|
||||
// Providers
|
||||
import { BwcErrorProvider } from '../../providers/bwc-error/bwc-error';
|
||||
import { ProfileProvider } from '../../providers/profile/profile';
|
||||
import { ReleaseProvider } from '../../providers/release/release';
|
||||
import { WalletProvider } from '../../providers/wallet/wallet';
|
||||
|
||||
@Component({
|
||||
selector: 'page-home',
|
||||
templateUrl: 'home.html'
|
||||
|
@ -27,7 +32,7 @@ export class HomePage {
|
|||
private walletProvider: WalletProvider,
|
||||
private bwcErrorProvider: BwcErrorProvider,
|
||||
private logger: Logger
|
||||
) {
|
||||
) {
|
||||
this.cachedBalanceUpdateOn = '';
|
||||
}
|
||||
|
||||
|
@ -85,6 +90,9 @@ export class HomePage {
|
|||
}
|
||||
|
||||
goToWalletDetails(wallet: any) {
|
||||
if (!wallet.isComplete()) {
|
||||
return this.navCtrl.push(CopayersPage, { walletId: wallet.credentials.walletId });
|
||||
}
|
||||
this.navCtrl.push(WalletDetailsPage, { walletId: wallet.credentials.walletId });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { SocialSharing } from '@ionic-native/social-sharing';
|
|||
|
||||
//pages
|
||||
import { AmountPage } from '../send/amount/amount';
|
||||
import { CopayersPage } from '../copayers/copayers';
|
||||
import { CopayersPage } from './../add/copayers/copayers';
|
||||
import { BackupGamePage } from '../backup/backup-game/backup-game';
|
||||
//providers
|
||||
import { WalletProvider } from '../../providers/wallet/wallet';
|
||||
|
@ -51,7 +51,7 @@ export class ReceivePage {
|
|||
this.updateQrAddress();
|
||||
this.onSelect(this.checkSelectedWallet(this.wallet, this.wallets));
|
||||
this.showShareButton = this.platformProvider.isCordova;
|
||||
this.events.subscribe('bwsEvent', (e, walletId, type, n) => {
|
||||
this.events.subscribe('bwsEvent', (walletId, type, n) => {
|
||||
// Update current address
|
||||
if (this.wallet && walletId == this.wallet.id && type == 'NewIncomingTx') this.setAddress(true);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import { Events } from 'ionic-angular';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
//providers
|
||||
|
@ -150,9 +150,8 @@ export class ProfileProvider {
|
|||
|
||||
wallet.on('walletCompleted', () => {
|
||||
this.logger.debug('Wallet completed');
|
||||
|
||||
this.updateCredentials(JSON.parse(wallet.export()))
|
||||
//$rootScope.$emit('Local/WalletCompleted', walletId); TODO
|
||||
this.events.publish('Local/WalletCompleted', walletId);
|
||||
});
|
||||
|
||||
wallet.initialize({
|
||||
|
@ -191,7 +190,7 @@ export class ProfileProvider {
|
|||
if (wallet.cachedTxps)
|
||||
wallet.cachedTxps.isValid = false;
|
||||
|
||||
//$rootScope.$emit('bwsEvent', wallet.id, n.type, n); TODO
|
||||
this.events.publish('bwsEvent', wallet.id, n.type, n);
|
||||
}
|
||||
|
||||
public updateCredentials(credentials: any): void {
|
||||
|
@ -615,7 +614,7 @@ export class ProfileProvider {
|
|||
return reject(err);
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
//$rootScope.$emit('Local/DeviceError', err); TODO
|
||||
this.events.publish('Local/DeviceError', err);
|
||||
return reject(err);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ import { BwcProvider } from '../bwc/bwc';
|
|||
//pages
|
||||
import { WalletDetailsPage } from '../../pages/wallet-details/wallet-details';
|
||||
import { HomePage } from '../../pages/home/home';
|
||||
import { CopayersPage } from '../../pages/copayers/copayers';
|
||||
import { CopayersPage } from '../../pages/add/copayers/copayers';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
|
|
Loading…
Reference in New Issue