mirror of https://github.com/BTCPrivate/copay.git
816 lines
40 KiB
HTML
816 lines
40 KiB
HTML
<!doctype html>
|
|
<html lang="en" ng-csp>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
<meta name="viewport" content="width=device-width">
|
|
<title>Copay - Multisignature Wallet</title>
|
|
<link rel="stylesheet" href="css/foundation.min.css">
|
|
<link rel="stylesheet" href="css/foundation-icons.css">
|
|
<link rel="stylesheet" href="lib/angular/angular-csp.css">
|
|
<link rel="stylesheet" href="css/main.css">
|
|
<link rel="shortcut icon" href="img/favicon.ico">
|
|
</head>
|
|
<body ng-cloak class="ng-cloak">
|
|
<div id="wrap">
|
|
<div data-ng-init="init()" data-ng-controller="HeaderController">
|
|
<div class="header">
|
|
<div class="header-content">
|
|
<div class="large-3 medium-3 small-3 columns">
|
|
<span class="logo"></span>
|
|
</div>
|
|
<div class="large-9 medium-9 small-9 columns text-center p10t" ng-show="$root.wallet">
|
|
<div class="large-4 medium-4 columns line-dashed-v">
|
|
<a href="#/addresses" class="has-tip" tooltip-placement="bottom" tooltip="{{$root.wallet.id}}">
|
|
<strong><span>{{$root.wallet.getName()}}</span></strong>
|
|
</a>
|
|
<a class="button radius small-icon" title="Manual Refresh"
|
|
ng-disabled="$root.loading"
|
|
ng-click="refresh()"><i class="fi-refresh"></i></a>
|
|
<a class="button radius small-icon" title="Signout"
|
|
ng-click="signout()"><i class="fi-power"></i></a>
|
|
</div>
|
|
<div class="large-4 medium-4 columns line-dashed-v">
|
|
Balance:
|
|
<span ng-if="$root.updatingBalance">
|
|
<i class="fi-bitcoin-circle icon-rotate spinner"></i>
|
|
</span>
|
|
<span ng-if="!$root.updatingBalance">{{totalBalance || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</div>
|
|
<div class="large-4 medium-4 columns">
|
|
Available to Spend:
|
|
<span ng-if="$root.updatingBalance">
|
|
<i class="fi-bitcoin-circle icon-rotate spinner"></i>
|
|
</span>
|
|
<span ng-if="!$root.updatingBalance">{{availableBalance || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="top-bar" data-topbar ng-show="$root.wallet">
|
|
<ul class="title-area">
|
|
<li class="name"></li>
|
|
<li class="toggle-topbar menu-icon">
|
|
<a ng-click="toggleCollapse()"></a>
|
|
</li>
|
|
</ul>
|
|
|
|
<section class="top-bar-section {{isCollapsed && 'hide_menu' || 'show_menu'}}">
|
|
<ul>
|
|
<li data-ng-repeat="item in menu" ui-route="/{{item.link}}" class="text-center" data-ng-class="{active: isActive(item)}">
|
|
<a href="{{item.link}}" ng-click="toggleCollapse()"> <i class="{{item.icon}}"></i> {{item.title}}
|
|
<span class="label alert round" ng-if="item.link=='#/transactions' && $root.pendingTxCount > 0">{{$root.pendingTxCount}}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
<div class="row" ng-if="updateVersion">
|
|
<div class="small-9 large-centered columns">
|
|
<div data-alert class="alert-box radius {{updateVersion}}">
|
|
A newer version of Copay is now available, please update your wallet to a latest version.
|
|
Please check <a href="http://www.copay.io">Copay.io</a>.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" ng-if='$root.$flashMessage.message' notification>
|
|
<div class="small-8 large-centered columns">
|
|
<div data-alert class="alert-box radius {{$root.$flashMessage.type}}">
|
|
{{$root.$flashMessage.message}}
|
|
<a ng-click="clearFlashMessage()" class="close">×</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div ng-if='$root.wallet && !$root.wallet.publicKeyRing.isComplete() && !loading'>
|
|
<div class="medium-12 small-12 columns">
|
|
<div class="alert-box secondary radius" data-alert>
|
|
<i class="fi-info"></i>
|
|
Not all copayers have joined your wallet yet.
|
|
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()>1">
|
|
{{$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers() }} people have
|
|
</span>
|
|
<span ng-show="$root.wallet.publicKeyRing.totalCopayers - $root.wallet.publicKeyRing.registeredCopayers()==1">
|
|
One person has
|
|
</span>
|
|
yet to join.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="medium-12 small-12 columns ">
|
|
<div class="panel radius m30v">
|
|
<h3 class="m15b">Share this secret with your other copayers
|
|
<small> for them to join your wallet</small>
|
|
</h3>
|
|
<div class="row">
|
|
<div class="large-9 medium-12 small-12 columns line-dashed-v text-gray">
|
|
<div class="panel input">
|
|
<p class="ellipsis text-gray">{{$root.wallet.getSecret()}}</p>
|
|
</div>
|
|
</div>
|
|
<div class="large-3 columns hide-for-medium hide-for-small" ng-show="$root.wallet">
|
|
<h5 class="m0">{{$root.wallet.getName()}}</h5>
|
|
<p class="text-gray">{{$root.wallet.requiredCopayers}}-of-{{$root.wallet.totalCopayers}} wallet</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div notifications="middle right"></div>
|
|
|
|
<div id="main" class="row" ng-class="{'main-home': !$root.wallet}">
|
|
<div class="large-12 columns" ng-view></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="footer" data-ng-controller="FooterController" ng-class="{'footer-home': !$root.wallet}">
|
|
<link rel="stylesheet" ng-href="{{theme}}">
|
|
<div ng-show="!$root.wallet">
|
|
<div class="large-12 columns text-right">
|
|
Copay
|
|
<small>v{{version}}</small>
|
|
</div>
|
|
</div>
|
|
<div class="p10t" ng-show="$root.wallet">
|
|
<div class="large-3 medium-3 hide-for-small columns">
|
|
<div>
|
|
<strong>{{$root.wallet.getName()}}</strong>
|
|
</div>
|
|
<div class="size-12 m10t">
|
|
{{$root.wallet.requiredCopayers}}-of-{{$root.wallet.totalCopayers}} wallet
|
|
</div>
|
|
<div class="size-12 m10t" ng-if="themes.length > 1">
|
|
<a class="size-12" ng-click="change_theme(th)" ng-repeat="th in themes">{{th}} {{$last ? '' : '· '}}</a>
|
|
</div>
|
|
</div>
|
|
<div class="large-9 medium-9 small-9 columns">
|
|
<a href="#/addresses" > </a>
|
|
<div class="bottom-copay"
|
|
ng-repeat="c in $root.wallet.getRegisteredPeerIds()" class="has-tip" tooltip-popup-delay="1000" tooltip-placement="top" tooltip="{{c.nick}}">
|
|
<video ng-if="$root.videoInfo[c.peerId]"
|
|
avatar peer="{{c}}"
|
|
autoplay
|
|
ng-class="($root.wallet.getOnlinePeerIDs().indexOf(c.peerId) != -1) ? 'online' : 'offline'"
|
|
ng-src="{{getVideoURL(c.peerId)}}"
|
|
></video>
|
|
<img ng-if="!$root.videoInfo[c.peerId]"
|
|
avatar peer="{{c}}"
|
|
ng-class="($root.wallet.getOnlinePeerIDs().indexOf(c.peerId) != -1) ? 'online' : 'offline'"
|
|
src="./img/satoshi.gif"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Templates -->
|
|
<script type="text/ng-template" id="signin.html">
|
|
<div class="signin" ng-controller="SigninController">
|
|
<div data-alert class="alert-box info radius" ng-show="loading && !failure">
|
|
<i class="size-21 fi-bitcoin-circle icon-rotate spinner"></i>
|
|
Authenticating and looking for peers...
|
|
</div>
|
|
<div class="alert-box error radius" ng-show="failure">
|
|
Oops, we had an error! Looks like you are already connected to this wallet,
|
|
please close all other Copay Wallets and <a ng-click='failure = false; loading = false'>Try again</a>.
|
|
</div>
|
|
<div ng-show="!loading">
|
|
<div class="row">
|
|
<div class="large-6 medium-6 columns">
|
|
<div class="box-signin radius">
|
|
<div ng-show="wallets.length">
|
|
<h3>Open Wallet</h3>
|
|
<form name="openForm" ng-submit="open(openForm)" novalidate>
|
|
<select class="form-control" ng-model="selectedWalletId" ng-options="w.id as w.show for w in wallets" required>
|
|
</select>
|
|
<input type="password" class="form-control" placeholder="Your password" name="openPassword" ng-model="openPassword" required>
|
|
<button type="submit" class="button secondary radius" ng-disabled="openForm.$invalid || loading" loading="Opening">Open</button>
|
|
</form>
|
|
</div>
|
|
<div ng-show="!wallets.length">
|
|
<h3>Create a new wallet</h3>
|
|
<p class="text-gray">
|
|
Copay is a free, open-source, multisignature bitcoin wallet. A single-owner bitcoin wallet's security depends on carefully securing the private keys. With copay you can have multiple people controlling the funds, using bitcoin's multisignature functionality, requiring no trust in any third party.
|
|
</p>
|
|
<a href="#setup" class="button secondary radius">Create</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="large-6 medium-6 columns">
|
|
<div class="box-signin radius">
|
|
<h3>Join a Wallet in Creation</h3>
|
|
<form name="joinForm" ng-submit="join(joinForm)" novalidate>
|
|
<input type="text" class="form-control" placeholder="Paste wallet secret here" name="connectionId" ng-model="connectionId" wallet-secret required>
|
|
<input type="password" class="form-control" placeholder="Choose your password" name="joinPassword" ng-model="$parent.joinPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required>
|
|
<input type="text" class="form-control" placeholder="Your name (optional)" name="nickname" ng-model="nickname">
|
|
<button type="submit" class="button primary radius" ng-disabled="joinForm.$invalid || loading" loading="Joining">Join</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="large-12 columns text-center line-dashed">
|
|
<a href="#settings">Settings</a> ·
|
|
<span ng-show="wallets.length">
|
|
<a href="#setup">Create a new wallet</a> ·
|
|
</span>
|
|
<a href="#import">Import a backup</a>
|
|
</div>
|
|
</div>
|
|
</div> <!-- End !loading -->
|
|
</div>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="import.html">
|
|
<div ng-controller="ImportController">
|
|
<div data-alert class="alert-box info radius" ng-show="loading">
|
|
<i class="size-21 fi-bitcoin-circle icon-rotate spinner"></i>
|
|
Importing wallet...
|
|
</div>
|
|
<div ng-init="choosefile=0; pastetext=0" ng-show="!loading">
|
|
<h3>{{title}}</h3>
|
|
<form name="importForm" ng-submit="import(importForm)" novalidate>
|
|
<div class="row">
|
|
<div class="large-6 large-centered medium-6 medium-centered columns">
|
|
<fieldset>
|
|
<legend>Select which method want to use to restore</legend>
|
|
<label for="backupFile" ng-click="choosefile=!choosefile" class="m10b">· Choose backup file from your computer <i class="fi-laptop"></i></label>
|
|
<input type="file" class="form-control" placeholder="Select a backup file" name="backupFile" ng-model="backupFile" ng-file-select ng-show="choosefile">
|
|
<label for="backupText" ng-click="pastetext=!pastetext" class="m10b">· Paste backup plain text code <i class="fi-clipboard"></i></label>
|
|
<textarea class="form-control" name="backupText" ng-model="backupText" rows="5" ng-show="pastetext"></textarea>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="large-6 large-centered medium-6 medium-centered columns">
|
|
<label for="password">Password <small>Required</small></label>
|
|
<input type="password" class="form-control" placeholder="Your wallet password" name="password" ng-model="password" required>
|
|
</div>
|
|
</div>
|
|
<div class="row line-dashed">
|
|
<div class="large-6 medium-6 small-5 columns text-left">
|
|
<a class="button secondary radius" href="#signin">Go back</a>
|
|
</div>
|
|
<div class="large-6 medium-6 small-5 columns text-right">
|
|
<button type="submit" class="button primary radius right" ng-disabled="importForm.$invalid" loading="Importing">
|
|
Import backup
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="setup.html">
|
|
<div ng-controller="SetupController">
|
|
<div data-alert class="alert-box info radius" ng-show="loading">
|
|
<i class="size-21 fi-bitcoin-circle icon-rotate spinner"></i>
|
|
Creating wallet...
|
|
</div>
|
|
<div ng-show="!loading">
|
|
<form name="setupForm" ng-submit="create(setupForm)" novalidate>
|
|
<h3>Create new wallet</h3>
|
|
<div class="row">
|
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns">
|
|
<label>Wallet name <small>Optional</small>
|
|
<input type="text" placeholder="Family vacation funds" class="form-control" ng-model="walletName">
|
|
</label>
|
|
</div>
|
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns">
|
|
<div class="row">
|
|
<div class="small-12 medium-6 large-6 columns">
|
|
<label>Your name <small>Optional</small>
|
|
<input type="text" placeholder="Name" class="form-control" ng-model="myNickname">
|
|
</label>
|
|
</div>
|
|
<div class="small-12 medium-6 large-6 columns">
|
|
<label>Your Wallet Password <small class="has-tip" tooltip="doesn't need to be shared">Required</small>
|
|
<input type="password" placeholder="Choose your password" class="form-control"
|
|
ng-model="$parent.walletPassword" check-strength="passwordStrength" tooltip="Password strength: {{passwordStrength}}" tooltip-trigger="focus" required>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="small-12 medium-8 medium-centered large-8 large-centered columns box-setup">
|
|
<fieldset>
|
|
<div class="row">
|
|
<div class="large-6 medium-6 columns line-dashed-v">
|
|
<label>Select total number of copayers
|
|
<select ng-model="totalCopayers" ng-options="totalCopayers as totalCopayers for totalCopayers in TCValues">
|
|
</select>
|
|
</label>
|
|
</div>
|
|
<div class="large-6 medium-6 columns">
|
|
<label>Select required signatures
|
|
<select ng-model="requiredCopayers" ng-options="requiredCopayers as requiredCopayers for requiredCopayers in RCValues">
|
|
</select>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
<div class="small-12 medium-6 medium-centered large-6 large-centered columns m10b">
|
|
<div class="box-setup-copayers">
|
|
<div class="box-setup-copayers-fix">
|
|
<img class="box-setup-copay" ng-repeat="i in getNumber(totalCopayers) track by $index" src="./img/satoshi.gif" alt="Copayer {{$index+1}}-{{totalCopayers}}" ng-class="{'box-setup-copay-required': ($index+1) <= requiredCopayers}">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row line-dashed">
|
|
<div class="large-6 medium-6 small-5 columns text-left">
|
|
<a class="button secondary radius" href="#signin">Go back</a>
|
|
</div>
|
|
<div class="large-6 medium-6 small-7 columns text-right">
|
|
<button type="submit" class="button primary radius" ng-disabled="setupForm.$invalid || loading">
|
|
Create {{requiredCopayers}}-of-{{totalCopayers}} wallet
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- ADDRESS -->
|
|
<script type="text/ng-template" id="addresses.html">
|
|
<div class="addresses" ng-controller="AddressesController">
|
|
<div ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
|
<div class="row">
|
|
<div class="large-9 medium-12 columns" ng-if="addresses[0]">
|
|
<div class="large-8 medium-8 columns" ng-init="showAll=0">
|
|
<a class="panel radius db" ng-repeat="addr in addresses | limitAddress:showAll"
|
|
ng-click="selectAddress(addr)"
|
|
ng-class="{selected : addr.address == selectedAddr.address}">
|
|
|
|
<span>{{addr.address}}</span>
|
|
<small ng-if="addr.isChange">change</small>
|
|
|
|
<span class="right">
|
|
<span ng-if="addrWithFund == addr.address">
|
|
<span ng-if="$root.updatingBalance">
|
|
<i class="fi-bitcoin-circle icon-rotate spinner"></i>
|
|
</span>
|
|
<span ng-if="!$root.updatingBalance">
|
|
{{$root.balanceByAddr[addr.address] || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</span>
|
|
<span ng-if="addrWithFund != addr.address">
|
|
{{addr.balance || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</span>
|
|
</a>
|
|
|
|
<a class="secondary radius" ng-click="showAll=!showAll" ng-show="(addresses|withoutFunds) > 1">
|
|
<span ng-if="!showAll">Show all</span>
|
|
<span ng-if="showAll">Show less</span>
|
|
</a>
|
|
</div>
|
|
<div class="large-4 medium-4 columns line-dashed-v text-center" ng-show="selectedAddr">
|
|
<qrcode size="160" data="{{selectedAddr.address}}"></qrcode>
|
|
<p class="m10t">
|
|
<strong>
|
|
<span ng-if="addrWithFund == selectedAddr.address">
|
|
<span ng-if="$root.updatingBalance">
|
|
<i class="fi-bitcoin-circle icon-rotate spinner"></i>
|
|
</span>
|
|
<span ng-if="!$root.updatingBalance">{{balanceByAddr[selectedAddr.address] || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</span>
|
|
<span ng-if="addrWithFund != selectedAddr.address">
|
|
{{selectedAddr.balance || 0}}
|
|
<i class="fi-bitcoin"></i>
|
|
</span>
|
|
</strong>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="columns text-center m10t" ng-class="{'large-3' : !!addresses[0]}">
|
|
<p> Create a New <strong> Address </strong> </p>
|
|
<button class="secondary radius expandi new-address" ng-click="newAddr()"
|
|
ng-disabled="loading" loading="Creating"> Create </button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- TRANSACTIONS -->
|
|
<script type="text/ng-template" id="transactions.html">
|
|
<div class="transactions" data-ng-controller="TransactionsController">
|
|
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
|
<div class="large-12 columns">
|
|
<h4> Transaction proposals <small>({{txs.length}})</small></h4>
|
|
|
|
<ul class="inline-list">
|
|
<li> <a class="text-gray size-12" ng-click="show(true)" ng-disabled="loading || onlyPending" loading="Updating" ng-class="{'active' : onlyPending}"> [ Pending ] </a> </li>
|
|
<li> <a class="text-gray size-12" ng-click="show()" ng-disabled="loading || !onlyPending" loading="Updating" ng-class="{'active' : !onlyPending}"> [ All ] </a> </li>
|
|
</ul>
|
|
<div class="panel radius pending" ng-repeat="tx in txs | paged">
|
|
<div class="txheader row m10">
|
|
<div class="large-8 medium-8 small-12 columns">
|
|
<div class="row" ng-repeat="out in tx.outs">
|
|
<div class="large-3 medium-3 small-3 columns ellipsis"> {{out.value}} <i class="fi-bitcoin size-18"></i></div>
|
|
<div class="large-1 medium-1 small-2 columns fi-arrow-right size-24"> </div>
|
|
<div class="large-8 medium-8 small-7 columns ellipsis"> {{out.address}} </div>
|
|
</div>
|
|
</div>
|
|
<div class="large-4 medium-4 small-12 columns text-right">
|
|
<h6>{{tx.createdTs | amCalendar}}</h6>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tx-copayers">
|
|
|
|
<div class="box-copayers" ng-repeat="(cId, actions) in tx.peerActions">
|
|
<figure class="left">
|
|
<a href="#/transactions" class="has-tip" tooltip-popup-delay="1000" tooltip="{{cId === $root.wallet.getMyCopayerId() ? 'You' : $root.wallet.publicKeyRing.nicknameForCopayer(cId)}}">
|
|
<img src="./img/satoshi.gif" alt="{{cId}}" width="200">
|
|
</a>
|
|
</figure>
|
|
<div class="box-status">
|
|
<span ng-repeat="(action, ts) in actions">
|
|
<a ng-if="action == 'create'" href="#/transactions" class="has-tip" tooltip-popup-delay="1000" tooltip="Created {{ts | amTimeAgo}}">
|
|
<i class="fi-crown size-12 icon-status icon-active"></i>
|
|
</a>
|
|
<a ng-if="action == 'seen'" href="#/transactions" class="has-tip" tooltip-popup-delay="1000" tooltip="Seen {{ts | amTimeAgo}}">
|
|
<i class="fi-eye size-12 icon-status icon-active"></i>
|
|
</a>
|
|
<a ng-if="action == 'sign'" href="#/transactions" class="has-tip" tooltip-popup-delay="1000" tooltip="Signed {{ts | amTimeAgo}}">
|
|
<i class="fi-check size-12 icon-status icon-active-check"></i>
|
|
</a>
|
|
<a ng-if="action == 'rejected'" href="#/transactions" class="has-tip" tooltip-popup-delay="1000" tooltip="Rejected {{ts | amTimeAgo}}">
|
|
<i class="fi-x size-12 icon-status icon-active-x"></i>
|
|
</a>
|
|
</span>
|
|
</div>
|
|
|
|
<div class="text-center" style="margin-right:16px; color:#999; font-size:12px">
|
|
{{$root.wallet.publicKeyRing.nicknameForCopayer(cId)}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row m10">
|
|
<div class="large-5 medium-5 columns" ng-show="!tx.sentTs">
|
|
<div ng-show="!tx.signedByUs && !tx.rejectedByUs && !tx.finallyRejected && tx.missingSignatures">
|
|
<button class="secondary radius m10r" ng-click="sign(tx.ntxid)" ng-disabled="loading" loading="Signing">
|
|
<i class="fi-check"></i> Sign
|
|
</button>
|
|
<button class="warning radius" ng-click="reject(tx.ntxid)" ng-disabled="loading" loading="Rejecting">
|
|
<i class="fi-x" ></i> Reject
|
|
</button>
|
|
</div>
|
|
<div ng-show="!tx.missingSignatures && !tx.sentTs">
|
|
<button class="primary radius" ng-click="send(tx.ntxid)" ng-disabled="loading" loading="Broadcasting"> <i class=".fi-upload-cloud"></i>
|
|
Broadcast Transaction
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="large-7 medium-7 columns text-right">
|
|
<div ng-show="tx.finallyRejected" class="text-warning m10b">
|
|
Transaction finally rejected
|
|
</div>
|
|
<div ng-show="!tx.missingSignatures && tx.sentTs">
|
|
<div class="success m10b">
|
|
<strong>Sent</strong> <span class="text-gray" am-time-ago="tx.sentTs"></span>
|
|
</div>
|
|
<div class="ellipsis small">
|
|
Transaction ID:
|
|
<a href="http://{{getShortNetworkName()}}.insight.is/tx/{{tx.sentTxid}}" target="blank">
|
|
{{tx.sentTxid}}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<p class="text-gray m5b" ng-show="!tx.finallyRejected && tx.missingSignatures==1">
|
|
One signature missing
|
|
</p>
|
|
<p class="text-gray m5b" ng-show="!tx.finallyRejected && tx.missingSignatures>1">
|
|
{{tx.missingSignatures}} signatures missing</p>
|
|
<div class="ellipsis small text-gray">
|
|
<strong>Fee:</strong> <i class="fi-bitcoin"></i> {{tx.fee}}
|
|
<strong>Proposal ID:</strong> {{tx.ntxid}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p ng-show="onlyPending && txs.length == 0">No pending transactions proposals.</p>
|
|
<p ng-show="!onlyPending && txs.length == 0">No transactions proposals yet.</p>
|
|
<pagination ng-show="!onlyPending && txs.length > 0" total-items="txs.length" items-per-page="txpItemsPerPage" page="txpCurrentPage" on-select-page="show()" class="pagination-small primary"></pagination>
|
|
</div>
|
|
<div class="large-12 columns">
|
|
<h4>Last transactions</h4>
|
|
<div class="m10b size-12">
|
|
<a class="text-gray active" ng-click="toogleLast()" ng-disabled="loading" loading="Loading" ng-hide="lastShowed && !loading">[ Show ]</a>
|
|
<a class="text-gray" ng-click="toogleLast()" ng-disabled="loading" loading="Loading" ng-show="lastShowed && !loading">[ Hide ]</a>
|
|
</div>
|
|
<div class="btransactions" ng-if="lastShowed">
|
|
<div ng-if="!blockchain_txs[0].txid && !loading">
|
|
No transactions yet.
|
|
</div>
|
|
<div class="panel radius" ng-repeat="btx in blockchain_txs | orderBy: 'firstSeenTs':true">
|
|
<div class="m10 size-12">
|
|
<div class="row">
|
|
<div class="large-8 columns">
|
|
<a class="ellipsis" href="http://{{getShortNetworkName()}}.insight.is/tx/{{btx.txid}}" target="blank">
|
|
{{btx.txid}}
|
|
</a>
|
|
</div>
|
|
<div class="large-4 columns text-right">
|
|
<div data-ng-show="btx.firstSeenTs">
|
|
first seen at
|
|
<time>{{btx.firstSeenTs * 1000 | amCalendar}}</time>
|
|
</div>
|
|
<div data-ng-show="btx.time && !btx.firstSeenTs">
|
|
mined at
|
|
<time>{{btx.time * 1000 | amCalendar}}</time>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tx-copayers">
|
|
<div class="row">
|
|
<div class="large-5 medium-5 small-5 columns">
|
|
<div ng-repeat="vin in btx.vinSimple">
|
|
<small class="right m5t">{{vin.value}}</small>
|
|
<p class="ellipsis text-gray size-12"> {{vin.addr}} </p>
|
|
</div>
|
|
</div>
|
|
<div class="large-1 medium-1 small-1 columns text-center">
|
|
<i class="fi-arrow-right"></i>
|
|
</div>
|
|
<div class="large-6 medium-6 small-6 columns">
|
|
<div ng-repeat="vout in btx.voutSimple">
|
|
<small class="right m5t">{{vout.value}}</small>
|
|
<p class="ellipsis text-gray size-12"> {{vout.addr}} </p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="m10 size-12 text-gray">
|
|
<div class="row">
|
|
<div class="large-4 medium-4 small-4 columns">Fees: {{btx.fees}}</div>
|
|
<div class="large-4 medium-4 small-4 columns text-center">Confirmations: {{btx.confirmations || 0}}</div>
|
|
<div class="large-4 medium-4 small-4 columns text-right">Total: {{btx.valueOut}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- SEND -->
|
|
<script type="text/ng-template" id="send.html">
|
|
<div class="send" data-ng-controller="SendController">
|
|
<div class="row" ng-show='$root.wallet.publicKeyRing.isComplete()'>
|
|
<div class="medium-6 medium-centered large-6 large-centered columns">
|
|
<h3>{{title}}</h3>
|
|
<form name="sendForm" ng-submit="submitForm(sendForm)" novalidate>
|
|
<div class="row">
|
|
<div class="large-12 columns">
|
|
<div class="row collapse">
|
|
<label for="address">To address
|
|
<small ng-hide="!sendForm.address.$pristine || address">required</small>
|
|
<small class="is-valid" ng-show="!sendForm.address.$invalid && address">valid!</small>
|
|
<small class="has-error" ng-show="sendForm.address.$invalid && address">
|
|
not valid</small>
|
|
</label>
|
|
<div class="small-10 columns">
|
|
<input type="text" id="address" name="address" ng-disabled="loading"
|
|
placeholder="Send to" ng-model="address" valid-address required>
|
|
</div>
|
|
<div class="small-2 columns" ng-hide="showScanner || !isHttp">
|
|
<a class="postfix button secondary" ng-click="openScanner()"><i class="fi-camera"></i></a>
|
|
</div>
|
|
<div class="small-2 columns" ng-show="showScanner && isHttp">
|
|
<a class="postfix button warning" ng-click="cancelScanner()">Cancel</a>
|
|
</div>
|
|
</div>
|
|
<div id="scanner" class="row" ng-if="showScanner">
|
|
<div class="text-centered">
|
|
<canvas id="qr-canvas" width="200" height="150"></canvas>
|
|
<div ng-show="isMobile">
|
|
<div id="file-input-wrapper" class="btn btn-primary">
|
|
<span class="pull-left text-centered">
|
|
<i class="glyphicon glyphicon-refresh icon-rotate"></i>
|
|
Get QR code
|
|
</span>
|
|
<input id="qrcode-camera" type="file" capture="camera" accept="image/*">
|
|
</div>
|
|
</div>
|
|
<div ng-hide="isMobile">
|
|
<video id="qrcode-scanner-video" width="300" height="225" ng-hide="isMobile"></video>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="large-6 medium-6 columns">
|
|
<div class="row collapse">
|
|
<label for="amount">Amount
|
|
<small ng-hide="!sendForm.amount.$pristine">required</small>
|
|
<small class="is-valid" ng-show="!sendForm.amount.$invalid && !sendForm.amount.$pristine">valid!</small>
|
|
<small class="has-error" ng-show="sendForm.amount.$invalid && !sendForm.amount.$pristine">
|
|
not valid.</small>
|
|
<small ng-show="notEnoughAmount">{{notEnoughAmount}}</small>
|
|
</label>
|
|
<div class="small-9 columns">
|
|
<input type="number" id="amount" ng-disabled="loading"
|
|
name="amount" placeholder="Amount" ng-model="amount"
|
|
min="0.0001" max="10000000" enough-amount required>
|
|
</div>
|
|
<div class="small-3 columns">
|
|
<span class="postfix">BTC</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="large-5 columns">
|
|
<button type="submit" class="button secondary radius text-center" ng-disabled="sendForm.$invalid || loading" loading="Sending">
|
|
Send
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- BACKUP -->
|
|
<script type="text/ng-template" id="backup.html">
|
|
<div class="backup" ng-controller="BackupController">
|
|
<h3>{{title}}</h3>
|
|
<div class="row text-center">
|
|
<div class="large-6 medium-6 columns">
|
|
<a class="panel radius box-backup" ng-click="download()">
|
|
<i class="fi-download size-72"></i>
|
|
<p> Download File </p>
|
|
</a>
|
|
</div>
|
|
<div class="large-6 medium-6 columns">
|
|
<a class="panel radius box-backup" ng-click="openModal()">
|
|
<i class="fi-mail size-72"></i>
|
|
<p> Backup to email </p>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="backupModal.html">
|
|
<h3>Insert your email</h3>
|
|
<form name="emailForm" ng-submit="submit(emailForm)">
|
|
<p><input type="email" ng-model="$parent.email" placeholder="your@email.com" required/></p>
|
|
<input type="submit" class="button" value="Send" ng-disabled="emailForm.$invalid"/>
|
|
</form>
|
|
<a class="close-reveal-modal" ng-click="cancel()">×</a>
|
|
</script>
|
|
|
|
<!-- CONFIG -->
|
|
<script type="text/ng-template" id="settings.html">
|
|
<div class="settings" ng-controller="SettingsController">
|
|
<h3>{{title}}</h3>
|
|
<form name="settingsForm">
|
|
<div class="small-12 medium-6 medium-centered large-6 large-centered columns">
|
|
<fieldset>
|
|
<legend>Bitcoin Network</legend>
|
|
<input id="network-name" type="checkbox" ng-model="networkName" ng-true-value="livenet" ng-false-value="testnet" class="form-control">
|
|
<label for="network-name">Livenet</label>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>Insight API server</legend>
|
|
<div class="row">
|
|
<label for="insight-host">Host</label>
|
|
<input type="text" ng-model="insightHost" class="form-control" name="insight-host">
|
|
</div>
|
|
<div class="row">
|
|
<label for="insight-port">Port</label>
|
|
<input type="number" ng-model="insightPort" class="form-control" name="insight-port">
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<legend>PeerJS server</legend>
|
|
<div class="row">
|
|
<label for="peerjs-key">Key</label>
|
|
<input type="text" ng-model="networkKey" class="form-control" name="peerjs-key">
|
|
</div>
|
|
<div class="row">
|
|
<label for="peerjs-host">Host</label>
|
|
<input type="text" ng-model="networkHost" class="form-control" name="peerjs-host">
|
|
</div>
|
|
<div class="row">
|
|
<label for="peerjs-port">Port</label>
|
|
<input type="number" ng-model="networkPort" class="form-control" name="peerjs-port">
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
<div class="row">
|
|
<div class="large-12 columns line-dashed">
|
|
<button type="submit" class="button primary radius right ng-binding" ng-disabled="setupForm.$invalid || loading" disabled="disabled" ng-click="save()">
|
|
Save
|
|
</button>
|
|
<a class="button secondary radius" href="#signin" ng-hide="$root.wallet">Home</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- UNSUPPORTED -->
|
|
<script type="text/ng-template" id="unsupported.html">
|
|
<h2 class="text-center">Browser unsupported</h2>
|
|
<h3 class="text-center">
|
|
Copay uses webRTC for peer-to-peer communications,
|
|
but your browser does not support it.
|
|
Please use
|
|
a current version of Google Chrome, Mozilla Firefox, or Opera.
|
|
<br><br>
|
|
|
|
For more information
|
|
on supported browsers please check <a href="http://www.webrtc.org/">http://www.webrtc.org/</a>
|
|
</h3>
|
|
|
|
</script>
|
|
|
|
<!-- NOT FOUND -->
|
|
<script type="text/ng-template" id="404.html">
|
|
<h2 class="text-center">404</h2>
|
|
<h3 class="text-center">Page not found</h3>
|
|
<p class="text-center"><a href="#/">go back...</a></p>
|
|
</script>
|
|
|
|
|
|
<script src="config.js"></script>
|
|
<!-- <script src="js/shell.js"></script> -->
|
|
<script src="lib/angular/angular.min.js"></script>
|
|
<script src="lib/moment/moment.js"></script>
|
|
<script src="lib/angular-moment/angular-moment.js"></script>
|
|
<script src="lib/qrcode-generator/js/qrcode.js"></script>
|
|
<script src="lib/angular-qrcode/qrcode.js"></script>
|
|
<script src="lib/angular-route/angular-route.min.js"></script>
|
|
<script src="lib/angular-foundation/mm-foundation.min.js"></script>
|
|
<script src="lib/angular-foundation/mm-foundation-tpls.min.js"></script>
|
|
<script src="lib/peer.js"></script> <!-- TODO Change this on new PeerJS version -->
|
|
<script src="lib/bitcore/browser/bundle.js"></script>
|
|
<script src="lib/crypto-js/rollups/sha256.js"></script>
|
|
<script src="lib/crypto-js/rollups/pbkdf2.js"></script>
|
|
<script src="lib/crypto-js/rollups/aes.js"></script>
|
|
<script src="lib/file-saver/FileSaver.js"></script>
|
|
<script src="lib/socket.io.js"></script>
|
|
<script src="lib/sjcl.js"></script>
|
|
<script src="lib/ios-imagefile-megapixel/megapix-image.js"></script>
|
|
<script src="lib/qrcode-decoder-js/lib/qrcode-decoder.min.js"></script>
|
|
<script src="js/copayBundle.js"></script>
|
|
|
|
<script src="js/app.js"></script>
|
|
<script src="js/routes.js"></script>
|
|
<script src="js/directives.js"></script>
|
|
<script src="js/filters.js"></script>
|
|
<script src="js/services/socket.js"></script>
|
|
<script src="js/services/video.js"></script>
|
|
<script src="js/services/walletFactory.js"></script>
|
|
<script src="js/services/controllerUtils.js"></script>
|
|
<script src="js/services/passphrase.js"></script>
|
|
<script src="js/services/notifications.js"></script>
|
|
|
|
<script src="js/controllers/header.js"></script>
|
|
<script src="js/controllers/footer.js"></script>
|
|
<script src="js/controllers/addresses.js"></script>
|
|
<script src="js/controllers/transactions.js"></script>
|
|
<script src="js/controllers/send.js"></script>
|
|
<script src="js/controllers/backup.js"></script>
|
|
<script src="js/controllers/signin.js"></script>
|
|
<script src="js/controllers/setup.js"></script>
|
|
<script src="js/controllers/import.js"></script>
|
|
<script src="js/controllers/settings.js"></script>
|
|
|
|
<script src="js/init.js"></script>
|
|
</body>
|
|
</html>
|