diff --git a/.gitignore b/.gitignore index dc101e2e9..a91c52300 100644 --- a/.gitignore +++ b/.gitignore @@ -106,6 +106,7 @@ src/js/appConfig.js src/js/externalServices.js chrome-app/manifest.json www/img/app +www/index.html cordova/android/res/ diff --git a/README.md b/README.md index eaa9cf2fd..2183d7209 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://secure.travis-ci.org/bitpay/copay.svg)](http://travis-ci.org/bitpay/copay) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/copay/localized.png)](https://crowdin.com/project/copay) -Copay is an easy-to-use, open-source, multiplatform, multisignature, secure bitcoin wallet platform for both individuals and companies. Copay uses [Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service) (BWS) for peer synchronization and network interfacing. +Copay is an easy-to-use, open-source, multiplatform, multisignature, secure bitcoin wallet platform for both individuals and companies. Copay uses [Bitcore Wallet Service](https://github.com/bitpay/bitcore-wallet-service) (BWS) for peer synchronization and network interfacing. Binary versions of Copay are available for download at [Copay.io](https://copay.io/#download). Copay Binaries are signed with the key `copay@bitpay.com` – See the section [`How to Verify Copay Signatures`](https://github.com/bitpay/copay#how-to-verify-copay-signatures) for details. @@ -29,7 +29,9 @@ For a list of frequently asked questions please visit the [Copay FAQ](https://gi - Multiple languages supported - Available for [iOS](https://itunes.apple.com/us/app/copay/id951330296), [Android](https://play.google.com/store/apps/details?id=com.bitpay.copay&hl=en), [Windows Phone](http://www.windowsphone.com/en-us/store/app/copay-wallet/4372479b-a064-4d18-8bd3-74a3bdb81c3a), [Chrome App](https://chrome.google.com/webstore/detail/copay/cnidaodnidkbaplmghlelgikaiejfhja?hl=en), [Linux](https://github.com/bitpay/copay/releases/latest), [Windows](https://github.com/bitpay/copay/releases/latest) and [OS X](https://github.com/bitpay/copay/releases/latest) devices -## Install For Development +## Testing in a Browser + +> **Note:** This method should only be used for development purposes. When running Copay in a normal browser environment, browser extensions and other malicious code might have access to internal data and private keys. For production use, see the latest official [releases](https://github.com/bitpay/copay/releases/). Clone the repo and open the directory: @@ -47,68 +49,83 @@ npm start Visit [`localhost:3000`](http://localhost:3000/) to view the app. -> **Note:** This method should only be used for development purposes. When running Copay in a normal browser environment, browser extensions and other malicious code might have access to internal data and private keys. For production use, see the latest official [releases](https://github.com/bitpay/copay/releases/). +A watch task is also available to rebuild components of the app as changes are made. This task can be run in a separate process – while the server started by `npm start` is running – to quickly test changes. -## Build Copay App Bundles +``` +npm run watch +``` + +## Testing on Real Devices + +It's recommended that all final testing be done on a real device – both to assess performance and to enable features that are unavailable to the emulator (e.g. a device camera). ### Android -- Install Android SDK -- Run `make android` +Follow the [Cordova Android Platform Guide](https://cordova.apache.org/docs/en/latest/guide/platforms/android/) to set up your development environment. + +When your developement enviroment is ready, run the `start:android` npm package script. + +```sh +npm run apply:copay +npm run start:android +``` ### iOS -- Install Xcode 6.1 (or newer) -- Run `make ios-prod` +Follow the [Cordova iOS Platform Guide](https://cordova.apache.org/docs/en/latest/guide/platforms/android/) to set up your development environment. -##### Notes for Xcode 7.0 +When your developement enviroment is ready, run the `start:ios` npm package script. -###### ATS support - -Before starting Copay from Xcode, add these lines to "Custom iOS Target Properties": - -``` -NSAppTransportSecurity - - NSAllowsArbitraryLoads - - +```sh +npm run apply:copay +npm run start:ios ``` -![Example](http://i.stack.imgur.com/nGw3j.png) +### Desktop (Linux, macOS, and Windows) +The desktop version of Copay currently uses NW.js, an app runtime based on Chromium. To get started, first install NW.js on your system from [the NW.js website](https://nwjs.io/). -App Transport Security (ATS) enforces best practices in the secure connections between an app and its back end. [Read complete documentation](https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9.html). - -###### Invalid Bundle while submitting application - -`iPad Multitasking support requires launch story board in bundle` - -To fix this problem, add the following: +When NW.js is installed, run the `start:desktop` npm package script. +```sh +npm run apply:copay +npm run start:desktop ``` -UIRequiresFullScreen -YES + +## Build Copay App Bundles + +Before building the release version for a platform, run the `clean-all` command to delete any untracked files in your current working directory. (Be sure to stash any uncommited changes you've made.) This guarantees consistency across builds for the current state of this repository. + +The `final` commands build the production version of the app, and bundle it with the release version of the platform being built. + +### Android + +```sh +npm run clean-all +npm run apply:copay +npm run final:android ``` -###### Build settings, headers search path - -Add this line to your Build Settings -> Header Search Paths -> Release - -"$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include" +### iOS +```sh +npm run clean-all +npm run apply:copay +npm run final:ios +``` ### Windows Phone - Install Visual Studio 2013 (or newer) - Run `make wp8-prod` -### Desktop versions (Windows, OS X, Linux) +### Desktop (Linux, macOS, and Windows) -Copay uses NW.js (also know as node-webkit) for its desktop version. NW.js is an app runtime based on `Chromium` and `node.js`. - -- Install NW.js on your system from [nwjs.io](http://nwjs.io/) -- Run `grunt desktop` +```sh +npm run clean-all +npm run apply:copay +npm run final:desktop +``` ### Google Chrome App @@ -116,10 +133,6 @@ Copay uses NW.js (also know as node-webkit) for its desktop version. NW.js is an On success, the Chrome extension will be located at: `browser-extensions/chrome/copay-chrome-extension`. To install it go to `chrome://extensions/` in your browser and ensure you have the 'developer mode' option enabled in the settings. Then click on "Load unpacked chrome extension" and choose the directory mentioned above. -### Firefox Add-on - -The Copay Firefox Extension has been deprecated and is no longer supported. - ## About Copay ### General diff --git a/app-template/apply.js b/app-template/apply.js index f641e72cd..4f20f052f 100755 --- a/app-template/apply.js +++ b/app-template/apply.js @@ -6,6 +6,7 @@ var templates = { 'package.json': '/', + 'index.html': 'www/', 'Makefile': 'cordova/', 'ProjectMakefile': 'cordova/', 'config-template.xml': '/', diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 1d646660f..9f54116f4 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -75,6 +75,7 @@ + diff --git a/www/index.html b/app-template/index.html similarity index 92% rename from www/index.html rename to app-template/index.html index 26ca9be38..af88781c4 100644 --- a/www/index.html +++ b/app-template/index.html @@ -7,7 +7,7 @@ - {{appConfig.nameCase}} - {{appConfig.description}} + *USERVISIBLENAME* - *PURPOSELINE* diff --git a/app-template/package.json b/app-template/package.json index afd2928f4..16130160b 100644 --- a/app-template/package.json +++ b/app-template/package.json @@ -23,6 +23,9 @@ "frame": true, "width": 400, "height": 650, + "min_width": 400, + "max_width": 800, + "min_height": 650, "position": "center", "fullscreen": false }, @@ -95,6 +98,8 @@ "final:www": "npm run build:www-release", "final:ios": "npm run final:www && npm run build:ios-release && npm run open:ios", "final:android": "npm run final:www && npm run build:android-release && npm run run:android", + "final:desktop": "grunt desktop", + "sign:android": "rm -f platforms/android/build/outputs/apk/android-release-signed-aligned.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../copay.keystore -signedjar platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-unsigned.apk copay_play && ../android-sdk-macosx/build-tools/21.1.1/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk", "run:android": "cordova run android --device", "log:android": "adb logcat | grep chromium", "apply:copay": "cd app-template && node apply.js copay && cordova prepare", diff --git a/bower.json b/bower.json index 912826903..ac2e0a9ee 100644 --- a/bower.json +++ b/bower.json @@ -10,7 +10,7 @@ "angular-mocks": "1.4.10", "angular-gettext": "2.2.1", "angular-moment": "0.10.1", - "angular-qrcode": "monospaced/angular-qrcode#~6.2.1", + "angular-qrcode": "bitpay/angular-qrcode#~6.3.0", "ionic": "1.3.1", "moment": "2.10.3", "ng-lodash": "0.2.3", diff --git a/package.json b/package.json index 8f5f3d3db..a1fb7d865 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,116 @@ -{ - "name": "distribution-not-selected", - "description": "Choose a distribution by running 'npm run apply:copay' or 'npm run apply:bitpay'.", - "primary-package-json": "See the tempate in app-template/package.json", - "scripts": { - "postinstall": "npm run apply:copay && npm install", - "apply:copay": "cd app-template && node apply.js copay", - "apply:bitpay": "cd app-template && node apply.js bitpay" + { + "//":"Changes to this file will be overwritten", + "//":" Modify it in the app-template directory", + + "name": "bitpay", + "description": "Secure Bitcoin Wallet", + "author": "BitPay", + "version": "0.14.0", + "keywords": [ + "bitcoin", + "wallet", + "bitpay", + "copay", + "multisignature", + "bitcore" + ], + "main": "www/index.html", + "window": { + "title": "BitPay - Secure Bitcoin Wallet", + "icon": "www/img/icon-128.png", + "toolbar": false, + "show": true, + "visible": true, + "resizable": true, + "frame": true, + "width": 400, + "height": 650, + "position": "center", + "fullscreen": false }, - "dependencies": { - "fs-extra": "^0.30.0" + "webkit": { + "page-cache": false, + "java": false, + "plugin": false }, + "dom_storage_quota": 200, + "id": "jid1-x7bV5evAaI1P9Q", + "homepage": "https://bitpay.com", "license": "MIT", "repository": { - "url": "git://github.com/bitpay/copay.git", + "url": "git://github.com/bitpay/bitpay-wallet.git", "type": "git" + }, + "bugs": { + "url": "https://github.com/bitpay/bitpay-wallet/issues" + }, + "dependencies": { + "adm-zip": "^0.4.7", + "angular": "1.4.6", + "angular-mocks": "1.4.10", + "bezier-easing": "^2.0.3", + "bhttp": "^1.2.1", + "bitauth": "^0.3.2", + "bitcore-wallet-client": "4.3.2", + "bower": "^1.7.9", + "chai": "^3.5.0", + "cordova-android": "5.1.1", + "cordova-custom-config": "^3.0.5", + "cordova-plugin-qrscanner": "^2.3.1", + "coveralls": "^2.11.9", + "express": "^4.11.2", + "fs": "0.0.2", + "fs-extra": "^0.30.0", + "grunt-angular-gettext": "^2.2.3", + "grunt-browserify": "^5.0.0", + "grunt-cli": "^1.2.0", + "grunt-contrib-compress": "^1.3.0", + "grunt-contrib-concat": "^1.0.1", + "grunt-contrib-copy": "^1.0.0", + "grunt-contrib-uglify": "^2.0.0", + "grunt-contrib-watch": "^1.0.0", + "grunt-exec": "^1.0.0", + "grunt-nw-builder": "^2.0.3", + "grunt-sass": "^1.2.0", + "load-grunt-tasks": "^3.5.0", + "mocha": "^2.4.5", + "phantomjs-prebuilt": "^2.1.7", + "shelljs": "^0.3.0" + }, + "scripts": { + "preinstall": "bower install && npm install fs-extra", + "postinstall": "echo && echo \"To finish, choose a distribution by running 'npm run apply:copay' or 'npm run apply:bitpay'.\" && echo", + "start": "npm run build:www && ionic serve --nolivereload --nogulp -s", + "start:ios": "npm run build:www && npm run build:ios && npm run open:ios", + "start:android": "npm run build:www && npm run build:android && npm run run:android", + "start:desktop": "grunt desktop", + "watch": "grunt watch", + "build:www": "grunt", + "build:www-release": "grunt prod", + "build:ios": "cordova prepare ios && cordova build ios --debug", + "build:android": "cordova prepare android && cordova build android --debug", + "build:ios-release": "cordova prepare ios && cordova build ios --release", + "build:android-release": "cordova prepare android && cordova build android --release", + "open:ios": "open platforms/ios/*.xcodeproj", + "open:android": "open -a open -a /Applications/Android\\ Studio.app platforms/android", + "final:www": "npm run build:www-release", + "final:ios": "npm run final:www && npm run build:ios-release && npm run open:ios", + "final:android": "npm run final:www && npm run build:android-release && npm run run:android", + "final:desktop": "grunt desktop", + "sign:android": "rm -f platforms/android/build/outputs/apk/android-release-signed-aligned.apk; jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ../copay.keystore -signedjar platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-unsigned.apk copay_play && ../android-sdk-macosx/build-tools/21.1.1/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk", + "run:android": "cordova run android --device", + "log:android": "adb logcat | grep chromium", + "apply:copay": "cd app-template && node apply.js copay && cordova prepare", + "apply:bitpay": "cd app-template && node apply.js bitpay && cordova prepare", + "test": "./node_modules/.bin/grunt test-coveralls", + "clean": "trash platforms && trash plugins && cordova prepare", + "clean-all": "git clean -dfx && npm install" + }, + "devDependencies": { + "cordova": "^6.3.1", + "grunt": "^1.0.1", + "ionic": "^2.1.0", + "trash-cli": "^1.4.0", + "lodash": "^4.3.0" } } diff --git a/src/js/controllers/buyGlidera.js b/src/js/controllers/buyGlidera.js index e25612418..e15632185 100644 --- a/src/js/controllers/buyGlidera.js +++ b/src/js/controllers/buyGlidera.js @@ -139,7 +139,6 @@ angular.module('copayApp.controllers').controller('buyGlideraController', $scope.wallets = profileService.getWallets({ network: $scope.network, - n: 1, onlyComplete: true }); }); diff --git a/src/js/controllers/onboarding/notifications.js b/src/js/controllers/onboarding/notifications.js index be45c4bcb..0b315608f 100644 --- a/src/js/controllers/onboarding/notifications.js +++ b/src/js/controllers/onboarding/notifications.js @@ -1,14 +1,29 @@ 'use strict'; -angular.module('copayApp.controllers').controller('notificationsController', function($scope, $state, $timeout, $stateParams, $ionicConfig, profileService, configService) { +angular.module('copayApp.controllers').controller('notificationsController', function($scope, $state, $timeout, $stateParams, $ionicConfig, profileService, configService, $interval) { $ionicConfig.views.swipeBackEnabled(false); $scope.walletId = $stateParams.walletId; $scope.allowNotif = function() { + $scope.notificationDialogOpen = true; $timeout(function() { profileService.pushNotificationsInit(); }); + $scope.notificationPromise = $interval(function() { + PushNotification.hasPermission(function(data) { + if (data.isEnabled) { + $interval.cancel($scope.notificationPromise); + $state.go('onboarding.backupRequest', { + walletId: $scope.walletId + }); + } + }); + }, 100); + } + + $scope.continue = function() { + $interval.cancel($scope.notificationPromise); $state.go('onboarding.backupRequest', { walletId: $scope.walletId }); diff --git a/src/js/directives/directives.js b/src/js/directives/directives.js index ecf849b10..5334924f5 100644 --- a/src/js/directives/directives.js +++ b/src/js/directives/directives.js @@ -113,10 +113,13 @@ angular.module('copayApp.directives') } } }) - .directive('contact', ['addressbookService', 'lodash', - function(addressbookService, lodash) { + .directive('contact', ['addressbookService', 'lodash', 'gettextCatalog', + function(addressbookService, lodash, gettextCatalog) { return { restrict: 'E', + scope: { + label: '=' + }, link: function(scope, element, attrs) { var addr = attrs.address; addressbookService.get(addr, function(err, ab) { @@ -124,7 +127,11 @@ angular.module('copayApp.directives') var name = lodash.isObject(ab) ? ab.name : ab; element.append(name); } else { - element.append(addr); + if (scope.label && scope.label == 'Sent') { + element.append(gettextCatalog.getString('Sent')); + } else { + element.append(addr); + } } }); } diff --git a/src/js/directives/gravatar.js b/src/js/directives/gravatar.js index 2d28168d4..c76817b5e 100644 --- a/src/js/directives/gravatar.js +++ b/src/js/directives/gravatar.js @@ -12,9 +12,10 @@ angular.module('copayApp.directives') email: '@' }, link: function(scope, el, attr) { - scope.emailHash = md5.createHash(scope.email || ''); + if(typeof scope.email === "string"){ + scope.emailHash = md5.createHash(scope.email.toLowerCase() || ''); + } }, template: '{{ name }}' } }); - diff --git a/src/js/services/configService.js b/src/js/services/configService.js index 86a6031f4..c065a94bf 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -23,10 +23,10 @@ angular.module('copayApp.services').factory('configService', function(storageSer reconnectDelay: 5000, idleDurationMin: 4, settings: { - unitName: 'bits', + unitName: 'BTC', unitToSatoshi: 100, unitDecimals: 2, - unitCode: 'bit', + unitCode: 'btc', alternativeName: 'US Dollar', alternativeIsoCode: 'USD', } diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index de2c29e98..3c210bcbc 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -601,6 +601,16 @@ angular.module('copayApp.services') $log.debug('Importing Wallet:', opts); try { + var c = JSON.parse(str); + + if (c.xPrivKey && c.xPrivKeyEncrypted) { + $log.warn('Found both encrypted and decrypted key. Deleting the encrypted version'); + delete c.xPrivKeyEncrypted; + delete c.mnemonicEncrypted; + } + + str = JSON.stringify(c); + walletClient.import(str, { compressed: opts.compressed, password: opts.password @@ -609,14 +619,6 @@ angular.module('copayApp.services') return cb(gettext('Could not import. Check input file and spending password')); } - str = JSON.parse(str); - - if (str.xPrivKey && str.xPrivKeyEncrypted) { - $log.warn('Found both encrypted and decrypted key. Deleting the encrypted version'); - delete str.xPrivKeyEncrypted; - delete str.mnemonicEncrypted; - } - var addressBook = str.addressBook || {}; addAndBindWalletClient(walletClient, { diff --git a/src/sass/views/amount.scss b/src/sass/views/amount.scss index dc5c62a96..bc1573d4b 100644 --- a/src/sass/views/amount.scss +++ b/src/sass/views/amount.scss @@ -52,6 +52,9 @@ position: absolute; bottom: 254px; top: 66px; + .light { + color: #A4A4A4; + } } } @@ -84,7 +87,8 @@ .operator-send { font-weight: bolder; - background-color: #f7f7f7; + color: #f8f8f8; + background-color: #1e3186; font-size: 36px; cursor: pointer; diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index 30df5f1d0..8f087a9fc 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -1,6 +1,5 @@ #tab-home { .icon-create-wallet { - background-image: url("../img/icon-wallet.svg"); background-color: #4A90E2; // default wallet color } .icon-buy-bitcoin { @@ -16,19 +15,17 @@ .icon-amazon { background-image: url("../img/icon-amazon.svg"); } + .bg { + &.wallet{ + padding: .25rem + } + } .card{ .item { color: #444; border-top:none; padding-bottom: 1.5rem; padding-top:1.5rem; - &.wallet{ - .big-icon-svg{ - & > .bg{ - padding: .25rem - } - } - } } .item-sub { &:first-child:before { diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index f3eea2550..e54502fb7 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -1,3 +1,30 @@ +.wallet-details { + &__tx-amount { + font-size: 16px; + &--recent { + color: $mid-gray; + font-weight: bold; + } + &--received { + color: #30af6c; + } + &--sent { + color: $dark-gray; + } + } + &__tx-time { + color: $light-gray; + } + &__tx-title { + padding-top: 10px; + color: $dark-gray; + } + &__tx-icon { + float: left; + margin-right: 10px; + } +} + #walletDetails { .bar-header { border: 0; @@ -31,23 +58,8 @@ .item.item-footer { font-weight: lighter; } -} - -.wallet-details-release { - cursor: pointer; - cursor: hand; - background-color: #E9E9EC; - margin-top: -30px; - margin-bottom: 5px; - padding-top: 30px; - padding-bottom: 20px; - text-align: center; - text-color: #444; - span { - margin-left: 15px; - } - i { - margin-right: 15px; + .tx-search:before { + font-size: 22px !important; } } diff --git a/www/img/icon-tx-moved.svg b/www/img/icon-tx-moved.svg new file mode 100644 index 000000000..4f86c7722 --- /dev/null +++ b/www/img/icon-tx-moved.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/www/img/icon-tx-received.svg b/www/img/icon-tx-received.svg new file mode 100644 index 000000000..37d4d84c9 --- /dev/null +++ b/www/img/icon-tx-received.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/www/img/icon-tx-sent.svg b/www/img/icon-tx-sent.svg new file mode 100644 index 000000000..fc8148465 --- /dev/null +++ b/www/img/icon-tx-sent.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/www/views/amount.html b/www/views/amount.html index 29dd08a5d..11614da7a 100644 --- a/www/views/amount.html +++ b/www/views/amount.html @@ -35,15 +35,14 @@
-
{{amount || "0.00" }}
-
+
{{amount || "0.00" }}
+
{{globalResult}} {{amountResult || '0.00'}} {{alternativeIsoCode}}
{{globalResult}} {{alternativeResult || '0.00'}} {{unitName}}
-
diff --git a/www/views/buyAmazon.html b/www/views/buyAmazon.html index 8dc95908e..88cb917b0 100644 --- a/www/views/buyAmazon.html +++ b/www/views/buyAmazon.html @@ -33,7 +33,7 @@ ng-submit="buy.confirm()" novalidate> -
+