Merge pull request #6893 from Gamboster/feat/walletService

Feat: Wallet service v4
This commit is contained in:
Gustavo Maximiliano Cortez 2017-10-16 09:34:59 -03:00 committed by GitHub
commit 4521286bf4
11 changed files with 1425 additions and 234 deletions

View File

@ -83,7 +83,7 @@
"angular2-template-loader": "0.6.2",
"codecov": "2.2.0",
"html-loader": "0.4.5",
"ionic": "3.12.0",
"ionic": "3.13.0",
"jasmine-core": "2.6.4",
"jasmine-spec-reporter": "4.1.1",
"karma": "1.7.0",

View File

@ -61,20 +61,22 @@ import { CustomAmountPage } from '../pages/receive/custom-amount/custom-amount';
/* Providers */
import { AppProvider } from '../providers/app/app';
import { BwcProvider } from '../providers/bwc/bwc';
import { BwcErrorProvider } from '../providers/bwc-error/bwc-error';
import { ConfigProvider } from '../providers/config/config';
import { DerivationPathHelperProvider } from '../providers/derivationPathHelper/derivationPathHelper';
import { FilterProvider } from '../providers/filter/filter';
import { LanguageProvider } from '../providers/language/language';
import { OnGoingProcessProvider } from '../providers/on-going-process/on-going-process';
import { PersistenceProvider, persistenceProviderFactory } from '../providers/persistence/persistence';
import { PlatformProvider } from '../providers/platform/platform';
import { PopupProvider } from '../providers/popup/popup';
import { ProfileProvider } from '../providers/profile/profile';
import { RateProvider } from '../providers/rate/rate';
import { ReleaseProvider } from '../providers/release/release';
import { ScanProvider } from '../providers/scan/scan';
import { TouchIdProvider } from '../providers/touchid/touchid';
import { TxFormatProvider } from '../providers/tx-format/tx-format';
import { WalletProvider } from '../providers/wallet/wallet';
import { ReleaseProvider } from '../providers/release/release';
import { DerivationPathHelperProvider } from '../providers/derivationPathHelper/derivationPathHelper';
export function createTranslateLoader(http: Http) {
return new TranslatePoHttpLoader(http, 'assets/i18n', '.po');
@ -113,15 +115,19 @@ let providers: any = [
AndroidFingerprintAuth,
AppProvider,
BwcProvider,
BwcErrorProvider,
ConfigProvider,
Clipboard,
DerivationPathHelperProvider,
FilterProvider,
LanguageProvider,
OnGoingProcessProvider,
PlatformProvider,
ProfileProvider,
PopupProvider,
QRScanner,
RateProvider,
ReleaseProvider,
StatusBar,
SplashScreen,
ScanProvider,
@ -131,8 +137,6 @@ let providers: any = [
TouchIdProvider,
TxFormatProvider,
WalletProvider,
ReleaseProvider,
DerivationPathHelperProvider,
{
provide: ErrorHandler,
useClass: IonicErrorHandler

View File

@ -115,35 +115,6 @@ export class CreateWalletPage implements OnInit{
this.formData.selectedSeed = {
id: this.seedOptions[0].id
};
/* Disable Hardware Wallets for BitPay distribution */
var opts = [];
if (this.appName == 'copay') {
// if (n > 1 && walletService.externalSource.ledger.supported)
// opts.push({
// id: walletService.externalSource.ledger.id,
// label: walletService.externalSource.ledger.longName,
// supportsTestnet: walletService.externalSource.ledger.supportsTestnet
// });
// if (walletService.externalSource.trezor.supported) {
// opts.push({
// id: walletService.externalSource.trezor.id,
// label: walletService.externalSource.trezor.longName,
// supportsTestnet: walletService.externalSource.trezor.supportsTestnet
// });
// }
// if (walletService.externalSource.intelTEE.supported) {
// opts.push({
// id: walletService.externalSource.intelTEE.id,
// label: walletService.externalSource.intelTEE.longName,
// supportsTestnet: walletService.externalSource.intelTEE.supportsTestnet
// });
// }
}
this.seedOptions = this.seedOptions.concat(opts);
};
seedOptionsChange(seed: any) {

View File

@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
@Injectable()
export class BwcErrorProvider {
constructor() {
console.log('Hello BwcErrorProvider Provider');
}
//TODO
msg(err: any, prefix?: string){
return "TODO: bwcError msg(err, prefix)";
}
cb(err: string, prefix?: string): Promise<any> {
return new Promise((resolve, reject)=> {
resolve(this.msg(err, prefix));
});
};
}

View File

@ -0,0 +1,14 @@
import { Injectable } from '@angular/core';
@Injectable()
export class OnGoingProcessProvider {
constructor() {
console.log('Hello OnGoingProcessProvider Provider');
}
public set (processName: string, isOn: boolean, customHandler?: any) {
console.log('TODO: OnGoingProcessProvider set()...');
}
}

View File

@ -12,12 +12,7 @@ export class PlatformProvider {
isNW: boolean;
ua: string;
isMobile: boolean;
isChromeApp: boolean;
isDevel: boolean;
supportsLedger: boolean;
supportsTrezor: boolean;
versionIntelTEE: string;
supportsIntelTEE: boolean;
constructor(private platform: Platform, private log: Logger) {
let chrome: any;
@ -38,12 +33,7 @@ export class PlatformProvider {
this.isCordova = platform.is('cordova');
this.isNW = this.isNodeWebkit();
this.isMobile = platform.is('mobile');
this.isChromeApp = this.getBrowserName() == 'chrome' && chrome && chrome.runtime && chrome.runtime.id && !this.isNW;
this.isDevel = !this.isMobile && !this.isChromeApp && !this.isNW;
this.supportsLedger = this.isChromeApp;
this.supportsTrezor = this.isChromeApp || this.isDevel;
this.versionIntelTEE = this.getVersionIntelTee();
this.supportsIntelTEE = this.versionIntelTEE.length > 0;
this.isDevel = !this.isMobile && !this.isNW;
}
getBrowserName(): string {
@ -70,26 +60,4 @@ export class PlatformProvider {
}
}
}
getVersionIntelTee(): string {
let v = '';
let isWindows = navigator.platform.indexOf('Win') > -1;
if (!this.isNodeWebkit() || !isWindows) {
return v;
}
try {
var IntelWallet = require('intelWalletCon');
if (IntelWallet.getVersion) {
v = IntelWallet.getVersion();
} else {
v = 'Alpha';
}
if (v.length > 0) {
this.log.info('Intel TEE library ' + v);
}
} catch (e) { }
return v;
}
}

View File

@ -6,7 +6,7 @@ export class PopupProvider {
constructor(public alertCtrl: AlertController) {
}
ionicAlert(title, subTitle, okText): void {
ionicAlert(title: string, subTitle?: string, okText?: string): void {
let alert = this.alertCtrl.create({
title: title,
subTitle: subTitle,
@ -37,32 +37,35 @@ export class PopupProvider {
confirm.present();
};
ionicPrompt(title, message, okText, cancelText, opts) {
opts = opts || {};
let prompt = this.alertCtrl.create({
title: title,
message: message,
inputs: [
{
name: 'title',
placeholder: 'Title'
},
],
buttons: [
{
text: cancelText,
handler: data => {
console.log('Cancel clicked');
ionicPrompt(title: string, message: string, okText?: string, cancelText?: string): Promise<any> {
return new Promise((resolve, reject) => {
let prompt = this.alertCtrl.create({
title: title,
message: message,
inputs: [
{
name: 'title',
placeholder: 'Title'
},
],
buttons: [
{
text: cancelText,
handler: data => {
console.log('Cancel clicked');
reject(data);
}
},
{
text: okText,
handler: data => {
console.log('Saved clicked');
resolve(data);
}
}
},
{
text: okText,
handler: data => {
console.log('Saved clicked');
}
}
]
]
});
prompt.present();
});
prompt.present();
}
}

View File

@ -72,9 +72,9 @@ export class ProfileProvider {
if (!l) return wallets;
let credentials = this.profile.credentials;
_.each(credentials, (credential) => {
/*_.each(credentials, (credential) => {
wallets.push(this.wallet.bind(credential));
});
}); */
return wallets;
}

View File

@ -12,10 +12,11 @@ export class RateProvider {
private _ratesBCH: Object;
private SAT_TO_BTC: any;
private BTC_TO_SAT: any;
private _isAvailable: boolean = false;
private rateServiceUrl = 'https://bitpay.com/api/rates';
private bchRateServiceUrl = 'https://api.kraken.com/0/public/Ticker?pair=BCHUSD,BCHEUR';
constructor(public http: Http) {
console.log('Hello RateProvider Provider');
this._rates = {};
@ -48,6 +49,7 @@ export class RateProvider {
self._ratesBCH[code] = rate;
});
this._isAvailable = true;
resolve();
})
.catch((errorBCH) => {
@ -112,4 +114,17 @@ export class RateProvider {
return _.uniqBy(alternatives, 'isoCode');
};
//TODO IMPROVE WHEN AVAILABLE
whenAvailable() {
return new Promise((resolve, reject)=> {
if (this._isAvailable) resolve();
else {
this.updateRates().then(()=>{
resolve();
});
}
});
}
}

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { PlatformProvider } from '../platform/platform';
import { ConfigProvider } from '../config/config';
import { TouchID } from '@ionic-native/touch-id';
import { AndroidFingerprintAuth } from '@ionic-native/android-fingerprint-auth';
@ -7,95 +8,114 @@ import { AndroidFingerprintAuth } from '@ionic-native/android-fingerprint-auth';
@Injectable()
export class TouchIdProvider {
private _isAvailable: boolean = false;
private _isAvailable: boolean = false;
constructor(
private touchId: TouchID,
private androidFingerprintAuth: AndroidFingerprintAuth,
private platform: PlatformProvider
) { }
constructor(
private touchId: TouchID,
private androidFingerprintAuth: AndroidFingerprintAuth,
private platform: PlatformProvider,
private config: ConfigProvider
) { }
init() {
if (this.platform.isAndroid) this.checkAndroid();
if (this.platform.isIOS) this.checkIOS();
}
init() {
if (this.platform.isAndroid) this.checkAndroid();
if (this.platform.isIOS) this.checkIOS();
}
checkIOS() {
this.touchId.isAvailable()
.then(
res => this._isAvailable = true,
err => console.log("Fingerprint is not available")
);
}
checkIOS() {
this.touchId.isAvailable()
.then(
res => this._isAvailable = true,
err => console.log("Fingerprint is not available")
);
}
checkAndroid() {
this.androidFingerprintAuth.isAvailable()
.then(
res => {
if (res.isAvailable) this._isAvailable = true
else console.log("Fingerprint is not available")
});
}
checkAndroid() {
this.androidFingerprintAuth.isAvailable()
.then(
res => {
if (res.isAvailable) this._isAvailable = true
else console.log("Fingerprint is not available")
});
}
verifyIOSFingerprint(): Promise<any> {
return new Promise((resolve, reject) => {
this.touchId.verifyFingerprint('Scan your fingerprint please')
.then(
res => resolve(),
err => reject()
);
verifyIOSFingerprint(): Promise<any> {
return new Promise((resolve, reject) => {
this.touchId.verifyFingerprint('Scan your fingerprint please')
.then(
res => resolve(),
err => reject()
);
});
}
verifyAndroidFingerprint(): Promise<any> {
return new Promise((resolve, reject) => {
this.androidFingerprintAuth.encrypt({ clientId: 'Copay' })
.then(result => {
if (result.withFingerprint) {
console.log('Successfully authenticated with fingerprint.');
resolve();
} else if (result.withBackup) {
console.log('Successfully authenticated with backup password!');
resolve();
} else console.log('Didn\'t authenticate!');
}).catch(error => {
if (error === this.androidFingerprintAuth.ERRORS.FINGERPRINT_CANCELLED) {
console.log('Fingerprint authentication cancelled');
reject();
} else {
console.error(error);
resolve();
};
});
}
});
}
verifyAndroidFingerprint(): Promise<any> {
return new Promise((resolve, reject) => {
this.androidFingerprintAuth.encrypt({ clientId: 'Copay' })
.then(result => {
if (result.withFingerprint) {
console.log('Successfully authenticated with fingerprint.');
resolve();
} else if (result.withBackup) {
console.log('Successfully authenticated with backup password!');
resolve();
} else console.log('Didn\'t authenticate!');
})
.catch(error => {
if (error === this.androidFingerprintAuth.ERRORS.FINGERPRINT_CANCELLED) {
console.log('Fingerprint authentication cancelled');
reject();
} else {
console.error(error);
resolve();
}
});
isAvailable() {
return this._isAvailable;
}
check(): Promise<any> {
return new Promise((resolve, reject) => {
if (!this.isAvailable()) reject();
if (this.platform.isIOS) {
this.verifyIOSFingerprint()
.then(() => {
resolve();
})
.catch(() => {
reject();
});
};
if (this.platform.isAndroid) {
this.verifyAndroidFingerprint()
.then(() => {
resolve();
})
.catch(() => {
reject();
});
};
});
}
isNeeded(wallet: any) {
let config: any = this.config.get();
config.touchIdFor = config.touchIdFor || {};
return config.touchIdFor[wallet.credentials.walletId];
}
checkWallet(wallet: any): Promise<any> {
return new Promise((resolve, reject) => {
if (!this.isAvailable()) reject();
if (this.isNeeded(wallet)) {
this.check().then(() => {
resolve();
}).catch(() => {
reject();
});
}
isAvailable() {
return this._isAvailable;
}
check(): Promise<any> {
return new Promise((resolve, reject) => {
if (!this.isAvailable()) reject();
if (this.platform.isIOS) {
this.verifyIOSFingerprint()
.then(() => {
resolve();
})
.catch(() => {
reject();
});
}
if (this.platform.isAndroid) {
this.verifyAndroidFingerprint()
.then(() => {
resolve();
})
.catch(() => {
reject();
});
}
});
}
};
});
}
}

File diff suppressed because it is too large Load Diff