mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #6534 from isocolsky/copay-v4
WIP: Migrate StorageProvider
This commit is contained in:
commit
d18aa715a2
21
package.json
21
package.json
|
@ -14,19 +14,18 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "4.1.3",
|
||||
"@angular/compiler": "4.1.3",
|
||||
"@angular/compiler-cli": "4.1.3",
|
||||
"@angular/core": "4.1.3",
|
||||
"@angular/forms": "4.1.3",
|
||||
"@angular/http": "4.1.3",
|
||||
"@angular/platform-browser": "4.1.3",
|
||||
"@angular/platform-browser-dynamic": "4.1.3",
|
||||
"@angular/tsc-wrapped": "^4.3.2",
|
||||
"@ionic-native/core": "3.12.1",
|
||||
"@ionic-native/splash-screen": "3.12.1",
|
||||
"@ionic-native/status-bar": "3.12.1",
|
||||
"@ionic/storage": "2.0.1",
|
||||
"@nsalaun/ng-logger": "^2.0.1",
|
||||
"@types/lodash": "^4.14.71",
|
||||
"autoprefixer": "^7.1.2",
|
||||
"ionic-angular": "3.5.3",
|
||||
"ionicons": "3.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
|
@ -36,17 +35,18 @@
|
|||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/app-scripts": "2.0.2",
|
||||
"@ionic/cli-plugin-cordova": "1.4.1",
|
||||
"@ionic/cli-plugin-ionic-angular": "1.3.2",
|
||||
"ionic": "3.6.0",
|
||||
"typescript": "2.3.4",
|
||||
"@angular/cli": "^1.2.5",
|
||||
"@angular/compiler": "^4.3.1",
|
||||
"@angular/compiler-cli": "^4.3.1",
|
||||
"@ionic/app-scripts": "2.0.2",
|
||||
"@ionic/cli-plugin-cordova": "1.5.0",
|
||||
"@ionic/cli-plugin-ionic-angular": "1.4.0",
|
||||
"@types/chrome": "0.0.47",
|
||||
"@types/jasmine": "^2.5.53",
|
||||
"@types/node": "^8.0.17",
|
||||
"@types/lodash": "^4.14.71",
|
||||
"@types/node": "^8.0.19",
|
||||
"codecov": "^2.2.0",
|
||||
"ionic": "3.6.0",
|
||||
"jasmine-core": "^2.6.4",
|
||||
"jasmine-spec-reporter": "^4.1.1",
|
||||
"karma": "^1.7.0",
|
||||
|
@ -56,7 +56,8 @@
|
|||
"karma-remap-istanbul": "^0.6.0",
|
||||
"ts-node": "^3.3.0",
|
||||
"tslint": "^5.5.0",
|
||||
"tslint-eslint-rules": "^4.1.1"
|
||||
"tslint-eslint-rules": "^4.1.1",
|
||||
"typescript": "2.3.4"
|
||||
},
|
||||
"description": "Copay Bitcoin Wallet"
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { StatusBar } from '@ionic-native/status-bar';
|
|||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import { AppService } from '../providers/app-service/app-service';
|
||||
import { AppProvider } from '../providers/app/app';
|
||||
|
||||
import { TabsPage } from '../pages/tabs/tabs';
|
||||
|
||||
|
@ -12,23 +12,23 @@ import { TabsPage } from '../pages/tabs/tabs';
|
|||
templateUrl: 'app.html'
|
||||
})
|
||||
export class Copay {
|
||||
rootPage:any = TabsPage;
|
||||
rootPage: any = TabsPage;
|
||||
|
||||
constructor(
|
||||
platform: Platform,
|
||||
statusBar: StatusBar,
|
||||
splashScreen: SplashScreen,
|
||||
log: Logger,
|
||||
appSrv: AppService
|
||||
app: AppProvider
|
||||
) {
|
||||
platform.ready().then(() => {
|
||||
appSrv.getName().subscribe((name) => {
|
||||
app.getName().subscribe((name) => {
|
||||
log.info('Name: ' + name);
|
||||
});
|
||||
appSrv.getVersion().subscribe((version) => {
|
||||
app.getVersion().subscribe((version) => {
|
||||
log.info('Version: ' + version);
|
||||
});
|
||||
appSrv.getCommitHash().subscribe((commit) => {
|
||||
app.getCommitHash().subscribe((commit) => {
|
||||
log.info('Commit Hash: #' + commit);
|
||||
});
|
||||
log.info('Platform: ' + platform.platforms());
|
||||
|
|
|
@ -19,14 +19,15 @@ import { TermsOfUsePage } from '../pages/terms-of-use/terms-of-use';
|
|||
import { StatusBar } from '@ionic-native/status-bar';
|
||||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
|
||||
import { WalletService } from '../providers/wallet-service/wallet-service';
|
||||
import { StorageService } from '../providers/storage-service/storage-service';
|
||||
import { AppService } from '../providers/app-service/app-service';
|
||||
import { WalletProvider } from '../providers/wallet/wallet';
|
||||
import { StorageProvider } from '../providers/storage/storage';
|
||||
import { AppProvider } from '../providers/app/app';
|
||||
import { PlatformProvider } from '../providers/platform/platform';
|
||||
|
||||
// Set different log level depending on environment.
|
||||
const LOG_LEVEL = Level.LOG;
|
||||
if (isDevMode()){
|
||||
const LOG_LEVEL = Level.ERROR;
|
||||
if (isDevMode()) {
|
||||
const LOG_LEVEL = Level.ERROR;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
@ -60,10 +61,11 @@ if (isDevMode()){
|
|||
providers: [
|
||||
StatusBar,
|
||||
SplashScreen,
|
||||
{provide: ErrorHandler, useClass: IonicErrorHandler},
|
||||
WalletService,
|
||||
StorageService,
|
||||
AppService
|
||||
{ provide: ErrorHandler, useClass: IonicErrorHandler },
|
||||
WalletProvider,
|
||||
StorageProvider,
|
||||
AppProvider,
|
||||
PlatformProvider
|
||||
]
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule { }
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Logger } from '@nsalaun/ng-logger';
|
|||
|
||||
import { TermsOfUsePage } from '../terms-of-use/terms-of-use';
|
||||
|
||||
import { AppService } from '../../providers/app-service/app-service';
|
||||
import { AppProvider } from '../../providers/app/app';
|
||||
|
||||
@Component({
|
||||
selector: 'page-about',
|
||||
|
@ -18,16 +18,16 @@ export class AboutPage {
|
|||
constructor(
|
||||
public navCtrl: NavController,
|
||||
public navParams: NavParams,
|
||||
private appSrv: AppService,
|
||||
private app: AppProvider,
|
||||
private log: Logger
|
||||
) {}
|
||||
) { }
|
||||
|
||||
ionViewDidLoad() {
|
||||
this.log.log('ionViewDidLoad AboutPage');
|
||||
this.appSrv.getCommitHash().subscribe((data) => {
|
||||
this.app.getCommitHash().subscribe((data) => {
|
||||
this.commitHash = data;
|
||||
});
|
||||
this.appSrv.getVersion().subscribe((data) => {
|
||||
this.app.getVersion().subscribe((data) => {
|
||||
this.version = data;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { NavController, NavParams } from 'ionic-angular';
|
||||
|
||||
import { AppService } from '../../providers/app-service/app-service';
|
||||
import { AppProvider } from '../../providers/app/app';
|
||||
|
||||
import { AboutPage } from '../about/about';
|
||||
|
||||
|
@ -15,9 +15,9 @@ export class SettingPage {
|
|||
constructor(
|
||||
public navCtrl: NavController,
|
||||
public navParams: NavParams,
|
||||
public appSrv: AppService
|
||||
public app: AppProvider
|
||||
) {
|
||||
appSrv.getName().subscribe((data) => {
|
||||
app.getName().subscribe((data) => {
|
||||
this.appName = data;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Http, Response } from '@angular/http';
|
|||
import 'rxjs/add/operator/map';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
export class AppProvider {
|
||||
private jsonPath: string = '../assets/appConfig.json';
|
||||
|
||||
constructor(public http: Http) {}
|
|
@ -0,0 +1,93 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Platform } from 'ionic-angular';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
|
||||
@Injectable()
|
||||
export class PlatformProvider {
|
||||
isAndroid: boolean;
|
||||
isIOS: boolean;
|
||||
isWP: boolean;
|
||||
isSafari: boolean;
|
||||
isCordova: boolean;
|
||||
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) {
|
||||
var ua = navigator ? navigator.userAgent : null;
|
||||
|
||||
if (!ua) {
|
||||
console.log('Could not determine navigator. Using fixed string');
|
||||
ua = 'dummy user-agent';
|
||||
}
|
||||
|
||||
// Fixes IOS WebKit UA
|
||||
ua = ua.replace(/\(\d+\)$/, '');
|
||||
|
||||
this.isAndroid = platform.is('android');
|
||||
this.isIOS = platform.is('ios');
|
||||
this.isWP = platform.is('windows') && platform.is('mobile');
|
||||
this.ua = ua;
|
||||
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;
|
||||
}
|
||||
|
||||
getBrowserName(): string {
|
||||
let userAgent = window.navigator.userAgent;
|
||||
let browsers = { chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i };
|
||||
|
||||
for (let key in browsers) {
|
||||
if (browsers[key].test(userAgent)) {
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
isNodeWebkit(): boolean {
|
||||
let isNode = (typeof process !== "undefined" && typeof require !== "undefined");
|
||||
if (isNode) {
|
||||
try {
|
||||
return (typeof require('nw.gui') !== "undefined");
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import { StorageService } from './storage-service';
|
||||
|
||||
describe('Storage Service', () => {
|
||||
it('should do nothing', () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
it('should get', () => {
|
||||
var storage = new StorageService();
|
||||
expect(storage.get('myKey')).toEqual('myKey');
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class StorageService {
|
||||
|
||||
constructor() {
|
||||
console.log('Hello StorageService Provider');
|
||||
}
|
||||
|
||||
public get(key:string):string {
|
||||
return key;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export interface IStorage {
|
||||
get(k: string, cb: (err: Error, v: string) => void);
|
||||
set(k: string, v: any, cb: (err: Error) => void);
|
||||
remove(k: string, cb: (err: Error) => void);
|
||||
create(k: string, v: any, cb: (err: Error) => void);
|
||||
}
|
||||
|
||||
export let ISTORAGE = new InjectionToken<IStorage>('storage');
|
|
@ -0,0 +1,53 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { PlatformProvider } from '../platform/platform';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { IStorage } from './istorage';
|
||||
|
||||
export class KeyAlreadyExistsError extends Error {
|
||||
constructor() {
|
||||
super('Key already exists');
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class LocalStorage implements IStorage {
|
||||
ls: Storage;
|
||||
constructor(private platform: PlatformProvider, private log: Logger) {
|
||||
this.ls = (typeof window.localStorage !== "undefined") ? window.localStorage : null;
|
||||
if (!this.ls) throw new Error('localstorage not available');
|
||||
}
|
||||
|
||||
get(k: string, cb: (err: Error, v: string) => void) {
|
||||
return cb(null, this.ls.getItem(k));
|
||||
}
|
||||
|
||||
set(k: string, v: any, cb: (err: Error) => void) {
|
||||
if (_.isObject(v)) {
|
||||
v = JSON.stringify(v);
|
||||
}
|
||||
if (v && !_.isString(v)) {
|
||||
v = v.toString();
|
||||
}
|
||||
|
||||
this.ls.setItem(k, v);
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
remove(k: string, cb: (err: Error) => void) {
|
||||
this.ls.removeItem(k);
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
create(k: string, v: any, cb: (err: Error) => void) {
|
||||
this.get(k,
|
||||
function (err, data) {
|
||||
if (data) {
|
||||
return cb(new KeyAlreadyExistsError());
|
||||
} else {
|
||||
return this.set(k, v, cb);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
import { StorageProvider } from './storage';
|
||||
import { LocalStorage, KeyAlreadyExistsError } from './local-storage';
|
||||
import { IStorage, ISTORAGE } from './istorage';
|
||||
|
||||
class StorageMock implements IStorage {
|
||||
hash = {};
|
||||
|
||||
get(k: string, cb: (err: Error, v: string) => void) {
|
||||
return cb(null, this.hash[k]);
|
||||
};
|
||||
set(k: string, v: any, cb: (err: Error) => void) {
|
||||
this.hash[k] = v.toString();
|
||||
return cb(null);
|
||||
};
|
||||
remove(k: string, cb: (err: Error) => void) {
|
||||
delete this.hash[k];
|
||||
return cb(null);
|
||||
};
|
||||
create(k: string, v: any, cb: (err: Error) => void) {
|
||||
this.get(k,
|
||||
function (err, data) {
|
||||
if (data) {
|
||||
return cb(new KeyAlreadyExistsError());
|
||||
} else {
|
||||
this.set(k, v, cb);
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
describe('Storage Service', () => {
|
||||
let storage: IStorage = new StorageMock();
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
StorageProvider,
|
||||
{ provide: ISTORAGE, useValue: storage },
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should do nothing', inject([StorageProvider], (service: StorageProvider) => {
|
||||
storage.set('profile', { name: 'john doe' }, (err) => {
|
||||
service.getProfile((err, profile) => {
|
||||
expect(err).toBeNull;
|
||||
console.log(JSON.stringify(profile));
|
||||
expect(profile.name).toEqual('john doe');
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { InjectionToken, Inject } from '@angular/core';
|
||||
import { IStorage, ISTORAGE } from './istorage';
|
||||
|
||||
@Injectable()
|
||||
export class StorageProvider {
|
||||
constructor( @Inject(ISTORAGE) private storage: IStorage) {
|
||||
}
|
||||
|
||||
storeNewProfile(profile, cb) {
|
||||
this.storage.create('profile', profile.toObj(), cb);
|
||||
};
|
||||
|
||||
storeProfile(profile, cb) {
|
||||
this.storage.set('profile', profile.toObj(), cb);
|
||||
};
|
||||
|
||||
getProfile(cb) {
|
||||
this.storage.get('profile', cb);
|
||||
// decryptOnMobile(str, function (err, str) {
|
||||
// if (err) return cb(err);
|
||||
// var p, err;
|
||||
// try {
|
||||
// p = Profile.fromString(str);
|
||||
// } catch (e) {
|
||||
// $log.debug('Could not read profile:', e);
|
||||
// err = new Error('Could not read profile:' + p);
|
||||
// }
|
||||
// return cb(err, p);
|
||||
// });
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class WalletService {
|
||||
export class WalletProvider {
|
||||
|
||||
constructor() {
|
||||
console.log('Hello WalletService Provider');
|
|
@ -22,5 +22,10 @@
|
|||
"compileOnSave": false,
|
||||
"atom": {
|
||||
"rewriteTsconfig": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"types": [
|
||||
"chrome",
|
||||
"lodash"
|
||||
"node"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue