commit
3bf7202831
20 changed files with 1104 additions and 546 deletions
|
|
@ -78,7 +78,6 @@ module.exports = function(grunt) {
|
||||||
},
|
},
|
||||||
angular: {
|
angular: {
|
||||||
src: [
|
src: [
|
||||||
'bower_components/fastclick/lib/fastclick.js',
|
|
||||||
'bower_components/qrcode-generator/js/qrcode.js',
|
'bower_components/qrcode-generator/js/qrcode.js',
|
||||||
'bower_components/qrcode-decoder-js/lib/qrcode-decoder.js',
|
'bower_components/qrcode-decoder-js/lib/qrcode-decoder.js',
|
||||||
'bower_components/moment/min/moment-with-locales.js',
|
'bower_components/moment/min/moment-with-locales.js',
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
"angular-bitcore-wallet-client": "^0.0.18",
|
"angular-bitcore-wallet-client": "^0.0.18",
|
||||||
"angular-ui-router": "~0.2.13",
|
"angular-ui-router": "~0.2.13",
|
||||||
"qrcode-decoder-js": "*",
|
"qrcode-decoder-js": "*",
|
||||||
"fastclick": "*",
|
|
||||||
"angular-ui-switch": "~0.1.0"
|
"angular-ui-switch": "~0.1.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
<div notifications="right top"></div>
|
<div notifications="right top"></div>
|
||||||
<div ng-include="'views/includes/offline.html'" ng-if="index.isOffline"></div>
|
<div ng-include="'views/includes/offline.html'" ng-if="index.isOffline"></div>
|
||||||
|
|
||||||
<div ng-include="'views/includes/clientError.html'" ng-if="index.clientError"></div>
|
<div ng-include="'views/includes/clientError.html'" ng-if="index.clientError"></div>
|
||||||
|
|
||||||
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"
|
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1 @@
|
||||||
<div class="history" ng-controller="historyController as history">
|
|
||||||
<div class="row m20t" ng-show="!index.txHistory[0]">
|
|
||||||
<div class="large-12 columns">
|
|
||||||
<div class="oh text-center">
|
|
||||||
<span ng-if="index.updatingTxHistory" class="text-gray animated flash infinite" translate>Getting transactions...</span>
|
|
||||||
<span ng-if="!index.updatingTxHistory">
|
|
||||||
<span ng-show="index.txHistoryError && !index.notAuthorized" ng-click='index.openWallet()'>
|
|
||||||
<span translate>Could not fetch transaction history</span>
|
|
||||||
<br> [<span translate>Tap to retry</span>]
|
|
||||||
</span>
|
|
||||||
<span ng-if="!index.txHistoryError" translate>
|
|
||||||
No transactions yet
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ng-show="index.txHistory[0]" class="scroll">
|
|
||||||
<div ng-repeat="btx in index.txHistory"
|
|
||||||
ng-click="history.openTxModal(btx)"
|
|
||||||
class="row collapse last-transactions-content">
|
|
||||||
<div class="large-3 medium-3 small-3 columns">
|
|
||||||
<span class="label tu radius" ng-show="btx.action == 'received'"
|
|
||||||
ng-style="{'background-color':index.backgroundColor}" translate>Received</span>
|
|
||||||
<span class="label tu gray radius" ng-show="btx.action == 'sent'" translate>Sent</span>
|
|
||||||
<span class="label tu gray radius" ng-show="btx.action == 'moved'" translate>Moved</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="large-5 medium-5 small-5 columns">
|
|
||||||
<span class="size-16">
|
|
||||||
<span ng-if="btx.action == 'received'">+</span>
|
|
||||||
<span ng-if="btx.action == 'sent'">-</span>
|
|
||||||
{{btx.amountStr}}
|
|
||||||
{{history.getUnitName()}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="large-4 medium-4 small-4 columns text-right">
|
|
||||||
<div class="m5t size-12 text-gray">
|
|
||||||
<time ng-if="btx.time">{{btx.time * 1000 | amTimeAgo}}</time>
|
|
||||||
<span translate class="text-warning"
|
|
||||||
ng-show="!btx.time && (!btx.confirmations || btx.confirmations == 0)">
|
|
||||||
Unconfirmed
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="size-14 text-gray columns m5t" ng-if="btx.message || btx.addressTo">
|
|
||||||
{{btx.message || btx.addressTo}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="m20t row">
|
|
||||||
<div class="columns">
|
|
||||||
<button class="outline light-gray small expand" ng-disabled="index.updatingTxHistory"
|
|
||||||
ng-click="index.updateTxHistory(index.skipHistory)" ng-show="index.txHistoryPaging">
|
|
||||||
<span ng-show="!index.updatingTxHistory">
|
|
||||||
<span translate>More</span> <i class="icon-arrow-down4 ng-scope"></i>
|
|
||||||
</span>
|
|
||||||
<span ng-show="index.updatingTxHistory" translate>
|
|
||||||
Getting transactions...
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="extra-margin-bottom"></div>
|
<div class="extra-margin-bottom"></div>
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,8 @@
|
||||||
<i class="fi-alert"></i>
|
<i class="fi-alert"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="dr-notification-content">
|
<div class="dr-notification-content">
|
||||||
<h3 class="dr-notification-title" translate>Wallet Service Error</h3>
|
<h3 class="dr-notification-title">Wallet Service Error</h3>
|
||||||
<div class="dr-notification-text ellipsis">
|
<div class="dr-notification-text ellipsis">{{index.clientError.message || index.clientError}}</div>
|
||||||
{{index.clientError.error || index.clientError.message || index.clientError}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
<div
|
<div
|
||||||
class="bottom-bar row collapse">
|
class="bottom-bar row collapse">
|
||||||
<div class="medium-3 small-3 columns text-center bottombar-item" ng-repeat="item in index.menu">
|
<div class="medium-3 small-3 columns text-center bottombar-item" ng-repeat="item in index.menu">
|
||||||
<a ng-click="$root.go(item.link)" ng-class="{'active': activeMenu == item.link}"
|
<a id="menu-{{item.link}}" ng-click="index.setTab(item.link)" class="{{item.active? 'active': ''}}" style="border-top-color:{{item.active? index.backgroundColor: ''}}" >
|
||||||
ng-style="{'border-top-color':activeMenu==item.link ? index.backgroundColor : ''}">
|
|
||||||
<i class="size-36 {{item.icon}} db"></i>
|
<i class="size-36 {{item.icon}} db"></i>
|
||||||
<div class="size-10 tu">
|
<div class="size-10 tu">
|
||||||
{{item.title|translate}}
|
{{item.title|translate}}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<nav ng-controller="topbarController as topbar" class="tab-bar">
|
<nav ng-controller="topbarController as topbar" class="tab-bar animated fadeIn">
|
||||||
<section class="left-small">
|
<section class="left-small">
|
||||||
<a class="p10" ng-show="!goBackToState && !index.noFocusedWallet"
|
<a class="p10" ng-show="!goBackToState && !index.noFocusedWallet"
|
||||||
ng-click="index.openMenu()"><i class="fi-list size-24"></i>
|
ng-click="index.openMenu()"><i class="fi-list size-24"></i>
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,18 @@
|
||||||
<div class="ellipsis"><b translate>Address</b>: {{uri.address.toString()}}</div>
|
<div class="ellipsis"><b translate>Address</b>: {{uri.address.toString()}}</div>
|
||||||
<div ng-show="uri.amount"><b translate>Amount</b>: {{uri.amount}}</div>
|
<div ng-show="uri.amount"><b translate>Amount</b>: {{uri.amount}}</div>
|
||||||
<div ng-show="uri.message"><b translate>Message</b>: {{uri.message}}</div>
|
<div ng-show="uri.message"><b translate>Message</b>: {{uri.message}}</div>
|
||||||
|
<div ng-show="uri.network == 'testnet'"><b translate>Network</b>: {{uri.network}}</div>
|
||||||
</div>
|
</div>
|
||||||
<h2 translate>Select a wallet</h2>
|
<h2 translate>Select a wallet</h2>
|
||||||
<ul class="no-bullet" ng-init="wallets = payment.getWallets()">
|
<ul class="no-bullet" ng-init="wallets = payment.getWallets(uri.network)">
|
||||||
<li class="panel" ng-repeat="w in wallets">
|
<li class="panel" ng-repeat="w in wallets">
|
||||||
<a ng-click="payment.selectWallet(w.id)">
|
<a ng-click="payment.selectWallet(w.id)">
|
||||||
<div class="avatar-wallet"
|
<div class="avatar-wallet"
|
||||||
ng-style="{'background-color':w.color}">{{(w.name || w.id) | limitTo: 1}}</div>
|
ng-style="{'background-color':w.color}">{{(w.name || w.id) | limitTo: 1}}</div>
|
||||||
<div class="ellipsis">{{w.name || w.id}}</div>
|
<div class="ellipsis">{{w.name || w.id}}</div>
|
||||||
<div class="size-12">{{w.m}} of {{w.n}}</div>
|
<div class="size-12">{{w.m}} of {{w.n}}
|
||||||
|
<span ng-show="w.network=='testnet'">[Testnet]</span>
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -1,70 +1,2 @@
|
||||||
<div class="receive" ng-controller="receiveController as receive" ng-init="receive.getAddress()">
|
|
||||||
|
|
||||||
<div ng-show="index.needsBackup && !receive.skipBackup" class="p60t row text-center">
|
|
||||||
<div class="text-warning text-bold m15b">
|
|
||||||
<i class="fi-alert"></i>
|
|
||||||
<span translate>
|
|
||||||
WARNING: Backup needed
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-gray m15h" translate>
|
|
||||||
Before receiving funds, it is highly recommended you backup your wallet keys.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="small-6 columns m20t">
|
|
||||||
<span class="button expand outline dark-gray tiny"
|
|
||||||
ng-click="receive.skipBackup = true">
|
|
||||||
<span translate>SKIP BACKUP</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="small-6 columns m20t">
|
|
||||||
<span class="button black expand radius tiny"
|
|
||||||
ng-click="$root.go('backup')" ng-style="{'background-color':index.backgroundColor}" >
|
|
||||||
<span translate>Backup now</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-show="!index.needsBackup || receive.skipBackup">
|
|
||||||
|
|
||||||
<div class="box-notification" ng-show="receive.error ">
|
|
||||||
<span class="text-warning size-14">
|
|
||||||
{{receive.error|translate}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row" ng-if="receive.addr">
|
|
||||||
<!-- Address-->
|
|
||||||
<div class="large-12 columns">
|
|
||||||
<h2 class="text-center m10t" translate>My Bitcoin address</h2>
|
|
||||||
<div class="text-center animated fadeIn" ng-click="receive.copyAddress(receive.addr)">
|
|
||||||
<qrcode size="220" data="bitcoin:{{receive.addr}}"></qrcode>
|
|
||||||
<div class="m10t">
|
|
||||||
<h4 ng-class="{'enable_text_select': !index.isCordova}" class="size-12">{{receive.addr}}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="m10t text-center" ng-show="index.isCordova">
|
|
||||||
<span class="button outline dark-gray tiny"
|
|
||||||
ng-click="receive.shareAddress(receive.addr)">
|
|
||||||
<i class="fi-share"></i>
|
|
||||||
<span translate>Share address</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="line-t size-12" translate>
|
|
||||||
Share this with anyone to have them send you payments. To protect your privacy, new addresses are generated automatically once you use them.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row m20t" ng-if="receive.addr">
|
|
||||||
<div class="large-12 columns">
|
|
||||||
<button class="button black expand radius" ng-click="receive.newAddress()"
|
|
||||||
ng-style="{'background-color':index.backgroundColor}" ng-disabled="receive.generatingAddress" translate>
|
|
||||||
Generate new address
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="extra-margin-bottom"></div>
|
<div class="extra-margin-bottom"></div>
|
||||||
|
|
|
||||||
|
|
@ -1,117 +1,405 @@
|
||||||
<div class="home-wallet" ng-controller="walletHomeController as home">
|
<div ng-controller="walletHomeController as home">
|
||||||
<div class="oh" ng-show="!index.noFocusedWallet">
|
<div id="walletHome" class="walletHome tab-view tab-in">
|
||||||
<div class="amount" ng-style="{'background-color':index.backgroundColor}">
|
<div class="oh" ng-show="!index.noFocusedWallet">
|
||||||
<div ng-if="!index.anyOnGoingProcess && !index.notAuthorized">
|
<div class="amount" ng-style="{'background-color':index.backgroundColor}">
|
||||||
<div ng-show="index.updateError" ng-click='index.openWallet()'>
|
<div ng-if="!index.anyOnGoingProcess && !index.notAuthorized">
|
||||||
<span translate>Could not update Wallet</span>
|
<div ng-show="index.updateError" ng-click='index.openWallet()'>
|
||||||
<br><span translate>Tap to retry</span>
|
<span translate>Could not update Wallet</span>
|
||||||
</div>
|
<br><span translate>Tap to retry</span>
|
||||||
|
|
||||||
<div ng-show="index.walletScanStatus == 'error'" ng-click='index.retryScan()'>
|
|
||||||
<span translate>Scan status finished with error</span>
|
|
||||||
<br><span translate>Tap to retry</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-show="!index.updateError && index.walletScanStatus != 'error'">
|
|
||||||
<div class="size-36 animated fadeIn">
|
|
||||||
<strong>{{index.totalBalanceStr}}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="size-14"
|
|
||||||
ng-if="index.totalBalanceAlternative">
|
<div ng-show="index.walletScanStatus == 'error'" ng-click='index.retryScan()'>
|
||||||
<span ng-class="{'animated fadeIn':!index.hideBalance}">
|
<span translate>Scan status finished with error</span>
|
||||||
|
<br><span translate>Tap to retry</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="!index.updateError && index.walletScanStatus != 'error'">
|
||||||
|
<strong class="size-36">{{index.totalBalanceStr}}</strong>
|
||||||
|
<div class="size-14"
|
||||||
|
ng-if="index.totalBalanceAlternative">
|
||||||
{{index.totalBalanceAlternative}} {{index.alternativeIsoCode}}
|
{{index.totalBalanceAlternative}} {{index.alternativeIsoCode}}
|
||||||
</span>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="index.anyOnGoingProcess">
|
||||||
|
<div class="size-36">
|
||||||
|
<strong>...</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pr columns line-b">
|
||||||
<div ng-if="index.anyOnGoingProcess">
|
<div class="avatar-wallet left"
|
||||||
<div class="size-36">
|
ng-style="{'background-color':index.backgroundColor}">{{index.walletName | limitTo: 1}}</div>
|
||||||
<strong>...</strong>
|
<div class="right">
|
||||||
|
<a ng-click="$root.go('preferences')" class="button outline light-gray tiny m0">
|
||||||
|
<i class="fi-widget size-18 vm"></i>
|
||||||
|
<span class="show-for-medium-up" translate>Preferences</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="wallet-info" ng-click="openCopayersModal(index.copayers, index.copayerId)">
|
||||||
|
<p class="m0">
|
||||||
|
{{index.m}} <span translate>of</span> {{index.n}}
|
||||||
|
</p>
|
||||||
|
<div class="size-12 text-gray">
|
||||||
|
<span ng-if="index.n > 1" translate>Multisignature wallet </span>
|
||||||
|
<span ng-if="index.n == 1" translate>Personal Wallet</span>
|
||||||
|
<span ng-if="index.network != 'livenet'"> - Testnet</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pr columns line-b">
|
|
||||||
<div class="avatar-wallet left"
|
<div class="onGoingProcess"
|
||||||
ng-class="{'updating':index.anyOnGoingProcess}"
|
ng-show="index.anyOnGoingProcess"
|
||||||
ng-style="{'background-color':index.backgroundColor}">{{index.walletName | limitTo: 1}}</div>
|
ng-style="{'background-color':index.backgroundColor}"
|
||||||
<div class="right">
|
ng-class="{'opacityCycle':index.anyOnGoingProcess}"
|
||||||
<a ng-click="$root.go('preferences')" class="button outline light-gray tiny m0">
|
>
|
||||||
<i class="fi-widget size-18 vm"></i>
|
<span translate ng-show="index.onGoingProcessName == 'openingWallet'">Opening Wallet...</span>
|
||||||
<span class="show-for-medium-up" translate>Preferences</span>
|
<span translate ng-show="index.onGoingProcessName == 'updatingStatus'">Updating Status...</span>
|
||||||
</a>
|
<span translate ng-show="index.onGoingProcessName == 'updatingBalance'">Updating Balance...</span>
|
||||||
|
<span translate ng-show="index.onGoingProcessName == 'updatingPendingTxps'">Updating Pending Transactions...</span>
|
||||||
|
<span translate ng-show="index.onGoingProcessName == 'scanning'">Scanning Wallet funds...</span>
|
||||||
|
<span translate ng-show="index.onGoingProcessName == 'recreating'">Recreating Wallet on BWS...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="m20t" ng-show="index.notAuthorized">
|
||||||
|
<div class="text-center text-warning">
|
||||||
|
<i class="fi-alert"></i>
|
||||||
|
<span translate>
|
||||||
|
WARNING: Wallet not registered
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-center text-gray m15r m15l" translate>
|
||||||
|
This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information.
|
||||||
|
</div>
|
||||||
|
<div class="text-center m10t ">
|
||||||
|
<span class="button outline dark-gray tiny"
|
||||||
|
ng-click="index.recreate()">
|
||||||
|
<span translate>Recreate</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div ng-show="index.requiresMultipleSignatures && index.txps[0]">
|
||||||
|
<h4 class="title m0" translate>Spend proposals</h4>
|
||||||
|
<div class="last-transactions pr" ng-repeat="tx in index.txps"
|
||||||
|
ng-include="'views/includes/transaction.html'">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-gray text-center size-12 p10t"
|
||||||
|
ng-show="index.lockedBalance && !index.updatingStatus">
|
||||||
|
<span translate>Total Locked Balance</span>:
|
||||||
|
<b>{{index.lockedBalance}} {{index.unitName}} </b>
|
||||||
|
<span> {{index.lockedBalanceAlternative}}
|
||||||
|
{{index.alternativeIsoCode}} </span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pr" ng-if="!index.txps[0]">
|
||||||
|
<p translate>No pending spend proposals at the moment.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="!index.requiresMultipleSignatures && index.txps[0]">
|
||||||
|
<h4 class="title m0" translate>Unsent transactions</h4>
|
||||||
|
<div class="last-transactions pr" ng-repeat="tx in index.txps"
|
||||||
|
ng-include="'views/includes/transaction.html'">
|
||||||
</div>
|
</div>
|
||||||
<div class="wallet-info" ng-click="openCopayersModal(index.copayers, index.copayerId)">
|
|
||||||
<p class="m0">
|
|
||||||
{{index.m}} <span translate>of</span> {{index.n}}
|
|
||||||
</p>
|
|
||||||
<div class="size-12 text-gray">
|
|
||||||
<span ng-if="index.n > 1" translate>Multisignature wallet </span>
|
|
||||||
<span ng-if="index.n == 1" translate>Personal Wallet</span>
|
|
||||||
<span ng-if="index.network != 'livenet'"> - Testnet</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="onGoingProcess"
|
<!--
|
||||||
ng-show="index.anyOnGoingProcess"
|
|
||||||
ng-style="{'background-color':index.backgroundColor}"
|
|
||||||
ng-class="{'opacityCycle':index.anyOnGoingProcess}"
|
|
||||||
>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'openingWallet'">Opening Wallet...</span>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'updatingStatus'">Updating Status...</span>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'updatingBalance'">Updating Balance...</span>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'updatingPendingTxps'">Updating Pending Transactions...</span>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'scanning'">Scanning Wallet funds...</span>
|
|
||||||
<span translate ng-show="index.onGoingProcessName == 'recreating'">Recreating Wallet on BWS...</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="m20t" ng-show="index.notAuthorized">
|
receive
|
||||||
<div class="text-center text-warning">
|
|
||||||
|
-->
|
||||||
|
<div id="receive" class="receive tab-view">
|
||||||
|
|
||||||
|
<div ng-show="index.needsBackup && !home.skipBackup" class="p60t row text-center">
|
||||||
|
<div class="text-warning text-bold m15b">
|
||||||
<i class="fi-alert"></i>
|
<i class="fi-alert"></i>
|
||||||
<span translate>
|
<span translate>
|
||||||
WARNING: Wallet not registered
|
WARNING: Backup needed
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center text-gray m15r m15l" translate>
|
<div class="text-gray m15h" translate>
|
||||||
This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information.
|
Before receiving funds, it is highly recommended you backup your wallet keys.
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center m10t ">
|
|
||||||
<span class="button outline dark-gray tiny"
|
<div class="small-6 columns m20t">
|
||||||
ng-click="index.recreate()">
|
<span class="button expand outline dark-gray tiny"
|
||||||
<span translate>Recreate</span>
|
ng-click="home.skipBackup = true">
|
||||||
|
<span translate>SKIP BACKUP</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="small-6 columns m20t">
|
||||||
|
<span class="button black expand radius tiny"
|
||||||
|
ng-click="$root.go('backup')" ng-style="{'background-color':index.backgroundColor}" >
|
||||||
|
<span translate>Backup now</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div ng-show="!index.needsBackup || home.skipBackup">
|
||||||
|
<div class="box-notification" ng-show="home.error ">
|
||||||
<div ng-show="index.requiresMultipleSignatures && index.txps[0]">
|
<span class="text-warning size-14">
|
||||||
<h4 class="title m0" translate>Spend proposals</h4>
|
{{home.error|translate}}
|
||||||
<div class="last-transactions pr" ng-repeat="tx in index.txps"
|
</span>
|
||||||
ng-include="'views/includes/transaction.html'">
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" ng-if="home.addr">
|
||||||
<div class="text-gray text-center size-12 p10t"
|
<!-- Address-->
|
||||||
ng-show="index.lockedBalance && !index.updatingStatus">
|
<div class="large-12 columns">
|
||||||
<span translate>Total Locked Balance</span>:
|
<h2 class="text-center m10t" translate>My Bitcoin address</h2>
|
||||||
<b>{{index.lockedBalance}} {{index.unitName}} </b>
|
<div class="text-center" ng-click="home.copyAddress(home.addr)">
|
||||||
<span> {{index.lockedBalanceAlternative}}
|
<qrcode size="220" data="bitcoin:{{home.addr}}"></qrcode>
|
||||||
{{index.alternativeIsoCode}} </span>
|
<div class="m10t">
|
||||||
|
<h4 ng-class="{'enable_text_select': !index.isCordova}" class="size-12">{{home.addr}}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m10t text-center" ng-show="index.isCordova">
|
||||||
|
<span class="button outline dark-gray tiny"
|
||||||
|
ng-click="home.shareAddress(home.addr)">
|
||||||
|
<i class="fi-share"></i>
|
||||||
|
<span translate>Share address</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="line-t size-12" translate>
|
||||||
|
Share this with anyone to have them send you payments. To protect your privacy, new addresses are generated automatically once you use them.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row m20t" ng-if="home.addr">
|
||||||
<div class="pr" ng-if="!index.txps[0]">
|
<div class="large-12 columns">
|
||||||
<p translate>No pending spend proposals at the moment.</p>
|
<button class="button black expand radius" ng-click="home.newAddress()"
|
||||||
|
ng-style="{'background-color':index.backgroundColor}" ng-disabled="home.generatingAddress" translate>
|
||||||
|
Generate new address
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="!index.requiresMultipleSignatures && index.txps[0]">
|
</div>
|
||||||
<h4 class="title m0" translate>Unsent transactions</h4>
|
|
||||||
<div class="last-transactions pr" ng-repeat="tx in index.txps"
|
|
||||||
ng-include="'views/includes/transaction.html'">
|
<!--
|
||||||
</div>
|
|
||||||
|
send
|
||||||
|
|
||||||
|
-->
|
||||||
|
<div id="send" class="send tab-view">
|
||||||
|
<div ng-show="index.lockedBalance">
|
||||||
|
<h4 class="title m0">
|
||||||
|
<div class="left">
|
||||||
|
<i class="fi-info size-36 m10r lh"></i>
|
||||||
|
</div>
|
||||||
|
<div class="size-12">
|
||||||
|
<span class="db text-bold">
|
||||||
|
<span translate>Available Balance</span>:
|
||||||
|
{{index.availableBalanceStr }}
|
||||||
|
</span>
|
||||||
|
<span class="text-gray">
|
||||||
|
{{index.lockedBalanceStr}}
|
||||||
|
<span translate>in pending transactions</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="row m20t">
|
||||||
|
<div class="large-12 large-centered columns">
|
||||||
|
<div class="box-notification" ng-show="home.fetchingURL">
|
||||||
|
<span class="text-secondary size-14" translate>
|
||||||
|
Fetching Payment Information...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<form ng-show="!home.fetchingURL" name="sendForm" ng-submit="home.submitForm(sendForm)" ng-disabled="home.blockUx" novalidate>
|
||||||
|
<div class="box-notification" ng-show="home.error" ng-click="home.resetError()">
|
||||||
|
<span class="text-warning">
|
||||||
|
{{home.error|translate}}
|
||||||
|
</span>
|
||||||
|
<a class="close-notification text-warning">×</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-hide="home._paypro || home.hideAddress">
|
||||||
|
<div class="row collapse">
|
||||||
|
|
||||||
|
<label for="address" class="left" >
|
||||||
|
<span translate>To</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<span ng-hide="sendForm.address.$pristine">
|
||||||
|
<span class="has-error right size-12" ng-show="sendForm.address.$invalid && _address">
|
||||||
|
<span class="icon-input">
|
||||||
|
<i class="fi-x"></i>
|
||||||
|
</span>
|
||||||
|
<span translate>Not valid</span>
|
||||||
|
</span>
|
||||||
|
<small class="icon-input right" ng-show="!sendForm.address.$invalid">
|
||||||
|
<i class="fi-check"></i>
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input">
|
||||||
|
<input type="text" id="address" name="address" ng-disabled="home.blockUx || home.lockAddress" ng-attr-placeholder="{{'Bitcoin address'|translate}}" ng-model="_address" valid-address required ng-focus="home.formFocus('address')" ng-blur="home.formFocus(false)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="home._paypro && !home.hideAddress">
|
||||||
|
<div class="row collapse" ng-click="home.openPPModal(home._paypro)">
|
||||||
|
|
||||||
|
<label for="domain">
|
||||||
|
<span translate>Payment to</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="input block">
|
||||||
|
<input class="p45li" type="text" id="domain" name="domain" ng-model="home._paypro.domain" ng-disabled="1">
|
||||||
|
<i ng-show="home._paypro.verified" class="fi-lock color-greeni"></i>
|
||||||
|
<i ng-show="!home._paypro.verified" class="fi-unlock color-yellowi"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" ng-init="showAlternative = false" ng-hide="home.hideAmount">
|
||||||
|
<div class="large-12 medium-12 columns">
|
||||||
|
<div class="m5b right" ng-hide="sendForm.amount.$pristine">
|
||||||
|
<span class="has-error right size-12" ng-show="sendForm.amount.$invalid">
|
||||||
|
<span class="icon-input"><i class="fi-x"></i></span>
|
||||||
|
<span translate>Not valid</span>
|
||||||
|
</span>
|
||||||
|
<small class="icon-input right" ng-show="!sendForm.amount.$invalid">
|
||||||
|
<i class="fi-check"></i>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div ng-show="!showAlternative">
|
||||||
|
<label for="amount">
|
||||||
|
<span translate>Amount</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="input">
|
||||||
|
<input type="number" id="amount" ng-disabled="home.blockUx || home.lockAmount" name="amount" ng-attr-placeholder="{{'Amount'|translate}}" ng-minlength="0.00000001" ng-maxlength="10000000000" ng-model="_amount" valid-amount required autocomplete="off" ng-focus="home.formFocus('amount')" ng-blur="home.formFocus(false)">
|
||||||
|
<a class="postfix" ng-click="showAlternative = true">{{home.unitName}}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="showAlternative">
|
||||||
|
<label for="alternative"><span translate>Amount in</span> {{ home.alternativeName }}
|
||||||
|
</label>
|
||||||
|
<div class="input">
|
||||||
|
<input type="number" id="alternative" ng-disabled="home.blockUx || !home.isRateAvailable || home.lockAmount" name="alternative" ng-attr-placeholder="{{'Amount'|translate}}" ng-model="_alternative" requiredautocomplete="off" ng-focus="home.formFocus('amount')" ng-blur="home.formFocus(false)">
|
||||||
|
<a class="postfix" ng-click="showAlternative = false"> {{ home.alternativeIsoCode }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<label for="comment"><span translate>Note</span>
|
||||||
|
<small translate ng-hide="!sendForm.comment.$pristine">optional</small>
|
||||||
|
<small translate class="has-error" ng-show="sendForm.comment.$invalid && !sendForm.comment.$pristine">too long!</small>
|
||||||
|
</label>
|
||||||
|
<div class="input">
|
||||||
|
<textarea id="comment" ng-disabled="home.blockUx" name="comment"
|
||||||
|
ng-maxlength="100" ng-model="_comment" ng-focus="home.formFocus('msg')"
|
||||||
|
ng-blur="home.formFocus(false)"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="home.onGoingProcess" class="text-gray text-center m10t">
|
||||||
|
<span class="animated infinite flash">{{home.onGoingProcess|translate}}...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row" ng-show="!home.onGoingProcess">
|
||||||
|
<div class="large-6 medium-6 small-6 columns" ng-show="!home.blockUx && (home._paypro || home.lockAddress)">
|
||||||
|
<a ng-click="home.resetForm(sendForm)" class="button expand outline dark-gray" translate>Cancel</a>
|
||||||
|
</div>
|
||||||
|
<div class="columns" ng-class="{'small-6 medium-6 large-6':(home._paypro || home.lockAddress)}">
|
||||||
|
<button type="submit" class="button black radius expand" ng-disabled="sendForm.$invalid || home.blockUx"
|
||||||
|
ng-style="{'background-color':index.backgroundColor}" translate>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end of row -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
history
|
||||||
|
|
||||||
|
-->
|
||||||
|
<div id="history" class="history tab-view">
|
||||||
|
<div class="row m20t" ng-show="!index.txHistory[0]">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<div class="oh text-center">
|
||||||
|
<span ng-if="index.updatingTxHistory" class="text-gray animated flash infinite" translate>Getting transactions...</span>
|
||||||
|
<span ng-if="!index.updatingTxHistory">
|
||||||
|
<span ng-show="index.txHistoryError && !index.notAuthorized" ng-click='index.openWallet()'>
|
||||||
|
<span translate>Could not fetch transaction history</span>
|
||||||
|
<br> [<span translate>Tap to retry</span>]
|
||||||
|
</span>
|
||||||
|
<span ng-if="!index.txHistoryError" translate>
|
||||||
|
No transactions yet
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="index.txHistory[0]" class="scroll">
|
||||||
|
<div ng-repeat="btx in index.txHistory"
|
||||||
|
ng-click="home.openTxModal(btx)"
|
||||||
|
class="row collapse last-transactions-content">
|
||||||
|
<div class="large-3 medium-3 small-3 columns">
|
||||||
|
<span class="label tu radius" ng-show="btx.action == 'received'"
|
||||||
|
ng-style="{'background-color':index.backgroundColor}" translate>Received</span>
|
||||||
|
<span class="label tu gray radius" ng-show="btx.action == 'sent'" translate>Sent</span>
|
||||||
|
<span class="label tu gray radius" ng-show="btx.action == 'moved'" translate>Moved</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="large-5 medium-5 small-5 columns">
|
||||||
|
<span class="size-16">
|
||||||
|
<span ng-if="btx.action == 'received'">+</span>
|
||||||
|
<span ng-if="btx.action == 'sent'">-</span>
|
||||||
|
{{btx.amountStr}}
|
||||||
|
{{home.getUnitName()}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="large-4 medium-4 small-4 columns text-right">
|
||||||
|
<div class="m5t size-12 text-gray">
|
||||||
|
<time ng-if="btx.time">{{btx.time * 1000 | amTimeAgo}}</time>
|
||||||
|
<span translate class="text-warning"
|
||||||
|
ng-show="!btx.time && (!btx.confirmations || btx.confirmations == 0)">
|
||||||
|
Unconfirmed
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="size-14 text-gray columns m5t" ng-if="btx.message || btx.addressTo">
|
||||||
|
{{btx.message || btx.addressTo}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m20t row">
|
||||||
|
<div class="columns">
|
||||||
|
<button class="outline light-gray small expand" ng-disabled="index.updatingTxHistory"
|
||||||
|
ng-click="index.updateTxHistory(index.skipHistory)" ng-show="index.txHistoryPaging">
|
||||||
|
<span ng-show="!index.updatingTxHistory">
|
||||||
|
<span translate>More</span> <i class="icon-arrow-down4 ng-scope"></i>
|
||||||
|
</span>
|
||||||
|
<span ng-show="index.updatingTxHistory" translate>
|
||||||
|
Getting transactions...
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- END -->
|
||||||
<div class="row columns m20tp" ng-show="index.noFocusedWallet">
|
<div class="row columns m20tp" ng-show="index.noFocusedWallet">
|
||||||
<div class="text-center text-warning m20b">
|
<div class="text-center text-warning m20b">
|
||||||
<i class="fi-alert"></i> <span translate>You do not have any wallet</span>
|
<i class="fi-alert"></i> <span translate>You do not have any wallet</span>
|
||||||
|
|
|
||||||
101
src/css/main.css
101
src/css/main.css
|
|
@ -144,6 +144,7 @@ input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill, inpu
|
||||||
.main {
|
.main {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 45px 0 80px 0;
|
padding: 45px 0 80px 0;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-setup {
|
.logo-setup {
|
||||||
|
|
@ -1106,104 +1107,6 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.updating {
|
|
||||||
-webkit-animation-iteration-count: infinite;
|
|
||||||
-webkit-animation-name: up-animation;
|
|
||||||
-webkit-animation-duration: 1s;
|
|
||||||
-webkit-animation-iteration-count: infinite;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
animation-name: up-animation;
|
|
||||||
animation-duration: 1s;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Generated with Bounce.js. Edit at http://goo.gl/Vn2Euz */
|
|
||||||
|
|
||||||
@-webkit-keyframes up-animation {
|
|
||||||
0% { -webkit-transform: matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
3.4% { -webkit-transform: matrix3d(0.658, 0, 0, 0, 0, 0.703, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.658, 0, 0, 0, 0, 0.703, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
4.7% { -webkit-transform: matrix3d(0.725, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.725, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
6.81% { -webkit-transform: matrix3d(0.83, 0, 0, 0, 0, 0.946, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.83, 0, 0, 0, 0, 0.946, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
9.41% { -webkit-transform: matrix3d(0.942, 0, 0, 0, 0, 1.084, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.942, 0, 0, 0, 0, 1.084, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
10.21% { -webkit-transform: matrix3d(0.971, 0, 0, 0, 0, 1.113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.971, 0, 0, 0, 0, 1.113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
13.61% { -webkit-transform: matrix3d(1.062, 0, 0, 0, 0, 1.166, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.062, 0, 0, 0, 0, 1.166, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
14.11% { -webkit-transform: matrix3d(1.07, 0, 0, 0, 0, 1.165, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.07, 0, 0, 0, 0, 1.165, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
17.52% { -webkit-transform: matrix3d(1.104, 0, 0, 0, 0, 1.12, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.104, 0, 0, 0, 0, 1.12, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
18.72% { -webkit-transform: matrix3d(1.106, 0, 0, 0, 0, 1.094, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.106, 0, 0, 0, 0, 1.094, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
21.32% { -webkit-transform: matrix3d(1.098, 0, 0, 0, 0, 1.035, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.098, 0, 0, 0, 0, 1.035, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
24.32% { -webkit-transform: matrix3d(1.075, 0, 0, 0, 0, 0.98, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.075, 0, 0, 0, 0, 0.98, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
25.23% { -webkit-transform: matrix3d(1.067, 0, 0, 0, 0, 0.969, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.067, 0, 0, 0, 0, 0.969, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
29.03% { -webkit-transform: matrix3d(1.031, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.031, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
29.93% { -webkit-transform: matrix3d(1.024, 0, 0, 0, 0, 0.949, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.024, 0, 0, 0, 0, 0.949, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
35.54% { -webkit-transform: matrix3d(0.99, 0, 0, 0, 0, 0.981, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.99, 0, 0, 0, 0, 0.981, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
36.74% { -webkit-transform: matrix3d(0.986, 0, 0, 0, 0, 0.989, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.986, 0, 0, 0, 0, 0.989, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
41.04% { -webkit-transform: matrix3d(0.98, 0, 0, 0, 0, 1.011, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.98, 0, 0, 0, 0, 1.011, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
44.44% { -webkit-transform: matrix3d(0.983, 0, 0, 0, 0, 1.016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.983, 0, 0, 0, 0, 1.016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
52.15% { -webkit-transform: matrix3d(0.996, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.996, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
59.86% { -webkit-transform: matrix3d(1.003, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.003, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
63.26% { -webkit-transform: matrix3d(1.004, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.004, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
75.28% { -webkit-transform: matrix3d(1.001, 0, 0, 0, 0, 1.002, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.001, 0, 0, 0, 0, 1.002, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
85.49% { -webkit-transform: matrix3d(0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
90.69% { -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
100% { -webkit-transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@keyframes up-animation {
|
|
||||||
0% { transform: matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
3.4% { transform: matrix3d(0.658, 0, 0, 0, 0, 0.703, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.658, 0, 0, 0, 0, 0.703, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
4.7% { transform: matrix3d(0.725, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.725, 0, 0, 0, 0, 0.8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
6.81% { transform: matrix3d(0.83, 0, 0, 0, 0, 0.946, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.83, 0, 0, 0, 0, 0.946, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
9.41% { transform: matrix3d(0.942, 0, 0, 0, 0, 1.084, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.942, 0, 0, 0, 0, 1.084, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
10.21% { transform: matrix3d(0.971, 0, 0, 0, 0, 1.113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.971, 0, 0, 0, 0, 1.113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
13.61% { transform: matrix3d(1.062, 0, 0, 0, 0, 1.166, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.062, 0, 0, 0, 0, 1.166, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
14.11% { transform: matrix3d(1.07, 0, 0, 0, 0, 1.165, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.07, 0, 0, 0, 0, 1.165, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
17.52% { transform: matrix3d(1.104, 0, 0, 0, 0, 1.12, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.104, 0, 0, 0, 0, 1.12, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
18.72% { transform: matrix3d(1.106, 0, 0, 0, 0, 1.094, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.106, 0, 0, 0, 0, 1.094, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
21.32% { transform: matrix3d(1.098, 0, 0, 0, 0, 1.035, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.098, 0, 0, 0, 0, 1.035, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
24.32% { transform: matrix3d(1.075, 0, 0, 0, 0, 0.98, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.075, 0, 0, 0, 0, 0.98, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
25.23% { transform: matrix3d(1.067, 0, 0, 0, 0, 0.969, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.067, 0, 0, 0, 0, 0.969, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
29.03% { transform: matrix3d(1.031, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.031, 0, 0, 0, 0, 0.948, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
29.93% { transform: matrix3d(1.024, 0, 0, 0, 0, 0.949, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.024, 0, 0, 0, 0, 0.949, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
35.54% { transform: matrix3d(0.99, 0, 0, 0, 0, 0.981, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.99, 0, 0, 0, 0, 0.981, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
36.74% { transform: matrix3d(0.986, 0, 0, 0, 0, 0.989, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.986, 0, 0, 0, 0, 0.989, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
41.04% { transform: matrix3d(0.98, 0, 0, 0, 0, 1.011, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.98, 0, 0, 0, 0, 1.011, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
44.44% { transform: matrix3d(0.983, 0, 0, 0, 0, 1.016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.983, 0, 0, 0, 0, 1.016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
52.15% { transform: matrix3d(0.996, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.996, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
59.86% { transform: matrix3d(1.003, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.003, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
63.26% { transform: matrix3d(1.004, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.004, 0, 0, 0, 0, 0.996, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
75.28% { transform: matrix3d(1.001, 0, 0, 0, 0, 1.002, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1.001, 0, 0, 0, 0, 1.002, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
85.49% { transform: matrix3d(0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(0.999, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
90.69% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
100% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.opacityCycle {
|
|
||||||
-webkit-animation-iteration-count: infinite;
|
|
||||||
-webkit-animation-name: opCycle-animation;
|
|
||||||
-webkit-animation-duration: 20s;
|
|
||||||
-webkit-animation-iteration-count: infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@-webkit-keyframes opCycle-animation
|
|
||||||
{
|
|
||||||
0% {opacity:1}
|
|
||||||
15% {opacity:0.7}
|
|
||||||
30% {opacity:0.85}
|
|
||||||
45% {opacity:0.5}
|
|
||||||
60% {opacity:0.8}
|
|
||||||
75% {opacity:0.7}
|
|
||||||
99% {opacity:1;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.onGoingProcess {
|
.onGoingProcess {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 14.5rem;
|
max-width: 14.5rem;
|
||||||
|
|
@ -1211,7 +1114,7 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
|
||||||
top:auto;
|
top:auto;
|
||||||
left:0;
|
left:0;
|
||||||
right:0;
|
right:0;
|
||||||
bottom:90px;
|
bottom: 130px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
|
||||||
|
|
@ -172,11 +172,11 @@ _:-ms-fullscreen, :root .main {
|
||||||
height:100%;
|
height:100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-wallet {
|
.walletHome {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-wallet .avatar-wallet {
|
.walletHome .avatar-wallet {
|
||||||
padding: 1.7rem 1rem;
|
padding: 1.7rem 1rem;
|
||||||
width: 75px;
|
width: 75px;
|
||||||
height: 75px;
|
height: 75px;
|
||||||
|
|
@ -193,7 +193,7 @@ _:-ms-fullscreen, :root .main {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-wallet .wallet-info {
|
.walletHome .wallet-info {
|
||||||
margin-left: 85px;
|
margin-left: 85px;
|
||||||
line-height: 110%;
|
line-height: 110%;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
@ -642,24 +642,22 @@ a.pin-button:active {
|
||||||
|
|
||||||
.animation-left.ng-enter, .animation-left.ng-leave,
|
.animation-left.ng-enter, .animation-left.ng-leave,
|
||||||
.animation-right.ng-enter, .animation-right.ng-leave {
|
.animation-right.ng-enter, .animation-right.ng-leave {
|
||||||
-webkit-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 250ms;
|
-webkit-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 300ms;
|
||||||
-moz-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 250ms;
|
-moz-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 300ms;
|
||||||
-ms-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 250ms;
|
-ms-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 300ms;
|
||||||
-o-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 250ms;
|
-o-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 300ms;
|
||||||
transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 250ms;
|
transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 300ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.animation-left.ng-enter {
|
.animation-left.ng-enter {
|
||||||
-webkit-transform: translate3d(100%, 0, 0);
|
-webkit-transform: translate3d(100%, 0, 0);
|
||||||
transform: translate3d(100%, 0, 0);
|
transform: translate3d(100%, 0, 0);
|
||||||
-webkit-transition-delay: 0.05s;
|
opacity: 0.6;
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
.animation-right.ng-enter {
|
.animation-right.ng-enter {
|
||||||
-webkit-transform: translate3d(-100%, 0, 0);
|
-webkit-transform: translate3d(-100%, 0, 0);
|
||||||
transform: translate3d(-100%, 0, 0);
|
transform: translate3d(-100%, 0, 0);
|
||||||
-webkit-transition-delay: 0.05s;
|
opacity: 0.6;
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
.animation-left.ng-enter.ng-enter-active,
|
.animation-left.ng-enter.ng-enter-active,
|
||||||
.animation-right.ng-enter.ng-enter-active {
|
.animation-right.ng-enter.ng-enter-active {
|
||||||
|
|
@ -672,18 +670,37 @@ a.pin-button:active {
|
||||||
.animation-right.ng-leave {
|
.animation-right.ng-leave {
|
||||||
-webkit-transform: translate3d(0, 0, 0);
|
-webkit-transform: translate3d(0, 0, 0);
|
||||||
transform: translate3d(0, 0, 0);
|
transform: translate3d(0, 0, 0);
|
||||||
opacity: 0;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
.animation-left.ng-leave.animation-left.ng-leave-active {
|
.animation-left.ng-leave.animation-left.ng-leave-active {
|
||||||
-webkit-transform: translate3d(-100%, 0, 0);
|
-webkit-transform: translate3d(-100%, 0, 0);
|
||||||
transform: translate3d(-100%, 0, 0);
|
transform: translate3d(-100%, 0, 0);
|
||||||
-webkit-transition-delay: 0.05s;
|
opacity: 0.6;
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
.animation-right.ng-leave.animation-right.ng-leave-active {
|
.animation-right.ng-leave.animation-right.ng-leave-active {
|
||||||
-webkit-transform: translate3d(100%, 0, 0);
|
-webkit-transform: translate3d(100%, 0, 0);
|
||||||
transform: translate3d(100%, 0, 0);
|
transform: translate3d(100%, 0, 0);
|
||||||
-webkit-transition-delay: 0.05s;
|
opacity: 0.6;
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-view {
|
||||||
|
-webkit-transform: translate3d(-100%, 0, 0);
|
||||||
|
transform: translate3d(-100%, 0, 0);
|
||||||
|
width:100%;
|
||||||
|
position: absolute;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-in {
|
||||||
|
-webkit-transform: translate3d(0, 0, 0) !important;
|
||||||
|
transform: translate3d(0, 0, 0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-out {
|
||||||
|
-webkit-transform: translate3d(-100%, 0, 0) !important;
|
||||||
|
transform: translate3d(-100%, 0, 0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,76 +3,4 @@
|
||||||
angular.module('copayApp.controllers').controller('historyController',
|
angular.module('copayApp.controllers').controller('historyController',
|
||||||
function($scope, $rootScope, $filter, $timeout, $modal, $log, profileService, notification, go, configService, rateService, lodash) {
|
function($scope, $rootScope, $filter, $timeout, $modal, $log, profileService, notification, go, configService, rateService, lodash) {
|
||||||
|
|
||||||
function strip(number) {
|
|
||||||
return (parseFloat(number.toPrecision(12)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var fc = profileService.focusedClient;
|
|
||||||
var config = configService.getSync().wallet.settings;
|
|
||||||
this.unitToSatoshi = config.unitToSatoshi;
|
|
||||||
this.satToUnit = 1 / this.unitToSatoshi;
|
|
||||||
this.unitName = config.unitName;
|
|
||||||
this.alternativeIsoCode = config.alternativeIsoCode;
|
|
||||||
|
|
||||||
this.getUnitName = function() {
|
|
||||||
return this.unitName;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getAlternativeIsoCode = function() {
|
|
||||||
return this.alternativeIsoCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
this._addRates = function(txs, cb) {
|
|
||||||
if (!txs || txs.length == 0) return cb();
|
|
||||||
var index = lodash.groupBy(txs, 'rateTs');
|
|
||||||
|
|
||||||
rateService.getHistoricRates(config.alternativeIsoCode, lodash.keys(index), function(err, res) {
|
|
||||||
if (err || !res) return cb(err);
|
|
||||||
lodash.each(res, function(r) {
|
|
||||||
lodash.each(index[r.ts], function(tx) {
|
|
||||||
var alternativeAmount = (r.rate != null ? tx.amount * rateService.SAT_TO_BTC * r.rate : null);
|
|
||||||
tx.alternativeAmount = alternativeAmount ? $filter('noFractionNumber')(alternativeAmount, 2) : null;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.openTxModal = function(btx) {
|
|
||||||
var self = this;
|
|
||||||
var fc = profileService.focusedClient;
|
|
||||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
|
||||||
$scope.btx = btx;
|
|
||||||
$scope.settings = config;
|
|
||||||
$scope.color = fc.backgroundColor;
|
|
||||||
|
|
||||||
$scope.getAmount = function(amount) {
|
|
||||||
return self.getAmount(amount);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.getUnitName = function() {
|
|
||||||
return self.getUnitName();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.getShortNetworkName = function() {
|
|
||||||
var n = fc.credentials.network;
|
|
||||||
return n.substring(0, 4);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
|
||||||
$modalInstance.dismiss('cancel');
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
$modal.open({
|
|
||||||
templateUrl: 'views/modals/tx-details.html',
|
|
||||||
windowClass: 'full',
|
|
||||||
controller: ModalInstanceCtrl,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.hasAction = function(actions, action) {
|
|
||||||
return actions.hasOwnProperty('create');
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
var self = this;
|
var self = this;
|
||||||
self.isCordova = isCordova;
|
self.isCordova = isCordova;
|
||||||
self.onGoingProcess = {};
|
self.onGoingProcess = {};
|
||||||
self.limitHistory = 5;
|
self.limitHistory = 5;
|
||||||
|
|
||||||
function strip(number) {
|
function strip(number) {
|
||||||
return (parseFloat(number.toPrecision(12)));
|
return (parseFloat(number.toPrecision(12)));
|
||||||
|
|
@ -13,7 +13,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
self.menu = [{
|
self.menu = [{
|
||||||
'title': 'Home',
|
'title': 'Home',
|
||||||
'icon': 'icon-home',
|
'icon': 'icon-home',
|
||||||
'link': 'walletHome'
|
'link': 'walletHome',
|
||||||
|
'active': true,
|
||||||
}, {
|
}, {
|
||||||
'title': 'Receive',
|
'title': 'Receive',
|
||||||
'icon': 'icon-receive',
|
'icon': 'icon-receive',
|
||||||
|
|
@ -26,7 +27,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
'title': 'History',
|
'title': 'History',
|
||||||
'icon': 'icon-history',
|
'icon': 'icon-history',
|
||||||
'link': 'history'
|
'link': 'history'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
self.tab = 'walletHome';
|
||||||
|
|
||||||
self.availableLanguages = [{
|
self.availableLanguages = [{
|
||||||
name: 'English',
|
name: 'English',
|
||||||
|
|
@ -100,6 +103,34 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.setTab = function(tab) {
|
||||||
|
|
||||||
|
if (self.tab === tab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!self.tab)
|
||||||
|
self.tab = 'walletHome';
|
||||||
|
|
||||||
|
if (document.getElementById(self.tab)) {
|
||||||
|
document.getElementById(self.tab).className = 'tab-out tab-view ' + self.tab;
|
||||||
|
var old = document.getElementById('menu-' + self.tab);
|
||||||
|
if (old) {
|
||||||
|
old.className = '';
|
||||||
|
old.style.borderTopColor = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById(tab)) {
|
||||||
|
document.getElementById(tab).className = 'tab-in tab-view ' + tab;
|
||||||
|
var newe = document.getElementById('menu-' + tab);
|
||||||
|
newe.className = 'active';
|
||||||
|
newe.style.borderTopColor = self.backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tab = tab;
|
||||||
|
$rootScope.$emit('Local/TabChanged', tab);
|
||||||
|
};
|
||||||
|
|
||||||
self.updateAll = function(walletStatus) {
|
self.updateAll = function(walletStatus) {
|
||||||
var get = function(cb) {
|
var get = function(cb) {
|
||||||
if (walletStatus)
|
if (walletStatus)
|
||||||
|
|
@ -223,8 +254,8 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
self.openWallet = function() {
|
self.openWallet = function() {
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
self.updateColor();
|
self.updateColor();
|
||||||
$rootScope.$apply();
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
self.setOngoingProcess('openingWallet', true);
|
self.setOngoingProcess('openingWallet', true);
|
||||||
self.updateError = false;
|
self.updateError = false;
|
||||||
fc.openWallet(function(err, walletStatus) {
|
fc.openWallet(function(err, walletStatus) {
|
||||||
|
|
@ -454,8 +485,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
gettextCatalog.setCurrentLanguage(userLang);
|
gettextCatalog.setCurrentLanguage(userLang);
|
||||||
amMoment.changeLocale(userLang);
|
amMoment.changeLocale(userLang);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
configService.set({
|
configService.set({
|
||||||
wallet: {
|
wallet: {
|
||||||
settings: {
|
settings: {
|
||||||
|
|
@ -468,7 +498,9 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.defaultLanguageIsoCode = setLang || userLang;
|
self.defaultLanguageIsoCode = setLang || userLang;
|
||||||
self.defaultLanguageName = lodash.result(lodash.find(self.availableLanguages, { 'isoCode': self.defaultLanguageIsoCode }), 'name');
|
self.defaultLanguageName = lodash.result(lodash.find(self.availableLanguages, {
|
||||||
|
'isoCode': self.defaultLanguageIsoCode
|
||||||
|
}), 'name');
|
||||||
};
|
};
|
||||||
|
|
||||||
// UX event handlers
|
// UX event handlers
|
||||||
|
|
@ -607,6 +639,10 @@ angular.module('copayApp.controllers').controller('indexController', function($r
|
||||||
self.updateTxHistory();
|
self.updateTxHistory();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('Local/SetTab', function(event, tab) {
|
||||||
|
self.setTab(tab);
|
||||||
|
});
|
||||||
|
|
||||||
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
|
$rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) {
|
||||||
self.askPassword = {
|
self.askPassword = {
|
||||||
isSetup: isSetup,
|
isSetup: isSetup,
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,68 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.controllers').controller('paymentUriController',
|
angular.module('copayApp.controllers').controller('paymentUriController',
|
||||||
function($rootScope, $stateParams, $location, $timeout, profileService, configService, lodash, bitcore, go) {
|
function($rootScope, $stateParams, $location, $timeout, profileService, configService, lodash, bitcore, go) {
|
||||||
|
|
||||||
function strip(number) {
|
function strip(number) {
|
||||||
return (parseFloat(number.toPrecision(12)));
|
return (parseFloat(number.toPrecision(12)));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build bitcoinURI with querystring
|
// Build bitcoinURI with querystring
|
||||||
this.checkBitcoinUri = function() {
|
this.checkBitcoinUri = function() {
|
||||||
var query = [];
|
var query = [];
|
||||||
angular.forEach($location.search(), function(value, key) {
|
angular.forEach($location.search(), function(value, key) {
|
||||||
query.push(key + "=" + value);
|
query.push(key + "=" + value);
|
||||||
});
|
});
|
||||||
var queryString = query ? query.join("&") : null;
|
var queryString = query ? query.join("&") : null;
|
||||||
this.bitcoinURI = $stateParams.data + ( queryString ? '?' + queryString : '');
|
this.bitcoinURI = $stateParams.data + (queryString ? '?' + queryString : '');
|
||||||
|
|
||||||
var URI = bitcore.URI;
|
var URI = bitcore.URI;
|
||||||
var isUriValid = URI.isValid(this.bitcoinURI);
|
var isUriValid = URI.isValid(this.bitcoinURI);
|
||||||
if (!URI.isValid(this.bitcoinURI)) {
|
if (!URI.isValid(this.bitcoinURI)) {
|
||||||
this.error = true;
|
this.error = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var uri = new URI(this.bitcoinURI);
|
var uri = new URI(this.bitcoinURI);
|
||||||
|
|
||||||
if (uri && uri.address) {
|
if (uri && uri.address) {
|
||||||
var config = configService.getSync().wallet.settings;
|
var config = configService.getSync().wallet.settings;
|
||||||
var unitToSatoshi = config.unitToSatoshi;
|
var unitToSatoshi = config.unitToSatoshi;
|
||||||
var satToUnit = 1 / unitToSatoshi;
|
var satToUnit = 1 / unitToSatoshi;
|
||||||
var unitName = config.unitName;
|
var unitName = config.unitName;
|
||||||
|
|
||||||
uri.amount = strip(uri.amount * satToUnit) + ' ' + unitName;
|
uri.amount = strip(uri.amount * satToUnit) + ' ' + unitName;
|
||||||
return uri;
|
uri.network = uri.address.network.name;
|
||||||
}
|
return uri;
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.getWallets = function() {
|
this.getWallets = function(network) {
|
||||||
if (!profileService.profile) return;
|
if (!profileService.profile) return;
|
||||||
var config = configService.getSync();
|
var config = configService.getSync();
|
||||||
config.colorFor = config.colorFor || {};
|
config.colorFor = config.colorFor || {};
|
||||||
var ret = lodash.map(profileService.profile.credentials, function(c) {
|
var ret = lodash.map(profileService.profile.credentials, function(c) {
|
||||||
return {
|
return {
|
||||||
m: c.m,
|
m: c.m,
|
||||||
n: c.n,
|
n: c.n,
|
||||||
name: c.walletName,
|
name: c.walletName,
|
||||||
id: c.walletId,
|
id: c.walletId,
|
||||||
color: config.colorFor[c.walletId] || '#2C3E50'
|
network: c.network,
|
||||||
};
|
color: config.colorFor[c.walletId] || '#2C3E50'
|
||||||
});
|
};
|
||||||
return lodash.sortBy(ret, 'walletName');
|
});
|
||||||
};
|
ret = lodash.filter(ret, function(w) {
|
||||||
|
return (w.network == network);
|
||||||
|
});
|
||||||
|
return lodash.sortBy(ret, 'walletName');
|
||||||
|
};
|
||||||
|
|
||||||
this.selectWallet = function(wid) {
|
this.selectWallet = function(wid) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (wid != profileService.focusedClient.credentials.walletId) {
|
if (wid != profileService.focusedClient.credentials.walletId) {
|
||||||
profileService.setAndStoreFocus(wid, function() {});
|
profileService.setAndStoreFocus(wid, function() {});
|
||||||
}
|
}
|
||||||
go.send();
|
go.send();
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$rootScope.$emit('paymentUri', self.bitcoinURI);
|
$rootScope.$emit('paymentUri', self.bitcoinURI);
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
angular.module('copayApp.controllers').controller('receiveController',
|
angular.module('copayApp.controllers').controller('receiveController',
|
||||||
function($rootScope, $scope, $timeout, $modal, $log, isCordova, isMobile, profileService, storageService) {
|
function($rootScope, $scope, $timeout, $modal, $log, isCordova, isMobile, profileService, storageService) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var fc = profileService.focusedClient;
|
|
||||||
|
|
||||||
|
|
||||||
this.isCordova = isCordova;
|
this.isCordova = isCordova;
|
||||||
self.addresses = [];
|
self.addresses = [];
|
||||||
|
|
@ -15,6 +13,7 @@ angular.module('copayApp.controllers').controller('receiveController',
|
||||||
$scope.$on('$destroy', newAddrListener);
|
$scope.$on('$destroy', newAddrListener);
|
||||||
|
|
||||||
this.newAddress = function() {
|
this.newAddress = function() {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
self.generatingAddress = true;
|
self.generatingAddress = true;
|
||||||
self.error = null;
|
self.error = null;
|
||||||
fc.createAddress(function(err, addr) {
|
fc.createAddress(function(err, addr) {
|
||||||
|
|
@ -32,6 +31,7 @@ angular.module('copayApp.controllers').controller('receiveController',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getAddress = function() {
|
this.getAddress = function() {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
storageService.getLastAddress(fc.credentials.walletId, function(err, addr) {
|
storageService.getLastAddress(fc.credentials.walletId, function(err, addr) {
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ angular.module('copayApp.controllers').controller('topbarController', function($
|
||||||
}, 100);
|
}, 100);
|
||||||
alert('Scanning error');
|
alert('Scanning error');
|
||||||
});
|
});
|
||||||
go.send();
|
go.send();
|
||||||
};
|
};
|
||||||
|
|
||||||
var modalOpenScanner = function() {
|
var modalOpenScanner = function() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,72 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, notification, txStatus, isCordova, profileService, lodash) {
|
angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
$rootScope.hideMenuBar = false;
|
$rootScope.hideMenuBar = false;
|
||||||
|
$rootScope.wpInputFocused = false;
|
||||||
|
|
||||||
|
// INIT
|
||||||
|
var config = configService.getSync().wallet.settings;
|
||||||
|
this.unitToSatoshi = config.unitToSatoshi;
|
||||||
|
this.satToUnit = 1 / this.unitToSatoshi;
|
||||||
|
this.unitName = config.unitName;
|
||||||
|
this.alternativeIsoCode = config.alternativeIsoCode;
|
||||||
|
this.alternativeName = config.alternativeName;
|
||||||
|
this.alternativeAmount = 0;
|
||||||
|
this.unitDecimals = config.unitDecimals;
|
||||||
|
this.isCordova = isCordova;
|
||||||
|
this.addresses = [];
|
||||||
|
this.isMobile = isMobile.any();
|
||||||
|
this.isWindowsPhoneApp = isMobile.Windows() && isCordova;
|
||||||
|
this.blockUx = false;
|
||||||
|
this.isRateAvailable = false;
|
||||||
|
this.showScanner = false;
|
||||||
|
this.isMobile = isMobile.any();
|
||||||
|
|
||||||
|
var disableScannerListener = $rootScope.$on('dataScanned', function(event, data) {
|
||||||
|
$scope.$emit('Local/SetTab', 'send');
|
||||||
|
self.setForm(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var disablePaymentUriListener = $rootScope.$on('paymentUri', function(event, uri) {
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$emit('Local/SetTab', 'send');
|
||||||
|
self.setForm(uri);
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
var disableAddrListener = $rootScope.$on('Local/NeedNewAddress', function() {
|
||||||
|
self.getAddress();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var disableTabListener = $rootScope.$on('Local/TabChanged', function(e,tab){
|
||||||
|
switch(tab) {
|
||||||
|
case 'send':
|
||||||
|
self.resetError();
|
||||||
|
self.setInputs();
|
||||||
|
case 'receive':
|
||||||
|
self.getAddress();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
disableAddrListener();
|
||||||
|
disableScannerListener();
|
||||||
|
disablePaymentUriListener();
|
||||||
|
disableTabListener();
|
||||||
|
$rootScope.hideMenuBar = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
rateService.whenAvailable(function() {
|
||||||
|
self.isRateAvailable = true;
|
||||||
|
$rootScope.$digest();
|
||||||
|
});
|
||||||
|
|
||||||
|
// walletHome
|
||||||
|
|
||||||
|
|
||||||
$scope.openCopayersModal = function(copayers, copayerId) {
|
$scope.openCopayersModal = function(copayers, copayerId) {
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
|
|
@ -21,8 +85,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$scope.openTxModal = function(tx, copayers) {
|
$scope.openTxModal = function(tx, copayers) {
|
||||||
var fc = profileService.focusedClient;
|
var fc = profileService.focusedClient;
|
||||||
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||||
|
|
@ -213,4 +275,507 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Receive
|
||||||
|
|
||||||
|
this.newAddress = function() {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
self.generatingAddress = true;
|
||||||
|
self.error = null;
|
||||||
|
fc.createAddress(function(err, addr) {
|
||||||
|
self.generatingAddress = false;
|
||||||
|
if (err) {
|
||||||
|
$log.debug('Creating address ERROR:', err);
|
||||||
|
$scope.$emit('Local/ClientError', err);
|
||||||
|
self.error = 'Could not generate address';
|
||||||
|
} else {
|
||||||
|
self.addr = addr.address;
|
||||||
|
storageService.storeLastAddress(fc.credentials.walletId, addr.address, function() {});
|
||||||
|
}
|
||||||
|
$scope.$digest();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getAddress = function() {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
$timeout(function() {
|
||||||
|
storageService.getLastAddress(fc.credentials.walletId, function(err, addr) {
|
||||||
|
if (addr) {
|
||||||
|
self.addr = addr;
|
||||||
|
} else {
|
||||||
|
self.newAddress();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.copyAddress = function(addr) {
|
||||||
|
if (isCordova) {
|
||||||
|
window.cordova.plugins.clipboard.copy('bitcoin:' + addr);
|
||||||
|
window.plugins.toast.showShortCenter('Copied to clipboard');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.shareAddress = function(addr) {
|
||||||
|
if (isCordova) {
|
||||||
|
if (isMobile.Android() || isMobile.Windows()) {
|
||||||
|
window.ignoreMobilePause = true;
|
||||||
|
}
|
||||||
|
window.plugins.socialsharing.share('bitcoin:' + addr, null, null, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send
|
||||||
|
this.resetError = function() {
|
||||||
|
this.error = this.success = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var hideMenuBar = lodash.debounce(function(hide) {
|
||||||
|
if (hide) {
|
||||||
|
$rootScope.hideMenuBar = true;
|
||||||
|
} else {
|
||||||
|
$rootScope.hideMenuBar = false;
|
||||||
|
}
|
||||||
|
$rootScope.$digest();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
|
||||||
|
this.formFocus = function(what) {
|
||||||
|
if (isCordova) {
|
||||||
|
hideMenuBar(what);
|
||||||
|
}
|
||||||
|
if (!this.isWindowsPhoneApp) return
|
||||||
|
|
||||||
|
if (!what) {
|
||||||
|
this.hideAddress = false;
|
||||||
|
this.hideAmount = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (what == 'amount') {
|
||||||
|
this.hideAddress = true;
|
||||||
|
} else if (what == 'msg') {
|
||||||
|
this.hideAddress = true;
|
||||||
|
this.hideAmount = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$timeout(function() {
|
||||||
|
$rootScope.$digest();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setInputs = function() {
|
||||||
|
var unitToSat = this.unitToSatoshi;
|
||||||
|
var satToUnit = 1 / unitToSat;
|
||||||
|
/**
|
||||||
|
* Setting the two related amounts as properties prevents an infinite
|
||||||
|
* recursion for watches while preserving the original angular updates
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Object.defineProperty($scope,
|
||||||
|
"_alternative", {
|
||||||
|
get: function() {
|
||||||
|
return $scope.__alternative;
|
||||||
|
},
|
||||||
|
set: function(newValue) {
|
||||||
|
$scope.__alternative = newValue;
|
||||||
|
if (typeof(newValue) === 'number' && self.isRateAvailable) {
|
||||||
|
$scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty($scope,
|
||||||
|
"_amount", {
|
||||||
|
get: function() {
|
||||||
|
return $scope.__amount;
|
||||||
|
},
|
||||||
|
set: function(newValue) {
|
||||||
|
$scope.__amount = newValue;
|
||||||
|
if (typeof(newValue) === 'number' && self.isRateAvailable) {
|
||||||
|
$scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10);
|
||||||
|
} else {
|
||||||
|
$scope.__alternative = 0;
|
||||||
|
}
|
||||||
|
self.alternativeAmount = $scope.__alternative;
|
||||||
|
self.resetError();
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty($scope,
|
||||||
|
"_address", {
|
||||||
|
get: function() {
|
||||||
|
return $scope.__address;
|
||||||
|
},
|
||||||
|
set: function(newValue) {
|
||||||
|
$scope.__address = self.onAddressChange(newValue);
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setError = function(err) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
$log.warn(err);
|
||||||
|
var errMessage = 'The transaction' + (fc.credentials.m > 1 ? ' proposal' : '') +
|
||||||
|
|
||||||
|
' could not be created: ' + (err.message ? err.message : err);
|
||||||
|
|
||||||
|
this.error = errMessage;
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.setOngoingProcess = function(name) {
|
||||||
|
var self = this;
|
||||||
|
$timeout(function() {
|
||||||
|
self.onGoingProcess = name;
|
||||||
|
$rootScope.$apply();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
this.submitForm = function(form) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
var unitToSat = this.unitToSatoshi;
|
||||||
|
|
||||||
|
if (form.$invalid) {
|
||||||
|
this.error = 'Unable to send transaction proposal';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fc.isPrivKeyEncrypted()) {
|
||||||
|
profileService.unlockFC(function(err) {
|
||||||
|
if (err) return self.setError(err);
|
||||||
|
return self.submitForm(form);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.blockUx = true;
|
||||||
|
self.setOngoingProcess('Sending');
|
||||||
|
|
||||||
|
if (isCordova) {
|
||||||
|
window.plugins.spinnerDialog.show(null, 'Creating transaction...', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
var comment = form.comment.$modelValue;
|
||||||
|
var paypro = self._paypro;
|
||||||
|
var address, amount;
|
||||||
|
|
||||||
|
address = form.address.$modelValue;
|
||||||
|
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
|
||||||
|
|
||||||
|
fc.sendTxProposal({
|
||||||
|
toAddress: address,
|
||||||
|
amount: amount,
|
||||||
|
message: comment,
|
||||||
|
payProUrl: paypro ? paypro.url : null,
|
||||||
|
}, function(err, txp) {
|
||||||
|
self.setOngoingProcess();
|
||||||
|
if (err) {
|
||||||
|
profileService.lockFC();
|
||||||
|
if (isCordova) {
|
||||||
|
window.plugins.spinnerDialog.hide();
|
||||||
|
}
|
||||||
|
self.blockUx = false;
|
||||||
|
return self.setError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.signAndBroadcast(txp, function(err) {
|
||||||
|
self.setOngoingProcess();
|
||||||
|
if (isCordova) {
|
||||||
|
window.plugins.spinnerDialog.hide();
|
||||||
|
}
|
||||||
|
self.blockUx = false;
|
||||||
|
if (err) {
|
||||||
|
profileService.lockFC();
|
||||||
|
return self.setError(err);
|
||||||
|
}
|
||||||
|
self.resetForm(form);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.signAndBroadcast = function(txp, cb) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
self.setOngoingProcess('Signing');
|
||||||
|
fc.signTxProposal(txp, function(err, signedTx) {
|
||||||
|
profileService.lockFC();
|
||||||
|
self.setOngoingProcess();
|
||||||
|
|
||||||
|
if (err) return cb(err);
|
||||||
|
|
||||||
|
if (signedTx.status == 'accepted') {
|
||||||
|
self.setOngoingProcess('Broadcasting');
|
||||||
|
fc.broadcastTxProposal(signedTx, function(err, btx) {
|
||||||
|
self.setOngoingProcess();
|
||||||
|
if (err) {
|
||||||
|
$scope.error = 'Transaction not broadcasted. Please try again.';
|
||||||
|
$scope.$digest();
|
||||||
|
} else {
|
||||||
|
txStatus.notify(btx);
|
||||||
|
$scope.$emit('Local/TxProposalAction');
|
||||||
|
}
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
txStatus.notify(signedTx);
|
||||||
|
$scope.$emit('Local/TxProposalAction');
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setTopAmount = function() {
|
||||||
|
throw new Error('todo: setTopAmount');
|
||||||
|
var form = $scope.sendForm;
|
||||||
|
if (form) {
|
||||||
|
form.amount.$setViewValue(w.balanceInfo.topAmount);
|
||||||
|
form.amount.$render();
|
||||||
|
form.amount.$isValid = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setForm = function(to, amount, comment) {
|
||||||
|
var form = $scope.sendForm;
|
||||||
|
if (to) {
|
||||||
|
form.address.$setViewValue(to);
|
||||||
|
form.address.$isValid = true;
|
||||||
|
form.address.$render();
|
||||||
|
this.lockAddress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amount) {
|
||||||
|
form.amount.$setViewValue("" + amount);
|
||||||
|
form.amount.$isValid = true;
|
||||||
|
form.amount.$render();
|
||||||
|
this.lockAmount = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment) {
|
||||||
|
form.comment.$setViewValue(comment);
|
||||||
|
form.comment.$isValid = true;
|
||||||
|
form.comment.$render();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.resetForm = function(form) {
|
||||||
|
this.resetError();
|
||||||
|
this.fetchingURL = null;
|
||||||
|
this._paypro = null;
|
||||||
|
|
||||||
|
this.lockAddress = false;
|
||||||
|
this.lockAmount = false;
|
||||||
|
|
||||||
|
this._amount = this._address = null;
|
||||||
|
|
||||||
|
if (form && form.amount) {
|
||||||
|
form.amount.$pristine = true;
|
||||||
|
form.amount.$setViewValue('');
|
||||||
|
form.amount.$render();
|
||||||
|
|
||||||
|
form.comment.$setViewValue('');
|
||||||
|
form.comment.$render();
|
||||||
|
form.$setPristine();
|
||||||
|
|
||||||
|
if (form.address) {
|
||||||
|
form.address.$pristine = true;
|
||||||
|
form.address.$setViewValue('');
|
||||||
|
form.address.$render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$timeout(function() {
|
||||||
|
$rootScope.$digest();
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.openPPModal = function(paypro) {
|
||||||
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
var satToUnit = 1 / self.unitToSatoshi;
|
||||||
|
$scope.paypro = paypro;
|
||||||
|
$scope.alternative = self.alternativeAmount;
|
||||||
|
$scope.alternativeIsoCode = self.alternativeIsoCode;
|
||||||
|
$scope.isRateAvailable = self.isRateAvailable;
|
||||||
|
$scope.unitTotal = (paypro.amount * satToUnit).toFixed(self.unitDecimals);
|
||||||
|
$scope.unitName = self.unitName;
|
||||||
|
$scope.color = fc.backgroundColor;
|
||||||
|
|
||||||
|
$scope.cancel = function() {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
$modal.open({
|
||||||
|
templateUrl: 'views/modals/paypro.html',
|
||||||
|
windowClass: 'full',
|
||||||
|
controller: ModalInstanceCtrl,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setFromPayPro = function(uri, form) {
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
if (isChromeApp) {
|
||||||
|
this.error = 'Payment Protocol not supported on Chrome App';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var satToUnit = 1 / this.unitToSatoshi;
|
||||||
|
this.fetchingURL = uri;
|
||||||
|
this.blockUx = true;
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
$log.debug('Fetch PayPro Request...', uri);
|
||||||
|
$timeout(function() {
|
||||||
|
fc.fetchPayPro({
|
||||||
|
payProUrl: uri,
|
||||||
|
}, function(err, paypro) {
|
||||||
|
$log.debug(paypro);
|
||||||
|
self.blockUx = false;
|
||||||
|
self.fetchingURL = null;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
$log.warn(err);
|
||||||
|
self.resetForm(form);
|
||||||
|
var msg = err.toString();
|
||||||
|
if (msg.match('HTTP')) {
|
||||||
|
msg = 'Could not fetch payment information';
|
||||||
|
}
|
||||||
|
self.error = msg;
|
||||||
|
} else {
|
||||||
|
self._paypro = paypro;
|
||||||
|
self.setForm(paypro.toAddress, (paypro.amount * satToUnit).toFixed(self.unitDecimals),
|
||||||
|
paypro.memo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setFromUri = function(uri) {
|
||||||
|
function sanitizeUri(uri) {
|
||||||
|
// Fixes when a region uses comma to separate decimals
|
||||||
|
var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i;
|
||||||
|
var match = regex.exec(uri);
|
||||||
|
if (!match || match.length === 0) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
var value = match[0].replace(',', '.');
|
||||||
|
var newUri = uri.replace(regex, value);
|
||||||
|
return newUri;
|
||||||
|
};
|
||||||
|
|
||||||
|
var satToUnit = 1 / this.unitToSatoshi;
|
||||||
|
|
||||||
|
uri = sanitizeUri(uri);
|
||||||
|
|
||||||
|
if (!bitcore.URI.isValid(uri)) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
var parsed = new bitcore.URI(uri);
|
||||||
|
var addr = parsed.address.toString();
|
||||||
|
var message = parsed.message;
|
||||||
|
if (parsed.r)
|
||||||
|
return this.setFromPayPro(parsed.r);
|
||||||
|
|
||||||
|
var amount = parsed.amount ?
|
||||||
|
(parsed.amount.toFixed(0) * satToUnit).toFixed(this.unitDecimals) : 0;
|
||||||
|
|
||||||
|
this.setForm(addr, amount, message);
|
||||||
|
return addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.onAddressChange = function(value) {
|
||||||
|
this.resetError();
|
||||||
|
if (!value) return '';
|
||||||
|
|
||||||
|
if (this._paypro)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
if (value.indexOf('bitcoin:') === 0) {
|
||||||
|
return this.setFromUri(value);
|
||||||
|
} else if (/^https?:\/\//.test(value)) {
|
||||||
|
return this.setFromPayPro(value);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// History
|
||||||
|
|
||||||
|
function strip(number) {
|
||||||
|
return (parseFloat(number.toPrecision(12)));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getUnitName = function() {
|
||||||
|
return this.unitName;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getAlternativeIsoCode = function() {
|
||||||
|
return this.alternativeIsoCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
this._addRates = function(txs, cb) {
|
||||||
|
if (!txs || txs.length == 0) return cb();
|
||||||
|
var index = lodash.groupBy(txs, 'rateTs');
|
||||||
|
|
||||||
|
rateService.getHistoricRates(config.alternativeIsoCode, lodash.keys(index), function(err, res) {
|
||||||
|
if (err || !res) return cb(err);
|
||||||
|
lodash.each(res, function(r) {
|
||||||
|
lodash.each(index[r.ts], function(tx) {
|
||||||
|
var alternativeAmount = (r.rate != null ? tx.amount * rateService.SAT_TO_BTC * r.rate : null);
|
||||||
|
tx.alternativeAmount = alternativeAmount ? $filter('noFractionNumber')(alternativeAmount, 2) : null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.openTxModal = function(btx) {
|
||||||
|
var self = this;
|
||||||
|
var fc = profileService.focusedClient;
|
||||||
|
var ModalInstanceCtrl = function($scope, $modalInstance) {
|
||||||
|
$scope.btx = btx;
|
||||||
|
$scope.settings = config;
|
||||||
|
$scope.color = fc.backgroundColor;
|
||||||
|
|
||||||
|
$scope.getAmount = function(amount) {
|
||||||
|
return self.getAmount(amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.getUnitName = function() {
|
||||||
|
return self.getUnitName();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.getShortNetworkName = function() {
|
||||||
|
var n = fc.credentials.network;
|
||||||
|
return n.substring(0, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function() {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$modal.open({
|
||||||
|
templateUrl: 'views/modals/tx-details.html',
|
||||||
|
windowClass: 'full',
|
||||||
|
controller: ModalInstanceCtrl,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hasAction = function(actions, action) {
|
||||||
|
return actions.hasOwnProperty('create');
|
||||||
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -179,63 +179,6 @@ angular
|
||||||
templateUrl: 'views/profile.html',
|
templateUrl: 'views/profile.html',
|
||||||
needProfile: true
|
needProfile: true
|
||||||
})
|
})
|
||||||
.state('receive', {
|
|
||||||
url: '/receive',
|
|
||||||
walletShouldBeComplete: true,
|
|
||||||
needProfile: true,
|
|
||||||
views: {
|
|
||||||
'main': {
|
|
||||||
templateUrl: 'views/receive.html'
|
|
||||||
},
|
|
||||||
'topbar': {
|
|
||||||
templateUrl: 'views/includes/topbar.html'
|
|
||||||
},
|
|
||||||
'menu': {
|
|
||||||
templateUrl: 'views/includes/menu.html',
|
|
||||||
controller: function($scope) {
|
|
||||||
$scope.activeMenu = 'receive';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('send', {
|
|
||||||
url: '/send',
|
|
||||||
walletShouldBeComplete: true,
|
|
||||||
needProfile: true,
|
|
||||||
views: {
|
|
||||||
'main': {
|
|
||||||
templateUrl: 'views/send.html'
|
|
||||||
},
|
|
||||||
'topbar': {
|
|
||||||
templateUrl: 'views/includes/topbar.html'
|
|
||||||
},
|
|
||||||
'menu': {
|
|
||||||
templateUrl: 'views/includes/menu.html',
|
|
||||||
controller: function($scope) {
|
|
||||||
$scope.activeMenu = 'send';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('history', {
|
|
||||||
url: '/history',
|
|
||||||
walletShouldBeComplete: true,
|
|
||||||
needProfile: true,
|
|
||||||
views: {
|
|
||||||
'main': {
|
|
||||||
templateUrl: 'views/history.html'
|
|
||||||
},
|
|
||||||
'topbar': {
|
|
||||||
templateUrl: 'views/includes/topbar.html'
|
|
||||||
},
|
|
||||||
'menu': {
|
|
||||||
templateUrl: 'views/includes/menu.html',
|
|
||||||
controller: function($scope) {
|
|
||||||
$scope.activeMenu = 'history';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('preferences', {
|
.state('preferences', {
|
||||||
url: '/preferences',
|
url: '/preferences',
|
||||||
templateUrl: 'views/preferences.html',
|
templateUrl: 'views/preferences.html',
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,11 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope,
|
||||||
var ref = window.open(url, '_blank', 'location=no');
|
var ref = window.open(url, '_blank', 'location=no');
|
||||||
};
|
};
|
||||||
|
|
||||||
root.path = function(path) {
|
root.path = function(path, cb) {
|
||||||
$state.transitionTo(path);
|
$state.transitionTo(path)
|
||||||
|
.then(function() {
|
||||||
|
if (cb) return cb();
|
||||||
|
});
|
||||||
hideSidebars();
|
hideSidebars();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -51,10 +54,19 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope,
|
||||||
if (fc && !fc.isComplete()) {
|
if (fc && !fc.isComplete()) {
|
||||||
root.path('copayers');
|
root.path('copayers');
|
||||||
} else {
|
} else {
|
||||||
root.path('walletHome');
|
root.path('walletHome', function() {
|
||||||
|
$rootScope.$emit('Local/SetTab', 'walletHome');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
root.send = function() {
|
||||||
|
root.path('walletHome', function() {
|
||||||
|
$rootScope.$emit('Local/SetTab', 'send');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
root.home = function() {
|
root.home = function() {
|
||||||
if ($rootScope.iden)
|
if ($rootScope.iden)
|
||||||
root.walletHome();
|
root.walletHome();
|
||||||
|
|
@ -66,10 +78,6 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope,
|
||||||
$state.go('add');
|
$state.go('add');
|
||||||
};
|
};
|
||||||
|
|
||||||
root.send = function() {
|
|
||||||
$state.go('send');
|
|
||||||
};
|
|
||||||
|
|
||||||
root.preferences = function() {
|
root.preferences = function() {
|
||||||
$state.go('preferences');
|
$state.go('preferences');
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue