mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #7016 from gabrielbazan7/feat/wallet
Wallet creation and address generation
This commit is contained in:
commit
2dfd458114
|
@ -14,19 +14,19 @@
|
|||
<div *ngIf="isShared">
|
||||
<ion-item>
|
||||
<ion-label stacked>Your name</ion-label>
|
||||
<ion-input type="text" [(ngModel)]="formData.copayerName" formControlName="copayerName" required></ion-input>
|
||||
<ion-input type="text" [(ngModel)]="formData.myName" formControlName="myName" required></ion-input>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item>
|
||||
<ion-label stacked>Total number of copayers</ion-label>
|
||||
<ion-select [(ngModel)]="formData.copayerSelected" formControlName="copayerSelected" (ionChange)="copayersChange(formData.copayerSelected)">
|
||||
<ion-select [(ngModel)]="formData.totalCopayers" formControlName="totalCopayers" (ionChange)="copayersChange(formData.totalCopayers)">
|
||||
<ion-option *ngFor="let copayer of copayers" [value]="copayer">{{copayer}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item>
|
||||
<ion-label stacked>Required number of signatures</ion-label>
|
||||
<ion-select [(ngModel)]="formData.signatureSelected" formControlName="signatureSelected" (ionChange)="signaturesChange(formData.signatureSelected)">
|
||||
<ion-select [(ngModel)]="formData.requiredCopayers" formControlName="requiredCopayers" (ionChange)="signaturesChange(formData.requiredCopayers)">
|
||||
<ion-option *ngFor="let signature of signatures" [value]="signature">{{signature}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
@ -51,12 +51,12 @@
|
|||
<ion-option *ngFor="let opt of seedOptions" [value]="opt.id">{{opt.label}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item *ngIf="formData.selectedSeed.id == 'set'">
|
||||
<ion-label stacked>Wallet recovery phrase</ion-label>
|
||||
<ion-input type="text" [(ngModel)]="formData.recoveryPhrase" formControlName="recoveryPhrase"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item>
|
||||
<ion-label stacked>Add a password</ion-label>
|
||||
<ion-toggle [(ngModel)]="formData.addPassword" formControlName="addPassword" (ionChange)="resetFormFields()"></ion-toggle>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<ion-label stacked>Password</ion-label>
|
||||
<ion-input type="password" [(ngModel)]="formData.password" formControlName="password"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item>
|
||||
<ion-label stacked>Confirm password</ion-label>
|
||||
<ion-input type="password" [(ngModel)]="formData.confirmPassword" formControlName="confirmPassword"></ion-input>
|
||||
|
@ -87,7 +87,7 @@
|
|||
|
||||
<ion-item *ngIf="formData.selectedSeed.id == 'new'">
|
||||
<ion-label stacked>Testnet</ion-label>
|
||||
<ion-toggle [(ngModel)]="formData.testnet" formControlName="testnet" (ionChange)="setDerivationPath()"></ion-toggle>
|
||||
<ion-toggle [(ngModel)]="formData.testnetEnabled" formControlName="testnetEnabled" (ionChange)="setDerivationPath()"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item *ngIf="formData.selectedSeed.id == 'set'">
|
||||
|
|
|
@ -3,13 +3,17 @@ import { NavController, NavParams } from 'ionic-angular';
|
|||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
|
||||
import { AppProvider } from '../../../providers/app/app';
|
||||
import { ProfileProvider } from '../../../providers/profile/profile';
|
||||
|
||||
import { HomePage } from '../../../pages/home/home';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'page-create-wallet',
|
||||
templateUrl: 'create-wallet.html'
|
||||
})
|
||||
export class CreateWalletPage implements OnInit{
|
||||
export class CreateWalletPage implements OnInit {
|
||||
public formData: any;
|
||||
public showAdvOpts: boolean;
|
||||
public COPAYER_PAIR_LIMITS: Array<any>;
|
||||
|
@ -25,24 +29,25 @@ export class CreateWalletPage implements OnInit{
|
|||
private createForm: FormGroup;
|
||||
|
||||
constructor(
|
||||
public navCtrl: NavController,
|
||||
public navParams: NavParams,
|
||||
private navCtrl: NavController,
|
||||
private navParams: NavParams,
|
||||
private app: AppProvider,
|
||||
private fb: FormBuilder
|
||||
private fb: FormBuilder,
|
||||
private profileProvider: ProfileProvider
|
||||
) {
|
||||
this.isShared = navParams.get('isShared');
|
||||
this.title = this.isShared ? 'Create shared wallet' : 'Create personal wallet';
|
||||
this.derivationPathByDefault = "m/44'/0'/0'";
|
||||
this.derivationPathForTestnet = "m/44'/1'/0'";
|
||||
this.showAdvOpts = false;
|
||||
this.COPAYER_PAIR_LIMITS = [2, 3, 4, 5, 6];
|
||||
this.COPAYER_PAIR_LIMITS = [1, 2, 3, 4, 5, 6];
|
||||
this.copayers = _.clone(this.COPAYER_PAIR_LIMITS);
|
||||
this.signatures = _.clone(this.COPAYER_PAIR_LIMITS);
|
||||
this.formData = {
|
||||
walletName: null,
|
||||
copayerName: null,
|
||||
copayerSelected: this.copayers[0],
|
||||
signatureSelected: this.copayers[0],
|
||||
myName: null,
|
||||
totalCopayers: 1,
|
||||
requiredCopayers: 1,
|
||||
bwsURL: 'https://bws.bitpay.com/bws/api',
|
||||
recoveryPhrase: null,
|
||||
addPassword: false,
|
||||
|
@ -50,7 +55,7 @@ export class CreateWalletPage implements OnInit{
|
|||
confirmPassword: null,
|
||||
recoveryPhraseBackedUp: null,
|
||||
derivationPath: this.derivationPathByDefault,
|
||||
testnet: false,
|
||||
testnetEnabled: false,
|
||||
singleAddress: false,
|
||||
};
|
||||
this.appName = this.app.info.name;
|
||||
|
@ -60,9 +65,9 @@ export class CreateWalletPage implements OnInit{
|
|||
ngOnInit() {
|
||||
this.createForm = this.fb.group({
|
||||
walletName: ['', Validators.required],
|
||||
copayerName: [''],
|
||||
copayerSelected: [''],
|
||||
signatureSelected: [''],
|
||||
myName: [''],
|
||||
totalCopayers: [''],
|
||||
requiredCopayers: [''],
|
||||
bwsURL: [''],
|
||||
selectedSeed: [''],
|
||||
recoveryPhrase: [''],
|
||||
|
@ -71,19 +76,19 @@ export class CreateWalletPage implements OnInit{
|
|||
confirmPassword: [''],
|
||||
recoveryPhraseBackedUp: [''],
|
||||
derivationPath: [''],
|
||||
testnet: [''],
|
||||
testnetEnabled: [''],
|
||||
singleAddress: [''],
|
||||
});
|
||||
|
||||
if (this.isShared) {
|
||||
this.createForm.get('copayerName').setValidators([Validators.required]);
|
||||
this.createForm.get('myName').setValidators([Validators.required]);
|
||||
}
|
||||
|
||||
this.createForm.get('addPassword').valueChanges.subscribe((addPassword: boolean) => {
|
||||
if (addPassword) {
|
||||
this.createForm.get('password').setValidators([Validators.required]);
|
||||
this.createForm.get('confirmPassword').setValidators([Validators.required]);
|
||||
}else {
|
||||
} else {
|
||||
this.createForm.get('password').clearValidators();
|
||||
this.createForm.get('confirmPassword').clearValidators();
|
||||
}
|
||||
|
@ -131,7 +136,7 @@ export class CreateWalletPage implements OnInit{
|
|||
signaturesChange(signature: any) {
|
||||
// TODO modify based on copayers
|
||||
console.log(signature);
|
||||
}
|
||||
}
|
||||
|
||||
resetFormFields() {
|
||||
this.formData.password = null;
|
||||
|
@ -145,6 +150,21 @@ export class CreateWalletPage implements OnInit{
|
|||
}
|
||||
|
||||
create() {
|
||||
console.log(this.formData);
|
||||
var opts = {
|
||||
name: this.formData.walletName,
|
||||
m: this.formData.requiredCopayers,
|
||||
n: this.formData.totalCopayers,
|
||||
myName: this.formData.totalCopayers > 1 ? this.formData.myName : null,
|
||||
networkName: this.formData.testnetEnabled && this.formData.coin != 'bch' ? 'testnet' : 'livenet',
|
||||
bwsurl: this.formData.bwsurl,
|
||||
singleAddress: this.formData.singleAddressEnabled,
|
||||
walletPrivKey: this.formData._walletPrivKey, // Only for testing
|
||||
coin: this.formData.coin
|
||||
};
|
||||
|
||||
this.profileProvider.createWallet(opts).then((wallet) => {
|
||||
this.navCtrl.setRoot(HomePage);
|
||||
this.navCtrl.popToRoot();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,9 @@
|
|||
<img src="assets/img/icon-wallet.svg" class="icon-wallet">
|
||||
</ion-icon>
|
||||
<h2>{{wallet.credentials.walletName}} {{wallet.credentials.m}}-{{wallet.credentials.n}}</h2>
|
||||
<p>{{wallet.credentials.coin}} - 10 BTC</p>
|
||||
<p *ngIf="!wallet.scanning">{{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' · ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' )}}</p>
|
||||
<span *ngIf="wallet.scanning"> Scanning funds... </span>
|
||||
</button>
|
||||
</ion-list>
|
||||
</ion-card>
|
||||
</ion-content>
|
||||
</ion-content>
|
|
@ -3,38 +3,58 @@ 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 * as _ from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'page-home',
|
||||
templateUrl: 'home.html'
|
||||
})
|
||||
export class HomePage {
|
||||
public wallets;
|
||||
public wallets: any;
|
||||
|
||||
constructor(
|
||||
public navCtrl: NavController,
|
||||
private profile: ProfileProvider,
|
||||
private release: ReleaseProvider,
|
||||
private navCtrl: NavController,
|
||||
private profileProvider: ProfileProvider,
|
||||
private releaseProvider: ReleaseProvider,
|
||||
private walletProvider: WalletProvider,
|
||||
private bwcErrorProvider: BwcErrorProvider
|
||||
) {
|
||||
this.release.getLatestAppVersion()
|
||||
.catch((err) => {
|
||||
console.log('Error:', err)
|
||||
})
|
||||
.then((version) => {
|
||||
console.log('Current app version:', version);
|
||||
var result = this.release.checkForUpdates(version);
|
||||
console.log('Update available:', result.updateAvailable);
|
||||
});
|
||||
this.checkUpdate();
|
||||
this.wallets = this.profileProvider.getWallets();
|
||||
this.updateAllWallets();
|
||||
}
|
||||
|
||||
ionViewDidLoad() {
|
||||
console.log('ionViewDidLoad HomePage');
|
||||
|
||||
this.wallets = this.profile.getWallets();
|
||||
console.log('[home.ts:20]', this.wallets); //TODO
|
||||
}
|
||||
|
||||
goToAddView() {
|
||||
private updateAllWallets(): void {
|
||||
_.each(this.wallets, (wallet: any) => {
|
||||
this.walletProvider.getStatus(wallet, {}).then((status: any) => {
|
||||
wallet.status = status;
|
||||
this.profileProvider.setLastKnownBalance(wallet.id, wallet.status.totalBalanceStr);
|
||||
}).catch((err) => {
|
||||
wallet.error = (err === 'WALLET_NOT_REGISTERED') ? 'Wallet not registered' : this.bwcErrorProvider.msg(err);
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private checkUpdate(): void {
|
||||
this.releaseProvider.getLatestAppVersion()
|
||||
.then((version) => {
|
||||
console.log('Current app version:', version);
|
||||
var result = this.releaseProvider.checkForUpdates(version);
|
||||
console.log('Update available:', result.updateAvailable);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('Error:', err);
|
||||
})
|
||||
}
|
||||
|
||||
public goToAddView(): void {
|
||||
this.navCtrl.push(AddPage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NavController, NavParams } from 'ionic-angular';
|
||||
import { AmountPage } from '../send/amount/amount';
|
||||
import { WalletProvider } from '../../providers/wallet/wallet';
|
||||
import { ProfileProvider } from '../../providers/profile/profile';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'page-receive',
|
||||
|
@ -11,27 +15,57 @@ export class ReceivePage {
|
|||
public protocolHandler: string;
|
||||
public address: string;
|
||||
public qrAddress: string;
|
||||
public wallets: any;
|
||||
public wallet: any;
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams) {
|
||||
this.protocolHandler = "bitcoin";
|
||||
this.address = "1FgGP9dKqtWC1Q9xGhPYVmAeyezeZCFjhf";
|
||||
constructor(
|
||||
private navCtrl: NavController,
|
||||
private navParams: NavParams,
|
||||
private profileProvider: ProfileProvider,
|
||||
private walletProvider: WalletProvider
|
||||
) {
|
||||
this.wallets = this.profileProvider.getWallets();
|
||||
this.updateQrAddress();
|
||||
}
|
||||
|
||||
ionViewDidLoad() {
|
||||
console.log('ionViewDidLoad ReceivePage');
|
||||
this.onSelect(this.checkSelectedWallet(this.wallet, this.wallets));
|
||||
}
|
||||
|
||||
requestSpecificAmount() {
|
||||
this.navCtrl.push(AmountPage, {address: this.address, sending: false});
|
||||
private onSelect(wallet: any): any {
|
||||
this.wallet = wallet;
|
||||
this.setProtocolHandler();
|
||||
this.setAddress();
|
||||
}
|
||||
|
||||
setAddress() {
|
||||
this.address = this.address === "1FgGP9dKqtWC1Q9xGhPYVmAeyezeZCFjhf" ? "1RTes3reeRTs1Q9xGhPYVmQFrdUyCr3EsX" : "1FgGP9dKqtWC1Q9xGhPYVmAeyezeZCFjhf";
|
||||
this.updateQrAddress();
|
||||
private setProtocolHandler(): void {
|
||||
this.protocolHandler = this.walletProvider.getProtocolHandler(this.wallet);
|
||||
}
|
||||
|
||||
updateQrAddress () {
|
||||
private checkSelectedWallet(wallet: any, wallets: any): any {
|
||||
if (!wallet) return wallets[0];
|
||||
let w = _.find(wallets, (w: any) => {
|
||||
return w.id == wallet.id;
|
||||
});
|
||||
if (!w) return wallets[0];
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public requestSpecificAmount(): void {
|
||||
this.navCtrl.push(AmountPage, { address: this.address, sending: false });
|
||||
}
|
||||
|
||||
private setAddress(newAddr?: boolean): void {
|
||||
this.walletProvider.getAddress(this.wallet, newAddr).then((addr) => {
|
||||
this.address = addr;
|
||||
this.updateQrAddress();
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
private updateQrAddress(): void {
|
||||
this.qrAddress = this.protocolHandler + ":" + this.address;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ export class ProfileProvider {
|
|||
private needsBackup(wallet: any): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.requiresBackup(wallet)) {
|
||||
return reject(false);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
this.persistenceProvider.getBackupFlag(wallet.credentials.walletId).then((val: string) => {
|
||||
|
@ -111,6 +111,7 @@ export class ProfileProvider {
|
|||
wallet.m = wallet.credentials.m;
|
||||
wallet.n = wallet.credentials.n;
|
||||
wallet.coin = wallet.credentials.coin;
|
||||
wallet.status = {};
|
||||
|
||||
this.updateWalletSettings(wallet);
|
||||
this.wallet[walletId] = wallet;
|
||||
|
@ -155,7 +156,7 @@ export class ProfileProvider {
|
|||
wallet.setNotificationsInterval(this.UPDATE_PERIOD);
|
||||
wallet.openWallet((err: any) => {
|
||||
if (wallet.status !== true)
|
||||
this.logger.debug('Wallet + ' + walletId + ' status:' + wallet.status)
|
||||
this.logger.debug('Wallet + ' + walletId + ' status:' + JSON.stringify(wallet.status));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -209,24 +210,21 @@ export class ProfileProvider {
|
|||
let now = Math.floor(Date.now() / 1000);
|
||||
let showRange = 600; // 10min;
|
||||
|
||||
this.getLastKnownBalance(wallet.id).then((data: string) => {
|
||||
this.getLastKnownBalance(wallet.id).then((data: any) => {
|
||||
if (data) {
|
||||
let parseData: any = JSON.parse(data);
|
||||
let parseData: any = data;
|
||||
wallet.cachedBalance = parseData.balance;
|
||||
wallet.cachedBalanceUpdatedOn = (parseData.updatedOn < now - showRange) ? parseData.updatedOn : null;
|
||||
}
|
||||
return resolve();
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public setLastKnownBalance(wid: string, balance: number): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.persistenceProvider.setBalanceCache(wid, { balance: balance, updatedOn: Math.floor(Date.now() / 1000), });
|
||||
return resolve();
|
||||
});
|
||||
public setLastKnownBalance(wid: string, balance: number): void {
|
||||
this.persistenceProvider.setBalanceCache(wid, { balance: balance, updatedOn: Math.floor(Date.now() / 1000) });
|
||||
}
|
||||
|
||||
private runValidation(wallet: any, delay?: number, retryDelay?: number) {
|
||||
|
|
|
@ -144,7 +144,7 @@ export class WalletProvider {
|
|||
}
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(null);
|
||||
return resolve(ret);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
@ -223,6 +223,8 @@ export class WalletProvider {
|
|||
|
||||
cache.alternativeBalanceAvailable = true;
|
||||
cache.isRateAvailable = true;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -246,8 +248,10 @@ export class WalletProvider {
|
|||
};
|
||||
|
||||
let _getStatus = (initStatusHash: any, tries: number): Promise<any> => {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (isStatusCached() && !opts.force) {
|
||||
|
||||
this.logger.debug('Wallet status cache hit:' + wallet.id);
|
||||
cacheStatus(wallet.cachedStatus);
|
||||
processPendingTxps(wallet.cachedStatus);
|
||||
|
@ -258,6 +262,7 @@ export class WalletProvider {
|
|||
|
||||
this.logger.debug('Updating Status:', wallet.credentials.walletName, tries);
|
||||
get().then((status) => {
|
||||
|
||||
let currentStatusHash = walletStatusHash(status);
|
||||
this.logger.debug('Status update. hash:' + currentStatusHash + ' Try:' + tries);
|
||||
if (opts.untilItChanges && initStatusHash == currentStatusHash && tries < this.WALLET_STATUS_MAX_TRIES && walletId == wallet.credentials.walletId) {
|
||||
|
@ -283,7 +288,11 @@ export class WalletProvider {
|
|||
});
|
||||
};
|
||||
|
||||
_getStatus(walletStatusHash(null), 0);
|
||||
_getStatus(walletStatusHash(null), 0).then((status) => {
|
||||
resolve(status);
|
||||
}).catch((err) => {
|
||||
return reject(err);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -302,7 +311,7 @@ export class WalletProvider {
|
|||
});
|
||||
}
|
||||
|
||||
private getAddress(wallet: any, forceNew: boolean): Promise<any> {
|
||||
public getAddress(wallet: any, forceNew: boolean): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.persistenceProvider.getLastAddress(wallet.id).then((addr) => {
|
||||
if (!forceNew && addr) return resolve(addr);
|
||||
|
|
Loading…
Reference in New Issue