mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #6556 from isocolsky/copay-v4
Storage Provider + tests
This commit is contained in:
commit
457d639ed0
20
package.json
20
package.json
|
@ -14,12 +14,12 @@
|
|||
"extract": "ngx-translate-extract --input ./src --output ./src/assets/i18n/app.pot --clean --sort --format pot"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "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/common": "4.2.3",
|
||||
"@angular/core": "4.2.3",
|
||||
"@angular/forms": "4.2.3",
|
||||
"@angular/http": "4.2.3",
|
||||
"@angular/platform-browser": "4.2.3",
|
||||
"@angular/platform-browser-dynamic": "4.2.3",
|
||||
"@angular/tsc-wrapped": "^4.3.2",
|
||||
"@biesbjerg/ngx-translate-po-http-loader": "^1.0.1",
|
||||
"@ionic-native/core": "3.12.1",
|
||||
|
@ -38,9 +38,9 @@
|
|||
"zone.js": "0.8.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "^1.2.5",
|
||||
"@angular/compiler": "^4.3.1",
|
||||
"@angular/compiler-cli": "^4.3.1",
|
||||
"@angular/cli": "^1.2.7",
|
||||
"@angular/compiler": "4.2.3",
|
||||
"@angular/compiler-cli": "4.2.3",
|
||||
"@ionic/app-scripts": "2.0.2",
|
||||
"@ionic/cli-plugin-cordova": "1.5.0",
|
||||
"@ionic/cli-plugin-ionic-angular": "1.4.0",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"@types/node": "^8.0.19",
|
||||
"codecov": "^2.2.0",
|
||||
"@biesbjerg/ngx-translate-extract": "^2.3.2",
|
||||
"ionic": "3.6.0",
|
||||
"ionic": "3.7.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"jasmine-core": "^2.6.4",
|
||||
"jasmine-spec-reporter": "^4.1.1",
|
||||
|
|
|
@ -2,7 +2,7 @@ import { NgModule, ErrorHandler } from '@angular/core';
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HttpModule, Http } from '@angular/http';
|
||||
|
||||
import { NgLoggerModule, Level } from '@nsalaun/ng-logger';
|
||||
import { NgLoggerModule, Logger, Level } from '@nsalaun/ng-logger';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslatePoHttpLoader } from '@biesbjerg/ngx-translate-po-http-loader';
|
||||
|
||||
|
@ -22,12 +22,12 @@ import { StatusBar } from '@ionic-native/status-bar';
|
|||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
|
||||
import { WalletProvider } from '../providers/wallet/wallet';
|
||||
import { StorageProvider } from '../providers/storage/storage';
|
||||
import { PersistenceProvider, persistenceProviderFactory } from '../providers/persistence/persistence';
|
||||
import { AppProvider } from '../providers/app/app';
|
||||
import { PlatformProvider } from '../providers/platform/platform';
|
||||
|
||||
export function createTranslateLoader(http: Http) {
|
||||
return new TranslatePoHttpLoader(http, './assets/i18n/', '.po');
|
||||
return new TranslatePoHttpLoader(http, './assets/i18n/', '.po');
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
|
@ -70,7 +70,7 @@ export function createTranslateLoader(http: Http) {
|
|||
SplashScreen,
|
||||
{ provide: ErrorHandler, useClass: IonicErrorHandler },
|
||||
WalletProvider,
|
||||
StorageProvider,
|
||||
{ provide: PersistenceProvider, useFactory: persistenceProviderFactory, deps: [PlatformProvider, Logger], multi: true },
|
||||
AppProvider,
|
||||
PlatformProvider
|
||||
]
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
import { PersistenceProvider } from './persistence';
|
||||
import { IStorage, ISTORAGE } from './storage/istorage';
|
||||
import { RamStorage } from './storage/ram-storage';
|
||||
import { LocalStorage } from './storage/local-storage';
|
||||
import { Logger, Level as LoggerLevel } from '@nsalaun/ng-logger';
|
||||
import { PlatformProvider } from '../platform/platform';
|
||||
import { Platform } from 'ionic-angular';
|
||||
|
||||
describe('Storage Service', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
PersistenceProvider,
|
||||
{ provide: Logger, useValue: new Logger(LoggerLevel.DEBUG) },
|
||||
{ provide: PlatformProvider },
|
||||
{ provide: ISTORAGE, useClass: RamStorage, deps: [PlatformProvider, Logger] },
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
describe('#profile', () => {
|
||||
let service: PersistenceProvider;
|
||||
beforeEach(inject([PersistenceProvider], (pp: PersistenceProvider) => {
|
||||
service = pp;
|
||||
}));
|
||||
it('should correctly perform a profile roundtrip', () => {
|
||||
let p = { name: 'My profile' };
|
||||
service.storeNewProfile(p)
|
||||
.catch((err) => expect(err).toBeNull)
|
||||
.then(() => {
|
||||
return service.getProfile();
|
||||
})
|
||||
.then((profile) => {
|
||||
expect(typeof profile).toEqual('object');
|
||||
expect(profile.name).toEqual('My profile');
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to create a profile when one already exists', () => {
|
||||
let p = { name: 'My profile' };
|
||||
service.storeNewProfile(p)
|
||||
.then(() => {
|
||||
return service.storeNewProfile(p);
|
||||
}).catch((err) => {
|
||||
expect(err.message).toEqual('Key already exists');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,450 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { InjectionToken, Inject } from '@angular/core';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { IStorage, ISTORAGE } from './storage/istorage';
|
||||
import { PlatformProvider } from '../platform/platform';
|
||||
import { LocalStorage } from './storage/local-storage';
|
||||
import { RamStorage } from './storage/ram-storage';
|
||||
|
||||
const Keys = {
|
||||
ADDRESS_BOOK: network => 'addressbook-' + network,
|
||||
AGREE_DISCLAIMER: 'agreeDisclaimer',
|
||||
AMAZON_GIFT_CARDS: network => 'amazonGiftCards-' + network,
|
||||
APP_IDENTITY: network => 'appIdentity-' + network,
|
||||
BACKUP: walletId => 'backup-' + walletId,
|
||||
BALANCE_CACHE: cardId => 'balanceCache-' + cardId,
|
||||
BITPAY_ACCOUNTS_V2: network => 'bitpayAccounts-v2-' + network,
|
||||
CLEAN_AND_SCAN_ADDRESSES: 'CleanAndScanAddresses',
|
||||
COINBASE_REFRESH_TOKEN: network => 'coinbaseRefreshToken-' + network,
|
||||
COINBASE_TOKEN: network => 'coinbaseToken-' + network,
|
||||
COINBASE_TXS: network => 'coinbaseTxs-' + network,
|
||||
CONFIG: 'config',
|
||||
FEEDBACK: 'feedback',
|
||||
FOCUSED_WALLET_ID: 'focusedWalletId',
|
||||
GLIDERA_PERMISSIONS: network => 'glideraPermissions-' + network,
|
||||
GLIDERA_STATUS: network => 'glideraStatus-' + network,
|
||||
GLIDERA_TOKEN: network => 'glideraToken-' + network,
|
||||
GLIDERA_TXS: network => 'glideraTxs-' + network,
|
||||
HIDE_BALANCE: walletId => 'hideBalance-' + walletId,
|
||||
HOME_TIP: 'homeTip',
|
||||
LAST_ADDRESS: walletId => 'lastAddress-' + walletId,
|
||||
LAST_CURRENCY_USED: 'lastCurrencyUsed',
|
||||
PROFILE: 'profile',
|
||||
REMOTE_PREF_STORED: 'remotePrefStored',
|
||||
TX_CONFIRM_NOTIF: txid => 'txConfirmNotif-' + txid,
|
||||
TX_HISTORY: walletId => 'txsHistory-' + walletId,
|
||||
};
|
||||
|
||||
export let persistenceProviderFactory = (platform: PlatformProvider, log: Logger) => {
|
||||
let storage = new RamStorage(platform, log);
|
||||
return new PersistenceProvider(storage, log);
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class PersistenceProvider {
|
||||
constructor( @Inject(ISTORAGE) public storage: IStorage, private log: Logger) {
|
||||
};
|
||||
|
||||
storeNewProfile(profile): Promise<void> {
|
||||
return this.storage.create(Keys.PROFILE, profile);
|
||||
};
|
||||
|
||||
storeProfile(profile): Promise<void> {
|
||||
return this.storage.set(Keys.PROFILE, profile);
|
||||
};
|
||||
|
||||
getProfile(): Promise<any> {
|
||||
return this.storage.get(Keys.PROFILE);
|
||||
};
|
||||
|
||||
deleteProfile(): Promise<void> {
|
||||
return this.storage.remove(Keys.PROFILE);
|
||||
};
|
||||
|
||||
setFeedbackInfo(feedbackValues: any): Promise<void> {
|
||||
return this.storage.set(Keys.FEEDBACK, feedbackValues);
|
||||
};
|
||||
|
||||
getFeedbackInfo(): Promise<void> {
|
||||
return this.storage.get(Keys.FEEDBACK);
|
||||
};
|
||||
|
||||
storeFocusedWalletId(walletId: string): Promise<void> {
|
||||
return this.storage.set(Keys.FOCUSED_WALLET_ID, walletId || '');
|
||||
};
|
||||
|
||||
getFocusedWalletId(): Promise<string> {
|
||||
return this.storage.get(Keys.FOCUSED_WALLET_ID);
|
||||
};
|
||||
|
||||
getLastAddress(walletId: string): Promise<any> {
|
||||
return this.storage.get(Keys.LAST_ADDRESS(walletId));
|
||||
};
|
||||
|
||||
storeLastAddress(walletId: string, address: any): Promise<void> {
|
||||
return this.storage.set(Keys.LAST_ADDRESS(walletId), address);
|
||||
};
|
||||
|
||||
clearLastAddress(walletId: string): Promise<void> {
|
||||
return this.storage.remove(Keys.LAST_ADDRESS(walletId));
|
||||
};
|
||||
|
||||
setBackupFlag(walletId: string): Promise<void> {
|
||||
return this.storage.set(Keys.BACKUP(walletId), Date.now());
|
||||
};
|
||||
|
||||
getBackupFlag(walletId: string): Promise<any> {
|
||||
return this.storage.get(Keys.BACKUP(walletId));
|
||||
};
|
||||
|
||||
clearBackupFlag(walletId: string): Promise<void> {
|
||||
return this.storage.remove(Keys.BACKUP(walletId));
|
||||
};
|
||||
|
||||
setCleanAndScanAddresses(walletId: string): Promise<void> {
|
||||
return this.storage.set(Keys.CLEAN_AND_SCAN_ADDRESSES, walletId);
|
||||
};
|
||||
|
||||
getCleanAndScanAddresses(): Promise<any> {
|
||||
return this.storage.get(Keys.CLEAN_AND_SCAN_ADDRESSES);
|
||||
};
|
||||
|
||||
removeCleanAndScanAddresses(): Promise<void> {
|
||||
return this.storage.remove(Keys.CLEAN_AND_SCAN_ADDRESSES);
|
||||
};
|
||||
|
||||
getConfig(): Promise<void> {
|
||||
return this.storage.get(Keys.CONFIG);
|
||||
};
|
||||
|
||||
storeConfig(config: any): Promise<void> {
|
||||
return this.storage.set(Keys.CONFIG, config);
|
||||
};
|
||||
|
||||
clearConfig(): Promise<void> {
|
||||
return this.storage.remove(Keys.CONFIG);
|
||||
};
|
||||
|
||||
getHomeTipAccepted(): Promise<any> {
|
||||
return this.storage.get(Keys.HOME_TIP);
|
||||
};
|
||||
|
||||
setHomeTipAccepted(homeTip: any): Promise<void> {
|
||||
return this.storage.set(Keys.HOME_TIP, homeTip);
|
||||
};
|
||||
|
||||
setHideBalanceFlag(walletId: string, val: any): Promise<void> {
|
||||
return this.storage.set(Keys.HIDE_BALANCE(walletId), val);
|
||||
};
|
||||
|
||||
getHideBalanceFlag(walletId: string): Promise<any> {
|
||||
return this.storage.get(Keys.HIDE_BALANCE(walletId));
|
||||
};
|
||||
|
||||
//for compatibility
|
||||
getCopayDisclaimerFlag(): Promise<any> {
|
||||
return this.storage.get(Keys.AGREE_DISCLAIMER);
|
||||
};
|
||||
|
||||
setRemotePrefsStoredFlag(): Promise<void> {
|
||||
return this.storage.set(Keys.REMOTE_PREF_STORED, true);
|
||||
};
|
||||
|
||||
getRemotePrefsStoredFlag(): Promise<any> {
|
||||
return this.storage.get(Keys.REMOTE_PREF_STORED);
|
||||
};
|
||||
|
||||
setGlideraToken(network: string, token: string): Promise<void> {
|
||||
return this.storage.set(Keys.GLIDERA_TOKEN(network), token);
|
||||
};
|
||||
|
||||
getGlideraToken(network: string): Promise<string> {
|
||||
return this.storage.get(Keys.GLIDERA_TOKEN(network));
|
||||
};
|
||||
|
||||
removeGlideraToken(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.GLIDERA_TOKEN(network));
|
||||
};
|
||||
|
||||
setGlideraPermissions(network: string, permissions: any): Promise<void> {
|
||||
return this.storage.set(Keys.GLIDERA_PERMISSIONS(network), permissions);
|
||||
};
|
||||
|
||||
getGlideraPermissions(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.GLIDERA_PERMISSIONS(network));
|
||||
};
|
||||
|
||||
removeGlideraPermissions(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.GLIDERA_PERMISSIONS(network));
|
||||
};
|
||||
|
||||
setGlideraStatus(network: string, status: any): Promise<void> {
|
||||
return this.storage.set(Keys.GLIDERA_STATUS(network), status);
|
||||
};
|
||||
|
||||
getGlideraStatus(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.GLIDERA_STATUS(network));
|
||||
};
|
||||
|
||||
removeGlideraStatus(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.GLIDERA_STATUS(network));
|
||||
};
|
||||
|
||||
setGlideraTxs(network: string, txs: any): Promise<void> {
|
||||
return this.storage.set(Keys.GLIDERA_TXS(network), txs);
|
||||
};
|
||||
|
||||
getGlideraTxs(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.GLIDERA_TXS(network));
|
||||
};
|
||||
|
||||
removeGlideraTxs(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.GLIDERA_TXS(network));
|
||||
};
|
||||
|
||||
setCoinbaseToken(network: string, token: string): Promise<void> {
|
||||
return this.storage.set(Keys.COINBASE_TOKEN(network), token);
|
||||
};
|
||||
|
||||
getCoinbaseToken(network: string): Promise<string> {
|
||||
return this.storage.get(Keys.COINBASE_TOKEN(network));
|
||||
};
|
||||
|
||||
removeCoinbaseToken(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.COINBASE_TOKEN(network));
|
||||
};
|
||||
|
||||
setCoinbaseRefreshToken(network: string, token: string): Promise<void> {
|
||||
return this.storage.set(Keys.COINBASE_REFRESH_TOKEN(network), token);
|
||||
};
|
||||
|
||||
getCoinbaseRefreshToken(network: string): Promise<string> {
|
||||
return this.storage.get(Keys.COINBASE_REFRESH_TOKEN(network));
|
||||
};
|
||||
|
||||
removeCoinbaseRefreshToken(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.COINBASE_REFRESH_TOKEN(network));
|
||||
};
|
||||
|
||||
setCoinbaseTxs(network: string, ctx: any): Promise<void> {
|
||||
return this.storage.set(Keys.COINBASE_TXS(network), ctx);
|
||||
};
|
||||
|
||||
getCoinbaseTxs(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.COINBASE_TXS(network));
|
||||
};
|
||||
|
||||
removeCoinbaseTxs(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.COINBASE_TXS(network));
|
||||
};
|
||||
|
||||
setAddressbook(network: string, addressbook: any): Promise<void> {
|
||||
return this.storage.set(Keys.ADDRESS_BOOK(network), addressbook);
|
||||
};
|
||||
|
||||
getAddressbook(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.ADDRESS_BOOK(network));
|
||||
};
|
||||
|
||||
removeAddressbook(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.ADDRESS_BOOK(network));
|
||||
};
|
||||
|
||||
setLastCurrencyUsed(lastCurrencyUsed: any): Promise<void> {
|
||||
return this.storage.set(Keys.LAST_CURRENCY_USED, lastCurrencyUsed);
|
||||
};
|
||||
|
||||
getLastCurrencyUsed(): Promise<any> {
|
||||
return this.storage.get(Keys.LAST_CURRENCY_USED);
|
||||
};
|
||||
|
||||
checkQuota(): void {
|
||||
let block = '';
|
||||
// 50MB
|
||||
for (let i = 0; i < 1024 * 1024; ++i) {
|
||||
block += '12345678901234567890123456789012345678901234567890';
|
||||
}
|
||||
this.storage.set('test', block).catch(err => {
|
||||
this.log.error('CheckQuota Return:' + err);
|
||||
});
|
||||
};
|
||||
|
||||
setTxHistory(walletId: string, txs: any): Promise<void> {
|
||||
return this.storage.set(Keys.TX_HISTORY(walletId), txs).catch(err => {
|
||||
this.log.error('Error saving tx History. Size:' + txs.length);
|
||||
this.log.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
getTxHistory(walletId: string): Promise<any> {
|
||||
return this.storage.get(Keys.TX_HISTORY(walletId));
|
||||
}
|
||||
|
||||
removeTxHistory(walletId: string): Promise<void> {
|
||||
return this.storage.remove(Keys.TX_HISTORY(walletId));
|
||||
}
|
||||
|
||||
setBalanceCache(cardId: string, data: any): Promise<void> {
|
||||
return this.storage.set(Keys.BALANCE_CACHE(cardId), data);
|
||||
};
|
||||
|
||||
getBalanceCache(cardId: string): Promise<any> {
|
||||
return this.storage.get(Keys.BALANCE_CACHE(cardId));
|
||||
};
|
||||
|
||||
removeBalanceCache(cardId: string): Promise<void> {
|
||||
return this.storage.remove(Keys.BALANCE_CACHE(cardId));
|
||||
};
|
||||
|
||||
setAppIdentity(network: string, data: any): Promise<void> {
|
||||
return this.storage.set(Keys.APP_IDENTITY(network), data);
|
||||
};
|
||||
|
||||
getAppIdentity(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.APP_IDENTITY(network)).then(data => {
|
||||
return JSON.parse(data || '{}');
|
||||
});
|
||||
};
|
||||
|
||||
removeAppIdentity(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.APP_IDENTITY(network));
|
||||
};
|
||||
|
||||
removeAllWalletData(walletId: string): Promise<void> {
|
||||
return this.clearLastAddress(walletId)
|
||||
.then(() => { return this.removeTxHistory(walletId); })
|
||||
.then(() => { return this.clearBackupFlag(walletId); });
|
||||
};
|
||||
|
||||
setAmazonGiftCards(network: string, gcs: any): Promise<void> {
|
||||
return this.storage.set(Keys.AMAZON_GIFT_CARDS(network), gcs);
|
||||
};
|
||||
|
||||
getAmazonGiftCards(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.AMAZON_GIFT_CARDS(network));
|
||||
};
|
||||
|
||||
removeAmazonGiftCards(network: string): Promise<void> {
|
||||
return this.storage.remove(Keys.AMAZON_GIFT_CARDS(network));
|
||||
};
|
||||
|
||||
setTxConfirmNotification(txid: string, val: any): Promise<void> {
|
||||
return this.storage.set(Keys.TX_CONFIRM_NOTIF(txid), val);
|
||||
};
|
||||
|
||||
getTxConfirmNotification(txid: string): Promise<any> {
|
||||
return this.storage.get(Keys.TX_CONFIRM_NOTIF(txid));
|
||||
};
|
||||
|
||||
removeTxConfirmNotification(txid: string): Promise<void> {
|
||||
return this.storage.remove(Keys.TX_CONFIRM_NOTIF(txid));
|
||||
};
|
||||
|
||||
|
||||
// cb(err, accounts)
|
||||
// accounts: {
|
||||
// email_1: {
|
||||
// token: account token
|
||||
// cards: {
|
||||
// <card-data>
|
||||
// }
|
||||
// }
|
||||
// ...
|
||||
// email_n: {
|
||||
// token: account token
|
||||
// cards: {
|
||||
// <card-data>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
getBitpayAccounts(network: string): Promise<any> {
|
||||
return this.storage.get(Keys.BITPAY_ACCOUNTS_V2(network));
|
||||
};
|
||||
|
||||
setBitpayAccount(network: string, data: {
|
||||
email: string,
|
||||
token: string,
|
||||
familyName?: string, // last name
|
||||
givenName?: string, // firstName
|
||||
}): Promise<any> {
|
||||
return this.getBitpayAccounts(network)
|
||||
.then(allAccounts => {
|
||||
allAccounts = allAccounts || {};
|
||||
let account = allAccounts[data.email] || {};
|
||||
account.token = data.token;
|
||||
account.familyName = data.familyName;
|
||||
account.givenName = data.givenName;
|
||||
allAccounts[data.email] = account;
|
||||
|
||||
this.log.info('Storing BitPay accounts with new account:' + data.email);
|
||||
return this.storage.set(Keys.BITPAY_ACCOUNTS_V2(network), allAccounts);
|
||||
});
|
||||
};
|
||||
|
||||
removeBitpayAccount(network: string, email: string): Promise<void> {
|
||||
return this.getBitpayAccounts(network)
|
||||
.then(allAccounts => {
|
||||
allAccounts = allAccounts || {};
|
||||
delete allAccounts[email];
|
||||
return this.storage.set(Keys.BITPAY_ACCOUNTS_V2(network), allAccounts);
|
||||
});
|
||||
};
|
||||
|
||||
// cards: [
|
||||
// eid: card id
|
||||
// id: card id
|
||||
// lastFourDigits: card number
|
||||
// token: card token
|
||||
// ]
|
||||
setBitpayDebitCards(network: string, email: string, cards: any): Promise<void> {
|
||||
return this.getBitpayAccounts(network)
|
||||
.then(allAccounts => {
|
||||
allAccounts = allAccounts || {};
|
||||
if (!allAccounts[email]) throw new Error('Cannot set cards for unknown account ' + email);
|
||||
allAccounts[email].cards = cards;
|
||||
return this.storage.set(Keys.BITPAY_ACCOUNTS_V2(network), allAccounts);
|
||||
});
|
||||
};
|
||||
|
||||
// cards: [
|
||||
// eid: card id
|
||||
// id: card id
|
||||
// lastFourDigits: card number
|
||||
// token: card token
|
||||
// email: account email
|
||||
// ]
|
||||
getBitpayDebitCards(network: string): Promise<any[]> {
|
||||
return this.getBitpayAccounts(network)
|
||||
.then(allAccounts => {
|
||||
let allCards = [];
|
||||
_.each(allAccounts, (account, email) => {
|
||||
if (account.cards) {
|
||||
// Add account's email to each card
|
||||
var cards = _.clone(account.cards);
|
||||
_.each(cards, function (x) {
|
||||
x.email = email;
|
||||
});
|
||||
|
||||
allCards = allCards.concat(cards);
|
||||
}
|
||||
});
|
||||
return allCards;
|
||||
});
|
||||
};
|
||||
|
||||
removeBitpayDebitCard(network: string, cardEid: string): Promise<void> {
|
||||
return this.getBitpayAccounts(network)
|
||||
.then(allAccounts => {
|
||||
return _.each(allAccounts, function (account) {
|
||||
account.cards = _.reject(account.cards, {
|
||||
eid: cardEid
|
||||
});
|
||||
});
|
||||
}).then(allAccounts => {
|
||||
return this.storage.set(Keys.BITPAY_ACCOUNTS_V2(network), allAccounts);
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export interface IStorage {
|
||||
get(k: string): Promise<any>;
|
||||
set(k: string, v: any): Promise<void>;
|
||||
remove(k: string): Promise<void>;
|
||||
create(k: string, v: any): Promise<void>;
|
||||
}
|
||||
|
||||
export class KeyAlreadyExistsError extends Error {
|
||||
constructor() {
|
||||
super('Key already exists');
|
||||
}
|
||||
}
|
||||
|
||||
export let ISTORAGE = new InjectionToken<IStorage>('storage');
|
|
@ -0,0 +1,55 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { PlatformProvider } from '../../platform/platform';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { IStorage, KeyAlreadyExistsError } from './istorage';
|
||||
|
||||
@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): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
let v = this.ls.getItem(k);
|
||||
if (!v) return resolve(null);
|
||||
if (!_.isString(v)) return resolve(v);
|
||||
let parsed: any;
|
||||
try {
|
||||
parsed = JSON.parse(v);
|
||||
} catch (e) {
|
||||
}
|
||||
resolve(parsed || v);
|
||||
});
|
||||
}
|
||||
|
||||
set(k: string, v: any): Promise<void> {
|
||||
return Promise.resolve().then(() => {
|
||||
if (_.isObject(v)) {
|
||||
v = JSON.stringify(v);
|
||||
}
|
||||
if (v && !_.isString(v)) {
|
||||
v = v.toString();
|
||||
}
|
||||
|
||||
this.ls.setItem(k, v);
|
||||
});
|
||||
}
|
||||
|
||||
remove(k: string): Promise<void> {
|
||||
return Promise.resolve().then(() => {
|
||||
this.ls.removeItem(k);
|
||||
});
|
||||
}
|
||||
|
||||
create(k: string, v: any): Promise<void> {
|
||||
return this.get(k).then((data) => {
|
||||
if (data) throw new KeyAlreadyExistsError();
|
||||
this.set(k, v);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { IStorage, KeyAlreadyExistsError } from './istorage';
|
||||
import { PlatformProvider } from '../../platform/platform';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
|
||||
export class RamStorage implements IStorage {
|
||||
hash = {};
|
||||
|
||||
constructor(private platform: PlatformProvider, private log: Logger) { }
|
||||
|
||||
get(k: string): Promise<any> {
|
||||
return Promise.resolve(this.hash[k]);
|
||||
};
|
||||
set(k: string, v: any): Promise<void> {
|
||||
return Promise.resolve().then(() => { this.hash[k] = v });
|
||||
};
|
||||
remove(k: string): Promise<void> {
|
||||
return Promise.resolve().then(() => { delete this.hash[k]; });
|
||||
};
|
||||
create(k: string, v: any): Promise<void> {
|
||||
return this.get(k).then((data) => {
|
||||
if (data) throw new KeyAlreadyExistsError();
|
||||
this.set(k, v);
|
||||
});
|
||||
};
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
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');
|
|
@ -1,53 +0,0 @@
|
|||
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);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
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');
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
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);
|
||||
// });
|
||||
};
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"types": [
|
||||
"chrome",
|
||||
"lodash"
|
||||
"lodash",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue