From 54e3545f6b4a5cedb8c883545d1ce105fdb590df Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 10 Aug 2016 15:29:31 -0300 Subject: [PATCH 1/3] First Bitpay Card Integration --- angular-bitcore-wallet-client/index.js | 2 + public/img/bitpay-card-visa.svg | 57 + public/img/bitpay-logo.svg | 1 + public/img/check.svg | 18 + public/img/mcc-icons/airplane.svg | 14 + public/img/mcc-icons/art.svg | 20 + public/img/mcc-icons/bicycle.svg | 21 + public/img/mcc-icons/bitcoin-topup.svg | 31 + public/img/mcc-icons/boat.svg | 17 + public/img/mcc-icons/books.svg | 27 + public/img/mcc-icons/bowling.svg | 19 + public/img/mcc-icons/bug.svg | 21 + public/img/mcc-icons/bus.svg | 21 + public/img/mcc-icons/camera.svg | 14 + public/img/mcc-icons/car.svg | 14 + public/img/mcc-icons/clean.svg | 21 + public/img/mcc-icons/clock.svg | 16 + public/img/mcc-icons/cocktail.svg | 14 + public/img/mcc-icons/coins.svg | 27 + public/img/mcc-icons/computer.svg | 21 + public/img/mcc-icons/default.svg | 20 + public/img/mcc-icons/diamond-ring.svg | 21 + public/img/mcc-icons/dollar-topup.svg | 21 + public/img/mcc-icons/euro-topup.svg | 24 + public/img/mcc-icons/film.svg | 27 + public/img/mcc-icons/food.svg | 23 + public/img/mcc-icons/football.svg | 18 + public/img/mcc-icons/furniture.svg | 26 + public/img/mcc-icons/game.svg | 21 + public/img/mcc-icons/gas.svg | 14 + public/img/mcc-icons/golf.svg | 22 + public/img/mcc-icons/hotel.svg | 30 + public/img/mcc-icons/law.svg | 21 + public/img/mcc-icons/mail.svg | 14 + public/img/mcc-icons/medical.svg | 20 + public/img/mcc-icons/money.svg | 19 + public/img/mcc-icons/motorcycle.svg | 17 + public/img/mcc-icons/music.svg | 20 + public/img/mcc-icons/newspaper.svg | 14 + public/img/mcc-icons/park.svg | 19 + public/img/mcc-icons/people.svg | 17 + public/img/mcc-icons/pet.svg | 20 + public/img/mcc-icons/plant.svg | 20 + public/img/mcc-icons/purchase.svg | 20 + public/img/mcc-icons/repair.svg | 16 + public/img/mcc-icons/sadface.svg | 20 + public/img/mcc-icons/scissors.svg | 19 + public/img/mcc-icons/search.svg | 17 + public/img/mcc-icons/shirt.svg | 21 + public/img/mcc-icons/shoes.svg | 18 + public/img/mcc-icons/smiley-face.svg | 19 + public/img/mcc-icons/suitcase.svg | 25 + public/img/mcc-icons/telephone.svg | 14 + public/img/mcc-icons/television.svg | 21 + public/img/mcc-icons/tent.svg | 20 + public/img/mcc-icons/ticket.svg | 18 + public/img/mcc-icons/toy.svg | 23 + public/img/mcc-icons/truck.svg | 24 + public/img/mcc-icons/watch.svg | 20 + public/img/sync.svg | 18 + public/views/bitpayCard.html | 274 ++++ public/views/includes/sidebar.html | 7 + .../modals/bitpay-card-confirmation.html | 18 + public/views/preferencesBitpayCard.html | 19 + src/js/controllers/bitpayCard.js | 364 +++++ .../modals/bitpayCardConfirmation.js | 16 + src/js/controllers/preferencesBitpayCard.js | 16 + src/js/routes.js | 20 + src/js/services/bitpayCardService.js | 1226 +++++++++++++++++ src/js/services/storageService.js | 12 + src/sass/main.scss | 12 + 71 files changed, 3181 insertions(+) create mode 100644 public/img/bitpay-card-visa.svg create mode 100644 public/img/bitpay-logo.svg create mode 100644 public/img/check.svg create mode 100644 public/img/mcc-icons/airplane.svg create mode 100644 public/img/mcc-icons/art.svg create mode 100644 public/img/mcc-icons/bicycle.svg create mode 100644 public/img/mcc-icons/bitcoin-topup.svg create mode 100644 public/img/mcc-icons/boat.svg create mode 100644 public/img/mcc-icons/books.svg create mode 100644 public/img/mcc-icons/bowling.svg create mode 100644 public/img/mcc-icons/bug.svg create mode 100644 public/img/mcc-icons/bus.svg create mode 100644 public/img/mcc-icons/camera.svg create mode 100644 public/img/mcc-icons/car.svg create mode 100644 public/img/mcc-icons/clean.svg create mode 100644 public/img/mcc-icons/clock.svg create mode 100644 public/img/mcc-icons/cocktail.svg create mode 100644 public/img/mcc-icons/coins.svg create mode 100644 public/img/mcc-icons/computer.svg create mode 100644 public/img/mcc-icons/default.svg create mode 100644 public/img/mcc-icons/diamond-ring.svg create mode 100644 public/img/mcc-icons/dollar-topup.svg create mode 100644 public/img/mcc-icons/euro-topup.svg create mode 100644 public/img/mcc-icons/film.svg create mode 100644 public/img/mcc-icons/food.svg create mode 100644 public/img/mcc-icons/football.svg create mode 100644 public/img/mcc-icons/furniture.svg create mode 100644 public/img/mcc-icons/game.svg create mode 100644 public/img/mcc-icons/gas.svg create mode 100644 public/img/mcc-icons/golf.svg create mode 100644 public/img/mcc-icons/hotel.svg create mode 100644 public/img/mcc-icons/law.svg create mode 100644 public/img/mcc-icons/mail.svg create mode 100644 public/img/mcc-icons/medical.svg create mode 100644 public/img/mcc-icons/money.svg create mode 100644 public/img/mcc-icons/motorcycle.svg create mode 100644 public/img/mcc-icons/music.svg create mode 100644 public/img/mcc-icons/newspaper.svg create mode 100644 public/img/mcc-icons/park.svg create mode 100644 public/img/mcc-icons/people.svg create mode 100644 public/img/mcc-icons/pet.svg create mode 100644 public/img/mcc-icons/plant.svg create mode 100644 public/img/mcc-icons/purchase.svg create mode 100644 public/img/mcc-icons/repair.svg create mode 100644 public/img/mcc-icons/sadface.svg create mode 100644 public/img/mcc-icons/scissors.svg create mode 100644 public/img/mcc-icons/search.svg create mode 100644 public/img/mcc-icons/shirt.svg create mode 100644 public/img/mcc-icons/shoes.svg create mode 100644 public/img/mcc-icons/smiley-face.svg create mode 100644 public/img/mcc-icons/suitcase.svg create mode 100644 public/img/mcc-icons/telephone.svg create mode 100644 public/img/mcc-icons/television.svg create mode 100644 public/img/mcc-icons/tent.svg create mode 100644 public/img/mcc-icons/ticket.svg create mode 100644 public/img/mcc-icons/toy.svg create mode 100644 public/img/mcc-icons/truck.svg create mode 100644 public/img/mcc-icons/watch.svg create mode 100644 public/img/sync.svg create mode 100644 public/views/bitpayCard.html create mode 100644 public/views/modals/bitpay-card-confirmation.html create mode 100644 public/views/preferencesBitpayCard.html create mode 100644 src/js/controllers/bitpayCard.js create mode 100644 src/js/controllers/modals/bitpayCardConfirmation.js create mode 100644 src/js/controllers/preferencesBitpayCard.js create mode 100644 src/js/services/bitpayCardService.js diff --git a/angular-bitcore-wallet-client/index.js b/angular-bitcore-wallet-client/index.js index a7d0c09d6..4174e65e1 100644 --- a/angular-bitcore-wallet-client/index.js +++ b/angular-bitcore-wallet-client/index.js @@ -1,5 +1,6 @@ var bwcModule = angular.module('bwcModule', []); var Client = require('../node_modules/bitcore-wallet-client'); +var pbkdf2Sync = require('pbkdf2').pbkdf2Sync; bwcModule.constant('MODULE_VERSION', '1.0.0'); @@ -24,6 +25,7 @@ bwcModule.provider("bwcService", function() { service.buildTx = Client.buildTx; service.parseSecret = Client.parseSecret; service.Client = Client; + service.pbkdf2Sync = pbkdf2Sync; service.getUtils = function() { return Client.Utils; diff --git a/public/img/bitpay-card-visa.svg b/public/img/bitpay-card-visa.svg new file mode 100644 index 000000000..ce5375715 --- /dev/null +++ b/public/img/bitpay-card-visa.svg @@ -0,0 +1,57 @@ + + + + bp-card + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/bitpay-logo.svg b/public/img/bitpay-logo.svg new file mode 100644 index 000000000..158e539c8 --- /dev/null +++ b/public/img/bitpay-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/check.svg b/public/img/check.svg new file mode 100644 index 000000000..23fdb8be7 --- /dev/null +++ b/public/img/check.svg @@ -0,0 +1,18 @@ + + + + DF90EF75-F651-4B5A-9143-4512A3D52EC8 + Created with sketchtool. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/airplane.svg b/public/img/mcc-icons/airplane.svg new file mode 100644 index 000000000..1d096a5f1 --- /dev/null +++ b/public/img/mcc-icons/airplane.svg @@ -0,0 +1,14 @@ + + + + airplane + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/art.svg b/public/img/mcc-icons/art.svg new file mode 100644 index 000000000..399d09c7d --- /dev/null +++ b/public/img/mcc-icons/art.svg @@ -0,0 +1,20 @@ + + + + art + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/bicycle.svg b/public/img/mcc-icons/bicycle.svg new file mode 100644 index 000000000..2460bfc20 --- /dev/null +++ b/public/img/mcc-icons/bicycle.svg @@ -0,0 +1,21 @@ + + + + bicycle + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/bitcoin-topup.svg b/public/img/mcc-icons/bitcoin-topup.svg new file mode 100644 index 000000000..17c97917c --- /dev/null +++ b/public/img/mcc-icons/bitcoin-topup.svg @@ -0,0 +1,31 @@ + + + + bitcoin-topup + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/boat.svg b/public/img/mcc-icons/boat.svg new file mode 100644 index 000000000..4c4df0585 --- /dev/null +++ b/public/img/mcc-icons/boat.svg @@ -0,0 +1,17 @@ + + + + boat + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/books.svg b/public/img/mcc-icons/books.svg new file mode 100644 index 000000000..ef2d319eb --- /dev/null +++ b/public/img/mcc-icons/books.svg @@ -0,0 +1,27 @@ + + + + books + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/bowling.svg b/public/img/mcc-icons/bowling.svg new file mode 100644 index 000000000..c3d438dc8 --- /dev/null +++ b/public/img/mcc-icons/bowling.svg @@ -0,0 +1,19 @@ + + + + bowling + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/bug.svg b/public/img/mcc-icons/bug.svg new file mode 100644 index 000000000..6cea4c70e --- /dev/null +++ b/public/img/mcc-icons/bug.svg @@ -0,0 +1,21 @@ + + + + bug + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/bus.svg b/public/img/mcc-icons/bus.svg new file mode 100644 index 000000000..bb32445e9 --- /dev/null +++ b/public/img/mcc-icons/bus.svg @@ -0,0 +1,21 @@ + + + + bus + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/camera.svg b/public/img/mcc-icons/camera.svg new file mode 100644 index 000000000..9abb6dc75 --- /dev/null +++ b/public/img/mcc-icons/camera.svg @@ -0,0 +1,14 @@ + + + + camera + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/car.svg b/public/img/mcc-icons/car.svg new file mode 100644 index 000000000..299164f0f --- /dev/null +++ b/public/img/mcc-icons/car.svg @@ -0,0 +1,14 @@ + + + + car + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/clean.svg b/public/img/mcc-icons/clean.svg new file mode 100644 index 000000000..2ca8b4179 --- /dev/null +++ b/public/img/mcc-icons/clean.svg @@ -0,0 +1,21 @@ + + + + clean + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/clock.svg b/public/img/mcc-icons/clock.svg new file mode 100644 index 000000000..2fd640f72 --- /dev/null +++ b/public/img/mcc-icons/clock.svg @@ -0,0 +1,16 @@ + + + + clock + Created with Sketch. + + + + + + clock + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/cocktail.svg b/public/img/mcc-icons/cocktail.svg new file mode 100644 index 000000000..c332c169c --- /dev/null +++ b/public/img/mcc-icons/cocktail.svg @@ -0,0 +1,14 @@ + + + + cocktail + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/coins.svg b/public/img/mcc-icons/coins.svg new file mode 100644 index 000000000..692866c8e --- /dev/null +++ b/public/img/mcc-icons/coins.svg @@ -0,0 +1,27 @@ + + + + coins + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/computer.svg b/public/img/mcc-icons/computer.svg new file mode 100644 index 000000000..a897e1644 --- /dev/null +++ b/public/img/mcc-icons/computer.svg @@ -0,0 +1,21 @@ + + + + computer + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/default.svg b/public/img/mcc-icons/default.svg new file mode 100644 index 000000000..379fa3d0c --- /dev/null +++ b/public/img/mcc-icons/default.svg @@ -0,0 +1,20 @@ + + + + default + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/diamond-ring.svg b/public/img/mcc-icons/diamond-ring.svg new file mode 100644 index 000000000..380d77351 --- /dev/null +++ b/public/img/mcc-icons/diamond-ring.svg @@ -0,0 +1,21 @@ + + + + diamond-ring + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/dollar-topup.svg b/public/img/mcc-icons/dollar-topup.svg new file mode 100644 index 000000000..06d7eef77 --- /dev/null +++ b/public/img/mcc-icons/dollar-topup.svg @@ -0,0 +1,21 @@ + + + + dollar-topup + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/euro-topup.svg b/public/img/mcc-icons/euro-topup.svg new file mode 100644 index 000000000..30f2782a1 --- /dev/null +++ b/public/img/mcc-icons/euro-topup.svg @@ -0,0 +1,24 @@ + + + + euro-topup + Created with Sketch. + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/film.svg b/public/img/mcc-icons/film.svg new file mode 100644 index 000000000..c66e4cbed --- /dev/null +++ b/public/img/mcc-icons/film.svg @@ -0,0 +1,27 @@ + + + + film + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/food.svg b/public/img/mcc-icons/food.svg new file mode 100644 index 000000000..d78db31fc --- /dev/null +++ b/public/img/mcc-icons/food.svg @@ -0,0 +1,23 @@ + + + + food + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/football.svg b/public/img/mcc-icons/football.svg new file mode 100644 index 000000000..b790ee7eb --- /dev/null +++ b/public/img/mcc-icons/football.svg @@ -0,0 +1,18 @@ + + + + football + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/furniture.svg b/public/img/mcc-icons/furniture.svg new file mode 100644 index 000000000..0ad767826 --- /dev/null +++ b/public/img/mcc-icons/furniture.svg @@ -0,0 +1,26 @@ + + + + furniture + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/game.svg b/public/img/mcc-icons/game.svg new file mode 100644 index 000000000..b8c90ab5a --- /dev/null +++ b/public/img/mcc-icons/game.svg @@ -0,0 +1,21 @@ + + + + game + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/gas.svg b/public/img/mcc-icons/gas.svg new file mode 100644 index 000000000..8d4fb7cba --- /dev/null +++ b/public/img/mcc-icons/gas.svg @@ -0,0 +1,14 @@ + + + + gas + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/golf.svg b/public/img/mcc-icons/golf.svg new file mode 100644 index 000000000..eb8702e83 --- /dev/null +++ b/public/img/mcc-icons/golf.svg @@ -0,0 +1,22 @@ + + + + golf + Created with Sketch. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/hotel.svg b/public/img/mcc-icons/hotel.svg new file mode 100644 index 000000000..1e38d1b1c --- /dev/null +++ b/public/img/mcc-icons/hotel.svg @@ -0,0 +1,30 @@ + + + + hotel + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/law.svg b/public/img/mcc-icons/law.svg new file mode 100644 index 000000000..b43462266 --- /dev/null +++ b/public/img/mcc-icons/law.svg @@ -0,0 +1,21 @@ + + + + law + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/mail.svg b/public/img/mcc-icons/mail.svg new file mode 100644 index 000000000..058276221 --- /dev/null +++ b/public/img/mcc-icons/mail.svg @@ -0,0 +1,14 @@ + + + + mail + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/medical.svg b/public/img/mcc-icons/medical.svg new file mode 100644 index 000000000..10b986d54 --- /dev/null +++ b/public/img/mcc-icons/medical.svg @@ -0,0 +1,20 @@ + + + + medical + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/money.svg b/public/img/mcc-icons/money.svg new file mode 100644 index 000000000..74477aacb --- /dev/null +++ b/public/img/mcc-icons/money.svg @@ -0,0 +1,19 @@ + + + + money + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/motorcycle.svg b/public/img/mcc-icons/motorcycle.svg new file mode 100644 index 000000000..ef452c618 --- /dev/null +++ b/public/img/mcc-icons/motorcycle.svg @@ -0,0 +1,17 @@ + + + + motorcycle + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/music.svg b/public/img/mcc-icons/music.svg new file mode 100644 index 000000000..ec9916802 --- /dev/null +++ b/public/img/mcc-icons/music.svg @@ -0,0 +1,20 @@ + + + + music + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/newspaper.svg b/public/img/mcc-icons/newspaper.svg new file mode 100644 index 000000000..041f29c87 --- /dev/null +++ b/public/img/mcc-icons/newspaper.svg @@ -0,0 +1,14 @@ + + + + newspaper + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/park.svg b/public/img/mcc-icons/park.svg new file mode 100644 index 000000000..2cf0741bf --- /dev/null +++ b/public/img/mcc-icons/park.svg @@ -0,0 +1,19 @@ + + + + park + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/people.svg b/public/img/mcc-icons/people.svg new file mode 100644 index 000000000..55949d8a0 --- /dev/null +++ b/public/img/mcc-icons/people.svg @@ -0,0 +1,17 @@ + + + + people + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/pet.svg b/public/img/mcc-icons/pet.svg new file mode 100644 index 000000000..49a4197fd --- /dev/null +++ b/public/img/mcc-icons/pet.svg @@ -0,0 +1,20 @@ + + + + pet + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/plant.svg b/public/img/mcc-icons/plant.svg new file mode 100644 index 000000000..1c4af2748 --- /dev/null +++ b/public/img/mcc-icons/plant.svg @@ -0,0 +1,20 @@ + + + + plant + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/purchase.svg b/public/img/mcc-icons/purchase.svg new file mode 100644 index 000000000..5a24fc1b0 --- /dev/null +++ b/public/img/mcc-icons/purchase.svg @@ -0,0 +1,20 @@ + + + + purchase + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/repair.svg b/public/img/mcc-icons/repair.svg new file mode 100644 index 000000000..3904d394e --- /dev/null +++ b/public/img/mcc-icons/repair.svg @@ -0,0 +1,16 @@ + + + + repair + Created with Sketch. + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/sadface.svg b/public/img/mcc-icons/sadface.svg new file mode 100644 index 000000000..a1ad7bea8 --- /dev/null +++ b/public/img/mcc-icons/sadface.svg @@ -0,0 +1,20 @@ + + + + sadface + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/scissors.svg b/public/img/mcc-icons/scissors.svg new file mode 100644 index 000000000..7a4ed1519 --- /dev/null +++ b/public/img/mcc-icons/scissors.svg @@ -0,0 +1,19 @@ + + + + scissors + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/search.svg b/public/img/mcc-icons/search.svg new file mode 100644 index 000000000..b77d2e5af --- /dev/null +++ b/public/img/mcc-icons/search.svg @@ -0,0 +1,17 @@ + + + + search + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/shirt.svg b/public/img/mcc-icons/shirt.svg new file mode 100644 index 000000000..2acdc5b0b --- /dev/null +++ b/public/img/mcc-icons/shirt.svg @@ -0,0 +1,21 @@ + + + + shirt + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/shoes.svg b/public/img/mcc-icons/shoes.svg new file mode 100644 index 000000000..f57f49f15 --- /dev/null +++ b/public/img/mcc-icons/shoes.svg @@ -0,0 +1,18 @@ + + + + shoes + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/smiley-face.svg b/public/img/mcc-icons/smiley-face.svg new file mode 100644 index 000000000..847e7ec7e --- /dev/null +++ b/public/img/mcc-icons/smiley-face.svg @@ -0,0 +1,19 @@ + + + + smiley-face + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/suitcase.svg b/public/img/mcc-icons/suitcase.svg new file mode 100644 index 000000000..af48e1730 --- /dev/null +++ b/public/img/mcc-icons/suitcase.svg @@ -0,0 +1,25 @@ + + + + business-48px-outline_briefcase-25 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/telephone.svg b/public/img/mcc-icons/telephone.svg new file mode 100644 index 000000000..2460721f9 --- /dev/null +++ b/public/img/mcc-icons/telephone.svg @@ -0,0 +1,14 @@ + + + + telephone + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/television.svg b/public/img/mcc-icons/television.svg new file mode 100644 index 000000000..1dd0dac55 --- /dev/null +++ b/public/img/mcc-icons/television.svg @@ -0,0 +1,21 @@ + + + + television + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/tent.svg b/public/img/mcc-icons/tent.svg new file mode 100644 index 000000000..ba19f2dd1 --- /dev/null +++ b/public/img/mcc-icons/tent.svg @@ -0,0 +1,20 @@ + + + + tent + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/ticket.svg b/public/img/mcc-icons/ticket.svg new file mode 100644 index 000000000..cf81a1272 --- /dev/null +++ b/public/img/mcc-icons/ticket.svg @@ -0,0 +1,18 @@ + + + + ticket + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/toy.svg b/public/img/mcc-icons/toy.svg new file mode 100644 index 000000000..370b15622 --- /dev/null +++ b/public/img/mcc-icons/toy.svg @@ -0,0 +1,23 @@ + + + + toy + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/truck.svg b/public/img/mcc-icons/truck.svg new file mode 100644 index 000000000..8bb2f9818 --- /dev/null +++ b/public/img/mcc-icons/truck.svg @@ -0,0 +1,24 @@ + + + + truck + Created with Sketch. + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/mcc-icons/watch.svg b/public/img/mcc-icons/watch.svg new file mode 100644 index 000000000..1b4ad96c7 --- /dev/null +++ b/public/img/mcc-icons/watch.svg @@ -0,0 +1,20 @@ + + + + watch + Created with Sketch. + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/img/sync.svg b/public/img/sync.svg new file mode 100644 index 000000000..ec32e621a --- /dev/null +++ b/public/img/sync.svg @@ -0,0 +1,18 @@ + + + + 1218C029-D515-4006-B1E3-E919177035E2 + Created with sketchtool. + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/views/bitpayCard.html b/public/views/bitpayCard.html new file mode 100644 index 000000000..d760655e7 --- /dev/null +++ b/public/views/bitpayCard.html @@ -0,0 +1,274 @@ +
+
+ +
+ +
+ +
+ + Sandbox version. Only for testing purpose +
+ +
+ Loading... +
+ +
+
+
+ +
+

+ Login to your account + 2-Step Verification +

+
+ {{bitpayCard.error}} +
+ +
+ + + + + +
+ +
+
+ +

+ Enter the verification code generated by the authenticator app on your phone. +

+ +
+ + + +
+ +
+
+
+
+ +
+
+
+
+ ${{bitpayCard.bitpayCardCurrentBalance}} +
Available balance
+
+
+ ... +
+
+
+ + + +
+
+ + + +
+ {{bitpayCard.error}} +
+ +
+ No transactions yet +
+ +
+ +
+ +
+
+ +
+ +
+
+ {{tx.merchant.name}} +
+
+ {{tx.merchant.city}}, {{tx.merchant.state}} +
+
+
+ {{desc}} +
+
+ + +
+
+
+ {{tx.amount | currency:'$':2 }} +
+ +
+
+
+ +
+
+
+ {{bitpayCard.error}} +
+
+ + + + +
+ + + + +
+ +

+ You selected a multisignature wallet. Please note that the transaction will only appear on your card's + Activity when the payment is fully signed. +

+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
diff --git a/public/views/includes/sidebar.html b/public/views/includes/sidebar.html index 21d6ca123..909d7f176 100644 --- a/public/views/includes/sidebar.html +++ b/public/views/includes/sidebar.html @@ -23,6 +23,13 @@
Create, join or import
+
  • + + +
    + BitPay Card +
    +
  • diff --git a/public/views/modals/bitpay-card-confirmation.html b/public/views/modals/bitpay-card-confirmation.html new file mode 100644 index 000000000..6d6160bb4 --- /dev/null +++ b/public/views/modals/bitpay-card-confirmation.html @@ -0,0 +1,18 @@ + +
    +
    +

    Are you sure you would like to log out of your Bitpay Card account?

    +

    You will need to log back for fill in your Bitpay Card.

    +
    + +
    +
    + +
    +
    +
    +
    diff --git a/public/views/preferencesBitpayCard.html b/public/views/preferencesBitpayCard.html new file mode 100644 index 000000000..01551563a --- /dev/null +++ b/public/views/preferencesBitpayCard.html @@ -0,0 +1,19 @@ +
    +
    + +
    + +
      +

      +
    • + + Log out +
    • +
    +

    + +
    +
    diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js new file mode 100644 index 000000000..132c43b6e --- /dev/null +++ b/src/js/controllers/bitpayCard.js @@ -0,0 +1,364 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $rootScope, $timeout, $log, $ionicModal, lodash, bitpayCardService, configService, profileService, walletService, fingerprintService, ongoingProcess, bwcError, bitcore, bwcService, moment, platformInfo) { + + var self = this; + var client; + + var network = 'livenet'; + self.sandbox = network == 'testnet' ? true : false; + + if (platformInfo.isCordova && StatusBar.isVisible) { + StatusBar.backgroundColorByHexString("#4B6178"); + } + + var handleEncryptedWallet = function(client, cb) { + if (!walletService.isEncrypted(client)) return cb(); + $rootScope.$emit('Local/NeedsPassword', false, function(err, password) { + if (err) return cb(err); + return cb(walletService.unlock(client, password)); + }); + }; + + var processTransactions = function(invoices, history) { + for (var i = 0; i < invoices.length; i++) { + var matched = false; + for (var j = 0; j < history.length; j++) { + if (history[j].description[0].indexOf(invoices[i].id) > -1) { + matched = true; + } + } + if (!matched && ['paid', 'confirmed', 'complete'].indexOf(invoices[i].status) > -1) { + + history.unshift({ + timestamp: invoices[i].invoiceTime, + description: invoices[i].itemDesc, + amount: invoices[i].price, + type: '00611 = Client Funded Deposit', + pending: true, + status: invoices[i].status + }); + } + } + return history; + }; + + var setDateRange = function(preset) { + var startDate, endDate; + preset = preset || 'last30Days'; + switch(preset) { + case 'last30Days': + startDate = moment().subtract(30, 'days').toISOString(); + endDate = moment().toISOString(); + break; + case 'lastMonth': + startDate = moment().startOf('month').subtract(1, 'month').toISOString(); + endDate = moment().startOf('month').toISOString(); + break; + case 'all': + startDate = null; + endDate = null; + break; + default: + return; + } + return { + startDate: startDate, + endDate: endDate + }; + }; + + this.update = function() { + var dateRange = setDateRange($scope.dateRange); + self.loadingSession = true; + bitpayCardService.setCredentials(network); + bitpayCardService.isAuthenticated(function(err, bpSession) { + self.loadingSession = false; + if (err) { + self.error = err.data.error || 'Incorrect email or password'; + return; + } + + self.bitpayCardAuthenticated = bpSession.isAuthenticated; + self.bitpayCardTwoFactorPending = bpSession.twoFactorPending ? true : false; + + if (self.bitpayCardTwoFactorPending) return; + + if (self.bitpayCardAuthenticated) { + $scope.loadingHistory = true; + bitpayCardService.invoiceHistory(function(err, invoices) { + if (err) $log.error(err); + bitpayCardService.transactionHistory(dateRange, function(err, history) { + $scope.loadingHistory = false; + if (err) { + self.error = err; + return; + } + + self.bitpayCardTransactionHistory = processTransactions(invoices, history.transactionList); + self.bitpayCardCurrentBalance = history.currentCardBalance; + }); + }); + } + $timeout(function() { + $scope.$apply(); + }); + }); + }; + + this.init = function() { + $scope.dateRange = 'last30Days'; + self.update(); + + self.allWallets = profileService.getWallets(network); + client = profileService.focusedClient; + + if (!client) return; + + if (lodash.isEmpty(self.allWallets)) return; + + if (client.credentials.network != network) return; + + if (client.credentials.n > 1) + self.isMultisigWallet = true; + + $timeout(function() { + self.selectedWalletId = client.credentials.walletId; + self.selectedWalletName = client.credentials.walletName; + $scope.$apply(); + }, 100); + }; + + $scope.openWalletsModal = function(wallets) { + self.error = null; + + $scope.wallets = wallets; + $scope.noColor = true; + $scope.self = self; + + $ionicModal.fromTemplateUrl('views/modals/wallets.html', { + scope: $scope, + animation: 'slide-in-up' + }).then(function(modal) { + $scope.walletsModal = modal; + $scope.walletsModal.show(); + }); + + $scope.$on('walletSelected', function(ev, walletId) { + $timeout(function() { + client = profileService.getClient(walletId); + self.isMultisigWallet = false; + self.selectedWalletId = walletId; + self.selectedWalletName = client.credentials.walletName; + if (client.credentials.n > 1) + self.isMultisigWallet = true; + $scope.$apply(); + }, 100); + $scope.walletsModal.hide(); + }); + }; + + this.sendFunds = function() { + self.error = null; + + var dataSrc = { + amount: $scope.fiat, + currency: 'USD' + }; + var outputs = []; + var config = configService.getSync(); + var configWallet = config.wallet; + var walletSettings = configWallet.settings; + + + ongoingProcess.set('Processing Transaction...', true); + $timeout(function() { + + bitpayCardService.topUp(dataSrc, function(err, invoiceId) { + if (err) { + ongoingProcess.set('Processing Transaction...', false); + self.error = bwcError.msg(err); + $timeout(function() { + $scope.$digest(); + }); + return; + } + + bitpayCardService.getInvoice(invoiceId, function(err, data) { + var address, comment, amount; + + address = data.bitcoinAddress; + amount = parseInt((data.btcPrice * 100000000).toFixed(0)); + comment = data.itemDesc; + + outputs.push({ + 'toAddress': address, + 'amount': amount, + 'message': comment + }); + + var txp = { + toAddress: address, + amount: amount, + outputs: outputs, + message: comment, + payProUrl: null, + excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true, + feeLevel: walletSettings.feeLevel || 'normal' + }; + + walletService.createTx(client, txp, function(err, createdTxp) { + ongoingProcess.set('Processing Transaction...', false); + if (err) { + self.error = bwcError.msg(err); + $timeout(function() { + $scope.$digest(); + }); + return; + } + $scope.$emit('Local/NeedsConfirmation', createdTxp, function(accept) { + if (accept) { + self.confirmTx(createdTxp, function(err, tx) { + ongoingProcess.set('Processing Transaction...', false); + if (err) { + self.error = bwcError.msg(err); + $timeout(function() { + $scope.$digest(); + }); + return; + } + self.update(); + $scope.addFunds = false; + $timeout(function() { + $scope.$digest(); + }); + }); + } + }); + }); + }); + }); + }, 100); + }; + + this.confirmTx = function(txp, cb) { + + fingerprintService.check(client, function(err) { + if (err) { + $log.debug(err); + return cb(err); + } + + handleEncryptedWallet(client, function(err) { + if (err) { + $log.debug(err); + return bwcError.cb(err, null, cb); + } + + ongoingProcess.set('Processing Transaction...', true); + walletService.publishTx(client, txp, function(err, publishedTxp) { + if (err) { + $log.debug(err); + return bwcError.cb(err, null, cb); + } + + walletService.signTx(client, publishedTxp, function(err, signedTxp) { + walletService.lock(client); + if (err) { + $log.debug(err); + walletService.removeTx(client, signedTxp, function(err) { + if (err) $log.debug(err); + }); + return bwcError.cb(err, null, cb); + } + + walletService.broadcastTx(client, signedTxp, function(err, broadcastedTxp) { + if (err) { + $log.debug(err); + walletService.removeTx(client, broadcastedTxp, function(err) { + if (err) $log.debug(err); + }); + return bwcError.cb(err, null, cb); + } + $timeout(function() { + return cb(null, broadcastedTxp); + }, 5000); + }); + }); + }); + }); + }); + }; + + this.authenticate = function() { + self.error = null; + + var data = { + emailAddress : $scope.email, + hashedPassword : bwcService.pbkdf2Sync($scope.password, '..............', 200, 64).toString('hex') + }; + + // POST /authenticate + // emailAddress: + // hashedPassword: + self.authenticating = true; + bitpayCardService.authenticate(data, function(err, auth) { + self.authenticating = false; + if (err && !err.data.error.twoFactorPending) { + self.error = 'Authentiation error'; + return; + } + + self.update(); + $timeout(function() { + $scope.$apply(); + }, 100); + }); + }; + + this.authenticate2FA = function() { + self.error = null; + + var data = { + twoFactorCode : $scope.twoFactorCode + }; + + self.authenticating = true; + bitpayCardService.authenticate2FA(data, function(err, auth) { + self.authenticating = false; + if (err) { + self.error = 'Authentiation error'; + return; + } + + self.update(); + $timeout(function() { + $scope.$apply(); + }, 100); + }); + }; + + this.getMerchantInfo = function(tx) { + var bpTranCodes = bitpayCardService.bpTranCodes; + lodash.keys(bpTranCodes).forEach(function(code) { + if (tx.type.indexOf(code) === 0) { + lodash.assign(tx, bpTranCodes[code]); + } + }); + }; + + this.getIconName = function(tx) { + var icon = tx.mcc || tx.category || null; + if (!icon) return 'default'; + return bitpayCardService.iconMap[icon]; + }; + + this.processDescription = function(tx) { + if (lodash.isArray(tx.description)) { + return tx.description[0]; + } + return tx.description; + }; + +}); + diff --git a/src/js/controllers/modals/bitpayCardConfirmation.js b/src/js/controllers/modals/bitpayCardConfirmation.js new file mode 100644 index 000000000..2ac75c25f --- /dev/null +++ b/src/js/controllers/modals/bitpayCardConfirmation.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('bitpayCardConfirmationController', function($scope, $timeout, go, bitpayCardService) { + + $scope.ok = function() { + bitpayCardService.logout(function() { + go.path('bitpayCard'); + }); + $scope.cancel(); + }; + + $scope.cancel = function() { + $scope.bitpayCardConfirmationModal.hide(); + }; + +}); diff --git a/src/js/controllers/preferencesBitpayCard.js b/src/js/controllers/preferencesBitpayCard.js new file mode 100644 index 000000000..991d91c74 --- /dev/null +++ b/src/js/controllers/preferencesBitpayCard.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('preferencesBitpayCardController', + function($scope, $ionicModal, bitpayCardService) { + + this.logout = function() { + $ionicModal.fromTemplateUrl('views/modals/bitpay-card-confirmation.html', { + scope: $scope, + animation: 'slide-in-up' + }).then(function(modal) { + $scope.bitpayCardConfirmationModal = modal; + $scope.bitpayCardConfirmationModal.show(); + }); + }; + + }); diff --git a/src/js/routes.js b/src/js/routes.js index 0d3879998..f26417545 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -257,6 +257,26 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }, } }) + .state('bitpayCard', { + url: '/bitpay-card', + walletShouldBeComplete: true, + needProfile: true, + views: { + 'main': { + templateUrl: 'views/bitpayCard.html' + }, + } + }) + .state('preferencesBitpayCard', { + url: '/preferences-bitpay-card', + walletShouldBeComplete: true, + needProfile: true, + views: { + 'main': { + templateUrl: 'views/preferencesBitpayCard.html' + }, + } + }) .state('coinbase', { url: '/coinbase', walletShouldBeComplete: true, diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js new file mode 100644 index 000000000..6abbb1fcc --- /dev/null +++ b/src/js/services/bitpayCardService.js @@ -0,0 +1,1226 @@ +'use strict'; + +angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService) { + var root = {}; + var credentials = {}; + var bpSession = {}; + + root.setCredentials = function(network) { + credentials.NETWORK = network; + if (network == 'testnet') { + credentials.BITPAY_API_URL = 'https://test.bitpay.com'; + } + else { + credentials.BITPAY_API_URL = 'https://bitpay.com'; + }; + }; + + var _getUser = function(cb) { + storageService.getBitpayCard(credentials.NETWORK, function(err, user) { + if (err) return cb(err); + if (lodash.isString(user)) { + user = JSON.parse(user); + } + return cb(null, user); + }); + }; + + var _setUser = function(user, cb) { + user = JSON.stringify(user); + storageService.setBitpayCard(credentials.NETWORK, user, function(err) { + return cb(err); + }); + }; + + var _getSession = function(cb) { + $http({ + method: 'GET', + url: credentials.BITPAY_API_URL + '/visa-api/session', + headers: { + 'content-type': 'application/json' + } + }).then(function(data) { + $log.info('BitPay Get Session: SUCCESS'); + bpSession = data.data.data; + return cb(null, bpSession); + }, function(data) { + $log.error('BitPay Get Session: ERROR ' + data.data.error); + return cb(data.data.error); + }); + }; + + var _getBitPay = function(endpoint) { + return { + method: 'GET', + url: credentials.BITPAY_API_URL + endpoint, + headers: { + 'content-type': 'application/json', + 'x-csrf-token': bpSession.csrfToken + } + }; + }; + + var _postBitPay = function(endpoint, data) { + return { + method: 'POST', + url: credentials.BITPAY_API_URL + endpoint, + headers: { + 'Content-Type': 'application/json', + 'x-csrf-token': bpSession.csrfToken + }, + data: data + }; + }; + + root.topUp = function(data, cb) { + var dataSrc = { + amount: data.amount, + currency: data.currency + }; + $http(_postBitPay('/visa-api/topUp', dataSrc)).then(function(data) { + $log.info('BitPay TopUp: SUCCESS'); + return cb(null, data.data.data.invoice); + }, function(data) { + $log.error('BitPay TopUp: ERROR ' + data.data.error); + return cb(data.data.error); + }); + }; + + root.transactionHistory = function(dateRange, cb) { + var params; + if (!dateRange.startDate) { + params = ''; + } else { + params = '/?startDate=' + dateRange.startDate + '&endDate=' + dateRange.endDate; + } + $http(_getBitPay('/visa-api/transactionHistory' + params)).then(function(data) { + $log.info('BitPay Get Transaction History: SUCCESS'); + return cb(null, data.data.data); + }, function(data) { + $log.error('BitPay Get Transaction History: ERROR ' + data.data); + return cb(data.data); + }); + }; + + root.invoiceHistory = function(cb) { + $http(_getBitPay('/visa-api/invoiceHistory')).then(function(data) { + $log.info('BitPay Get Invoice History: SUCCESS'); + return cb(null, data.data.data); + }, function(data) { + $log.error('BitPay Get Invoice History: ERROR ' + data.data); + return cb(data.data); + }); + }; + + root.getInvoice = function(id, cb) { + $http(_getBitPay('/invoices/' + id)).then(function(data) { + $log.info('BitPay Get Invoice: SUCCESS'); + return cb(null, data.data.data); + }, function(data) { + $log.error('BitPay Get Invoice: ERROR ' + data.data.error); + return cb(data.data.error); + }); + }; + + root.authenticate = function(userData, cb) { + _setUser(userData, function(err) { + $http(_postBitPay('/visa-api/authenticate', userData)).then(function(data) { + $log.info('BitPay Authenticate: SUCCESS'); + _getSession(function(err, session) { + if (err) return cb(err); + return cb(null, session); + }); + }, function(data) { + $log.error('BitPay Authenticate: ERROR'); + if (data.data.error.twoFactorPending) { + _getSession(function(err, session) { + if (err) return cb(err); + return cb(null, session); + }); + } else { + return cb(data); + } + }); + }); + }; + + root.authenticate2FA = function(userData, cb) { + $http(_postBitPay('/visa-api/verify-two-factor', userData)).then(function(data) { + $log.info('BitPay 2FA: SUCCESS'); + return cb(null, data); + }, function(data) { + $log.error('BitPay 2FA: ERROR'); + return cb(data); + }); + }; + + root.isAuthenticated = function(cb) { + _getSession(function(err, session) { + if (err) return cb(err); + if (!session.isAuthenticated) { + _getUser(function(err, user) { + if (err) return cb(err); + if (lodash.isEmpty(user)) return cb(null, session); + root.authenticate(user, function(err, session) { + if (err) return cb(err); + return cb(null, session); + }); + }); + } else { + return cb(null, session); + } + }); + }; + + root.logout = function(cb) { + storageService.removeBitpayCard(credentials.NETWORK, function(err) { + $http(_getBitPay('/visa-api/logout')).then(function(data) { + $log.info('BitPay Logout: SUCCESS'); + return cb(data); + }, function(data) { + $log.error('BitPay Logout: ERROR ' + data.data.error); + return cb(data.data.error); + }); + }); + }; + + /* + * CONSTANTS + */ + + root.bpTranCodes = { + '00611': { + merchant: { + name: 'BitPay', + city: 'Atlanta', + state: 'GA' + }, + category: 'bp001', + description: 'Top-Up' + }, + '602': { + merchant: { + name: 'ATM Withdrawal Fee', + }, + category: 'bp002', + description: '' + }, + '606': { + merchant: { + name: 'International ATM Fee', + }, + category: 'bp002', + description: '' + }, + '00240': { + merchant: { + name: 'ACH Debit Fee', + }, + category: 'bp002', + description: '' + }, + '5032': { + merchant: { + name: 'ACH Debit', + }, + category: 'bp002', + description: '' + }, + '37': { + merchant: { + name: 'ACH / Payroll Deposit', + }, + category: 'bp002', + description: '' + } + }; + + root.iconMap = { + 742: 'medical', + 763: 'plant', + 780: 'plant', + 1520: 'repair', + 1711: 'repair', + 1731: 'repair', + 1740: 'repair', + 1750: 'repair', + 1761: 'repair', + 1771: 'repair', + 1799: 'repair', + 2741: 'books', + 2791: 'books', + 2842: 'clean', + 3000: 'airplane', + 3001: 'airplane', + 3002: 'airplane', + 3003: 'airplane', + 3004: 'airplane', + 3005: 'airplane', + 3006: 'airplane', + 3007: 'airplane', + 3008: 'airplane', + 3009: 'airplane', + 3010: 'airplane', + 3011: 'airplane', + 3012: 'airplane', + 3013: 'airplane', + 3014: 'airplane', + 3015: 'airplane', + 3016: 'airplane', + 3017: 'airplane', + 3018: 'airplane', + 3019: 'airplane', + 3020: 'airplane', + 3021: 'airplane', + 3022: 'airplane', + 3023: 'airplane', + 3024: 'airplane', + 3025: 'airplane', + 3026: 'airplane', + 3027: 'airplane', + 3028: 'airplane', + 3029: 'airplane', + 3030: 'airplane', + 3031: 'airplane', + 3032: 'airplane', + 3033: 'airplane', + 3034: 'airplane', + 3035: 'airplane', + 3036: 'airplane', + 3037: 'airplane', + 3038: 'airplane', + 3039: 'airplane', + 3040: 'airplane', + 3041: 'airplane', + 3042: 'airplane', + 3043: 'airplane', + 3044: 'airplane', + 3045: 'airplane', + 3046: 'airplane', + 3047: 'airplane', + 3048: 'airplane', + 3049: 'airplane', + 3050: 'airplane', + 3051: 'airplane', + 3052: 'airplane', + 3053: 'airplane', + 3054: 'airplane', + 3055: 'airplane', + 3056: 'airplane', + 3057: 'airplane', + 3058: 'airplane', + 3059: 'airplane', + 3060: 'airplane', + 3061: 'airplane', + 3062: 'airplane', + 3063: 'airplane', + 3064: 'airplane', + 3065: 'airplane', + 3066: 'airplane', + 3067: 'airplane', + 3068: 'airplane', + 3069: 'airplane', + 3070: 'airplane', + 3071: 'airplane', + 3072: 'airplane', + 3073: 'airplane', + 3074: 'airplane', + 3075: 'airplane', + 3076: 'airplane', + 3077: 'airplane', + 3078: 'airplane', + 3079: 'airplane', + 3080: 'airplane', + 3081: 'airplane', + 3082: 'airplane', + 3083: 'airplane', + 3084: 'airplane', + 3085: 'airplane', + 3086: 'airplane', + 3087: 'airplane', + 3088: 'airplane', + 3089: 'airplane', + 3090: 'airplane', + 3091: 'airplane', + 3092: 'airplane', + 3093: 'airplane', + 3094: 'airplane', + 3095: 'airplane', + 3096: 'airplane', + 3097: 'airplane', + 3098: 'airplane', + 3099: 'airplane', + 3100: 'airplane', + 3101: 'airplane', + 3102: 'airplane', + 3103: 'airplane', + 3104: 'airplane', + 3105: 'airplane', + 3106: 'airplane', + 3107: 'airplane', + 3108: 'airplane', + 3109: 'airplane', + 3110: 'airplane', + 3111: 'airplane', + 3112: 'airplane', + 3113: 'airplane', + 3114: 'airplane', + 3115: 'airplane', + 3116: 'airplane', + 3117: 'airplane', + 3118: 'airplane', + 3119: 'airplane', + 3120: 'airplane', + 3121: 'airplane', + 3122: 'airplane', + 3123: 'airplane', + 3124: 'airplane', + 3125: 'airplane', + 3126: 'airplane', + 3127: 'airplane', + 3128: 'airplane', + 3129: 'airplane', + 3130: 'airplane', + 3131: 'airplane', + 3132: 'airplane', + 3133: 'airplane', + 3134: 'airplane', + 3135: 'airplane', + 3136: 'airplane', + 3137: 'airplane', + 3138: 'airplane', + 3139: 'airplane', + 3140: 'airplane', + 3141: 'airplane', + 3142: 'airplane', + 3143: 'airplane', + 3144: 'airplane', + 3145: 'airplane', + 3146: 'airplane', + 3147: 'airplane', + 3148: 'airplane', + 3149: 'airplane', + 3150: 'airplane', + 3151: 'airplane', + 3152: 'airplane', + 3153: 'airplane', + 3154: 'airplane', + 3155: 'airplane', + 3156: 'airplane', + 3157: 'airplane', + 3158: 'airplane', + 3159: 'airplane', + 3160: 'airplane', + 3161: 'airplane', + 3162: 'airplane', + 3163: 'airplane', + 3164: 'airplane', + 3165: 'airplane', + 3166: 'airplane', + 3167: 'airplane', + 3168: 'airplane', + 3169: 'airplane', + 3170: 'airplane', + 3171: 'airplane', + 3172: 'airplane', + 3173: 'airplane', + 3174: 'airplane', + 3175: 'airplane', + 3176: 'airplane', + 3177: 'airplane', + 3178: 'airplane', + 3179: 'airplane', + 3180: 'airplane', + 3181: 'airplane', + 3182: 'airplane', + 3183: 'airplane', + 3184: 'airplane', + 3185: 'airplane', + 3186: 'airplane', + 3187: 'airplane', + 3188: 'airplane', + 3189: 'airplane', + 3190: 'airplane', + 3191: 'airplane', + 3192: 'airplane', + 3193: 'airplane', + 3194: 'airplane', + 3195: 'airplane', + 3196: 'airplane', + 3197: 'airplane', + 3198: 'airplane', + 3199: 'airplane', + 3200: 'airplane', + 3201: 'airplane', + 3202: 'airplane', + 3203: 'airplane', + 3204: 'airplane', + 3205: 'airplane', + 3206: 'airplane', + 3207: 'airplane', + 3208: 'airplane', + 3209: 'airplane', + 3210: 'airplane', + 3211: 'airplane', + 3212: 'airplane', + 3213: 'airplane', + 3214: 'airplane', + 3215: 'airplane', + 3216: 'airplane', + 3217: 'airplane', + 3218: 'airplane', + 3219: 'airplane', + 3220: 'airplane', + 3221: 'airplane', + 3222: 'airplane', + 3223: 'airplane', + 3224: 'airplane', + 3225: 'airplane', + 3226: 'airplane', + 3227: 'airplane', + 3228: 'airplane', + 3229: 'airplane', + 3230: 'airplane', + 3231: 'airplane', + 3232: 'airplane', + 3233: 'airplane', + 3234: 'airplane', + 3235: 'airplane', + 3236: 'airplane', + 3237: 'airplane', + 3238: 'airplane', + 3239: 'airplane', + 3240: 'airplane', + 3241: 'airplane', + 3242: 'airplane', + 3243: 'airplane', + 3244: 'airplane', + 3245: 'airplane', + 3246: 'airplane', + 3247: 'airplane', + 3248: 'airplane', + 3249: 'airplane', + 3250: 'airplane', + 3251: 'airplane', + 3252: 'airplane', + 3253: 'airplane', + 3254: 'airplane', + 3255: 'airplane', + 3256: 'airplane', + 3257: 'airplane', + 3258: 'airplane', + 3259: 'airplane', + 3260: 'airplane', + 3261: 'airplane', + 3262: 'airplane', + 3263: 'airplane', + 3264: 'airplane', + 3265: 'airplane', + 3266: 'airplane', + 3267: 'airplane', + 3268: 'airplane', + 3269: 'airplane', + 3270: 'airplane', + 3271: 'airplane', + 3272: 'airplane', + 3273: 'airplane', + 3274: 'airplane', + 3275: 'airplane', + 3276: 'airplane', + 3277: 'airplane', + 3278: 'airplane', + 3279: 'airplane', + 3280: 'airplane', + 3281: 'airplane', + 3282: 'airplane', + 3283: 'airplane', + 3284: 'airplane', + 3285: 'airplane', + 3286: 'airplane', + 3287: 'airplane', + 3288: 'airplane', + 3289: 'airplane', + 3290: 'airplane', + 3291: 'airplane', + 3292: 'airplane', + 3293: 'airplane', + 3294: 'airplane', + 3295: 'airplane', + 3296: 'airplane', + 3297: 'airplane', + 3298: 'airplane', + 3299: 'airplane', + 3351: 'car', + 3352: 'car', + 3353: 'car', + 3354: 'car', + 3355: 'car', + 3356: 'car', + 3357: 'car', + 3358: 'car', + 3359: 'car', + 3360: 'car', + 3361: 'car', + 3362: 'car', + 3363: 'car', + 3364: 'car', + 3365: 'car', + 3366: 'car', + 3367: 'car', + 3368: 'car', + 3369: 'car', + 3370: 'car', + 3371: 'car', + 3372: 'car', + 3373: 'car', + 3374: 'car', + 3375: 'car', + 3376: 'car', + 3377: 'car', + 3378: 'car', + 3379: 'car', + 3380: 'car', + 3381: 'car', + 3382: 'car', + 3383: 'car', + 3384: 'car', + 3385: 'car', + 3386: 'car', + 3387: 'car', + 3388: 'car', + 3389: 'car', + 3390: 'car', + 3391: 'car', + 3392: 'car', + 3393: 'car', + 3394: 'car', + 3395: 'car', + 3396: 'car', + 3397: 'car', + 3398: 'car', + 3399: 'car', + 3400: 'car', + 3401: 'car', + 3402: 'car', + 3403: 'car', + 3404: 'car', + 3405: 'car', + 3406: 'car', + 3407: 'car', + 3408: 'car', + 3409: 'car', + 3410: 'car', + 3411: 'car', + 3412: 'car', + 3413: 'car', + 3414: 'car', + 3415: 'car', + 3416: 'car', + 3417: 'car', + 3418: 'car', + 3419: 'car', + 3420: 'car', + 3421: 'car', + 3422: 'car', + 3423: 'car', + 3424: 'car', + 3425: 'car', + 3426: 'car', + 3427: 'car', + 3428: 'car', + 3429: 'car', + 3430: 'car', + 3431: 'car', + 3432: 'car', + 3433: 'car', + 3434: 'car', + 3435: 'car', + 3436: 'car', + 3437: 'car', + 3438: 'car', + 3439: 'car', + 3440: 'car', + 3441: 'car', + 3501: 'hotel', + 3502: 'hotel', + 3503: 'hotel', + 3504: 'hotel', + 3505: 'hotel', + 3506: 'hotel', + 3507: 'hotel', + 3508: 'hotel', + 3509: 'hotel', + 3510: 'hotel', + 3511: 'hotel', + 3512: 'hotel', + 3513: 'hotel', + 3514: 'hotel', + 3515: 'hotel', + 3516: 'hotel', + 3517: 'hotel', + 3518: 'hotel', + 3519: 'hotel', + 3520: 'hotel', + 3521: 'hotel', + 3522: 'hotel', + 3523: 'hotel', + 3524: 'hotel', + 3525: 'hotel', + 3526: 'hotel', + 3527: 'hotel', + 3528: 'hotel', + 3529: 'hotel', + 3530: 'hotel', + 3531: 'hotel', + 3532: 'hotel', + 3533: 'hotel', + 3534: 'hotel', + 3535: 'hotel', + 3536: 'hotel', + 3537: 'hotel', + 3538: 'hotel', + 3539: 'hotel', + 3540: 'hotel', + 3541: 'hotel', + 3542: 'hotel', + 3543: 'hotel', + 3544: 'hotel', + 3545: 'hotel', + 3546: 'hotel', + 3547: 'hotel', + 3548: 'hotel', + 3549: 'hotel', + 3550: 'hotel', + 3551: 'hotel', + 3552: 'hotel', + 3553: 'hotel', + 3554: 'hotel', + 3555: 'hotel', + 3556: 'hotel', + 3557: 'hotel', + 3558: 'hotel', + 3559: 'hotel', + 3560: 'hotel', + 3561: 'hotel', + 3562: 'hotel', + 3563: 'hotel', + 3564: 'hotel', + 3565: 'hotel', + 3566: 'hotel', + 3567: 'hotel', + 3568: 'hotel', + 3569: 'hotel', + 3570: 'hotel', + 3571: 'hotel', + 3572: 'hotel', + 3573: 'hotel', + 3574: 'hotel', + 3575: 'hotel', + 3576: 'hotel', + 3577: 'hotel', + 3578: 'hotel', + 3579: 'hotel', + 3580: 'hotel', + 3581: 'hotel', + 3582: 'hotel', + 3583: 'hotel', + 3584: 'hotel', + 3585: 'hotel', + 3586: 'hotel', + 3587: 'hotel', + 3588: 'hotel', + 3589: 'hotel', + 3590: 'hotel', + 3591: 'hotel', + 3592: 'hotel', + 3593: 'hotel', + 3594: 'hotel', + 3595: 'hotel', + 3596: 'hotel', + 3597: 'hotel', + 3598: 'hotel', + 3599: 'hotel', + 3600: 'hotel', + 3601: 'hotel', + 3602: 'hotel', + 3603: 'hotel', + 3604: 'hotel', + 3605: 'hotel', + 3606: 'hotel', + 3607: 'hotel', + 3608: 'hotel', + 3609: 'hotel', + 3610: 'hotel', + 3611: 'hotel', + 3612: 'hotel', + 3613: 'hotel', + 3614: 'hotel', + 3615: 'hotel', + 3616: 'hotel', + 3617: 'hotel', + 3618: 'hotel', + 3619: 'hotel', + 3620: 'hotel', + 3621: 'hotel', + 3622: 'hotel', + 3623: 'hotel', + 3624: 'hotel', + 3625: 'hotel', + 3626: 'hotel', + 3627: 'hotel', + 3628: 'hotel', + 3629: 'hotel', + 3630: 'hotel', + 3631: 'hotel', + 3632: 'hotel', + 3633: 'hotel', + 3634: 'hotel', + 3635: 'hotel', + 3636: 'hotel', + 3637: 'hotel', + 3638: 'hotel', + 3639: 'hotel', + 3640: 'hotel', + 3641: 'hotel', + 3642: 'hotel', + 3643: 'hotel', + 3644: 'hotel', + 3645: 'hotel', + 3646: 'hotel', + 3647: 'hotel', + 3648: 'hotel', + 3649: 'hotel', + 3650: 'hotel', + 3651: 'hotel', + 3652: 'hotel', + 3653: 'hotel', + 3654: 'hotel', + 3655: 'hotel', + 3656: 'hotel', + 3657: 'hotel', + 3658: 'hotel', + 3659: 'hotel', + 3660: 'hotel', + 3661: 'hotel', + 3662: 'hotel', + 3663: 'hotel', + 3664: 'hotel', + 3665: 'hotel', + 3666: 'hotel', + 3667: 'hotel', + 3668: 'hotel', + 3669: 'hotel', + 3670: 'hotel', + 3671: 'hotel', + 3672: 'hotel', + 3673: 'hotel', + 3674: 'hotel', + 3675: 'hotel', + 3676: 'hotel', + 3677: 'hotel', + 3678: 'hotel', + 3679: 'hotel', + 3680: 'hotel', + 3681: 'hotel', + 3682: 'hotel', + 3683: 'hotel', + 3684: 'hotel', + 3685: 'hotel', + 3686: 'hotel', + 3687: 'hotel', + 3688: 'hotel', + 3689: 'hotel', + 3690: 'hotel', + 3691: 'hotel', + 3692: 'hotel', + 3693: 'hotel', + 3694: 'hotel', + 3695: 'hotel', + 3696: 'hotel', + 3697: 'hotel', + 3698: 'hotel', + 3699: 'hotel', + 3700: 'hotel', + 3701: 'hotel', + 3702: 'hotel', + 3703: 'hotel', + 3704: 'hotel', + 3705: 'hotel', + 3706: 'hotel', + 3707: 'hotel', + 3708: 'hotel', + 3709: 'hotel', + 3710: 'hotel', + 3711: 'hotel', + 3712: 'hotel', + 3713: 'hotel', + 3714: 'hotel', + 3715: 'hotel', + 3716: 'hotel', + 3717: 'hotel', + 3718: 'hotel', + 3719: 'hotel', + 3720: 'hotel', + 3721: 'hotel', + 3722: 'hotel', + 3723: 'hotel', + 3724: 'hotel', + 3725: 'hotel', + 3726: 'hotel', + 3727: 'hotel', + 3728: 'hotel', + 3729: 'hotel', + 3730: 'hotel', + 3731: 'hotel', + 3732: 'hotel', + 3733: 'hotel', + 3734: 'hotel', + 3735: 'hotel', + 3736: 'hotel', + 3737: 'hotel', + 3738: 'hotel', + 3739: 'hotel', + 3740: 'hotel', + 3741: 'hotel', + 3742: 'hotel', + 3743: 'hotel', + 3744: 'hotel', + 3745: 'hotel', + 3746: 'hotel', + 3747: 'hotel', + 3748: 'hotel', + 3749: 'hotel', + 3750: 'hotel', + 3751: 'hotel', + 3752: 'hotel', + 3753: 'hotel', + 3754: 'hotel', + 3755: 'hotel', + 3756: 'hotel', + 3757: 'hotel', + 3758: 'hotel', + 3759: 'hotel', + 3760: 'hotel', + 3761: 'hotel', + 3762: 'hotel', + 3763: 'hotel', + 3764: 'hotel', + 3765: 'hotel', + 3766: 'hotel', + 3767: 'hotel', + 3768: 'hotel', + 3769: 'hotel', + 3770: 'hotel', + 3771: 'hotel', + 3772: 'hotel', + 3773: 'hotel', + 3774: 'hotel', + 3775: 'hotel', + 3776: 'hotel', + 3777: 'hotel', + 3778: 'hotel', + 3779: 'hotel', + 3780: 'hotel', + 3781: 'hotel', + 3782: 'hotel', + 3783: 'hotel', + 3784: 'hotel', + 3785: 'hotel', + 3786: 'hotel', + 3787: 'hotel', + 3788: 'hotel', + 3789: 'hotel', + 3790: 'hotel', + 3816: 'hotel', + 3835: 'hotel', + 4011: 'car', + 4111: 'car', + 4112: 'car', + 4119: 'car', + 4121: 'car', + 4131: 'car', + 4214: 'car', + 4215: 'bus', + 4225: 'default', + 4411: 'boat', + 4457: 'boat', + 4468: 'boat', + 4511: 'airplane', + 4582: 'airplane', + 4722: 'airplane', + 4723: 'airplane', + 4784: 'car', + 4789: 'car', + 4812: 'car', + 4814: 'telephone', + 4815: 'telephone', + 4816: 'computer', + 4821: 'money', + 4829: 'money', + 4899: 'television', + 4900: 'gas', + 5013: 'car', + 5021: 'default', + 5039: 'repair', + 5044: 'computer', + 5045: 'computer', + 5046: 'default', + 5047: 'medical', + 5051: 'default', + 5065: 'default', + 5072: 'default', + 5074: 'default', + 5085: 'default', + 5094: 'diamond-ring', + 5099: 'default', + 5111: 'default', + 5122: 'medical', + 5131: 'default', + 5137: 'shirt', + 5139: 'shoes', + 5169: 'gas', + 5172: 'gas', + 5192: 'books', + 5193: 'plant', + 5198: 'repair', + 5199: 'repair', + 5200: 'repair', + 5211: 'repair', + 5231: 'repair', + 5251: 'default', + 5261: 'plant', + 5271: 'bus', + 5300: 'purchase', + 5309: 'purchase', + 5310: 'purchase', + 5311: 'purchase', + 5331: 'purchase', + 5399: 'purchase', + 5411: 'food', + 5422: 'food', + 5441: 'food', + 5451: 'food', + 5462: 'food', + 5499: 'food', + 5511: 'car', + 5521: 'car', + 5531: 'car', + 5532: 'car', + 5533: 'car', + 5541: 'gas', + 5542: 'gas', + 5551: 'boat', + 5561: 'motorcycle', + 5571: 'motorcycle', + 5592: 'default', + 5598: 'default', + 5599: 'car', + 5611: 'shirt', + 5621: 'shirt', + 5631: 'shirt', + 5641: 'shirt', + 5651: 'shirt', + 5655: 'shirt', + 5661: 'shoes', + 5681: 'default', + 5691: 'shirt', + 5697: 'default', + 5698: 'default', + 5699: 'default', + 5712: 'default', + 5713: 'default', + 5714: 'default', + 5718: 'default', + 5719: 'default', + 5722: 'default', + 5732: 'computer', + 5733: 'music', + 5734: 'computer', + 5735: 'music', + 5811: 'food', + 5812: 'food', + 5813: 'cocktail', + 5814: 'food', + 5815: 'books', + 5816: 'computer', + 5817: 'default', + 5818: 'default', + 5832: 'default', + 5912: 'medical', + 5921: 'cocktail', + 5931: 'default', + 5932: 'default', + 5933: 'default', + 5935: 'default', + 5937: 'default', + 5940: 'bicycle', + 5941: 'bicycle', + 5942: 'books', + 5943: 'default', + 5944: 'clock', + 5945: 'toy', + 5946: 'camera', + 5947: 'default', + 5948: 'default', + 5949: 'default', + 5950: 'default', + 5960: 'default', + 5961: 'mail', + 5962: 'telephone', + 5963: 'default', + 5964: 'telephone', + 5965: 'telephone', + 5966: 'telephone', + 5967: 'telephone', + 5968: 'telephone', + 5969: 'telephone', + 5970: 'art', + 5971: 'art', + 5972: 'coins', + 5973: 'default', + 5975: 'default', + 5976: 'default', + 5977: 'default', + 5978: 'default', + 5983: 'gas', + 5992: 'plant', + 5993: 'default', + 5994: 'newspaper', + 5995: 'pet', + 5996: 'cocktail', + 5997: 'purchase', + 5998: 'tent', + 5999: 'money', + 6010: 'money', + 6011: 'money', + 6012: 'money', + 6051: 'money', + 6211: 'money', + 6300: 'money', + 6381: 'money', + 6399: 'repair', + 6513: 'repair', + 7011: 'hotel', + 7012: 'hotel', + 7032: 'park', + 7033: 'park', + 7210: 'shirt', + 7211: 'shirt', + 7216: 'shirt', + 7217: 'default', + 7221: 'camera', + 7230: 'scissors', + 7251: 'shoe', + 7261: 'sadface', + 7273: 'smiley-face', + 7276: 'money', + 7277: 'people', + 7278: 'people', + 7296: 'shirt', + 7297: 'smiley-face', + 7298: 'smiley-face', + 7299: 'default', + 7311: 'default', + 7321: 'default', + 7332: 'computer', + 7333: 'camera', + 7338: 'computer', + 7339: 'people', + 7342: 'bug', + 7349: 'default', + 7361: 'people', + 7372: 'computer', + 7375: 'computer', + 7379: 'computer', + 7392: 'people', + 7393: 'search', + 7394: 'default', + 7395: 'car', + 7399: 'car', + 7511: 'truck', + 7512: 'car', + 7513: 'truck', + 7519: 'truck', + 7523: 'car', + 7531: 'car', + 7534: 'car', + 7535: 'car', + 7538: 'car', + 7542: 'car', + 7549: 'truck', + 7622: 'television', + 7623: 'default', + 7629: 'default', + 7631: 'watch', + 7641: 'furniture', + 7692: 'default', + 7699: 'default', + 7800: 'money', + 7801: 'money', + 7802: 'money', + 7829: 'money', + 7832: 'film', + 7841: 'film', + 7911: 'music', + 7922: 'ticket', + 7929: 'ticket', + 7932: 'music', + 7933: 'bowling', + 7941: 'football', + 7991: 'people', + 7992: 'golf', + 7993: 'game', + 7994: 'game', + 7995: 'coins', + 7996: 'ticket', + 7997: 'money', + 7998: 'ticket', + 7999: 'people', + 8011: 'medical', + 8021: 'medical', + 8031: 'medical', + 8041: 'medical', + 8042: 'medical', + 8043: 'medical', + 8044: 'medical', + 8049: 'medical', + 8050: 'medical', + 8062: 'medical', + 8071: 'medical', + 8099: 'medical', + 8111: 'law', + 8211: 'books', + 8220: 'books', + 8241: 'books', + 8244: 'books', + 8249: 'books', + 8299: 'people', + 8351: 'people', + 8398: 'people', + 8641: 'people', + 8651: 'people', + 8661: 'people', + 8675: 'car', + 8699: 'people', + 8734: 'medical', + 8911: 'tree', + 8931: 'books', + 8999: 'suitcase', + 9211: 'law', + 9222: 'law', + 9223: 'law', + 9311: 'law', + 9399: 'default', + 9402: 'mail', + 9405: 'default', + 9700: 'default', + 9701: 'default', + 9702: 'default', + 9950: 'default', + 'bp001': 'bitcoin-topup', + 'bp002': 'default' + }; + + return root; + +}); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 70d5b6014..6ff8a794f 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -306,6 +306,18 @@ angular.module('copayApp.services') storage.remove('coinbaseTxs-' + network, cb); }; + root.setBitpayCard = function(network, data, cb) { + storage.set('bitpayCard-' + network, data, cb); + }; + + root.getBitpayCard = function(network, cb) { + storage.get('bitpayCard-' + network, cb); + }; + + root.removeBitpayCard = function(network, cb) { + storage.remove('bitpayCard-' + network, cb); + }; + root.removeAllWalletData = function(walletId, cb) { root.clearLastAddress(walletId, function(err) { if (err) return cb(err); diff --git a/src/sass/main.scss b/src/sass/main.scss index c64c17736..392392c67 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -115,6 +115,18 @@ h4.title a { font-size: 16px; } +.bitpay_card select { + margin: 5px 0 5px 0; + padding: 0 20px; + font-size: 16px; + width: auto; + border: none; +} + +.bitpay_card select:focus { + background-color: transparent; +} + .preferences ul, .modal-content ul { font-size: 14px; background: white; From 4c55b8b5413d62a52e48c0617bb22b11ddf5339d Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 10 Aug 2016 15:34:13 -0300 Subject: [PATCH 2/3] Update topbar color --- src/js/controllers/bitpayCard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 132c43b6e..1a76e8e4c 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -9,7 +9,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi self.sandbox = network == 'testnet' ? true : false; if (platformInfo.isCordova && StatusBar.isVisible) { - StatusBar.backgroundColorByHexString("#4B6178"); + StatusBar.backgroundColorByHexString("#293C92"); } var handleEncryptedWallet = function(client, cb) { From 4bb2375ed0bc8d91188820d9f4c7d50336c81cf5 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 10 Aug 2016 16:08:11 -0300 Subject: [PATCH 3/3] Ref and add pbkdf2 as angular module --- .gitignore | 1 + Gruntfile.js | 4 +++- angular-bitcore-wallet-client/index.js | 2 -- angular-pbkdf2/index.js | 18 ++++++++++++++++++ src/js/app.js | 1 + src/js/controllers/bitpayCard.js | 4 ++-- test/karma.conf.js | 1 + 7 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 angular-pbkdf2/index.js diff --git a/.gitignore b/.gitignore index 4a30d65d8..62753becd 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ build/Release node_modules bower_components angular-bitcore-wallet-client/angular-bitcore-wallet-client.js +angular-pbkdf2/angular-pbkdf2.js # Users Environment Variables .lock-wscript diff --git a/Gruntfile.js b/Gruntfile.js index 3fd51b784..5691b2f4e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -105,6 +105,7 @@ module.exports = function(grunt) { 'bower_components/angular-sanitize/angular-sanitize.js', 'bower_components/ng-csv/build/ng-csv.js', 'bower_components/angular-mocks/angular-mocks.js', + 'angular-pbkdf2/angular-pbkdf2.js', 'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js' ], dest: 'public/lib/angular.js' @@ -260,7 +261,8 @@ module.exports = function(grunt) { browserify: { dist: { files: { - 'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js': ['angular-bitcore-wallet-client/index.js'] + 'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js': ['angular-bitcore-wallet-client/index.js'], + 'angular-pbkdf2/angular-pbkdf2.js': ['angular-pbkdf2/index.js'] }, } } diff --git a/angular-bitcore-wallet-client/index.js b/angular-bitcore-wallet-client/index.js index 4174e65e1..a7d0c09d6 100644 --- a/angular-bitcore-wallet-client/index.js +++ b/angular-bitcore-wallet-client/index.js @@ -1,6 +1,5 @@ var bwcModule = angular.module('bwcModule', []); var Client = require('../node_modules/bitcore-wallet-client'); -var pbkdf2Sync = require('pbkdf2').pbkdf2Sync; bwcModule.constant('MODULE_VERSION', '1.0.0'); @@ -25,7 +24,6 @@ bwcModule.provider("bwcService", function() { service.buildTx = Client.buildTx; service.parseSecret = Client.parseSecret; service.Client = Client; - service.pbkdf2Sync = pbkdf2Sync; service.getUtils = function() { return Client.Utils; diff --git a/angular-pbkdf2/index.js b/angular-pbkdf2/index.js new file mode 100644 index 000000000..4e1e0d9b9 --- /dev/null +++ b/angular-pbkdf2/index.js @@ -0,0 +1,18 @@ +var pbkdf2Module = angular.module('pbkdf2Module', []); +var pbkdf2Sync = require('../node_modules/pbkdf2').pbkdf2Sync; + +pbkdf2Module.constant('MODULE_VERSION', '1.0.0'); + +pbkdf2Module.provider("pbkdf2Service", function() { + var provider = {}; + + provider.$get = function() { + var service = {}; + + service.pbkdf2Sync = pbkdf2Sync; + + return service; + }; + + return provider; +}); diff --git a/src/js/app.js b/src/js/app.js index d0f6268cd..b9a2b4aba 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -10,6 +10,7 @@ var modules = [ 'ngSanitize', 'ngCsv', 'bwcModule', + 'pbkdf2Module', 'copayApp.filters', 'copayApp.services', 'copayApp.controllers', diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 1a76e8e4c..e4d35f8f0 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $rootScope, $timeout, $log, $ionicModal, lodash, bitpayCardService, configService, profileService, walletService, fingerprintService, ongoingProcess, bwcError, bitcore, bwcService, moment, platformInfo) { +angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $rootScope, $timeout, $log, $ionicModal, lodash, bitpayCardService, configService, profileService, walletService, fingerprintService, ongoingProcess, bwcError, bitcore, pbkdf2Service, moment, platformInfo) { var self = this; var client; @@ -295,7 +295,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi var data = { emailAddress : $scope.email, - hashedPassword : bwcService.pbkdf2Sync($scope.password, '..............', 200, 64).toString('hex') + hashedPassword : pbkdf2Service.pbkdf2Sync($scope.password, '..............', 200, 64).toString('hex') }; // POST /authenticate diff --git a/test/karma.conf.js b/test/karma.conf.js index ad396bdd6..17ac204fa 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -27,6 +27,7 @@ module.exports = function(config) { 'bower_components/angular-sanitize/angular-sanitize.js', 'bower_components/ng-csv/build/ng-csv.js', 'bower_components/angular-mocks/angular-mocks.js', + 'angular-pbkdf2/angular-pbkdf2.js', 'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js', 'src/js/**/*.js', 'test/helpers.js',