mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #6893 from Gamboster/feat/walletService
Feat: Wallet service v4
This commit is contained in:
commit
4521286bf4
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
});
|
||||
};
|
||||
}
|
|
@ -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()...');
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue