From b49c67210310676a343c3022441dd8f88e968089 Mon Sep 17 00:00:00 2001 From: JDonadio Date: Tue, 10 Oct 2017 17:51:17 -0300 Subject: [PATCH 1/3] import wallet --- src/app/app.module.ts | 2 + src/pages/add/add.ts | 3 +- .../add/import-wallet/import-wallet.html | 88 +++++++++++++ .../add/import-wallet/import-wallet.scss | 14 +++ src/pages/add/import-wallet/import-wallet.ts | 119 ++++++++++++++++++ 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/pages/add/import-wallet/import-wallet.html create mode 100644 src/pages/add/import-wallet/import-wallet.scss create mode 100644 src/pages/add/import-wallet/import-wallet.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 044130e51..7d8701138 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -26,6 +26,7 @@ import { CopayApp } from './app.component'; /* Pages */ import { AddPage } from '../pages/add/add'; import { CreateWalletPage } from '../pages/add/create-wallet/create-wallet'; +import { ImportWalletPage } from '../pages/add/import-wallet/import-wallet'; import { BackupRequestPage } from '../pages/onboarding/backup-request/backup-request'; import { DisclaimerPage } from '../pages/onboarding/disclaimer/disclaimer'; import { EmailPage } from '../pages/onboarding/email/email'; @@ -77,6 +78,7 @@ export function createTranslateLoader(http: Http) { let pages: any = [ AddPage, CreateWalletPage, + ImportWalletPage, AboutPage, AdvancedPage, AltCurrencyPage, diff --git a/src/pages/add/add.ts b/src/pages/add/add.ts index 021d332bc..9360f4483 100644 --- a/src/pages/add/add.ts +++ b/src/pages/add/add.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { CreateWalletPage } from "./create-wallet/create-wallet"; +import { ImportWalletPage } from "./import-wallet/import-wallet"; @Component({ selector: 'page-add', @@ -22,6 +23,6 @@ export class AddPage { } goToImportWallet() { - // this.navCtrl.push(); + this.navCtrl.push(ImportWalletPage); } } diff --git a/src/pages/add/import-wallet/import-wallet.html b/src/pages/add/import-wallet/import-wallet.html new file mode 100644 index 000000000..ce8bd1597 --- /dev/null +++ b/src/pages/add/import-wallet/import-wallet.html @@ -0,0 +1,88 @@ + + + Import wallet + + + + +
+
Recovery phrase
+
File/Text
+
Hardware wallet
+
+ +
+ + Type the recovery phrase (usually 12 words) + + + +
+ + Choose a backup file from your computer + + + + + Password + + +
+ +
+ + Wallet type + + {{opt.label}} + + + + + Account number + + + + + Shared wallet + + +
+ + + + + Show advanced options + Hide advanced options + + +
+
+ + Password + + + + + Derivation path + + + + + From hardware wallet + + + + + Testnet + + +
+ + + Wallet service URL + + +
+ +
+
\ No newline at end of file diff --git a/src/pages/add/import-wallet/import-wallet.scss b/src/pages/add/import-wallet/import-wallet.scss new file mode 100644 index 000000000..4b6cb4371 --- /dev/null +++ b/src/pages/add/import-wallet/import-wallet.scss @@ -0,0 +1,14 @@ +.tabs { + display: flex; + text-align: center; + padding-top: 13px; + padding-bottom: 13px; +} + +.tab { + width: 100%; +} + +.selected { + border-bottom: 2px solid; +} \ No newline at end of file diff --git a/src/pages/add/import-wallet/import-wallet.ts b/src/pages/add/import-wallet/import-wallet.ts new file mode 100644 index 000000000..8296d41df --- /dev/null +++ b/src/pages/add/import-wallet/import-wallet.ts @@ -0,0 +1,119 @@ +import { Component, OnInit } from '@angular/core'; +import { NavController } from 'ionic-angular'; +import { Validators, FormBuilder, FormGroup } from '@angular/forms'; + +import { AppProvider } from '../../../providers/app/app'; +import * as _ from 'lodash'; + +@Component({ + selector: 'page-import-wallet', + templateUrl: 'import-wallet.html' +}) +export class ImportWalletPage implements OnInit{ + public formData: any; + public showAdvOpts: boolean; + public selectedTab: string; + public seedOptions: any; + + private appName: string; + private derivationPathByDefault: string; + private derivationPathForTestnet: string; + private importForm: FormGroup; + + constructor( + public navCtrl: NavController, + private app: AppProvider, + private fb: FormBuilder + ) { + this.selectedTab = 'words'; + this.derivationPathByDefault = "m/44'/0'/0'"; + this.derivationPathForTestnet = "m/44'/1'/0'"; + this.showAdvOpts = false; + this.formData = { + words: null, + text: null, + filePassword: null, + selectedSeed: null, + isShared: null, + account: 1, + mnemonicPassword: null, + derivationPath: this.derivationPathByDefault, + fromHW: false, + testnet: false, + bwsURL: 'https://bws.bitpay.com/bws/api', + }; + this.appName = this.app.info.name; + this.updateSeedSourceSelect(); + } + + ngOnInit() { + this.importForm = this.fb.group({ + words: ['', Validators.required], + file: [''], + filePassword: [''], + selectedSeed: [''], + isShared: [''], + account: [''], + mnemonicPassword: [''], + derivationPath: [''], + fromHW: [''], + testnet: [''], + bwsURL: [''], + }); + } + + updateSeedSourceSelect() { + if (this.appName === 'bitpay') return; + + this.seedOptions = [{ + id: 'trezor', + label: 'Trezor hardware wallet', + supportsTestnet: false + }, { + id: 'ledger', + label: 'Ledger hardware wallet', + supportsTestnet: false + }]; + this.formData.selectedSeed = { + id: this.seedOptions[0].id + }; + } + + selectTab(tab: string) { + this.selectedTab = tab; + + switch (tab) { + case 'words': + this.importForm.get('words').setValidators([Validators.required]); + this.importForm.get('file').clearValidators(); + this.importForm.get('filePassword').clearValidators(); + break; + case 'file': + this.importForm.get('file').setValidators([Validators.required]); + this.importForm.get('filePassword').setValidators([Validators.required]); + this.importForm.get('words').clearValidators(); + break; + + default: + this.importForm.get('words').clearValidators(); + this.importForm.get('file').clearValidators(); + this.importForm.get('filePassword').clearValidators(); + break; + } + this.importForm.get('words').updateValueAndValidity(); + this.importForm.get('file').updateValueAndValidity(); + this.importForm.get('filePassword').updateValueAndValidity(); + } + + seedOptionsChange(id: string) { + if (id === 'trezor') this.formData.isShared = null; + } + + setDerivationPath() { + this.formData.derivationPath = this.formData.testnet ? this.derivationPathForTestnet : this.derivationPathByDefault; + } + + import() { + console.log(this.formData); + } +} From 4f93163f58ce0d59e17f46f7b7922b74d4930c68 Mon Sep 17 00:00:00 2001 From: JDonadio Date: Thu, 12 Oct 2017 09:36:25 -0300 Subject: [PATCH 2/3] get default values --- src/app/app.module.ts | 2 + .../add/import-wallet/import-wallet.html | 25 ------- src/pages/add/import-wallet/import-wallet.ts | 65 +++++++------------ .../derivationPathHelper.ts | 59 +++++++++++++++++ 4 files changed, 84 insertions(+), 67 deletions(-) create mode 100644 src/providers/derivationPathHelper/derivationPathHelper.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7d8701138..c002c4ce6 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -70,6 +70,7 @@ 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'); @@ -123,6 +124,7 @@ let providers: any = [ TxFormatProvider, WalletProvider, ReleaseProvider, + DerivationPathHelperProvider, { provide: ErrorHandler, useClass: IonicErrorHandler diff --git a/src/pages/add/import-wallet/import-wallet.html b/src/pages/add/import-wallet/import-wallet.html index ce8bd1597..d3da44e2d 100644 --- a/src/pages/add/import-wallet/import-wallet.html +++ b/src/pages/add/import-wallet/import-wallet.html @@ -8,7 +8,6 @@
Recovery phrase
File/Text
-
Hardware wallet
@@ -29,25 +28,6 @@ -
- - Wallet type - - {{opt.label}} - - - - - Account number - - - - - Shared wallet - - -
- @@ -67,11 +47,6 @@ - - From hardware wallet - - - Testnet diff --git a/src/pages/add/import-wallet/import-wallet.ts b/src/pages/add/import-wallet/import-wallet.ts index 8296d41df..11ae067c5 100644 --- a/src/pages/add/import-wallet/import-wallet.ts +++ b/src/pages/add/import-wallet/import-wallet.ts @@ -2,8 +2,10 @@ import { Component, OnInit } from '@angular/core'; import { NavController } from 'ionic-angular'; import { Validators, FormBuilder, FormGroup } from '@angular/forms'; -import { AppProvider } from '../../../providers/app/app'; -import * as _ from 'lodash'; +import { BwcProvider } from '../../../providers/bwc/bwc'; +import { WalletProvider } from '../../../providers/wallet/wallet'; +import { DerivationPathHelperProvider } from '../../../providers/derivationPathHelper/derivationPathHelper'; +import { ConfigProvider } from '../../../providers/config/config'; @Component({ selector: 'page-import-wallet', @@ -15,70 +17,45 @@ export class ImportWalletPage implements OnInit{ public selectedTab: string; public seedOptions: any; - private appName: string; private derivationPathByDefault: string; private derivationPathForTestnet: string; private importForm: FormGroup; constructor( public navCtrl: NavController, - private app: AppProvider, - private fb: FormBuilder + private fb: FormBuilder, + private bwc: BwcProvider, + private dpHelper: DerivationPathHelperProvider, + private wp: WalletProvider, + private cp: ConfigProvider, ) { this.selectedTab = 'words'; - this.derivationPathByDefault = "m/44'/0'/0'"; - this.derivationPathForTestnet = "m/44'/1'/0'"; + this.derivationPathByDefault = this.dpHelper.default; + this.derivationPathForTestnet = this.dpHelper.defaultTestnet; this.showAdvOpts = false; this.formData = { words: null, - text: null, - filePassword: null, - selectedSeed: null, - isShared: null, - account: 1, mnemonicPassword: null, + file: null, + filePassword: null, derivationPath: this.derivationPathByDefault, - fromHW: false, testnet: false, - bwsURL: 'https://bws.bitpay.com/bws/api', + bwsURL: this.cp.get()['bws']['url'], }; - this.appName = this.app.info.name; - this.updateSeedSourceSelect(); } ngOnInit() { this.importForm = this.fb.group({ words: ['', Validators.required], + mnemonicPassword: [''], file: [''], filePassword: [''], - selectedSeed: [''], - isShared: [''], - account: [''], - mnemonicPassword: [''], derivationPath: [''], - fromHW: [''], testnet: [''], bwsURL: [''], }); } - updateSeedSourceSelect() { - if (this.appName === 'bitpay') return; - - this.seedOptions = [{ - id: 'trezor', - label: 'Trezor hardware wallet', - supportsTestnet: false - }, { - id: 'ledger', - label: 'Ledger hardware wallet', - supportsTestnet: false - }]; - this.formData.selectedSeed = { - id: this.seedOptions[0].id - }; - } - selectTab(tab: string) { this.selectedTab = tab; @@ -105,13 +82,17 @@ export class ImportWalletPage implements OnInit{ this.importForm.get('filePassword').updateValueAndValidity(); } - seedOptionsChange(id: string) { - if (id === 'trezor') this.formData.isShared = null; - } - setDerivationPath() { this.formData.derivationPath = this.formData.testnet ? this.derivationPathForTestnet : this.derivationPathByDefault; } + + normalizeMnemonic(words: string) { + if (!words || !words.indexOf) return words; + var isJA = words.indexOf('\u3000') > -1; + var wordList = words.split(/[\u3000\s]+/); + + return wordList.join(isJA ? '\u3000' : ' '); + }; import() { console.log(this.formData); diff --git a/src/providers/derivationPathHelper/derivationPathHelper.ts b/src/providers/derivationPathHelper/derivationPathHelper.ts new file mode 100644 index 000000000..763a33306 --- /dev/null +++ b/src/providers/derivationPathHelper/derivationPathHelper.ts @@ -0,0 +1,59 @@ +import { Injectable } from '@angular/core'; + +@Injectable() +export class DerivationPathHelperProvider { + public default: string; + public defaultTestnet: string; + + public constructor() { + this.default = "m/44'/0'/0'"; + this.defaultTestnet = "m/44'/1'/0'"; + } + + parse(str: string) { + var arr = str.split('/'); + var ret = { + derivationStrategy: '', + networkName: '', + account: 0 + }; + + if (arr[0] != 'm') + return false; + + switch (arr[1]) { + case "44'": + ret.derivationStrategy = 'BIP44'; + break; + case "45'": + return { + derivationStrategy: 'BIP45', + networkName: 'livenet', + account: 0, + } + case "48'": + ret.derivationStrategy = 'BIP48'; + break; + default: + return false; + }; + + switch (arr[2]) { + case "0'": + ret.networkName = 'livenet'; + break; + case "1'": + ret.networkName = 'testnet'; + break; + default: + return false; + }; + + var match = arr[3].match(/(\d+)'/); + if (!match) + return false; + ret.account = +match[1] + + return ret; + }; +} \ No newline at end of file From df306aff10cf0fce6914ff91efa75c66cc1af5d0 Mon Sep 17 00:00:00 2001 From: JDonadio Date: Thu, 12 Oct 2017 13:14:08 -0300 Subject: [PATCH 3/3] rename providers --- src/pages/add/import-wallet/import-wallet.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pages/add/import-wallet/import-wallet.ts b/src/pages/add/import-wallet/import-wallet.ts index 11ae067c5..8454056d7 100644 --- a/src/pages/add/import-wallet/import-wallet.ts +++ b/src/pages/add/import-wallet/import-wallet.ts @@ -23,15 +23,15 @@ export class ImportWalletPage implements OnInit{ constructor( public navCtrl: NavController, - private fb: FormBuilder, + private form: FormBuilder, private bwc: BwcProvider, - private dpHelper: DerivationPathHelperProvider, - private wp: WalletProvider, - private cp: ConfigProvider, + private pathHelper: DerivationPathHelperProvider, + private walletProvider: WalletProvider, + private configProvider: ConfigProvider, ) { this.selectedTab = 'words'; - this.derivationPathByDefault = this.dpHelper.default; - this.derivationPathForTestnet = this.dpHelper.defaultTestnet; + this.derivationPathByDefault = this.pathHelper.default; + this.derivationPathForTestnet = this.pathHelper.defaultTestnet; this.showAdvOpts = false; this.formData = { words: null, @@ -40,12 +40,12 @@ export class ImportWalletPage implements OnInit{ filePassword: null, derivationPath: this.derivationPathByDefault, testnet: false, - bwsURL: this.cp.get()['bws']['url'], + bwsURL: this.configProvider.get()['bws']['url'], }; } ngOnInit() { - this.importForm = this.fb.group({ + this.importForm = this.form.group({ words: ['', Validators.required], mnemonicPassword: [''], file: [''],