Merge pull request #4518 from JDonadio/feat/import-qr
Export-Import Wallet using QR code
This commit is contained in:
commit
a77df6f458
7 changed files with 433 additions and 247 deletions
|
|
@ -5,23 +5,31 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content preferences" ng-controller="exportController" ng-init="init(index.prevState)">
|
<div class="content preferences" ng-controller="exportController" ng-init="init(index.prevState)">
|
||||||
<h4></h4>
|
<div ng-show="!index.canSign"><h4></h4></div>
|
||||||
|
<div ng-show="index.canSign" class="create-tab small-only-text-center">
|
||||||
|
<div class="row">
|
||||||
|
<div class="tab-container small-6 columns"
|
||||||
|
ng-class="{'selected':!exportQR}"
|
||||||
|
ng-style="{'border-color':!exportQR ? index.backgroundColor: 'inherit'}"
|
||||||
|
ng-click="exportQR = false">
|
||||||
|
<a href ng-style="{'color':!exportQR ? index.backgroundColor: 'inherit'}" translate>File/Text</a>
|
||||||
|
</div>
|
||||||
|
<div class="tab-container small-6 columns"
|
||||||
|
ng-class="{'selected':exportQR}"
|
||||||
|
ng-style="{'border-color':exportQR ? index.backgroundColor: 'inherit'}"
|
||||||
|
ng-click="exportQR = true">
|
||||||
|
<a href ng-style="{'color':exportQR ? index.backgroundColor: 'inherit'}" translate>QR Code</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div ng-show="!backupWalletPlainText">
|
<div ng-show="!backupWalletPlainText">
|
||||||
<div class="text-warning size-14 m20b" ng-show="error">
|
<div class="text-warning size-14 m20b" ng-show="error">
|
||||||
<i class="fi-alert size-12"></i>
|
<i class="fi-alert size-12"></i>
|
||||||
<span translate>Failed to export</span>
|
<span translate>Failed to export</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<form ng-show="!exportQR">
|
||||||
<div class="columns">
|
|
||||||
<div class="text-warning size-14 m20b" ng-show="isEncrypted">
|
|
||||||
<i class="fi-alert size-12"></i>
|
|
||||||
<span translate> A spending password is set for this wallet. Exporting keeps the spending password in the export archive.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form ng-hide="touchidEnabled && !touchidSuccess">
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<label for="password" translate>Set up a password </label>
|
<label for="password" translate>Set up a password </label>
|
||||||
|
|
@ -37,13 +45,36 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h4></h4>
|
<div class="m20t text-gray" ng-show="exportQR && supported">
|
||||||
|
<div class="text-center m20b">
|
||||||
|
<qrcode size="220" version="8" error-correction-level="M" data="{{exportWalletInfo}}"></qrcode>
|
||||||
|
</div>
|
||||||
|
<div class="text-center size-12 m10" translate>From the destination device, go to Add wallet > Import wallet and scan this QR code</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ion-toggle ng-model="noSignEnabled" toggle-class="toggle-balanced" class="r0">
|
<div class="m20t text-gray" ng-show="exportQR && !supported">
|
||||||
|
<div class="text-center size-12 m10" translate>Exporting via QR not supported for this wallet</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" ng-show="!exportQR && index.canSign">
|
||||||
|
<div class="columns m15t">
|
||||||
|
<a class="button outline light-gray expand tiny p10i" ng-click="showAdvanced = !showAdvanced">
|
||||||
|
<i class="fi-widget m3r"></i>
|
||||||
|
<span translate ng-hide="showAdvanced">Show advanced options</span>
|
||||||
|
<span translate ng-hide="!showAdvanced">Hide advanced options</span>
|
||||||
|
<i ng-if="!showAdvanced" class="icon-arrow-down4"></i>
|
||||||
|
<i ng-if="showAdvanced" class="icon-arrow-up4"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="showAdvanced">
|
||||||
|
<ion-toggle ng-model="noSignEnabled" toggle-class="toggle-balanced" class="r0" ng-change="noSignEnabledChange()">
|
||||||
<span class="toggle-label" translate>Do not include private key</span>
|
<span class="toggle-label" translate>Do not include private key</span>
|
||||||
</ion-toggle>
|
</ion-toggle>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="box-notification" ng-show="!index.canSign">
|
<div class="box-notification p15l" ng-show="!index.canSign">
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
<i class="fi-alert"></i>
|
<i class="fi-alert"></i>
|
||||||
<span translate>
|
<span translate>
|
||||||
|
|
@ -52,8 +83,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="box-notification p15l" ng-show="noSignEnabled">
|
||||||
<div class="box-notification" ng-show="noSign">
|
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
<i class="fi-alert"></i>
|
<i class="fi-alert"></i>
|
||||||
<span translate>
|
<span translate>
|
||||||
|
|
@ -62,19 +92,19 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row" ng-show="!exportQR">
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<button class="black round expand m20t" ng-click="downloadWalletBackup()"
|
<button class="black round expand m20t" ng-click="downloadWalletBackup()"
|
||||||
ng-disabled="(!password || password != repeatpassword)"
|
ng-disabled="(!password || password != repeatpassword)"
|
||||||
ng-style="{'background-color':index.backgroundColor}"
|
ng-style="{'background-color':index.backgroundColor}"
|
||||||
ng-show="!index.isSafari && !index.isCordova"><i class="fi-download"></i>
|
ng-show="!isSafari && !isCordova"><i class="fi-download"></i>
|
||||||
<span translate>Download</span></button>
|
<span translate>Download</span></button>
|
||||||
<button class="black round expand m20t" ng-click="viewWalletBackup()"
|
<button class="black round expand m20t" ng-click="viewWalletBackup()"
|
||||||
ng-disabled="(!password || password != repeatpassword)"
|
ng-disabled="(!password || password != repeatpassword)"
|
||||||
ng-style="{'background-color':index.backgroundColor}"
|
ng-style="{'background-color':index.backgroundColor}"
|
||||||
ng-show="index.isSafari && !index.isCordova"><i class="fi-eye"></i>
|
ng-show="isSafari && !isCordova"><i class="fi-eye"></i>
|
||||||
<span translate>View</span></button>
|
<span translate>View</span></button>
|
||||||
<div ng-show="index.isCordova">
|
<div ng-show="isCordova">
|
||||||
<h4 translate>Export options</h4>
|
<h4 translate>Export options</h4>
|
||||||
<button class="black round expand" ng-disabled="(!password || password != repeatpassword)"
|
<button class="black round expand" ng-disabled="(!password || password != repeatpassword)"
|
||||||
ng-style="{'background-color':index.backgroundColor}"
|
ng-style="{'background-color':index.backgroundColor}"
|
||||||
|
|
@ -87,7 +117,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" ng-show="backupWalletPlainText">
|
<div class="row" ng-show="backupWalletPlainText">
|
||||||
|
|
@ -102,6 +131,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="extra-margin-bottom"></div>
|
<div class="extra-margin-bottom"></div>
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,17 @@
|
||||||
ng-init="titleSection='Import wallet'; goBackToState = 'add'; noColor = true">
|
ng-init="titleSection='Import wallet'; goBackToState = 'add'; noColor = true">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content p20b" ng-controller="importController as import" ng-init="type='12'">
|
<div class="content p20b" ng-controller="importController" ng-init="type='12'">
|
||||||
<div class="create-tab pr small-only-text-center" ng-hide="create.hideTabs">
|
<div class="create-tab pr small-only-text-center" ng-hide="create.hideTabs">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type =='12'}">
|
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type =='12'}">
|
||||||
<a href ng-click="import.setType('12')" translate>Recovery Phrase</a>
|
<a href ng-click="setType('12')" translate>Recovery Phrase</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type=='file'}">
|
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type=='file'}">
|
||||||
<a href ng-click="import.setType('file')" translate>File/Text Backup</a>
|
<a href ng-click="setType('file')" translate>File/Text Backup</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type=='hwWallet'}">
|
<div class="tab-container small-4 medium-4 large-4" ng-class="{'selected': type=='hwWallet'}">
|
||||||
<a href ng-click="import.setType('hwWallet')" translate>Hardware Wallet</a>
|
<a href ng-click="setType('hwWallet')" translate>Hardware Wallet</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -23,15 +23,13 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<div class="box-notification m20b" ng-show="import.importErr">
|
<div class="box-notification m20b" ng-show="importErr">
|
||||||
<div ng-show="import.importErr" class="text-warning">
|
<div ng-show="importErr" class="text-warning">
|
||||||
<div class="m10 text-bold" translate>Could not access the wallet at the server. Please check:</div>
|
<div class="m10 text-bold" translate>Could not access the wallet at the server. Please check:</div>
|
||||||
<ul class="size-12">
|
<ul class="size-12">
|
||||||
<li translate>The password of the recovery phrase (if set)
|
<li translate>The password of the recovery phrase (if set)</li>
|
||||||
</li>
|
<li translate>The derivation path</li>
|
||||||
<li translate>The derivation path
|
<li translate>The wallet service URL</li>
|
||||||
</li>
|
|
||||||
<li translate>The wallet service URL
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="m15l">
|
<div class="m15l">
|
||||||
<span translate>NOTE: To import a wallet from a 3rd party software, please go to Add Wallet > Create Wallet, and specify the Recovery Phrase there.</span><br>
|
<span translate>NOTE: To import a wallet from a 3rd party software, please go to Add Wallet > Create Wallet, and specify the Recovery Phrase there.</span><br>
|
||||||
|
|
@ -39,25 +37,33 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box-notification m20b" ng-show="import.error">
|
<div class="box-notification m20b" ng-show="error">
|
||||||
<div class="text-warning">
|
<div class="text-warning">{{error|translate}}</div>
|
||||||
{{import.error|translate}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<form name="importForm12" ng-submit="import.importMnemonic(importForm12)" novalidate>
|
<form name="importForm12" ng-submit="importMnemonic(importForm12)" novalidate>
|
||||||
|
<label for="words" class="m25r">
|
||||||
<div >
|
|
||||||
<label for="words">
|
|
||||||
<span translate>Type the Recovery Phrase (usually 12 words)</span>:
|
<span translate>Type the Recovery Phrase (usually 12 words)</span>:
|
||||||
</label>
|
</label>
|
||||||
<textarea class="form-control" name="words" ng-model="import.words" rows="2" autocapitalize="off" spellcheck="false"></textarea>
|
|
||||||
|
<div class="qr-scanner-input-import" ng-show="!dataFromQR">
|
||||||
|
<qr-scanner on-scan="processWalletInfo(data)"></qr-scanner>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="lock-fromQR" ng-show="dataFromQR">
|
||||||
|
<div class="left m10l">
|
||||||
|
<i class="fi-lock color-greeni"></i>
|
||||||
|
</div>
|
||||||
|
<div class="right icon-close-import" ng-click="dataFromQR = null">
|
||||||
|
<i class="icon-close-circle size-14"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<textarea class="form-control m10t" ng-disabled="dataFromQR" name="words" ng-model="words" rows="2" autocapitalize="off" spellcheck="false"></textarea>
|
||||||
|
|
||||||
<div class="m10t oh" ng-init="hideAdv=true">
|
<div class="m10t oh" ng-init="hideAdv=true">
|
||||||
<a class="button outline light-gray expand tiny p10i" ng-click="hideAdv=!hideAdv">
|
<a class="button outline light-gray expand tiny p10i" ng-click="hideAdv=!hideAdv">
|
||||||
<i class="fi-widget m3r"></i>
|
<i class="fi-widget m3r"></i>
|
||||||
|
|
@ -67,13 +73,13 @@
|
||||||
<i ng-if="!hideAdv" class="icon-arrow-up4"></i>
|
<i ng-if="!hideAdv" class="icon-arrow-up4"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-hide="hideAdv" class="row">
|
<div ng-hide="hideAdv" class="row">
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
|
|
||||||
<label for="passphrase" class="oh"><span translate>Password</span> <small translate>The Wallet Recovery Phrase could require a password to be imported</small>
|
<label for="passphrase" class="oh"><span translate>Password</span> <small translate>The Wallet Recovery Phrase could require a password to be imported</small>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input type="password" class="form-control" placeholder="{{'Password'|translate}}"
|
<input type="password" class="form-control" placeholder="{{'Password'|translate}}"
|
||||||
name="passphrase" ng-model="import.passphrase">
|
name="passphrase" ng-model="passphrase">
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|
@ -96,10 +102,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button translate type="submit" class="button round expand black m10t"
|
<button translate type="submit" class="button round expand black m10t" ng-disabled="importForm12.$invalid">Import</button>
|
||||||
ng-disabled="importForm12.$invalid ">
|
|
||||||
Import
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -108,33 +111,33 @@
|
||||||
<div ng-show="type == 'file' ">
|
<div ng-show="type == 'file' ">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<div class="box-notification m20b" ng-show="import.error">
|
<div class="box-notification m20b" ng-show="error">
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
{{import.error|translate}}
|
{{error|translate}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<form name="importForm" ng-submit="import.importBlob(importForm)" novalidate>
|
<form name="importForm" ng-submit="importBlob(importForm)" novalidate>
|
||||||
|
|
||||||
<div ng-show="!index.isSafari && !index.isCordova" class="line-b m10b">
|
<div ng-show="!index.isSafari && !index.isCordova" class="line-b m10b">
|
||||||
<label for="backupFile">
|
<label for="backupFile">
|
||||||
<span translate>Choose a backup file from your computer</span> <i class="fi-laptop"></i>
|
<span translate>Choose a backup file from your computer</span> <i class="fi-laptop"></i>
|
||||||
</label>
|
</label>
|
||||||
<input type="file" class="form-control" placeholder="{{'Select a backup file'|translate}}"
|
<input type="file" class="form-control" placeholder="{{'Select a backup file'|translate}}"
|
||||||
name="backupFile" ng-model="import.backupFile" ng-file-select>
|
name="backupFile" ng-model="backupFile" ng-file-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="index.isSafari || index.isCordova">
|
<div ng-show="index.isSafari || index.isCordova">
|
||||||
<label for="backupText">
|
<label for="backupText">
|
||||||
<span translate>Paste the backup plain text code</span> <i class="fi-clipboard"></i>
|
<span translate>Paste the backup plain text code</span> <i class="fi-clipboard"></i>
|
||||||
</label>
|
</label>
|
||||||
<textarea class="form-control" name="backupText" ng-model="import.backupText" rows="5"></textarea>
|
<textarea class="form-control" name="backupText" ng-model="backupText" rows="5"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label for="password"><span translate>Password</span>
|
<label for="password"><span translate>Password</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input type="password" class="form-control" placeholder="{{'Your password'|translate}}"
|
<input type="password" class="form-control" placeholder="{{'Your password'|translate}}"
|
||||||
name="password" ng-model="import.password">
|
name="password" ng-model="password">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m10t oh" ng-init="hideAdv=true">
|
<div class="m10t oh" ng-init="hideAdv=true">
|
||||||
|
|
@ -157,7 +160,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button translate type="submit" class="button round expand black"
|
<button translate type="submit" class="button round expand black"
|
||||||
ng-disabled="importForm.$invalid || !import.password ">
|
ng-disabled="importForm.$invalid || !password ">
|
||||||
Import backup
|
Import backup
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -168,35 +171,34 @@
|
||||||
<div ng-show="type == 'hwWallet'">
|
<div ng-show="type == 'hwWallet'">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-12 columns">
|
<div class="large-12 columns">
|
||||||
<div class="box-notification m20b" ng-show="import.error">
|
<div class="box-notification m20b" ng-show="error">
|
||||||
<span class="text-warning size-14">
|
<span class="text-warning size-14">
|
||||||
{{import.error|translate}}
|
{{error|translate}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form name="importForm3" ng-submit="import.importHW(importForm3)" novalidate>
|
<form name="importForm3" ng-submit="importHW(importForm3)" novalidate>
|
||||||
<div class="large-12 columns">
|
<div ng-show="!seedOptions[0]">
|
||||||
<div ng-show="!import.seedOptions[0]">
|
|
||||||
<span translate>No hardware wallets supported on this device</span>
|
<span translate>No hardware wallets supported on this device</span>
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="import.seedOptions[0]">
|
<div ng-show="seedOptions[0]">
|
||||||
<div>
|
<div>
|
||||||
<label><span translate>Wallet Recovery Phrase</span>
|
<label><span translate>Wallet Recovery Phrase</span>
|
||||||
<select class="m10t" ng-model="seedSource"
|
<select class="m10t" ng-model="seedSource"
|
||||||
ng-options="seed as seed.label for seed in import.seedOptions"
|
ng-options="seed as seed.label for seed in seedOptions"
|
||||||
ng-change="import.setSeedSource()">
|
ng-change="setSeedSource()">
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="import.seedSourceId == 'trezor' || import.seedSourceId == 'ledger'">
|
<div ng-show="seedSourceId == 'trezor' || seedSourceId == 'ledger'">
|
||||||
|
|
||||||
<label class="oh"><span translate>Account Number</span>
|
<label class="oh"><span translate>Account Number</span>
|
||||||
<input type="number" id="account" ng-model="account">
|
<input type="number" id="account" ng-model="account">
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="oh" ng-show="import.seedSourceId == 'trezor'">
|
<div class="oh" ng-show="seedSourceId == 'trezor'">
|
||||||
<ion-toggle ng-model="isMultisig" toggle-class="toggle-balanced" class="bct">
|
<ion-toggle ng-model="isMultisig" toggle-class="toggle-balanced" class="bct">
|
||||||
<span class="toggle-label" translate>Shared Wallet</span>
|
<span class="toggle-label" translate>Shared Wallet</span>
|
||||||
</ion-toggle>
|
</ion-toggle>
|
||||||
|
|
@ -221,12 +223,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<button translate type="submit" class="button round expand black">
|
<button translate type="submit" class="button round expand black">
|
||||||
Import
|
Import
|
||||||
</button>
|
</button>
|
||||||
</div> <!-- seedoptions show -->
|
</div> <!-- seedoptions show -->
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ angular.module('copayApp.controllers').controller('backupController',
|
||||||
|
|
||||||
handleEncryptedWallet(fc, function(err) {
|
handleEncryptedWallet(fc, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
$scope.error = bwsError.msg(err, gettext('Could not decrypt'));
|
|
||||||
$log.warn('Error decrypting credentials:', $scope.error);
|
$log.warn('Error decrypting credentials:', $scope.error);
|
||||||
|
go.path(prevState);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$scope.credentialsEncrypted = false;
|
$scope.credentialsEncrypted = false;
|
||||||
|
|
@ -69,10 +69,13 @@ angular.module('copayApp.controllers').controller('backupController',
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goBack = function() {
|
$scope.goBack = function() {
|
||||||
walletService.lock(fc);
|
|
||||||
go.path(prevState || 'walletHome');
|
go.path(prevState || 'walletHome');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
walletService.lock(fc);
|
||||||
|
});
|
||||||
|
|
||||||
$scope.goToStep = function(n) {
|
$scope.goToStep = function(n) {
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
$scope.initFlow();
|
$scope.initFlow();
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,109 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('exportController',
|
angular.module('copayApp.controllers').controller('exportController',
|
||||||
function($scope, $timeout, $log, backupService, fingerprintService, configService, storageService, profileService, platformInfo, notification, go, gettext, gettextCatalog) {
|
function($rootScope, $scope, $timeout, $log, lodash, backupService, walletService, fingerprintService, configService, storageService, profileService, platformInfo, notification, go, gettext, gettextCatalog) {
|
||||||
|
var prevState;
|
||||||
var isWP = platformInfo.isWP;
|
var isWP = platformInfo.isWP;
|
||||||
var isAndroid = platformInfo.isAndroid;
|
var isAndroid = platformInfo.isAndroid;
|
||||||
var isCordova = platformInfo.isCordova;
|
|
||||||
|
|
||||||
$scope.error = null;
|
|
||||||
$scope.success = null;
|
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
$scope.isEncrypted = fc.isPrivKeyEncrypted();
|
$scope.isEncrypted = fc.isPrivKeyEncrypted();
|
||||||
$scope.touchidSuccess = null;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
$scope.touchidEnabled = null;
|
$scope.isSafari = platformInfo.isSafari;
|
||||||
$scope.error = null;
|
$scope.error = null;
|
||||||
|
|
||||||
$scope.init = function(state) {
|
$scope.init = function(state) {
|
||||||
if (!isCordova) return;
|
$scope.supported = true;
|
||||||
|
$scope.exportQR = false;
|
||||||
var config = configService.getSync();
|
$scope.noSignEnabled = false;
|
||||||
var touchidAvailable = fingerprintService.isAvailable();
|
$scope.showAdvanced = false;
|
||||||
var touchidEnabled = $scope.touchidEnabled = config.touchIdFor ? config.touchIdFor[fc.credentials.walletId] : null;
|
prevState = state || 'walletHome';
|
||||||
|
|
||||||
if (!touchidAvailable || !touchidEnabled) return;
|
|
||||||
|
|
||||||
fingerprintService.check(fc, function(err) {
|
fingerprintService.check(fc, function(err) {
|
||||||
if (err)
|
if (err) {
|
||||||
go.path(state || 'walletHome');
|
go.path(prevState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.touchidSuccess = true;
|
handleEncryptedWallet(fc, function(err) {
|
||||||
|
if (err) {
|
||||||
|
go.path(prevState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.exportWalletInfo = encodeWalletInfo();
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
}, 10);
|
}, 1);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
EXPORT WITHOUT PRIVATE KEY - PENDING
|
||||||
|
|
||||||
|
$scope.noSignEnabledChange = function() {
|
||||||
|
$scope.exportWalletInfo = encodeWalletInfo();
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
walletService.lock(fc);
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleEncryptedWallet(client, cb) {
|
||||||
|
if (!walletService.isEncrypted(client)) {
|
||||||
|
$scope.credentialsEncrypted = false;
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$emit('Local/NeedsPassword', false, function(err, password) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
return cb(walletService.unlock(client, password));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function encodeWalletInfo() {
|
||||||
|
var c = fc.credentials;
|
||||||
|
var derivationPath = fc.credentials.getBaseAddressDerivationPath();
|
||||||
|
var encodingType = {
|
||||||
|
mnemonic: 1,
|
||||||
|
xpriv: 2,
|
||||||
|
xpub: 3
|
||||||
|
};
|
||||||
|
var info;
|
||||||
|
|
||||||
|
$scope.supported = (c.derivationStrategy == 'BIP44' && c.canSign());
|
||||||
|
|
||||||
|
if ($scope.supported) {
|
||||||
|
if (c.mnemonic) {
|
||||||
|
info = {
|
||||||
|
type: encodingType.mnemonic,
|
||||||
|
data: c.mnemonic,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info = {
|
||||||
|
type: encodingType.xpriv,
|
||||||
|
data: c.xPrivKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
EXPORT WITHOUT PRIVATE KEY - PENDING
|
||||||
|
|
||||||
|
info = {
|
||||||
|
type: encodingType.xpub,
|
||||||
|
data: c.xPubKey
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = info.type + '|' + info.data + '|' + c.network.toLowerCase() + '|' + derivationPath + '|' + (c.mnemonicHasPassphrase);
|
||||||
|
return code;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.downloadWalletBackup = function() {
|
$scope.downloadWalletBackup = function() {
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,89 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('importController',
|
angular.module('copayApp.controllers').controller('importController',
|
||||||
function($scope, $rootScope, $timeout, $log, profileService, configService, notification, go, sjcl, gettext, lodash, ledger, trezor, derivationPathHelper, platformInfo, bwsError, bwcService, ongoingProcess) {
|
function($scope, $rootScope, $timeout, $log, profileService, configService, notification, go, sjcl, gettext, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess) {
|
||||||
|
|
||||||
var isChromeApp = platformInfo.isChromeApp;
|
var isChromeApp = platformInfo.isChromeApp;
|
||||||
var isDevel = platformInfo.isDevel;
|
var isDevel = platformInfo.isDevel;
|
||||||
|
|
||||||
var self = this;
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
var defaults = configService.getDefaults();
|
var defaults = configService.getDefaults();
|
||||||
var errors = bwcService.getErrors();
|
var errors = bwcService.getErrors();
|
||||||
|
$scope.dataFromQR = null;
|
||||||
$scope.bwsurl = defaults.bws.url;
|
$scope.bwsurl = defaults.bws.url;
|
||||||
$scope.derivationPath = derivationPathHelper.default;
|
$scope.derivationPath = derivationPathHelper.default;
|
||||||
$scope.account = 1;
|
$scope.account = 1;
|
||||||
self.importErr = false;
|
$scope.importErr = false;
|
||||||
|
|
||||||
var updateSeedSourceSelect = function() {
|
var updateSeedSourceSelect = function() {
|
||||||
self.seedOptions = [];
|
$scope.seedOptions = [];
|
||||||
|
|
||||||
if (isChromeApp) {
|
if (isChromeApp) {
|
||||||
self.seedOptions.push({
|
$scope.seedOptions.push({
|
||||||
id: 'ledger',
|
id: 'ledger',
|
||||||
label: 'Ledger Hardware Wallet',
|
label: 'Ledger Hardware Wallet',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isChromeApp || isDevel) {
|
if (isChromeApp || isDevel) {
|
||||||
self.seedOptions.push({
|
$scope.seedOptions.push({
|
||||||
id: 'trezor',
|
id: 'trezor',
|
||||||
label: 'Trezor Hardware Wallet',
|
label: 'Trezor Hardware Wallet',
|
||||||
});
|
});
|
||||||
$scope.seedSource = self.seedOptions[0];
|
$scope.seedSource = $scope.seedOptions[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setType = function(type) {
|
$scope.processWalletInfo = function(code) {
|
||||||
|
$scope.dataFromQR = null;
|
||||||
|
$scope.importErr = false;
|
||||||
|
$scope.error = null;
|
||||||
|
var parsedCode = code.split('|');
|
||||||
|
|
||||||
|
if (parsedCode.length != 5) {
|
||||||
|
$scope.error = gettext('Cannot read the code properly. Missing parameters');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = {
|
||||||
|
type: parsedCode[0],
|
||||||
|
data: parsedCode[1],
|
||||||
|
network: parsedCode[2],
|
||||||
|
derivationPath: parsedCode[3],
|
||||||
|
hasPassphrase: parsedCode[4] == 'true' ? true : false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (info.type == 1 && info.hasPassphrase)
|
||||||
|
$scope.error = gettext('Password required. Make sure to enter your password in advanced options');
|
||||||
|
|
||||||
|
$scope.derivationPath = info.derivationPath;
|
||||||
|
$scope.testnetEnabled = info.network == 'testnet' ? true : false;
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.words = null;
|
||||||
|
$scope.dataFromQR = info.data;
|
||||||
|
$rootScope.$apply();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.setType = function(type) {
|
||||||
$scope.type = type;
|
$scope.type = type;
|
||||||
this.error = null;
|
$scope.error = null;
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
});
|
}, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
var _importBlob = function(str, opts) {
|
var _importBlob = function(str, opts) {
|
||||||
var str2, err;
|
var str2, err;
|
||||||
try {
|
try {
|
||||||
str2 = sjcl.decrypt(self.password, str);
|
str2 = sjcl.decrypt($scope.password, str);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
err = gettext('Could not decrypt file, check your password');
|
err = gettext('Could not decrypt file, check your password');
|
||||||
$log.warn(e);
|
$log.warn(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -67,7 +98,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
profileService.importWallet(str2, opts, function(err, walletId) {
|
profileService.importWallet(str2, opts, function(err, walletId) {
|
||||||
ongoingProcess.set('importingWallet', false);
|
ongoingProcess.set('importingWallet', false);
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
} else {
|
} else {
|
||||||
$rootScope.$emit('Local/WalletImported', walletId);
|
$rootScope.$emit('Local/WalletImported', walletId);
|
||||||
notification.success(gettext('Success'), gettext('Your wallet has been imported correctly'));
|
notification.success(gettext('Success'), gettext('Your wallet has been imported correctly'));
|
||||||
|
|
@ -84,9 +115,9 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
ongoingProcess.set('importingWallet', false);
|
ongoingProcess.set('importingWallet', false);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err instanceof errors.NOT_AUTHORIZED) {
|
if (err instanceof errors.NOT_AUTHORIZED) {
|
||||||
self.importErr = true;
|
$scope.importErr = true;
|
||||||
} else {
|
} else {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
}
|
}
|
||||||
return $timeout(function() {
|
return $timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
|
|
@ -100,6 +131,28 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPORT FROM PUBLIC KEY - PENDING
|
||||||
|
|
||||||
|
var _importExtendedPublicKey = function(xPubKey, opts) {
|
||||||
|
ongoingProcess.set('importingWallet', true);
|
||||||
|
$timeout(function() {
|
||||||
|
profileService.importExtendedPublicKey(opts, function(err, walletId) {
|
||||||
|
ongoingProcess.set('importingWallet', false);
|
||||||
|
if (err) {
|
||||||
|
$scope.error = err;
|
||||||
|
return $timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$rootScope.$emit('Local/WalletImported', walletId);
|
||||||
|
notification.success(gettext('Success'), gettext('Your wallet has been imported correctly'));
|
||||||
|
go.walletHome();
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
var _importMnemonic = function(words, opts) {
|
var _importMnemonic = function(words, opts) {
|
||||||
ongoingProcess.set('importingWallet', true);
|
ongoingProcess.set('importingWallet', true);
|
||||||
|
|
||||||
|
|
@ -109,9 +162,9 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err instanceof errors.NOT_AUTHORIZED) {
|
if (err instanceof errors.NOT_AUTHORIZED) {
|
||||||
self.importErr = true;
|
$scope.importErr = true;
|
||||||
} else {
|
} else {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
}
|
}
|
||||||
return $timeout(function() {
|
return $timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
|
|
@ -130,7 +183,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
$scope.derivationPath = derivationPathHelper.defaultTestnet;
|
$scope.derivationPath = derivationPathHelper.defaultTestnet;
|
||||||
else
|
else
|
||||||
$scope.derivationPath = derivationPathHelper.default;
|
$scope.derivationPath = derivationPathHelper.default;
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.getFile = function() {
|
$scope.getFile = function() {
|
||||||
// If we use onloadend, we need to check the readyState.
|
// If we use onloadend, we need to check the readyState.
|
||||||
|
|
@ -143,9 +196,9 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importBlob = function(form) {
|
$scope.importBlob = function(form) {
|
||||||
if (form.$invalid) {
|
if (form.$invalid) {
|
||||||
this.error = gettext('There is an error in the form');
|
$scope.error = gettext('There is an error in the form');
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -157,7 +210,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
var password = form.password.$modelValue;
|
var password = form.password.$modelValue;
|
||||||
|
|
||||||
if (!backupFile && !backupText) {
|
if (!backupFile && !backupText) {
|
||||||
this.error = gettext('Please, select your backup file');
|
$scope.error = gettext('Please, select your backup file');
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -174,9 +227,9 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importMnemonic = function(form) {
|
$scope.importMnemonic = function(form) {
|
||||||
if (form.$invalid) {
|
if (form.$invalid) {
|
||||||
this.error = gettext('There is an error in the form');
|
$scope.error = gettext('There is an error in the form');
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -187,32 +240,33 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
if ($scope.bwsurl)
|
if ($scope.bwsurl)
|
||||||
opts.bwsurl = $scope.bwsurl;
|
opts.bwsurl = $scope.bwsurl;
|
||||||
|
|
||||||
|
|
||||||
var pathData = derivationPathHelper.parse($scope.derivationPath);
|
var pathData = derivationPathHelper.parse($scope.derivationPath);
|
||||||
if (!pathData) {
|
if (!pathData) {
|
||||||
this.error = gettext('Invalid derivation path');
|
$scope.error = gettext('Invalid derivation path');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
opts.account = pathData.account;
|
opts.account = pathData.account;
|
||||||
opts.networkName = pathData.networkName;
|
opts.networkName = pathData.networkName;
|
||||||
opts.derivationStrategy = pathData.derivationStrategy;
|
opts.derivationStrategy = pathData.derivationStrategy;
|
||||||
|
|
||||||
var words = form.words.$modelValue;
|
var words = form.words.$modelValue || $scope.dataFromQR;
|
||||||
this.error = null;
|
$scope.error = null;
|
||||||
|
|
||||||
if (!words) {
|
if (!words) {
|
||||||
this.error = gettext('Please enter the recovery phrase');
|
$scope.error = gettext('Please enter the recovery phrase');
|
||||||
} else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) {
|
} else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) {
|
||||||
return _importExtendedPrivateKey(words, opts);
|
return _importExtendedPrivateKey(words, opts);
|
||||||
|
} else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) {
|
||||||
|
return _importExtendedPublicKey(words, opts);
|
||||||
} else {
|
} else {
|
||||||
var wordList = words.split(/[\u3000\s]+/);
|
var wordList = words.split(/[\u3000\s]+/);
|
||||||
|
|
||||||
if ((wordList.length % 3) != 0) {
|
if ((wordList.length % 3) != 0) {
|
||||||
this.error = gettext('Wrong number of recovery words:') + wordList.length;
|
$scope.error = gettext('Wrong number of recovery words:') + wordList.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.error) {
|
if ($scope.error) {
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -225,12 +279,12 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
_importMnemonic(words, opts);
|
_importMnemonic(words, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importTrezor = function(account, isMultisig) {
|
$scope.importTrezor = function(account, isMultisig) {
|
||||||
var self = this;
|
var $scope = $scope;
|
||||||
trezor.getInfoForNewWallet(isMultisig, account, function(err, lopts) {
|
trezor.getInfoForNewWallet(isMultisig, account, function(err, lopts) {
|
||||||
ongoingProcess.clear();
|
ongoingProcess.clear();
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +297,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
profileService.importExtendedPublicKey(lopts, function(err, walletId) {
|
profileService.importExtendedPublicKey(lopts, function(err, walletId) {
|
||||||
ongoingProcess.set('importingWallet', false);
|
ongoingProcess.set('importingWallet', false);
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
return $timeout(function() {
|
return $timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -255,56 +309,56 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importHW = function(form) {
|
$scope.importHW = function(form) {
|
||||||
if (form.$invalid || $scope.account < 0) {
|
if (form.$invalid || $scope.account < 0) {
|
||||||
this.error = gettext('There is an error in the form');
|
$scope.error = gettext('There is an error in the form');
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.error = '';
|
$scope.error = '';
|
||||||
this.importErr = false;
|
$scope.importErr = false;
|
||||||
|
|
||||||
var account = +$scope.account;
|
var account = +$scope.account;
|
||||||
|
|
||||||
if (self.seedSourceId == 'trezor') {
|
if ($scope.seedSourceId == 'trezor') {
|
||||||
if (account < 1) {
|
if (account < 1) {
|
||||||
this.error = gettext('Invalid account number');
|
$scope.error = gettext('Invalid account number');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
account = account - 1;
|
account = account - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (self.seedSourceId) {
|
switch ($scope.seedSourceId) {
|
||||||
case ('ledger'):
|
case ('ledger'):
|
||||||
ongoingProcess.set('connectingledger', true);
|
ongoingProcess.set('connectingledger', true);
|
||||||
self.importLedger(account);
|
$scope.importLedger(account);
|
||||||
break;
|
break;
|
||||||
case ('trezor'):
|
case ('trezor'):
|
||||||
ongoingProcess.set('connectingtrezor', true);
|
ongoingProcess.set('connectingtrezor', true);
|
||||||
self.importTrezor(account, $scope.isMultisig);
|
$scope.importTrezor(account, $scope.isMultisig);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw ('Error: bad source id');
|
throw ('Error: bad source id');
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setSeedSource = function() {
|
$scope.setSeedSource = function() {
|
||||||
if (!$scope.seedSource) return;
|
if (!$scope.seedSource) return;
|
||||||
self.seedSourceId = $scope.seedSource.id;
|
$scope.seedSourceId = $scope.seedSource.id;
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importLedger = function(account) {
|
$scope.importLedger = function(account) {
|
||||||
var self = this;
|
var $scope = $scope;
|
||||||
ledger.getInfoForNewWallet(true, account, function(err, lopts) {
|
ledger.getInfoForNewWallet(true, account, function(err, lopts) {
|
||||||
ongoingProcess.clear();
|
ongoingProcess.clear();
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +371,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
profileService.importExtendedPublicKey(lopts, function(err, walletId) {
|
profileService.importExtendedPublicKey(lopts, function(err, walletId) {
|
||||||
ongoingProcess.set('importingWallet', false);
|
ongoingProcess.set('importingWallet', false);
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error = err;
|
$scope.error = err;
|
||||||
return $timeout(function() {
|
return $timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -330,5 +384,5 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
};
|
};
|
||||||
|
|
||||||
updateSeedSourceSelect();
|
updateSeedSourceSelect();
|
||||||
self.setSeedSource('new');
|
$scope.setSeedSource('new');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
'importingWallet': gettext('Importing Wallet...'),
|
'importingWallet': gettext('Importing Wallet...'),
|
||||||
'sweepingWallet': gettext('Sweeping Wallet...'),
|
'sweepingWallet': gettext('Sweeping Wallet...'),
|
||||||
'deletingWallet': gettext('Deleting Wallet...'),
|
'deletingWallet': gettext('Deleting Wallet...'),
|
||||||
|
'extractingWalletInfo': gettext('Extracting Wallet Information...'),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.clear = function() {
|
root.clear = function() {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,16 @@ body {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-scanner-input-import {
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-close-import {
|
||||||
|
padding: 0px 40px 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
color: #2C3E50;
|
color: #2C3E50;
|
||||||
}
|
}
|
||||||
|
|
@ -606,6 +616,14 @@ ul.manage li {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.m40r {
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m25r {
|
||||||
|
margin-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.m10l {
|
.m10l {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
@ -695,6 +713,10 @@ ul.manage li {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p15l {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.p15 {
|
.p15 {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
@ -869,6 +891,12 @@ ul.manage li {
|
||||||
background-color: #1ABC9C;
|
background-color: #1ABC9C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lock-fromQR {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.tx-proposal i {
|
.tx-proposal i {
|
||||||
padding: .1rem .3rem;
|
padding: .1rem .3rem;
|
||||||
background-color: #A5B2BF;
|
background-color: #A5B2BF;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue