mirror of https://github.com/BTCPrivate/copay.git
send view and addressbook Provider
This commit is contained in:
parent
13809939b2
commit
d497baf662
|
@ -64,6 +64,8 @@ import { ConfirmPage } from '../pages/send/confirm/confirm';
|
|||
import { CustomAmountPage } from '../pages/receive/custom-amount/custom-amount';
|
||||
|
||||
/* Providers */
|
||||
|
||||
import { AddressBookProvider } from '../providers/address-book/address-book';
|
||||
import { AppProvider } from '../providers/app/app';
|
||||
import { BwcProvider } from '../providers/bwc/bwc';
|
||||
import { BwcErrorProvider } from '../providers/bwc-error/bwc-error';
|
||||
|
@ -124,6 +126,7 @@ let pages: any = [
|
|||
];
|
||||
|
||||
let providers: any = [
|
||||
AddressBookProvider,
|
||||
AndroidFingerprintAuth,
|
||||
AppProvider,
|
||||
BwcProvider,
|
||||
|
|
|
@ -9,13 +9,35 @@
|
|||
|
||||
<ion-content padding>
|
||||
<ion-list>
|
||||
|
||||
<ion-label>Recipient</ion-label>
|
||||
<ion-item>
|
||||
<ion-item *ngIf="hasWallets">
|
||||
<ion-icon name="logo-bitcoin" item-left></ion-icon>
|
||||
<ion-input type="text" placeholder="Search or enter bitcoin address" [(ngModel)]="search" (ngModelChange)="findContact(search)"></ion-input>
|
||||
<ion-icon class="scanner-icon" name="md-qr-scanner" item-right (click)="openScanner()"></ion-icon>
|
||||
</ion-item>
|
||||
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
<div *ngIf="contactsList">
|
||||
<ion-list>
|
||||
<ion-label>Contacts</ion-label>
|
||||
<ion-item *ngFor="let item of contactsList" (click)="goToAmount(item)">
|
||||
{{item.name}}
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
<div *ngIf="walletList">
|
||||
<ion-list>
|
||||
<ion-label>Transfer to Wallet</ion-label>
|
||||
<ion-item *ngFor="let item of walletList" (click)="goToAmount(item)">
|
||||
{{item.name}}
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
<ion-card *ngIf="!hasWallets">
|
||||
<ion-card-header>
|
||||
<span translate>To get started, you'll need to create a bitcoin wallet and get some bitcoin.</span>
|
||||
</ion-card-header>
|
||||
<ion-card-content>
|
||||
<button ion-button (click)="createWallet()" translate>Create bitcoin wallet</button>
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
</ion-content>
|
|
@ -1,33 +1,181 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import * as _ from 'lodash';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
|
||||
//providers
|
||||
import { ProfileProvider } from '../../providers/profile/profile';
|
||||
import { WalletProvider } from '../../providers/wallet/wallet';
|
||||
import { AddressBookProvider } from '../../providers/address-book/address-book';
|
||||
import { BwcProvider } from '../../providers/bwc/bwc';
|
||||
import { IncomingDataProvider } from '../../providers/incoming-data/incoming-data';
|
||||
import { PopupProvider } from '../../providers/popup/popup';
|
||||
|
||||
//pages
|
||||
import { AmountPage } from './amount/amount';
|
||||
import { CreateWalletPage } from '../add/create-wallet/create-wallet';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'page-send',
|
||||
templateUrl: 'send.html',
|
||||
})
|
||||
export class SendPage {
|
||||
public search: string;
|
||||
public search: string = '';
|
||||
public wallets: any;
|
||||
public walletList: any;
|
||||
public contactsList: any;
|
||||
public hasWallets: boolean;
|
||||
public hasContacts: boolean;
|
||||
public contactsShowMore: boolean;
|
||||
public searchFocus: boolean;
|
||||
private CONTACTS_SHOW_LIMIT: number = 10;
|
||||
private currentContactsPage: number = 0;
|
||||
|
||||
constructor(
|
||||
private navCtrl: NavController,
|
||||
private profileProvider: ProfileProvider,
|
||||
private walletProvider: WalletProvider,
|
||||
private addressBookProvider: AddressBookProvider,
|
||||
private logger: Logger,
|
||||
private bwcProvider: BwcProvider,
|
||||
private incomingDataProvider: IncomingDataProvider,
|
||||
private popupProvider: PopupProvider
|
||||
) {
|
||||
|
||||
constructor(public navCtrl: NavController) {
|
||||
}
|
||||
|
||||
|
||||
ionViewDidLoad() {
|
||||
this.search = '';
|
||||
console.log('ionViewDidLoad SendPage');
|
||||
}
|
||||
|
||||
openScanner() {
|
||||
ionViewDidEnter() {
|
||||
this.wallets = this.profileProvider.getWallets({
|
||||
onlyComplete: true
|
||||
});
|
||||
this.hasWallets = !(_.isEmpty(this.wallets));
|
||||
console.log(this.hasWallets);
|
||||
this.updateWalletsList();
|
||||
this.updateContactsList();
|
||||
}
|
||||
|
||||
private updateWalletsList(): void {
|
||||
if (!this.hasWallets) return;
|
||||
|
||||
this.walletList = [];
|
||||
_.each(this.wallets, (v: any) => {
|
||||
this.walletList.push({
|
||||
color: v.color,
|
||||
name: v.name,
|
||||
recipientType: 'wallet',
|
||||
coin: v.coin,
|
||||
network: v.network,
|
||||
getAddress: (): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.walletProvider.getAddress(v, false).then((addr) => {
|
||||
return resolve(addr);
|
||||
}).catch((err) => {
|
||||
return reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private updateContactsList() {
|
||||
this.addressBookProvider.list().then((ab: any) => {
|
||||
|
||||
this.hasContacts = _.isEmpty(ab) ? false : true;
|
||||
if (!this.hasContacts) return;
|
||||
|
||||
this.contactsList = [];
|
||||
_.each(ab, (v: any, k: string) => {
|
||||
this.contactsList.push({
|
||||
name: _.isObject(v) ? v.name : v,
|
||||
address: k,
|
||||
email: _.isObject(v) ? v.email : null,
|
||||
recipientType: 'contact',
|
||||
coin: this.getCoin(k),
|
||||
getAddress: (): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return resolve(k);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
let contacts = this.contactsList.slice(0, (this.currentContactsPage + 1) * this.CONTACTS_SHOW_LIMIT);
|
||||
this.contactsShowMore = this.contactsList.length > contacts.length;
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
private getCoin(address: string): string {
|
||||
let cashAddress = this.bwcProvider.getBitcoreCash().Address.isValid(address, 'livenet');
|
||||
if (cashAddress) {
|
||||
return 'bch';
|
||||
}
|
||||
return 'btc';
|
||||
}
|
||||
|
||||
public openScanner(): void {
|
||||
this.navCtrl.parent.select(2);
|
||||
}
|
||||
|
||||
findContact(search: string) {
|
||||
// TODO: Improve this function
|
||||
console.log("Send search string", search);
|
||||
if (search.length === 34) {
|
||||
this.navCtrl.push(AmountPage, {address: search, sending: true});
|
||||
public showMore(): void {
|
||||
this.currentContactsPage++;
|
||||
this.updateWalletsList();
|
||||
}
|
||||
|
||||
public searchInFocus(): void {
|
||||
this.searchFocus = true;
|
||||
}
|
||||
|
||||
public searchBlurred(): void {
|
||||
if (this.search == null || this.search.length == 0) {
|
||||
this.searchFocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
findContact(search: string): void {
|
||||
if (this.incomingDataProvider.redir(search)) return;
|
||||
if (!search || search.length < 2) {
|
||||
this.updateContactsList();
|
||||
return;
|
||||
}
|
||||
let result = _.filter(this.contactsList, (item: any) => {
|
||||
let val = item.name;
|
||||
return _.includes(val.toLowerCase(), search.toLowerCase());
|
||||
});
|
||||
this.contactsList = result;
|
||||
}
|
||||
|
||||
public goToAmount(item: any): void {
|
||||
item.getAddress().then((addr: string) => {
|
||||
if (!addr) {
|
||||
//Error is already formated
|
||||
this.popupProvider.ionicAlert('Error - no address');
|
||||
return;
|
||||
}
|
||||
this.logger.debug('Got toAddress:' + addr + ' | ' + item.name);
|
||||
this.navCtrl.push(AmountPage, {
|
||||
recipientType: item.recipientType,
|
||||
toAddress: addr,
|
||||
toName: item.name,
|
||||
toEmail: item.email,
|
||||
toColor: item.color,
|
||||
coin: item.coin
|
||||
});
|
||||
return;
|
||||
}).catch((err: any) => {
|
||||
this.logger.warn(err);
|
||||
});
|
||||
};
|
||||
|
||||
public createWallet(): void {
|
||||
this.navCtrl.push(CreateWalletPage, {});
|
||||
};
|
||||
|
||||
// TODO check if wallets have balance
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { BwcProvider } from '../bwc/bwc';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import { PersistenceProvider } from '../../providers/persistence/persistence';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@Injectable()
|
||||
export class AddressBookProvider {
|
||||
|
||||
constructor(
|
||||
private bwcProvider: BwcProvider,
|
||||
private logger: Logger,
|
||||
private persistenceProvider: PersistenceProvider,
|
||||
) {
|
||||
console.log('Hello AddressBookProvider Provider');
|
||||
}
|
||||
|
||||
private getNetwork(address: string): string {
|
||||
let network;
|
||||
try {
|
||||
network = (this.bwcProvider.getBitcore().Address(address)).network.name;
|
||||
} catch (e) {
|
||||
this.logger.warn('No valid bitcoin address. Trying bitcoin cash...');
|
||||
network = (this.bwcProvider.getBitcoreCash().Address(address)).network.name;
|
||||
}
|
||||
return network;
|
||||
};
|
||||
|
||||
private get(addr: string): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.persistenceProvider.getAddressbook('testnet').then((ab: any) => {
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
if (ab && ab[addr]) return resolve(ab[addr]);
|
||||
|
||||
this.persistenceProvider.getAddressbook('livenet').then((ab: any) => {
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
if (ab && ab[addr]) return resolve(ab[addr]);
|
||||
return resolve();
|
||||
}).catch((err: any) => {
|
||||
return reject();
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
return reject();
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
public list(): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.persistenceProvider.getAddressbook('testnet').then((ab: any) => {
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
|
||||
ab = ab || {};
|
||||
this.persistenceProvider.getAddressbook('livenet').then((ab2: any) => {
|
||||
if (ab2) ab2 = JSON.parse(ab2);
|
||||
|
||||
ab2 = ab2 || {};
|
||||
return resolve(_.defaults(ab2, ab));
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
return reject('Could not get the Addressbook');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
public add(entry: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
var network = this.getNetwork(entry.address);
|
||||
if (_.isEmpty(network)) return reject('Not valid bitcoin address');
|
||||
this.persistenceProvider.getAddressbook(network).then((ab: any) => {
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
ab = ab || {};
|
||||
if (_.isArray(ab)) ab = {}; // No array
|
||||
if (ab[entry.address]) return reject('Entry already exist');
|
||||
ab[entry.address] = entry;
|
||||
this.persistenceProvider.setAddressbook(network, JSON.stringify(ab)).then((ab: any) => {
|
||||
this.list().then((ab: any) => {
|
||||
return resolve(ab);
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
return reject('Error adding new entry');
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
public remove(addr: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
var network = this.getNetwork(addr);
|
||||
if (_.isEmpty(network)) return reject('Not valid bitcoin address');
|
||||
this.persistenceProvider.getAddressbook(network).then((ab: any) => {
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
ab = ab || {};
|
||||
if (_.isEmpty(ab)) return reject('Addressbook is empty');
|
||||
if (!ab[addr]) return reject('Entry does not exist');
|
||||
delete ab[addr];
|
||||
this.persistenceProvider.setAddressbook(network, JSON.stringify(ab)).then(() => {
|
||||
this.list().then((ab: any) => {
|
||||
return resolve(ab);
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
});
|
||||
}).catch(() => {
|
||||
return reject('Error deleting entry');
|
||||
});
|
||||
}).catch((err: any) => {
|
||||
return reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
public removeAll(): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.persistenceProvider.removeAddressbook('livenet').then(() => {
|
||||
this.persistenceProvider.removeAddressbook('testnet').then(() => {
|
||||
return resolve();
|
||||
});
|
||||
}).catch(() => {
|
||||
return reject('Error deleting addressbook');
|
||||
}).catch(() => {
|
||||
return reject('Error deleting addressbook');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Events, NavController } from 'ionic-angular';
|
||||
import { Injectable, Injector, ViewChild } from '@angular/core';
|
||||
import { Events, NavController, App } from 'ionic-angular';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
|
||||
//providers
|
||||
|
@ -18,10 +18,10 @@ import { ImportWalletPage } from '../../pages/add/import-wallet/import-wallet';
|
|||
|
||||
@Injectable()
|
||||
export class IncomingDataProvider {
|
||||
|
||||
private navCtrl: NavController;
|
||||
constructor(
|
||||
private app: App,
|
||||
private events: Events,
|
||||
private navCtrl: NavController,
|
||||
private bwcProvider: BwcProvider,
|
||||
private payproProvider: PayproProvider,
|
||||
private scanProvider: ScanProvider,
|
||||
|
@ -29,6 +29,8 @@ export class IncomingDataProvider {
|
|||
private logger: Logger,
|
||||
private appProvider: AppProvider
|
||||
) {
|
||||
//TODO Injecting NavController in constructor of service fails with no provider error
|
||||
this.navCtrl = app.getActiveNav();
|
||||
console.log('Hello IncomingDataProvider Provider');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue