Merge https://github.com/bitpay/copay into copay-cash
|
|
@ -1,13 +1,3 @@
|
||||||
# EditorConfig helps developers define and maintain consistent
|
|
||||||
# coding styles between different editors and IDEs
|
|
||||||
# http://editorconfig.org
|
|
||||||
|
|
||||||
## Plugins
|
|
||||||
# Atom (https://github.com/sindresorhus/atom-editorconfig)
|
|
||||||
# Vim (https://github.com/editorconfig/editorconfig-vim)
|
|
||||||
# Sublime (https://github.com/sindresorhus/editorconfig-sublime)
|
|
||||||
;
|
|
||||||
|
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
|
|
@ -27,4 +17,3 @@ indent_style = tab
|
||||||
[**.html]
|
[**.html]
|
||||||
max_char = 78
|
max_char = 78
|
||||||
brace_style = expand
|
brace_style = expand
|
||||||
|
|
||||||
|
|
|
||||||
3
.gitignore
vendored
|
|
@ -3,6 +3,9 @@ i18n/po/*.mo
|
||||||
i18n/crowdin_api_key.txt
|
i18n/crowdin_api_key.txt
|
||||||
src/js/translations.js
|
src/js/translations.js
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
|
||||||
# cordova
|
# cordova
|
||||||
plugins
|
plugins
|
||||||
platforms
|
platforms
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ module.exports = function(grunt) {
|
||||||
grunt.registerTask('desktop', ['prod', 'nwjs', 'copy:linux', 'compress:linux']);
|
grunt.registerTask('desktop', ['prod', 'nwjs', 'copy:linux', 'compress:linux']);
|
||||||
grunt.registerTask('osx', ['prod', 'nwjs', 'exec:macos', 'exec:osxsign']);
|
grunt.registerTask('osx', ['prod', 'nwjs', 'exec:macos', 'exec:osxsign']);
|
||||||
grunt.registerTask('osx-debug', ['default', 'nwjs']);
|
grunt.registerTask('osx-debug', ['default', 'nwjs']);
|
||||||
grunt.registerTask('chrome', ['exec:chrome']);
|
grunt.registerTask('chrome', ['default','exec:chrome']);
|
||||||
grunt.registerTask('wp', ['prod', 'exec:wp']);
|
grunt.registerTask('wp', ['prod', 'exec:wp']);
|
||||||
grunt.registerTask('wp-copy', ['default', 'exec:wpcopy']);
|
grunt.registerTask('wp-copy', ['default', 'exec:wpcopy']);
|
||||||
grunt.registerTask('wp-init', ['default', 'exec:wpinit']);
|
grunt.registerTask('wp-init', ['default', 'exec:wpinit']);
|
||||||
|
|
|
||||||
4
angular-bitcore-wallet-client/index.js
vendored
|
|
@ -13,6 +13,10 @@ bwcModule.provider("bwcService", function() {
|
||||||
return Client.Bitcore;
|
return Client.Bitcore;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
service.getBitcoreCash = function() {
|
||||||
|
return Client.BitcoreCash;
|
||||||
|
};
|
||||||
|
|
||||||
service.getErrors = function() {
|
service.getErrors = function() {
|
||||||
return Client.errors;
|
return Client.errors;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
"windowsAppId": "2d1002d7-ee34-4f60-bd29-0c871ba0c195",
|
"windowsAppId": "2d1002d7-ee34-4f60-bd29-0c871ba0c195",
|
||||||
"pushSenderId": "1036948132229",
|
"pushSenderId": "1036948132229",
|
||||||
"description": "Secure Bitcoin Wallet",
|
"description": "Secure Bitcoin Wallet",
|
||||||
"version": "3.7.1",
|
"version": "3.8.2",
|
||||||
"androidVersion": "371000",
|
"androidVersion": "382001",
|
||||||
"_extraCSS": null,
|
"_extraCSS": null,
|
||||||
"_enabledExtensions": {
|
"_enabledExtensions": {
|
||||||
"coinbase": true,
|
"coinbase": true,
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
<plugin name="cordova-plugin-customurlscheme" spec="https://github.com/cmgustavo/Custom-URL-scheme.git">
|
<plugin name="cordova-plugin-customurlscheme" spec="https://github.com/cmgustavo/Custom-URL-scheme.git">
|
||||||
<variable name="URL_SCHEME" value="bitcoin" />
|
<variable name="URL_SCHEME" value="bitcoin" />
|
||||||
<variable name="SECOND_URL_SCHEME" value="*APPURI*" />
|
<variable name="SECOND_URL_SCHEME" value="*APPURI*" />
|
||||||
|
<variable name="THIRD_URL_SCHEME" value="bitcoincash" />
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin name="cordova-custom-config" spec="~3.0.5" />
|
<plugin name="cordova-custom-config" spec="~3.0.5" />
|
||||||
<plugin name="cordova-plugin-queries-schemes" spec="~0.1.5" />
|
<plugin name="cordova-plugin-queries-schemes" spec="~0.1.5" />
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
"windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c",
|
"windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c",
|
||||||
"pushSenderId": "1036948132229",
|
"pushSenderId": "1036948132229",
|
||||||
"description": "A Secure Bitcoin Wallet",
|
"description": "A Secure Bitcoin Wallet",
|
||||||
"version": "3.7.1",
|
"version": "3.8.2",
|
||||||
"androidVersion": "371000",
|
"androidVersion": "382001",
|
||||||
"_extraCSS": null,
|
"_extraCSS": null,
|
||||||
"_enabledExtensions": {
|
"_enabledExtensions": {
|
||||||
"coinbase": true,
|
"coinbase": true,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "*PACKAGENAME*",
|
"name": "*PACKAGENAME*",
|
||||||
"description": "*DESCRIPTION*",
|
"description": "*DESCRIPTION*",
|
||||||
"author": "Bitcoin.com",
|
"author": "BitPay",
|
||||||
"version": "*VERSION*",
|
"version": "*VERSION*",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bitcoin",
|
"bitcoin",
|
||||||
|
|
@ -54,9 +54,9 @@
|
||||||
"angular": "1.4.6",
|
"angular": "1.4.6",
|
||||||
"angular-mocks": "1.4.10",
|
"angular-mocks": "1.4.10",
|
||||||
"bezier-easing": "^2.0.3",
|
"bezier-easing": "^2.0.3",
|
||||||
"bhttp": "^1.2.1",
|
"bhttp": "1.2.1",
|
||||||
"bitauth": "^0.2.1",
|
"bitauth": "^0.2.1",
|
||||||
"bitcore-wallet-client": "5.3.0",
|
"bitcore-wallet-client": "6.2.1",
|
||||||
"bower": "^1.7.9",
|
"bower": "^1.7.9",
|
||||||
"cordova-android": "5.1.1",
|
"cordova-android": "5.1.1",
|
||||||
"cordova-custom-config": "^3.0.5",
|
"cordova-custom-config": "^3.0.5",
|
||||||
|
|
@ -107,10 +107,9 @@
|
||||||
"run:android": "cordova run android --device",
|
"run:android": "cordova run android --device",
|
||||||
"run:android-release": "cordova run android --device --release",
|
"run:android-release": "cordova run android --device --release",
|
||||||
"log:android": "adb logcat | grep chromium",
|
"log:android": "adb logcat | grep chromium",
|
||||||
"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 bitcoin-com && ../android-sdk-macosx/build-tools/25.0.3/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk",
|
"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_HOME/build-tools/26.0.1/zipalign -v 4 platforms/android/build/outputs/apk/android-release-signed.apk platforms/android/build/outputs/apk/android-release-signed-aligned.apk",
|
||||||
"apply:copay": "npm i fs-extra && cd app-template && node apply.js copay && npm i && cordova prepare",
|
"apply:copay": "npm i fs-extra && cd app-template && node apply.js copay && npm i && cordova prepare",
|
||||||
"apply:bitpay": "npm i fs-extra && cd app-template && node apply.js bitpay && npm i && cordova prepare",
|
"apply:bitpay": "npm i fs-extra && cd app-template && node apply.js bitpay && npm i && cordova prepare",
|
||||||
"apply:bitcoincom": "npm i fs-extra && cd app-template && node apply.js bitcoincom && npm i && cordova prepare",
|
|
||||||
"test": "echo \"no package tests configured\"",
|
"test": "echo \"no package tests configured\"",
|
||||||
"clean": "trash platforms && trash plugins && cordova prepare",
|
"clean": "trash platforms && trash plugins && cordova prepare",
|
||||||
"unstage-package": "git reset package.json",
|
"unstage-package": "git reset package.json",
|
||||||
|
|
@ -119,9 +118,9 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cordova": "^6.3.1",
|
"cordova": "^6.3.1",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.1",
|
||||||
"ionic": "^2.1.0",
|
"ionic": "^3.6.0",
|
||||||
"trash-cli": "^1.4.0",
|
"trash-cli": "^1.4.0",
|
||||||
"lodash": "^4.3.0",
|
"lodash": "^4.17.4",
|
||||||
"pre-commit": "^1.1.3"
|
"pre-commit": "^1.1.3"
|
||||||
},
|
},
|
||||||
"pre-commit": "unstage-package"
|
"pre-commit": "unstage-package"
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
"moment": "2.10.3",
|
"moment": "2.10.3",
|
||||||
"ng-lodash": "0.2.3",
|
"ng-lodash": "0.2.3",
|
||||||
"qrcode-decoder-js": "*",
|
"qrcode-decoder-js": "*",
|
||||||
"trezor-connect": "*",
|
"trezor-connect": "https://github.com/trezor/connect.git#c1a00f9f0f4a13239ba13ddd589c6ca61f2e7876",
|
||||||
"ng-csv": "~0.3.6",
|
"ng-csv": "~0.3.6",
|
||||||
"ionic-toast": "^0.4.1",
|
"ionic-toast": "^0.4.1",
|
||||||
"angular-clipboard": "^1.4.2",
|
"angular-clipboard": "^1.4.2",
|
||||||
|
|
|
||||||
23
i18n/docs/appstore_nl.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
Beveilig bitcoin op je eigen voorwaarden met een open source, meervoudige ondertekening-portemonnee van BitPay.
|
||||||
|
Copay gebruikers kunnen individueel saldo beheren of veilig financiën delen met andere gebruikers door middel van portemonnees met meervoudige ondertekening, dit voorkomt ongeautoriseerde betalingen doordat meerdere goedkeuringen nodig zijn. Hier zijn een aantal manieren waarop Copay gebruikt kan worden met anderen:
|
||||||
|
|
||||||
|
Om te sparen voor vakanties of gezamenlijke aankopen met vrienden
|
||||||
|
Voor het bijhouden van de familieuitgaven en zakgeld
|
||||||
|
Voor het beheer van het saldo en de uitgaven van een bedrijf, club of organisatie
|
||||||
|
|
||||||
|
We hebben de volgende functies ingebouwd in deze versie van Copay voor een bitcoin portemonnee die niet inlevert op beveiliging of toegankelijkheid:
|
||||||
|
|
||||||
|
Het aanmaken en beheren van meerdere portemonnees binnen de app
|
||||||
|
Intuïtieve meervoudige-ondertekening beveiliging voor persoonlijke of gedeelde portemonnees
|
||||||
|
Eenvoudige bestedingsvoorstellen voor gedeelde portemonnees en groepsbetalingen
|
||||||
|
Hiërarchisch deterministische (HD) adres generatie en portemonnee backups
|
||||||
|
Apparaat gebaseerde beveiliging: alle privé sleutels worden lokaal opgeslagen, niet in de cloud
|
||||||
|
Ondersteuning voor Bitcoin testnet portemonnees
|
||||||
|
Gesynchroniseerde toegang vanaf alle grote mobiele en desktop platformen
|
||||||
|
Ondersteuning voor betalings protocol (BIP70-BIP73): gemakkelijk te herkennen betalingsverzoeken en verifieerbaar veilige bitcoin betalingen
|
||||||
|
Ondersteuning voor prijsweergave in 150+ valuta's en eenheid denominatie in BTC of bits
|
||||||
|
Email meldingen voor betalingen en overdrachten
|
||||||
|
Aanpasbare portemonnee namen en achtergrond kleuren
|
||||||
|
10 ondersteunde talen (EN, CZ, FR, DE, IT, ES, JA, PL, RU, NL)
|
||||||
|
|
||||||
|
Copay is gratis open source software draaiend op niet-merkgebonden servers, dus het is niet nodig te vertrouwen op enig bedrijf voor blijvende ondersteuning. Iedereen kan de broncode van Copay inzien of er aan bijdragen via GitHub (https://github.com/bitpay/copay).
|
||||||
0
i18n/docs/updateinfo_nl.txt
Normal file
1115
i18n/po/de.po
1121
i18n/po/es.po
1131
i18n/po/fr.po
1239
i18n/po/it.po
1205
i18n/po/ja.po
3630
i18n/po/nl.po
Normal file
1203
i18n/po/pl.po
1197
i18n/po/pt.po
1163
i18n/po/ru.po
1099
i18n/po/template.pot
1355
i18n/po/zh.po
|
|
@ -14,7 +14,7 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
var form = addressbookForm;
|
var form = addressbookForm;
|
||||||
if (data && form) {
|
if (data && form) {
|
||||||
data = data.replace('bitcoin:', '');
|
data = data.replace(/^bitcoin(cash)?:/, '');
|
||||||
form.address.$setViewValue(data);
|
form.address.$setViewValue(data);
|
||||||
form.address.$isValid = true;
|
form.address.$isValid = true;
|
||||||
form.address.$render();
|
form.address.$render();
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, $state, $timeout, $stateParams, lodash, addressbookService, popupService, $ionicHistory, platformInfo, gettextCatalog) {
|
angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, $state, $timeout, lodash, addressbookService, popupService, $ionicHistory, platformInfo, gettextCatalog, bitcoreCash) {
|
||||||
$scope.isChromeApp = platformInfo.isChromeApp;
|
$scope.isChromeApp = platformInfo.isChromeApp;
|
||||||
$scope.addressbookEntry = {};
|
$scope.addressbookEntry = {};
|
||||||
$scope.addressbookEntry.name = $stateParams.name;
|
var coin;
|
||||||
$scope.addressbookEntry.email = $stateParams.email;
|
|
||||||
$scope.addressbookEntry.address = $stateParams.address;
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
$scope.addressbookEntry = {};
|
||||||
|
$scope.addressbookEntry.name = data.stateParams.name;
|
||||||
|
$scope.addressbookEntry.email = data.stateParams.email;
|
||||||
|
$scope.addressbookEntry.address = data.stateParams.address;
|
||||||
|
|
||||||
|
var cashAddress = bitcoreCash.Address.isValid($scope.addressbookEntry.address, 'livenet');
|
||||||
|
if (cashAddress) {
|
||||||
|
coin = 'bch';
|
||||||
|
} else {
|
||||||
|
coin = 'btc';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$scope.sendTo = function() {
|
$scope.sendTo = function() {
|
||||||
$ionicHistory.removeBackView();
|
$ionicHistory.removeBackView();
|
||||||
|
|
@ -14,7 +26,8 @@ angular.module('copayApp.controllers').controller('addressbookViewController', f
|
||||||
$state.transitionTo('tabs.send.amount', {
|
$state.transitionTo('tabs.send.amount', {
|
||||||
toAddress: $scope.addressbookEntry.address,
|
toAddress: $scope.addressbookEntry.address,
|
||||||
toName: $scope.addressbookEntry.name,
|
toName: $scope.addressbookEntry.name,
|
||||||
toEmail: $scope.addressbookEntry.email
|
toEmail: $scope.addressbookEntry.email,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('addressesController', function($scope, $log, $stateParams, $state, $timeout, $ionicHistory, $ionicScrollDelegate, configService, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, bwcError, platformInfo, appConfigService, txFormatService, feeService) {
|
angular.module('copayApp.controllers').controller('addressesController', function($scope, $log, $stateParams, $state, $timeout, $ionicHistory, $ionicScrollDelegate, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, bwcError, platformInfo, appConfigService, txFormatService, feeService) {
|
||||||
var UNUSED_ADDRESS_LIMIT = 5;
|
var UNUSED_ADDRESS_LIMIT = 5;
|
||||||
var BALANCE_ADDRESS_LIMIT = 5;
|
var BALANCE_ADDRESS_LIMIT = 5;
|
||||||
var config = configService.getSync().wallet.settings;
|
|
||||||
var unitName = config.unitName;
|
|
||||||
var unitToSatoshi = config.unitToSatoshi;
|
|
||||||
var satToUnit = 1 / unitToSatoshi;
|
|
||||||
var unitDecimals = config.unitDecimals;
|
|
||||||
var withBalance, cachedWallet;
|
var withBalance, cachedWallet;
|
||||||
|
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
|
@ -55,7 +50,7 @@ angular.module('copayApp.controllers').controller('addressesController', functio
|
||||||
$scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT);
|
$scope.latestWithBalance = lodash.slice(withBalance, 0, BALANCE_ADDRESS_LIMIT);
|
||||||
|
|
||||||
lodash.each(withBalance, function(a) {
|
lodash.each(withBalance, function(a) {
|
||||||
a.balanceStr = txFormatService.formatAmount(a.amount);
|
a.balanceStr = txFormatService.formatAmountStr($scope.wallet.coin, a.amount);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.viewAll = {
|
$scope.viewAll = {
|
||||||
|
|
@ -75,11 +70,11 @@ angular.module('copayApp.controllers').controller('addressesController', functio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
feeService.getFeeLevels(function(err, levels){
|
feeService.getFeeLevels($scope.wallet.coin, function(err, levels){
|
||||||
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
|
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
|
|
||||||
if (resp.allUtxos && resp.allUtxos.length) {
|
if (resp && resp.allUtxos && resp.allUtxos.length) {
|
||||||
|
|
||||||
|
|
||||||
var allSum = lodash.sum(resp.allUtxos || 0, 'satoshis');
|
var allSum = lodash.sum(resp.allUtxos || 0, 'satoshis');
|
||||||
|
|
@ -88,9 +83,9 @@ angular.module('copayApp.controllers').controller('addressesController', functio
|
||||||
$scope.lowWarning = resp.warning;
|
$scope.lowWarning = resp.warning;
|
||||||
$scope.lowUtxosNb = resp.lowUtxos.length;
|
$scope.lowUtxosNb = resp.lowUtxos.length;
|
||||||
$scope.allUtxosNb = resp.allUtxos.length;
|
$scope.allUtxosNb = resp.allUtxos.length;
|
||||||
$scope.lowUtxosSum = txFormatService.formatAmountStr(lodash.sum(resp.lowUtxos || 0, 'satoshis'));
|
$scope.lowUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, lodash.sum(resp.lowUtxos || 0, 'satoshis'));
|
||||||
$scope.allUtxosSum = txFormatService.formatAmountStr(allSum);
|
$scope.allUtxosSum = txFormatService.formatAmountStr($scope.wallet.coin, allSum);
|
||||||
$scope.minFee = txFormatService.formatAmountStr(resp.minFee || 0);
|
$scope.minFee = txFormatService.formatAmountStr($scope.wallet.coin, resp.minFee || 0);
|
||||||
$scope.minFeePer = per.toFixed(2) + '%';
|
$scope.minFeePer = per.toFixed(2) + '%';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $log, configService, platformInfo) {
|
angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $log, configService, platformInfo, externalLinkService, gettextCatalog) {
|
||||||
|
|
||||||
var updateConfig = function() {
|
var updateConfig = function() {
|
||||||
var config = configService.getSync();
|
var config = configService.getSync();
|
||||||
|
|
@ -14,6 +14,7 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
|
||||||
$scope.hideNextSteps = {
|
$scope.hideNextSteps = {
|
||||||
value: config.hideNextSteps.enabled
|
value: config.hideNextSteps.enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.spendUnconfirmedChange = function() {
|
$scope.spendUnconfirmedChange = function() {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,14 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
var SMALL_FONT_SIZE_LIMIT = 10;
|
var SMALL_FONT_SIZE_LIMIT = 10;
|
||||||
var LENGTH_EXPRESSION_LIMIT = 19;
|
var LENGTH_EXPRESSION_LIMIT = 19;
|
||||||
var isNW = platformInfo.isNW;
|
var isNW = platformInfo.isNW;
|
||||||
|
|
||||||
|
var unitIndex = 0;
|
||||||
|
var altUnitIndex = 0;
|
||||||
|
var availableUnits = [];
|
||||||
|
var fiatCode;
|
||||||
|
|
||||||
|
var fixedUnit;
|
||||||
|
|
||||||
$scope.isChromeApp = platformInfo.isChromeApp;
|
$scope.isChromeApp = platformInfo.isChromeApp;
|
||||||
|
|
||||||
$scope.$on('$ionicView.leave', function() {
|
$scope.$on('$ionicView.leave', function() {
|
||||||
|
|
@ -16,19 +24,100 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
var config = configService.getSync().wallet.settings;
|
||||||
|
|
||||||
|
function setAvailableUnits() {
|
||||||
|
|
||||||
|
availableUnits = [];
|
||||||
|
|
||||||
|
var hasBTCWallets = profileService.getWallets({
|
||||||
|
coin: 'btc'
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
if (hasBTCWallets) {
|
||||||
|
availableUnits.push({
|
||||||
|
name: 'Bitcoin',
|
||||||
|
id: 'btc',
|
||||||
|
shortName: 'BTC',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var hasBCHWallets = profileService.getWallets({
|
||||||
|
coin: 'bch'
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (hasBCHWallets) {
|
||||||
|
availableUnits.push({
|
||||||
|
name: 'Bitcoin Cash',
|
||||||
|
id: 'bch',
|
||||||
|
shortName: 'BCH',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
unitIndex = 0;
|
||||||
|
|
||||||
|
if (data.stateParams.coin) {
|
||||||
|
var coins = data.stateParams.coin.split(',');
|
||||||
|
var newAvailableUnits = [];
|
||||||
|
|
||||||
|
lodash.each(coins, function(c) {
|
||||||
|
var coin = lodash.find(availableUnits, {
|
||||||
|
id: c
|
||||||
|
});
|
||||||
|
if (!coin) {
|
||||||
|
$log.warn('Could not find desired coin:' + data.stateParams.coin)
|
||||||
|
} else {
|
||||||
|
newAvailableUnits.push(coin);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newAvailableUnits.length > 0) {
|
||||||
|
availableUnits = newAvailableUnits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// currency have preference
|
||||||
|
var fiatName;
|
||||||
|
if (data.stateParams.currency) {
|
||||||
|
fiatCode = data.stateParams.currency;
|
||||||
|
altUnitIndex = unitIndex
|
||||||
|
unitIndex = availableUnits.length;
|
||||||
|
} else {
|
||||||
|
fiatCode = config.alternativeIsoCode || 'USD';
|
||||||
|
fiatName = config.alternanativeName || fiatCode;
|
||||||
|
altUnitIndex = availableUnits.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
availableUnits.push({
|
||||||
|
name: fiatName || fiatCode,
|
||||||
|
// TODO
|
||||||
|
id: fiatCode,
|
||||||
|
shortName: fiatCode,
|
||||||
|
isFiat: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.stateParams.fixedUnit) {
|
||||||
|
fixedUnit = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Go to...
|
// Go to...
|
||||||
_id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID)
|
_id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID)
|
||||||
$scope.nextStep = data.stateParams.nextStep;
|
$scope.nextStep = data.stateParams.nextStep;
|
||||||
$scope.currency = data.stateParams.currency;
|
|
||||||
$scope.forceCurrency = data.stateParams.forceCurrency;
|
|
||||||
|
|
||||||
$scope.showMenu = $ionicHistory.backView() && ($ionicHistory.backView().stateName == 'tabs.send' ||
|
|
||||||
$ionicHistory.backView().stateName == 'tabs.bitpayCard');
|
setAvailableUnits();
|
||||||
|
updateUnitUI();
|
||||||
|
|
||||||
|
$scope.showMenu = $ionicHistory.backView() && ($ionicHistory.backView().stateName == 'tabs.send' || $ionicHistory.backView().stateName == 'tabs.bitpayCard');
|
||||||
$scope.recipientType = data.stateParams.recipientType || null;
|
$scope.recipientType = data.stateParams.recipientType || null;
|
||||||
$scope.toAddress = data.stateParams.toAddress;
|
$scope.toAddress = data.stateParams.toAddress;
|
||||||
$scope.toName = data.stateParams.toName;
|
$scope.toName = data.stateParams.toName;
|
||||||
$scope.toEmail = data.stateParams.toEmail;
|
$scope.toEmail = data.stateParams.toEmail;
|
||||||
$scope.showAlternativeAmount = !!$scope.nextStep;
|
|
||||||
$scope.toColor = data.stateParams.toColor;
|
$scope.toColor = data.stateParams.toColor;
|
||||||
$scope.showSendMax = false;
|
$scope.showSendMax = false;
|
||||||
|
|
||||||
|
|
@ -52,23 +141,13 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
} else if (e.key.match(reOp)) {
|
} else if (e.key.match(reOp)) {
|
||||||
$scope.pushOperator(e.key);
|
$scope.pushOperator(e.key);
|
||||||
} else if (e.keyCode === 86) {
|
} else if (e.keyCode === 86) {
|
||||||
if (e.ctrlKey || e.metaKey)
|
if (e.ctrlKey || e.metaKey) processClipboard();
|
||||||
processClipboard();
|
} else if (e.keyCode === 13) $scope.finish();
|
||||||
} else if (e.keyCode === 13)
|
|
||||||
$scope.finish();
|
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var config = configService.getSync().wallet.settings;
|
|
||||||
$scope.unitName = config.unitName;
|
|
||||||
if (data.stateParams.currency) {
|
|
||||||
$scope.alternativeIsoCode = data.stateParams.currency;
|
|
||||||
} else {
|
|
||||||
$scope.alternativeIsoCode = config.alternativeIsoCode || 'USD';
|
|
||||||
}
|
|
||||||
$scope.specificAmount = $scope.specificAlternativeAmount = '';
|
$scope.specificAmount = $scope.specificAlternativeAmount = '';
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
unitToSatoshi = config.unitToSatoshi;
|
unitToSatoshi = config.unitToSatoshi;
|
||||||
|
|
@ -114,16 +193,59 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
$scope.finish();
|
$scope.finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleAlternative = function() {
|
|
||||||
if ($scope.forceCurrency) return;
|
|
||||||
$scope.showAlternativeAmount = !$scope.showAlternativeAmount;
|
|
||||||
|
|
||||||
|
$scope.toggleAlternative = function() {
|
||||||
if ($scope.amount && isExpression($scope.amount)) {
|
if ($scope.amount && isExpression($scope.amount)) {
|
||||||
var amount = evaluate(format($scope.amount));
|
var amount = evaluate(format($scope.amount));
|
||||||
$scope.globalResult = '= ' + processResult(amount);
|
$scope.globalResult = '= ' + processResult(amount);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updateUnitUI() {
|
||||||
|
$scope.unit = availableUnits[unitIndex].shortName;
|
||||||
|
$scope.alternativeUnit = availableUnits[altUnitIndex].shortName;
|
||||||
|
|
||||||
|
processAmount();
|
||||||
|
$log.debug('Update unit coin @amount unit:' + $scope.unit + " alternativeUnit:" + $scope.alternativeUnit);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.changeUnit = function() {
|
||||||
|
if (fixedUnit) return;
|
||||||
|
|
||||||
|
unitIndex++;
|
||||||
|
if (unitIndex >= availableUnits.length) unitIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (availableUnits[unitIndex].isFiat) {
|
||||||
|
// Always return to BTC... TODO?
|
||||||
|
altUnitIndex = 0;
|
||||||
|
} else {
|
||||||
|
altUnitIndex = lodash.findIndex(availableUnits, {
|
||||||
|
isFiat: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUnitUI();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$scope.changeAlternativeUnit = function() {
|
||||||
|
|
||||||
|
// Do nothing is fiat is not main unit
|
||||||
|
if (!availableUnits[unitIndex].isFiat) return;
|
||||||
|
|
||||||
|
var nextCoin = lodash.findIndex(availableUnits, function(x) {
|
||||||
|
if (x.isFiat) return false;
|
||||||
|
if (x.id == availableUnits[altUnitIndex].id) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nextCoin >= 0) {
|
||||||
|
altUnitIndex = nextCoin;
|
||||||
|
updateUnitUI();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function checkFontSize() {
|
function checkFontSize() {
|
||||||
if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true;
|
if ($scope.amount && $scope.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true;
|
||||||
else $scope.smallFont = false;
|
else $scope.smallFont = false;
|
||||||
|
|
@ -132,7 +254,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
$scope.pushDigit = function(digit) {
|
$scope.pushDigit = function(digit) {
|
||||||
if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return;
|
if ($scope.amount && $scope.amount.length >= LENGTH_EXPRESSION_LIMIT) return;
|
||||||
if ($scope.amount.indexOf('.') > -1 && digit == '.') return;
|
if ($scope.amount.indexOf('.') > -1 && digit == '.') return;
|
||||||
if ($scope.showAlternativeAmount && $scope.amount.indexOf('.') > -1 && $scope.amount[$scope.amount.indexOf('.') + 2]) return;
|
if (availableUnits[unitIndex].isFiat && $scope.amount.indexOf('.') > -1 && $scope.amount[$scope.amount.indexOf('.') + 2]) return;
|
||||||
|
|
||||||
$scope.amount = ($scope.amount + digit).replace('..', '.');
|
$scope.amount = ($scope.amount + digit).replace('..', '.');
|
||||||
checkFontSize();
|
checkFontSize();
|
||||||
|
|
@ -169,7 +291,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.resetAmount = function() {
|
$scope.resetAmount = function() {
|
||||||
$scope.amount = $scope.alternativeResult = $scope.amountResult = $scope.globalResult = '';
|
$scope.amount = $scope.alternativeAmount = $scope.globalResult = '';
|
||||||
$scope.allowSend = false;
|
$scope.allowSend = false;
|
||||||
checkFontSize();
|
checkFontSize();
|
||||||
};
|
};
|
||||||
|
|
@ -180,24 +302,39 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
$scope.allowSend = lodash.isNumber(result) && +result > 0;
|
$scope.allowSend = lodash.isNumber(result) && +result > 0;
|
||||||
if (lodash.isNumber(result)) {
|
if (lodash.isNumber(result)) {
|
||||||
$scope.globalResult = isExpression($scope.amount) ? '= ' + processResult(result) : '';
|
$scope.globalResult = isExpression($scope.amount) ? '= ' + processResult(result) : '';
|
||||||
$scope.amountResult = $filter('formatFiatAmount')(toFiat(result));
|
|
||||||
$scope.alternativeResult = txFormatService.formatAmount(fromFiat(result) * unitToSatoshi, true);
|
if (availableUnits[unitIndex].isFiat) {
|
||||||
|
|
||||||
|
var a = fromFiat(result);
|
||||||
|
if (a) {
|
||||||
|
$scope.alternativeAmount = txFormatService.formatAmount(a * unitToSatoshi, true);
|
||||||
|
} else {
|
||||||
|
if (result) {
|
||||||
|
$scope.alternativeAmount = 'N/A';
|
||||||
|
} else {
|
||||||
|
$scope.alternativeAmount = null;
|
||||||
|
}
|
||||||
|
$scope.allowSend = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$scope.alternativeAmount = $filter('formatFiatAmount')(toFiat(result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function processResult(val) {
|
function processResult(val) {
|
||||||
if ($scope.showAlternativeAmount)
|
if (availableUnits[unitIndex].isFiat) return $filter('formatFiatAmount')(val);
|
||||||
return $filter('formatFiatAmount')(val);
|
else return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true);
|
||||||
else
|
|
||||||
return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function fromFiat(val) {
|
function fromFiat(val) {
|
||||||
return parseFloat((rateService.fromFiat(val, $scope.alternativeIsoCode) * satToUnit).toFixed(unitDecimals));
|
return parseFloat((rateService.fromFiat(val, fiatCode, availableUnits[altUnitIndex].id) * satToUnit).toFixed(unitDecimals));
|
||||||
};
|
};
|
||||||
|
|
||||||
function toFiat(val) {
|
function toFiat(val) {
|
||||||
return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2));
|
if (!rateService.getRate(fiatCode)) return;
|
||||||
|
|
||||||
|
return parseFloat((rateService.toFiat(val * unitToSatoshi, fiatCode, availableUnits[unitIndex].id)).toFixed(2));
|
||||||
};
|
};
|
||||||
|
|
||||||
function evaluate(val) {
|
function evaluate(val) {
|
||||||
|
|
@ -212,33 +349,50 @@ angular.module('copayApp.controllers').controller('amountController', function($
|
||||||
};
|
};
|
||||||
|
|
||||||
function format(val) {
|
function format(val) {
|
||||||
|
if (!val) return;
|
||||||
|
|
||||||
var result = val.toString();
|
var result = val.toString();
|
||||||
|
|
||||||
if (isOperator(lodash.last(val)))
|
if (isOperator(lodash.last(val))) result = result.slice(0, -1);
|
||||||
result = result.slice(0, -1);
|
|
||||||
|
|
||||||
return result.replace('x', '*');
|
return result.replace('x', '*');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.finish = function() {
|
$scope.finish = function() {
|
||||||
|
|
||||||
|
var unit = availableUnits[unitIndex];
|
||||||
var _amount = evaluate(format($scope.amount));
|
var _amount = evaluate(format($scope.amount));
|
||||||
|
var coin = unit.id;
|
||||||
|
if (unit.isFiat) {
|
||||||
|
coin = availableUnits[altUnitIndex].id;
|
||||||
|
}
|
||||||
|
|
||||||
if ($scope.nextStep) {
|
if ($scope.nextStep) {
|
||||||
|
|
||||||
$state.transitionTo($scope.nextStep, {
|
$state.transitionTo($scope.nextStep, {
|
||||||
id: _id,
|
id: _id,
|
||||||
amount: $scope.useSendMax ? null : _amount,
|
amount: $scope.useSendMax ? null : _amount,
|
||||||
currency: $scope.showAlternativeAmount ? $scope.alternativeIsoCode : $scope.unitName,
|
currency: unit.id.toUpperCase(),
|
||||||
|
coin: coin,
|
||||||
useSendMax: $scope.useSendMax
|
useSendMax: $scope.useSendMax
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var amount = $scope.showAlternativeAmount ? fromFiat(_amount) : _amount;
|
var amount = _amount;
|
||||||
|
|
||||||
|
if (unit.isFiat) {
|
||||||
|
amount = (fromFiat(amount) * unitToSatoshi).toFixed(0);
|
||||||
|
} else {
|
||||||
|
amount = (amount * unitToSatoshi).toFixed(0);
|
||||||
|
}
|
||||||
|
|
||||||
$state.transitionTo('tabs.send.confirm', {
|
$state.transitionTo('tabs.send.confirm', {
|
||||||
recipientType: $scope.recipientType,
|
recipientType: $scope.recipientType,
|
||||||
toAmount: $scope.useSendMax ? null : (amount * unitToSatoshi).toFixed(0),
|
toAmount: amount,
|
||||||
toAddress: $scope.toAddress,
|
toAddress: $scope.toAddress,
|
||||||
toName: $scope.toName,
|
toName: $scope.toName,
|
||||||
toEmail: $scope.toEmail,
|
toEmail: $scope.toEmail,
|
||||||
toColor: $scope.toColor,
|
toColor: $scope.toColor,
|
||||||
|
coin: coin,
|
||||||
useSendMax: $scope.useSendMax
|
useSendMax: $scope.useSendMax
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('buyAmazonController', function($scope, $log, $state, $timeout, $filter, $ionicHistory, $ionicConfig, lodash, amazonService, popupService, profileService, ongoingProcess, configService, walletService, payproService, bwcError, externalLinkService, platformInfo, gettextCatalog, txFormatService) {
|
angular.module('copayApp.controllers').controller('buyAmazonController', function($scope, $log, $state, $timeout, $filter, $ionicHistory, $ionicConfig, lodash, amazonService, popupService, profileService, ongoingProcess, configService, walletService, payproService, bwcError, externalLinkService, platformInfo, gettextCatalog, txFormatService) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
var amount;
|
var amount;
|
||||||
var currency;
|
var currency;
|
||||||
var createdTx;
|
var createdTx;
|
||||||
|
|
@ -64,7 +65,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
|
||||||
};
|
};
|
||||||
|
|
||||||
var satToFiat = function(sat, cb) {
|
var satToFiat = function(sat, cb) {
|
||||||
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) {
|
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
|
||||||
return cb(value);
|
return cb(value);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -216,8 +217,8 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
|
||||||
});
|
});
|
||||||
|
|
||||||
var initialize = function(wallet) {
|
var initialize = function(wallet) {
|
||||||
var parsedAmount = txFormatService.parseAmount(amount, currency);
|
var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
|
||||||
$scope.currencyIsoCode = parsedAmount.alternativeIsoCode;
|
$scope.currencyIsoCode = parsedAmount.currency;
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
var dataSrc = {
|
var dataSrc = {
|
||||||
amount: parsedAmount.amount,
|
amount: parsedAmount.amount,
|
||||||
|
|
@ -260,7 +261,7 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
|
||||||
invoiceUrl: invoice.url,
|
invoiceUrl: invoice.url,
|
||||||
invoiceTime: invoice.invoiceTime
|
invoiceTime: invoice.invoiceTime
|
||||||
};
|
};
|
||||||
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount);
|
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
|
||||||
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
|
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -292,7 +293,8 @@ angular.module('copayApp.controllers').controller('buyAmazonController', functio
|
||||||
$scope.wallets = profileService.getWallets({
|
$scope.wallets = profileService.getWallets({
|
||||||
onlyComplete: true,
|
onlyComplete: true,
|
||||||
network: $scope.network,
|
network: $scope.network,
|
||||||
hasFunds: true
|
hasFunds: true,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
showErrorAndBack(null, gettextCatalog.getString('No wallets available'));
|
showErrorAndBack(null, gettextCatalog.getString('No wallets available'));
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('buyCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, txFormatService) {
|
angular.module('copayApp.controllers').controller('buyCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, txFormatService) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
var amount;
|
var amount;
|
||||||
var currency;
|
var currency;
|
||||||
|
|
||||||
|
|
@ -33,6 +34,52 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var processPaymentInfo = function() {
|
||||||
|
ongoingProcess.set('connectingCoinbase', true);
|
||||||
|
coinbaseService.init(function(err, res) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var accessToken = res.accessToken;
|
||||||
|
|
||||||
|
coinbaseService.buyPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, b) {
|
||||||
|
$scope.buyPrice = b.data || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.paymentMethods = [];
|
||||||
|
$scope.selectedPaymentMethodId = { value : null };
|
||||||
|
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasPrimary;
|
||||||
|
var pm;
|
||||||
|
for(var i = 0; i < p.data.length; i++) {
|
||||||
|
pm = p.data[i];
|
||||||
|
if (pm.allow_buy) {
|
||||||
|
$scope.paymentMethods.push(pm);
|
||||||
|
}
|
||||||
|
if (pm.allow_buy && pm.primary_buy) {
|
||||||
|
hasPrimary = true;
|
||||||
|
$scope.selectedPaymentMethodId.value = pm.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lodash.isEmpty($scope.paymentMethods)) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack('No payment method available to buy');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
|
||||||
|
$scope.buyRequest();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
||||||
$ionicConfig.views.swipeBackEnabled(true);
|
$ionicConfig.views.swipeBackEnabled(true);
|
||||||
});
|
});
|
||||||
|
|
@ -42,81 +89,22 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
|
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
|
||||||
var parsedAmount = txFormatService.parseAmount(
|
amount = data.stateParams.amount;
|
||||||
data.stateParams.amount,
|
currency = data.stateParams.currency;
|
||||||
data.stateParams.currency);
|
|
||||||
|
|
||||||
// Buy always in BTC
|
$scope.network = coinbaseService.getNetwork();
|
||||||
amount = (parsedAmount.amountSat / 100000000).toFixed(8);
|
$scope.wallets = profileService.getWallets({
|
||||||
currency = 'BTC';
|
onlyComplete: true,
|
||||||
|
network: $scope.network,
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
coin: coin
|
||||||
|
|
||||||
ongoingProcess.set('calculatingFee', true);
|
|
||||||
coinbaseService.checkEnoughFundsForFee(amount, function(err) {
|
|
||||||
ongoingProcess.set('calculatingFee', false);
|
|
||||||
if (err) {
|
|
||||||
showErrorAndBack(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.network = coinbaseService.getNetwork();
|
|
||||||
$scope.wallets = profileService.getWallets({
|
|
||||||
onlyComplete: true,
|
|
||||||
network: $scope.network
|
|
||||||
});
|
|
||||||
|
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
|
||||||
showErrorAndBack('No wallets available');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$scope.wallet = $scope.wallets[0]; // Default first wallet
|
|
||||||
|
|
||||||
ongoingProcess.set('connectingCoinbase', true);
|
|
||||||
coinbaseService.init(function(err, res) {
|
|
||||||
if (err) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var accessToken = res.accessToken;
|
|
||||||
|
|
||||||
coinbaseService.buyPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, b) {
|
|
||||||
$scope.buyPrice = b.data || null;
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.paymentMethods = [];
|
|
||||||
$scope.selectedPaymentMethodId = { value : null };
|
|
||||||
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
|
|
||||||
if (err) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasPrimary;
|
|
||||||
var pm;
|
|
||||||
for(var i = 0; i < p.data.length; i++) {
|
|
||||||
pm = p.data[i];
|
|
||||||
if (pm.allow_buy) {
|
|
||||||
$scope.paymentMethods.push(pm);
|
|
||||||
}
|
|
||||||
if (pm.allow_buy && pm.primary_buy) {
|
|
||||||
hasPrimary = true;
|
|
||||||
$scope.selectedPaymentMethodId.value = pm.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lodash.isEmpty($scope.paymentMethods)) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack('No payment method available to buy');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
|
|
||||||
$scope.buyRequest();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
|
showErrorAndBack('No wallets available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.buyRequest = function() {
|
$scope.buyRequest = function() {
|
||||||
|
|
@ -209,21 +197,31 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var _processBuyOrder = function() {
|
||||||
|
coinbaseService.getBuyOrder(accessToken, accountId, b.data.id, function (err, buyResp) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('buyingBitcoin', false, statusChangeHandler);
|
||||||
|
showError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tx = buyResp.data ? buyResp.data.transaction : null;
|
||||||
|
if (tx && tx.id) {
|
||||||
|
processBuyTx(tx);
|
||||||
|
} else {
|
||||||
|
$timeout(function() {
|
||||||
|
_processBuyOrder();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
var tx = b.data ? b.data.transaction : null;
|
var tx = b.data ? b.data.transaction : null;
|
||||||
if (tx) {
|
if (tx && tx.id) {
|
||||||
processBuyTx(tx);
|
processBuyTx(tx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
coinbaseService.getBuyOrder(accessToken, accountId, b.data.id, function (err, buyResp) {
|
_processBuyOrder();
|
||||||
if (err) {
|
|
||||||
ongoingProcess.set('buyingBitcoin', false, statusChangeHandler);
|
|
||||||
showError(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var tx = buyResp.data ? buyResp.data.transaction : null;
|
|
||||||
processBuyTx(tx);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, 8000);
|
}, 8000);
|
||||||
});
|
});
|
||||||
|
|
@ -238,6 +236,25 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct
|
||||||
|
|
||||||
$scope.onWalletSelect = function(wallet) {
|
$scope.onWalletSelect = function(wallet) {
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
var parsedAmount = txFormatService.parseAmount(
|
||||||
|
coin,
|
||||||
|
amount,
|
||||||
|
currency);
|
||||||
|
|
||||||
|
// Buy always in BTC
|
||||||
|
amount = (parsedAmount.amountSat / 100000000).toFixed(8);
|
||||||
|
currency = 'BTC';
|
||||||
|
|
||||||
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
ongoingProcess.set('calculatingFee', true);
|
||||||
|
coinbaseService.checkEnoughFundsForFee(amount, function(err) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
|
if (err) {
|
||||||
|
showErrorAndBack(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processPaymentInfo();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goBackHome = function() {
|
$scope.goBackHome = function() {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('buyGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, platformInfo, txFormatService) {
|
angular.module('copayApp.controllers').controller('buyGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, platformInfo, txFormatService) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
var amount;
|
var amount;
|
||||||
var currency;
|
var currency;
|
||||||
|
|
||||||
|
|
@ -35,36 +36,7 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
var processPaymentInfo = function() {
|
||||||
$ionicConfig.views.swipeBackEnabled(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
|
||||||
$ionicConfig.views.swipeBackEnabled(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
|
||||||
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
|
|
||||||
var parsedAmount = txFormatService.parseAmount(
|
|
||||||
data.stateParams.amount,
|
|
||||||
data.stateParams.currency);
|
|
||||||
|
|
||||||
amount = parsedAmount.amount;
|
|
||||||
currency = parsedAmount.currency;
|
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
|
||||||
|
|
||||||
$scope.network = glideraService.getNetwork();
|
|
||||||
$scope.wallets = profileService.getWallets({
|
|
||||||
onlyComplete: true,
|
|
||||||
network: $scope.network
|
|
||||||
});
|
|
||||||
|
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
|
||||||
showErrorAndBack('No wallets available');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$scope.wallet = $scope.wallets[0]; // Default first wallet
|
|
||||||
|
|
||||||
ongoingProcess.set('connectingGlidera', true);
|
ongoingProcess.set('connectingGlidera', true);
|
||||||
glideraService.init(function(err, data) {
|
glideraService.init(function(err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -88,6 +60,33 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
|
||||||
$scope.buyInfo = buy;
|
$scope.buyInfo = buy;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
|
||||||
|
amount = data.stateParams.amount;
|
||||||
|
currency = data.stateParams.currency;
|
||||||
|
|
||||||
|
$scope.network = glideraService.getNetwork();
|
||||||
|
$scope.wallets = profileService.getWallets({
|
||||||
|
onlyComplete: true,
|
||||||
|
network: $scope.network,
|
||||||
|
coin: coin
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
|
showErrorAndBack('No wallets available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
|
||||||
});
|
});
|
||||||
|
|
||||||
var ask2FaCode = function(mode, cb) {
|
var ask2FaCode = function(mode, cb) {
|
||||||
|
|
@ -162,6 +161,15 @@ angular.module('copayApp.controllers').controller('buyGlideraController', functi
|
||||||
|
|
||||||
$scope.onWalletSelect = function(wallet) {
|
$scope.onWalletSelect = function(wallet) {
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
var parsedAmount = txFormatService.parseAmount(
|
||||||
|
coin,
|
||||||
|
amount,
|
||||||
|
currency);
|
||||||
|
|
||||||
|
amount = parsedAmount.amount;
|
||||||
|
currency = parsedAmount.currency;
|
||||||
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
processPaymentInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goBackHome = function() {
|
$scope.goBackHome = function() {
|
||||||
|
|
|
||||||
354
src/js/controllers/buyMercadoLibre.js
Normal file
|
|
@ -0,0 +1,354 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('buyMercadoLibreController', function($scope, $log, $state, $timeout, $filter, $ionicHistory, $ionicConfig, lodash, mercadoLibreService, popupService, profileService, ongoingProcess, configService, walletService, payproService, bwcError, externalLinkService, platformInfo, txFormatService, gettextCatalog) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
|
var amount;
|
||||||
|
var currency;
|
||||||
|
var createdTx;
|
||||||
|
var message;
|
||||||
|
var invoiceId;
|
||||||
|
var configWallet = configService.getSync().wallet;
|
||||||
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
|
||||||
|
$scope.openExternalLink = function(url) {
|
||||||
|
externalLinkService.open(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
var _resetValues = function() {
|
||||||
|
$scope.totalAmountStr = $scope.amount = $scope.invoiceFee = $scope.networkFee = $scope.totalAmount = $scope.wallet = null;
|
||||||
|
createdTx = message = invoiceId = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var showErrorAndBack = function(title, msg) {
|
||||||
|
title = title || gettextCatalog.getString('Error');
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
$log.error(msg);
|
||||||
|
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
|
||||||
|
popupService.showAlert(title, msg, function() {
|
||||||
|
$ionicHistory.goBack();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var showError = function(title, msg, cb) {
|
||||||
|
cb = cb || function() {};
|
||||||
|
title = title || gettextCatalog.getString('Error');
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
$log.error(msg);
|
||||||
|
msg = (msg && msg.errors) ? msg.errors[0].message : msg;
|
||||||
|
popupService.showAlert(title, msg, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
var publishAndSign = function(wallet, txp, onSendStatusChange, cb) {
|
||||||
|
if (!wallet.canSign() && !wallet.isPrivKeyExternal()) {
|
||||||
|
var err = 'No signing proposal: No private key';
|
||||||
|
$log.info(err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
walletService.publishAndSign(wallet, txp, function(err, txp) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
return cb(null, txp);
|
||||||
|
}, onSendStatusChange);
|
||||||
|
};
|
||||||
|
|
||||||
|
var statusChangeHandler = function(processName, showName, isOn) {
|
||||||
|
$log.debug('statusChangeHandler: ', processName, showName, isOn);
|
||||||
|
if (processName == 'Comprando Vale-Presente' && !isOn) {
|
||||||
|
$scope.sendStatus = 'success';
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
}, 100);
|
||||||
|
} else if (showName) {
|
||||||
|
$scope.sendStatus = showName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var satToFiat = function(sat, cb) {
|
||||||
|
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
|
||||||
|
return cb(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var setTotalAmount = function(amountSat, invoiceFeeSat, networkFeeSat) {
|
||||||
|
satToFiat(amountSat, function(a) {
|
||||||
|
$scope.amount = Number(a);
|
||||||
|
|
||||||
|
satToFiat(invoiceFeeSat, function(i) {
|
||||||
|
$scope.invoiceFee = Number(i);
|
||||||
|
|
||||||
|
satToFiat(networkFeeSat, function(n) {
|
||||||
|
$scope.networkFee = Number(n);
|
||||||
|
$scope.totalAmount = $scope.amount + $scope.invoiceFee + $scope.networkFee;
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var createInvoice = function(data, cb) {
|
||||||
|
mercadoLibreService.createBitPayInvoice(data, function(err, dataInvoice) {
|
||||||
|
if (err) {
|
||||||
|
var err_title = gettextCatalog.getString('Error creating the invoice');
|
||||||
|
var err_msg;
|
||||||
|
if (err && err.message && err.message.match(/suspended/i)) {
|
||||||
|
err_title = gettextCatalog.getString('Service not available');
|
||||||
|
err_msg = gettextCatalog.getString('Mercadolibre Gift Card Service is not available at this moment. Please try back later.');
|
||||||
|
} else if (err && err.message) {
|
||||||
|
err_msg = err.message;
|
||||||
|
} else {
|
||||||
|
err_msg = gettextCatalog.getString('Could not access Gift Card Service');
|
||||||
|
};
|
||||||
|
|
||||||
|
return cb({
|
||||||
|
title: err_title,
|
||||||
|
message: err_msg
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessKey = dataInvoice ? dataInvoice.accessKey : null;
|
||||||
|
|
||||||
|
if (!accessKey) {
|
||||||
|
return cb({
|
||||||
|
message: gettextCatalog.getString('No access key defined')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mercadoLibreService.getBitPayInvoice(dataInvoice.invoiceId, function(err, invoice) {
|
||||||
|
if (err) {
|
||||||
|
return cb({
|
||||||
|
message: gettextCatalog.getString('Could not get the invoice')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(null, invoice, accessKey);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var createTx = function(wallet, invoice, message, cb) {
|
||||||
|
var payProUrl = (invoice && invoice.paymentUrls) ? invoice.paymentUrls.BIP73 : null;
|
||||||
|
|
||||||
|
if (!payProUrl) {
|
||||||
|
return cb({
|
||||||
|
title: gettextCatalog.getString('Error in Payment Protocol'),
|
||||||
|
message: gettextCatalog.getString('Invalid URL')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputs = [];
|
||||||
|
var toAddress = invoice.bitcoinAddress;
|
||||||
|
var amountSat = parseInt((invoice.btcDue * 100000000).toFixed(0)); // BTC to Satoshi
|
||||||
|
|
||||||
|
outputs.push({
|
||||||
|
'toAddress': toAddress,
|
||||||
|
'amount': amountSat,
|
||||||
|
'message': message
|
||||||
|
});
|
||||||
|
|
||||||
|
var txp = {
|
||||||
|
toAddress: toAddress,
|
||||||
|
amount: amountSat,
|
||||||
|
outputs: outputs,
|
||||||
|
message: message,
|
||||||
|
payProUrl: payProUrl,
|
||||||
|
excludeUnconfirmedUtxos: configWallet.spendUnconfirmed ? false : true,
|
||||||
|
feeLevel: configWallet.settings.feeLevel || 'normal'
|
||||||
|
};
|
||||||
|
|
||||||
|
walletService.createTx(wallet, txp, function(err, ctxp) {
|
||||||
|
if (err) {
|
||||||
|
return cb({
|
||||||
|
title: gettextCatalog.getString('Could not create transaction'),
|
||||||
|
message: bwcError.msg(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cb(null, ctxp);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var checkTransaction = lodash.throttle(function(count, dataSrc) {
|
||||||
|
mercadoLibreService.createGiftCard(dataSrc, function(err, giftCard) {
|
||||||
|
$log.debug("creating gift card " + count);
|
||||||
|
if (err) {
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
ongoingProcess.set('Comprando Vale-Presente', false, statusChangeHandler);
|
||||||
|
giftCard = {};
|
||||||
|
giftCard.status = 'FAILURE';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giftCard && giftCard.cardStatus && (giftCard.cardStatus != 'active' && giftCard.cardStatus != 'inactive' && giftCard.cardStatus != 'expired')) {
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
ongoingProcess.set('Comprando Vale-Presente', false, statusChangeHandler);
|
||||||
|
giftCard = {};
|
||||||
|
giftCard.status = 'FAILURE';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (giftCard.status == 'PENDING' && count < 3) {
|
||||||
|
$log.debug("Waiting for payment confirmation");
|
||||||
|
checkTransaction(count + 1, dataSrc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = moment().unix() * 1000;
|
||||||
|
|
||||||
|
var newData = giftCard;
|
||||||
|
newData['invoiceId'] = dataSrc.invoiceId;
|
||||||
|
newData['accessKey'] = dataSrc.accessKey;
|
||||||
|
newData['invoiceUrl'] = dataSrc.invoiceUrl;
|
||||||
|
newData['amount'] = dataSrc.amount;
|
||||||
|
newData['currency'] = dataSrc.currency;
|
||||||
|
newData['date'] = dataSrc.invoiceTime || now;
|
||||||
|
newData['uuid'] = dataSrc.uuid;
|
||||||
|
|
||||||
|
mercadoLibreService.savePendingGiftCard(newData, null, function(err) {
|
||||||
|
ongoingProcess.set('Comprando Vale-Presente', false, statusChangeHandler);
|
||||||
|
$log.debug("Saving new gift card with status: " + newData.status);
|
||||||
|
$scope.mlGiftCard = newData;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 8000, {
|
||||||
|
'leading': true
|
||||||
|
});
|
||||||
|
|
||||||
|
var initialize = function(wallet) {
|
||||||
|
var parsedAmount = txFormatService.parseAmount(coin, amount, currency);
|
||||||
|
$scope.currencyIsoCode = parsedAmount.currency;
|
||||||
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
var dataSrc = {
|
||||||
|
amount: parsedAmount.amount,
|
||||||
|
currency: parsedAmount.currency,
|
||||||
|
uuid: wallet.id
|
||||||
|
};
|
||||||
|
ongoingProcess.set('loadingTxInfo', true);
|
||||||
|
createInvoice(dataSrc, function(err, invoice, accessKey) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('loadingTxInfo', false);
|
||||||
|
showErrorAndBack(err.title, err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Sometimes API does not return this element;
|
||||||
|
invoice['buyerPaidBtcMinerFee'] = invoice.buyerPaidBtcMinerFee || 0;
|
||||||
|
var invoiceFeeSat = (invoice.buyerPaidBtcMinerFee * 100000000).toFixed();
|
||||||
|
|
||||||
|
message = gettextCatalog.getString("{{amountStr}} for Mercado Livre Brazil Gift Card", {
|
||||||
|
amountStr: $scope.amountUnitStr
|
||||||
|
});
|
||||||
|
|
||||||
|
createTx(wallet, invoice, message, function(err, ctxp) {
|
||||||
|
ongoingProcess.set('loadingTxInfo', false);
|
||||||
|
if (err) {
|
||||||
|
_resetValues();
|
||||||
|
showError(err.title, err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save in memory
|
||||||
|
createdTx = ctxp;
|
||||||
|
invoiceId = invoice.id;
|
||||||
|
|
||||||
|
createdTx['giftData'] = {
|
||||||
|
currency: dataSrc.currency,
|
||||||
|
amount: dataSrc.amount,
|
||||||
|
uuid: dataSrc.uuid,
|
||||||
|
accessKey: accessKey,
|
||||||
|
invoiceId: invoice.id,
|
||||||
|
invoiceUrl: invoice.url,
|
||||||
|
invoiceTime: invoice.invoiceTime
|
||||||
|
};
|
||||||
|
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
|
||||||
|
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
amount = data.stateParams.amount;
|
||||||
|
currency = data.stateParams.currency;
|
||||||
|
|
||||||
|
if (amount > 2000 || amount < 50) {
|
||||||
|
showErrorAndBack(null, gettextCatalog.getString('Purchase amount must be a value between 50 and 2000'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.network = mercadoLibreService.getNetwork();
|
||||||
|
$scope.wallets = profileService.getWallets({
|
||||||
|
onlyComplete: true,
|
||||||
|
network: $scope.network,
|
||||||
|
coin: coin
|
||||||
|
});
|
||||||
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
|
showErrorAndBack(null, gettextCatalog.getString('No wallets available'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.buyConfirm = function() {
|
||||||
|
|
||||||
|
if (!createdTx) {
|
||||||
|
showError(null, gettextCatalog.getString('Transaction has not been created'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = gettextCatalog.getString('Confirm');
|
||||||
|
var okText = gettextCatalog.getString('Ok');
|
||||||
|
var cancelText = gettextCatalog.getString('Cancel');
|
||||||
|
popupService.showConfirm(title, message, okText, cancelText, function(ok) {
|
||||||
|
if (!ok) {
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ongoingProcess.set('Comprando Vale-Presente', true, statusChangeHandler);
|
||||||
|
publishAndSign($scope.wallet, createdTx, function() {}, function(err, txSent) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('Comprando Vale-Presente', false, statusChangeHandler);
|
||||||
|
showError(gettextCatalog.getString('Could not send transaction'), err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkTransaction(1, createdTx.giftData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.showWalletSelector = function() {
|
||||||
|
$scope.walletSelectorTitle = 'Buy from';
|
||||||
|
$scope.showWallets = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onWalletSelect = function(wallet) {
|
||||||
|
$scope.wallet = wallet;
|
||||||
|
initialize(wallet);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.goBackHome = function() {
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true,
|
||||||
|
historyRoot: true
|
||||||
|
});
|
||||||
|
$ionicHistory.clearHistory();
|
||||||
|
$state.go('tabs.home').then(function() {
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true
|
||||||
|
});
|
||||||
|
$state.transitionTo('tabs.giftcards.mercadoLibre').then(function() {
|
||||||
|
$state.transitionTo('tabs.giftcards.mercadoLibre.cards', {
|
||||||
|
invoiceId: invoiceId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
192
src/js/controllers/cashScan.js
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('cashScanController',
|
||||||
|
function($rootScope, $timeout, $scope, $state, $ionicHistory, gettextCatalog, lodash, ongoingProcess, profileService, walletService, $log, txFormatService, bwcError, pushNotificationsService, bwcService, externalLinkService) {
|
||||||
|
var wallet;
|
||||||
|
var errors = bwcService.getErrors();
|
||||||
|
$scope.error = null;
|
||||||
|
$scope.walletDisabled = '#667';
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
updateAllWallets();
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.openRecoveryToolLink = function() {
|
||||||
|
var url = 'https://bitpay.github.io/copay-recovery/';
|
||||||
|
var optIn = true;
|
||||||
|
var title = null;
|
||||||
|
var message = gettextCatalog.getString('Open the recovery tool.');
|
||||||
|
var okText = gettextCatalog.getString('Open');
|
||||||
|
var cancelText = gettextCatalog.getString('Go Back');
|
||||||
|
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||||
|
};
|
||||||
|
|
||||||
|
var goHome = function() {
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true,
|
||||||
|
historyRoot: true
|
||||||
|
});
|
||||||
|
$ionicHistory.clearHistory();
|
||||||
|
$state.go('tabs.settings').then(function() {
|
||||||
|
$state.transitionTo('tabs.home');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateAllWallets = function() {
|
||||||
|
var walletsBTC = profileService.getWallets({
|
||||||
|
coin: 'btc',
|
||||||
|
onlyComplete: true,
|
||||||
|
network: 'livenet'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter out already duplicated wallets
|
||||||
|
var walletsBCH = profileService.getWallets({
|
||||||
|
coin: 'bch',
|
||||||
|
network: 'livenet'
|
||||||
|
});
|
||||||
|
var xPubKeyIndex = lodash.indexBy(walletsBCH, "credentials.xPubKey");
|
||||||
|
|
||||||
|
walletsBTC = lodash.filter(walletsBTC, function(w) {
|
||||||
|
return !xPubKeyIndex[w.credentials.xPubKey];
|
||||||
|
});
|
||||||
|
|
||||||
|
var availableWallets = [];
|
||||||
|
var nonEligibleWallets = [];
|
||||||
|
|
||||||
|
lodash.each(walletsBTC, function(w) {
|
||||||
|
if (w.credentials.derivationStrategy != 'BIP44') {
|
||||||
|
w.excludeReason = gettextCatalog.getString('Non BIP44 wallet');
|
||||||
|
nonEligibleWallets.push(w);
|
||||||
|
} else if (!w.canSign()) {
|
||||||
|
w.excludeReason = gettextCatalog.getString('Read only wallet');
|
||||||
|
nonEligibleWallets.push(w);
|
||||||
|
} else if (w.needsBackup) {
|
||||||
|
w.excludeReason = gettextCatalog.getString('Backup needed');
|
||||||
|
nonEligibleWallets.push(w);
|
||||||
|
} else {
|
||||||
|
availableWallets.push(w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.availableWallets = availableWallets;
|
||||||
|
$scope.nonEligibleWallets = nonEligibleWallets;
|
||||||
|
|
||||||
|
var i = availableWallets.length;
|
||||||
|
var j = 0;
|
||||||
|
lodash.each(availableWallets, function(wallet) {
|
||||||
|
walletService.getBalance(wallet, {
|
||||||
|
coin: 'bch'
|
||||||
|
}, function(err, balance) {
|
||||||
|
if (err) {
|
||||||
|
wallet.error = (err === 'WALLET_NOT_REGISTERED') ? gettextCatalog.getString('Wallet not registered') : bwcError.msg(err);
|
||||||
|
$log.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet.error = null;
|
||||||
|
wallet.bchBalance = txFormatService.formatAmountStr('bch', balance.availableAmount);
|
||||||
|
if (++j == i) {
|
||||||
|
//Done
|
||||||
|
$timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.duplicate = function(wallet) {
|
||||||
|
$scope.error = null;
|
||||||
|
$log.debug('Duplicating wallet for BCH:' + wallet.id + ':' + wallet.name);
|
||||||
|
|
||||||
|
var opts = {};
|
||||||
|
opts.name = wallet.name + '[BCH]';
|
||||||
|
opts.m = wallet.m;
|
||||||
|
opts.n = wallet.n;
|
||||||
|
opts.myName = wallet.credentials.copayerName;
|
||||||
|
opts.networkName = wallet.network;
|
||||||
|
opts.coin = 'bch';
|
||||||
|
opts.walletPrivKey = wallet.credentials.walletPrivKey;
|
||||||
|
opts.compliantDerivation = wallet.credentials.compliantDerivation;
|
||||||
|
|
||||||
|
|
||||||
|
function setErr(err, cb) {
|
||||||
|
|
||||||
|
if (!cb) cb = function() {};
|
||||||
|
|
||||||
|
$scope.error = bwcError.cb(err, gettextCatalog.getString('Could not duplicate'), function() {
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
$timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function importOrCreate(cb) {
|
||||||
|
walletService.getStatus(wallet, {}, function(err, status) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
|
||||||
|
opts.singleAddress = status.wallet.singleAddress;
|
||||||
|
|
||||||
|
// first try to import
|
||||||
|
profileService.importExtendedPrivateKey(opts.extendedPrivateKey, opts, function(err, newWallet) {
|
||||||
|
if (err && !(err instanceof errors.NOT_AUTHORIZED)) {
|
||||||
|
return setErr(err, cb);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
// create and store a wallet
|
||||||
|
return profileService.createWallet(opts, function(err, newWallet) {
|
||||||
|
if (err) return setErr(err, cb);
|
||||||
|
return cb(null, newWallet, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cb(null, newWallet);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Multisig wallets? add Copayers
|
||||||
|
function addCopayers(newWallet, isNew, cb) {
|
||||||
|
if (!isNew) return cb();
|
||||||
|
if (wallet.n == 1) return cb();
|
||||||
|
|
||||||
|
$log.info('Adding copayers for BCH wallet config:' + wallet.m + '-' + wallet.n);
|
||||||
|
|
||||||
|
walletService.copyCopayers(wallet, newWallet, function(err) {
|
||||||
|
if (err) return setErr(err, cb);
|
||||||
|
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
walletService.getKeys(wallet, function(err, keys) {
|
||||||
|
if (err) {
|
||||||
|
$scope.error = err;
|
||||||
|
return $timeout(function() {
|
||||||
|
$rootScope.$apply();
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
opts.extendedPrivateKey = keys.xPrivKey;
|
||||||
|
ongoingProcess.set('duplicatingWallet', true);
|
||||||
|
importOrCreate(function(err, newWallet, isNew) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('duplicatingWallet', false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walletService.updateRemotePreferences(newWallet);
|
||||||
|
pushNotificationsService.updateSubscription(newWallet);
|
||||||
|
|
||||||
|
addCopayers(newWallet, isNew, function(err) {
|
||||||
|
ongoingProcess.set('duplicatingWallet', false);
|
||||||
|
if (err)
|
||||||
|
return setErr(err);
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
walletService.startScan(newWallet, function() {});
|
||||||
|
|
||||||
|
goHome();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification) {
|
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService) {
|
||||||
|
|
||||||
var countDown = null;
|
var countDown = null;
|
||||||
var CONFIRM_LIMIT_USD = 20;
|
var CONFIRM_LIMIT_USD = 20;
|
||||||
|
|
@ -28,7 +28,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
function refresh() {
|
function refresh() {
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
}, 1);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -58,9 +58,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function setNoWallet(msg) {
|
function setNoWallet(msg, criticalError) {
|
||||||
$scope.wallet = null;
|
$scope.wallet = null;
|
||||||
$scope.noWalletMessage = msg;
|
$scope.noWalletMessage = msg;
|
||||||
|
$scope.criticalError = criticalError;
|
||||||
$log.warn('Not ready to make the payment:' + msg);
|
$log.warn('Not ready to make the payment:' + msg);
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
|
|
@ -69,18 +70,19 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
|
||||||
function setWalletSelector(network, minAmount, cb) {
|
function setWalletSelector(coin, network, minAmount, cb) {
|
||||||
|
|
||||||
// no min amount? (sendMax) => look for no empty wallets
|
// no min amount? (sendMax) => look for no empty wallets
|
||||||
minAmount = minAmount || 1;
|
minAmount = minAmount || 1;
|
||||||
|
|
||||||
$scope.wallets = profileService.getWallets({
|
$scope.wallets = profileService.getWallets({
|
||||||
onlyComplete: true,
|
onlyComplete: true,
|
||||||
network: network
|
network: network,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!$scope.wallets || !$scope.wallets.length) {
|
if (!$scope.wallets || !$scope.wallets.length) {
|
||||||
setNoWallet(gettextCatalog.getString('No wallets available'));
|
setNoWallet(gettextCatalog.getString('No wallets available'), true);
|
||||||
return cb();
|
return cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +111,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
return cb('Could not update any wallet');
|
return cb('Could not update any wallet');
|
||||||
|
|
||||||
if (lodash.isEmpty(filteredWallets)) {
|
if (lodash.isEmpty(filteredWallets)) {
|
||||||
setNoWallet(gettextCatalog.getString('Insufficient funds'));
|
setNoWallet(gettextCatalog.getString('Insufficient funds'), true);
|
||||||
}
|
}
|
||||||
$scope.wallets = lodash.clone(filteredWallets);
|
$scope.wallets = lodash.clone(filteredWallets);
|
||||||
return cb();
|
return cb();
|
||||||
|
|
@ -120,6 +122,30 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
|
|
||||||
// Setup $scope
|
// Setup $scope
|
||||||
|
|
||||||
|
var B = data.stateParams.coin == 'bch' ? bitcoreCash : bitcore;
|
||||||
|
var networkName;
|
||||||
|
try {
|
||||||
|
networkName = (new B.Address(data.stateParams.toAddress)).network.name;
|
||||||
|
} catch(e) {
|
||||||
|
var message = gettextCatalog.getString('Copay only supports Bitcoin Cash using new version numbers addresses');
|
||||||
|
var backText = gettextCatalog.getString('Go back');
|
||||||
|
var learnText = gettextCatalog.getString('Learn more');
|
||||||
|
popupService.showConfirm(null, message, backText, learnText, function(back) {
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true,
|
||||||
|
historyRoot: true
|
||||||
|
});
|
||||||
|
$state.go('tabs.send').then(function() {
|
||||||
|
$ionicHistory.clearHistory();
|
||||||
|
if (!back) {
|
||||||
|
var url = 'https://support.bitpay.com/hc/en-us/articles/115004671663';
|
||||||
|
externalLinkService.open(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Grab stateParams
|
// Grab stateParams
|
||||||
tx = {
|
tx = {
|
||||||
toAmount: parseInt(data.stateParams.toAmount),
|
toAmount: parseInt(data.stateParams.toAmount),
|
||||||
|
|
@ -136,33 +162,32 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
toName: data.stateParams.toName,
|
toName: data.stateParams.toName,
|
||||||
toEmail: data.stateParams.toEmail,
|
toEmail: data.stateParams.toEmail,
|
||||||
toColor: data.stateParams.toColor,
|
toColor: data.stateParams.toColor,
|
||||||
network: (new bitcore.Address(data.stateParams.toAddress)).network.name,
|
network: networkName,
|
||||||
|
coin: data.stateParams.coin,
|
||||||
txp: {},
|
txp: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (tx.coin && tx.coin == 'bch') tx.feeLevel = 'normal';
|
||||||
|
|
||||||
// Other Scope vars
|
// Other Scope vars
|
||||||
$scope.isCordova = isCordova;
|
$scope.isCordova = isCordova;
|
||||||
$scope.isWindowsPhoneApp = isWindowsPhoneApp;
|
$scope.isWindowsPhoneApp = isWindowsPhoneApp;
|
||||||
$scope.showAddress = false;
|
$scope.showAddress = false;
|
||||||
|
|
||||||
updateTx(tx, null, {}, function() {
|
$scope.walletSelectorTitle = gettextCatalog.getString('Send from');
|
||||||
|
|
||||||
$scope.walletSelectorTitle = gettextCatalog.getString('Send from');
|
setWalletSelector(tx.coin, tx.network, tx.toAmount, function(err) {
|
||||||
|
if (err) {
|
||||||
setWalletSelector(tx.network, tx.toAmount, function(err) {
|
return exitWithError('Could not update wallets');
|
||||||
if (err) {
|
}
|
||||||
return exitWithError('Could not update wallets');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.wallets.length > 1) {
|
|
||||||
$scope.showWalletSelector();
|
|
||||||
} else if ($scope.wallets.length) {
|
|
||||||
setWallet($scope.wallets[0], tx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
if ($scope.wallets.length > 1) {
|
||||||
|
$scope.showWalletSelector();
|
||||||
|
} else if ($scope.wallets.length) {
|
||||||
|
setWallet($scope.wallets[0], tx);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -227,6 +252,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateTx(tx, wallet, opts, cb) {
|
function updateTx(tx, wallet, opts, cb) {
|
||||||
|
ongoingProcess.set('calculatingFee', true);
|
||||||
|
|
||||||
if (opts.clearCache) {
|
if (opts.clearCache) {
|
||||||
tx.txp = {};
|
tx.txp = {};
|
||||||
|
|
@ -238,10 +264,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
if (!tx.toAmount) return;
|
if (!tx.toAmount) return;
|
||||||
|
|
||||||
// Amount
|
// Amount
|
||||||
tx.amountStr = txFormatService.formatAmountStr(tx.toAmount);
|
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.toAmount);
|
||||||
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
||||||
tx.amountUnitStr = tx.amountStr.split(' ')[1];
|
tx.amountUnitStr = tx.amountStr.split(' ')[1];
|
||||||
txFormatService.formatAlternativeStr(tx.toAmount, function(v) {
|
txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) {
|
||||||
tx.alternativeAmountStr = v;
|
tx.alternativeAmountStr = v;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -250,19 +276,23 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
// End of quick refresh, before wallet is selected.
|
// End of quick refresh, before wallet is selected.
|
||||||
if (!wallet) return cb();
|
if (!wallet) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
feeService.getFeeRate(tx.network, tx.feeLevel, function(err, feeRate) {
|
feeService.getFeeRate(wallet.coin, tx.network, tx.feeLevel, function(err, feeRate) {
|
||||||
if (err) return cb(err);
|
if (err) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!usingCustomFee) tx.feeRate = feeRate;
|
if (!usingCustomFee) tx.feeRate = feeRate;
|
||||||
tx.feeLevelName = feeService.feeOpts[tx.feeLevel];
|
tx.feeLevelName = feeService.feeOpts[tx.feeLevel];
|
||||||
|
|
||||||
if (!wallet)
|
|
||||||
return cb();
|
|
||||||
|
|
||||||
getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) {
|
getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
var msg = gettextCatalog.getString('Error getting SendMax information');
|
var msg = gettextCatalog.getString('Error getting SendMax information');
|
||||||
return setSendError(msg);
|
return setSendError(msg);
|
||||||
}
|
}
|
||||||
|
|
@ -272,6 +302,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
$log.debug('Send max info', sendMaxInfo);
|
$log.debug('Send max info', sendMaxInfo);
|
||||||
|
|
||||||
if (tx.sendMax && sendMaxInfo.amount == 0) {
|
if (tx.sendMax && sendMaxInfo.amount == 0) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
setNoWallet(gettextCatalog.getString('Insufficient funds'));
|
setNoWallet(gettextCatalog.getString('Insufficient funds'));
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'));
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'));
|
||||||
return cb('no_funds');
|
return cb('no_funds');
|
||||||
|
|
@ -280,20 +311,27 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
tx.sendMaxInfo = sendMaxInfo;
|
tx.sendMaxInfo = sendMaxInfo;
|
||||||
tx.toAmount = tx.sendMaxInfo.amount;
|
tx.toAmount = tx.sendMaxInfo.amount;
|
||||||
updateAmount();
|
updateAmount();
|
||||||
showSendMaxWarning(sendMaxInfo);
|
ongoingProcess.set('calculatingFee', false);
|
||||||
|
$timeout(function() {
|
||||||
|
showSendMaxWarning(wallet, sendMaxInfo);
|
||||||
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
// txp already generated for this wallet?
|
// txp already generated for this wallet?
|
||||||
if (tx.txp[wallet.id]) {
|
if (tx.txp[wallet.id]) {
|
||||||
|
ongoingProcess.set('calculatingFee', false);
|
||||||
refresh();
|
refresh();
|
||||||
return cb();
|
return cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
|
getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) {
|
||||||
if (err) return cb(err);
|
ongoingProcess.set('calculatingFee', false);
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
txp.feeStr = txFormatService.formatAmountStr(txp.fee);
|
txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee);
|
||||||
txFormatService.formatAlternativeStr(txp.fee, function(v) {
|
txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) {
|
||||||
txp.alternativeFeeStr = v;
|
txp.alternativeFeeStr = v;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -321,14 +359,26 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
}
|
}
|
||||||
|
|
||||||
function setButtonText(isMultisig, isPayPro) {
|
function setButtonText(isMultisig, isPayPro) {
|
||||||
$scope.buttonText = gettextCatalog.getString(isCordova && !isWindowsPhoneApp ? 'Slide' : 'Click') + ' ';
|
|
||||||
|
|
||||||
if (isPayPro) {
|
if (isPayPro) {
|
||||||
$scope.buttonText += gettextCatalog.getString('to pay');
|
if (isCordova && !isWindowsPhoneApp) {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Slide to pay');
|
||||||
|
} else {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Click to pay');
|
||||||
|
}
|
||||||
} else if (isMultisig) {
|
} else if (isMultisig) {
|
||||||
$scope.buttonText += gettextCatalog.getString('to accept');
|
if (isCordova && !isWindowsPhoneApp) {
|
||||||
} else
|
$scope.buttonText = gettextCatalog.getString('Slide to accept');
|
||||||
$scope.buttonText += gettextCatalog.getString('to send');
|
} else {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Click to accept');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isCordova && !isWindowsPhoneApp) {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Slide to send');
|
||||||
|
} else {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Click to send');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -337,26 +387,26 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function showSendMaxWarning(sendMaxInfo) {
|
function showSendMaxWarning(wallet, sendMaxInfo) {
|
||||||
|
|
||||||
function verifyExcludedUtxos() {
|
function verifyExcludedUtxos() {
|
||||||
var warningMsg = [];
|
var warningMsg = [];
|
||||||
if (sendMaxInfo.utxosBelowFee > 0) {
|
if (sendMaxInfo.utxosBelowFee > 0) {
|
||||||
warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", {
|
warningMsg.push(gettextCatalog.getString("A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided.", {
|
||||||
amountBelowFeeStr: txFormatService.formatAmountStr(sendMaxInfo.amountBelowFee)
|
amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sendMaxInfo.utxosAboveMaxSize > 0) {
|
if (sendMaxInfo.utxosAboveMaxSize > 0) {
|
||||||
warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", {
|
warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", {
|
||||||
amountAboveMaxSizeStr: txFormatService.formatAmountStr(sendMaxInfo.amountAboveMaxSize)
|
amountAboveMaxSizeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountAboveMaxSize)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return warningMsg.join('\n');
|
return warningMsg.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
|
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
|
||||||
fee: txFormatService.formatAmountStr(sendMaxInfo.fee)
|
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
|
||||||
});
|
});
|
||||||
var warningMsg = verifyExcludedUtxos();
|
var warningMsg = verifyExcludedUtxos();
|
||||||
|
|
||||||
|
|
@ -422,6 +472,11 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
|
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
|
||||||
|
// If select another wallet
|
||||||
|
tx.coin = wallet.coin;
|
||||||
|
tx.feeLevel = wallet.coin == 'bch' ? 'normal' : configFeeLevel;
|
||||||
|
usingCustomFee = null;
|
||||||
|
|
||||||
setButtonText(wallet.credentials.m > 1, !!tx.paypro);
|
setButtonText(wallet.credentials.m > 1, !!tx.paypro);
|
||||||
|
|
||||||
if (tx.paypro)
|
if (tx.paypro)
|
||||||
|
|
@ -483,7 +538,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
if (walletService.isEncrypted(wallet))
|
if (walletService.isEncrypted(wallet))
|
||||||
return cb();
|
return cb();
|
||||||
|
|
||||||
var amountUsd = parseFloat(txFormatService.formatToUSD(txp.amount));
|
var amountUsd = parseFloat(txFormatService.formatToUSD(wallet.coin, txp.amount));
|
||||||
if (amountUsd <= CONFIRM_LIMIT_USD)
|
if (amountUsd <= CONFIRM_LIMIT_USD)
|
||||||
return cb();
|
return cb();
|
||||||
|
|
||||||
|
|
@ -563,10 +618,13 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
|
|
||||||
$scope.chooseFeeLevel = function(tx, wallet) {
|
$scope.chooseFeeLevel = function(tx, wallet) {
|
||||||
|
|
||||||
|
if (wallet.coin == 'bch') return;
|
||||||
|
|
||||||
var scope = $rootScope.$new(true);
|
var scope = $rootScope.$new(true);
|
||||||
scope.network = tx.network;
|
scope.network = tx.network;
|
||||||
scope.feeLevel = tx.feeLevel;
|
scope.feeLevel = tx.feeLevel;
|
||||||
scope.noSave = true;
|
scope.noSave = true;
|
||||||
|
scope.coin = wallet.coin;
|
||||||
|
|
||||||
if (usingCustomFee) {
|
if (usingCustomFee) {
|
||||||
scope.customFeePerKB = tx.feeRate;
|
scope.customFeePerKB = tx.feeRate;
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,16 @@ angular.module('copayApp.controllers').controller('createController',
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
$scope.formData = {};
|
$scope.formData = {};
|
||||||
var defaults = configService.getDefaults();
|
var defaults = configService.getDefaults();
|
||||||
|
var config = configService.getSync();
|
||||||
var tc = $state.current.name == 'tabs.add.create-personal' ? 1 : defaults.wallet.totalCopayers;
|
var tc = $state.current.name == 'tabs.add.create-personal' ? 1 : defaults.wallet.totalCopayers;
|
||||||
$scope.formData.account = 1;
|
$scope.formData.account = 1;
|
||||||
$scope.formData.bwsurl = defaults.bws.url;
|
$scope.formData.bwsurl = defaults.bws.url;
|
||||||
$scope.TCValues = lodash.range(2, defaults.limits.totalCopayers + 1);
|
$scope.TCValues = lodash.range(2, defaults.limits.totalCopayers + 1);
|
||||||
$scope.formData.derivationPath = derivationPathHelper.default;
|
$scope.formData.derivationPath = derivationPathHelper.default;
|
||||||
|
$scope.formData.coin = data.stateParams.coin;
|
||||||
|
|
||||||
|
if (config.cashSupport) $scope.enableCash = true;
|
||||||
|
|
||||||
$scope.setTotalCopayers(tc);
|
$scope.setTotalCopayers(tc);
|
||||||
updateRCSelect(tc);
|
updateRCSelect(tc);
|
||||||
resetPasswordFields();
|
resetPasswordFields();
|
||||||
|
|
@ -133,10 +138,11 @@ angular.module('copayApp.controllers').controller('createController',
|
||||||
m: $scope.formData.requiredCopayers,
|
m: $scope.formData.requiredCopayers,
|
||||||
n: $scope.formData.totalCopayers,
|
n: $scope.formData.totalCopayers,
|
||||||
myName: $scope.formData.totalCopayers > 1 ? $scope.formData.myName : null,
|
myName: $scope.formData.totalCopayers > 1 ? $scope.formData.myName : null,
|
||||||
networkName: $scope.formData.testnetEnabled ? 'testnet' : 'livenet',
|
networkName: $scope.formData.testnetEnabled && $scope.formData.coin != 'bch' ? 'testnet' : 'livenet',
|
||||||
bwsurl: $scope.formData.bwsurl,
|
bwsurl: $scope.formData.bwsurl,
|
||||||
singleAddress: $scope.formData.singleAddressEnabled,
|
singleAddress: $scope.formData.singleAddressEnabled,
|
||||||
walletPrivKey: $scope.formData._walletPrivKey, // Only for testing
|
walletPrivKey: $scope.formData._walletPrivKey, // Only for testing
|
||||||
|
coin: $scope.formData.coin
|
||||||
};
|
};
|
||||||
|
|
||||||
var setSeed = $scope.formData.seedSource.id == 'set';
|
var setSeed = $scope.formData.seedSource.id == 'set';
|
||||||
|
|
@ -170,6 +176,11 @@ angular.module('copayApp.controllers').controller('createController',
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.formData.seedSource.id == walletService.externalSource.ledger.id || $scope.formData.seedSource.id == walletService.externalSource.trezor.id || $scope.formData.seedSource.id == walletService.externalSource.intelTEE.id) {
|
if ($scope.formData.seedSource.id == walletService.externalSource.ledger.id || $scope.formData.seedSource.id == walletService.externalSource.trezor.id || $scope.formData.seedSource.id == walletService.externalSource.intelTEE.id) {
|
||||||
|
if ($scope.formData.coin == 'bch') {
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Hardware wallets are not yet supported with Bitcoin Cash'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var account = $scope.formData.account;
|
var account = $scope.formData.account;
|
||||||
if (!account || account < 1) {
|
if (!account || account < 1) {
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number'));
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number'));
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ angular.module('copayApp.controllers').controller('customAmountController', func
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var setProtocolHandler = function() {
|
||||||
|
$scope.protocolHandler = walletService.getProtocolHandler($scope.wallet);
|
||||||
|
}
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
var walletId = data.stateParams.id;
|
var walletId = data.stateParams.id;
|
||||||
|
|
||||||
|
|
@ -20,6 +24,8 @@ angular.module('copayApp.controllers').controller('customAmountController', func
|
||||||
|
|
||||||
$scope.wallet = profileService.getWallet(walletId);
|
$scope.wallet = profileService.getWallet(walletId);
|
||||||
|
|
||||||
|
setProtocolHandler();
|
||||||
|
|
||||||
walletService.getAddress($scope.wallet, false, function(err, addr) {
|
walletService.getAddress($scope.wallet, false, function(err, addr) {
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
showErrorAndBack('Error', 'Could not get the address');
|
showErrorAndBack('Error', 'Could not get the address');
|
||||||
|
|
@ -28,7 +34,9 @@ angular.module('copayApp.controllers').controller('customAmountController', func
|
||||||
|
|
||||||
$scope.address = addr;
|
$scope.address = addr;
|
||||||
|
|
||||||
|
$scope.coin = data.stateParams.coin;
|
||||||
var parsedAmount = txFormatService.parseAmount(
|
var parsedAmount = txFormatService.parseAmount(
|
||||||
|
$scope.wallet.coin,
|
||||||
data.stateParams.amount,
|
data.stateParams.amount,
|
||||||
data.stateParams.currency);
|
data.stateParams.currency);
|
||||||
|
|
||||||
|
|
@ -37,17 +45,17 @@ angular.module('copayApp.controllers').controller('customAmountController', func
|
||||||
var currency = parsedAmount.currency;
|
var currency = parsedAmount.currency;
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
|
||||||
if (currency != 'BTC') {
|
if (currency != 'BTC' && currency != 'BCH') {
|
||||||
// Convert to BTC
|
// Convert to BTC or BCH
|
||||||
var config = configService.getSync().wallet.settings;
|
var config = configService.getSync().wallet.settings;
|
||||||
var amountUnit = txFormatService.satToUnit(parsedAmount.amountSat);
|
var amountUnit = txFormatService.satToUnit(parsedAmount.amountSat);
|
||||||
var btcParsedAmount = txFormatService.parseAmount(amountUnit, config.unitName);
|
var btcParsedAmount = txFormatService.parseAmount($scope.wallet.coin, amountUnit, $scope.wallet.coin);
|
||||||
|
|
||||||
$scope.amountBtc = btcParsedAmount.amount;
|
$scope.amountBtc = btcParsedAmount.amount;
|
||||||
$scope.altAmountStr = btcParsedAmount.amountUnitStr;
|
$scope.altAmountStr = btcParsedAmount.amountUnitStr;
|
||||||
} else {
|
} else {
|
||||||
$scope.amountBtc = amount; // BTC
|
$scope.amountBtc = amount; // BTC or BCH
|
||||||
$scope.altAmountStr = txFormatService.formatAlternativeStr(parsedAmount.amountSat);
|
$scope.altAmountStr = txFormatService.formatAlternativeStr($scope.wallet.coin, parsedAmount.amountSat);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -61,12 +69,16 @@ angular.module('copayApp.controllers').controller('customAmountController', func
|
||||||
|
|
||||||
$scope.shareAddress = function() {
|
$scope.shareAddress = function() {
|
||||||
if (!platformInfo.isCordova) return;
|
if (!platformInfo.isCordova) return;
|
||||||
var data = 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc;
|
var protocol = 'bitcoin';
|
||||||
|
if ($scope.wallet.coin == 'bch') protocol += 'cash';
|
||||||
|
var data = protocol + ':' + $scope.address + '?amount=' + $scope.amountBtc;
|
||||||
window.plugins.socialsharing.share(data, null, null, null);
|
window.plugins.socialsharing.share(data, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.copyToClipboard = function() {
|
$scope.copyToClipboard = function() {
|
||||||
return 'bitcoin:' + $scope.address + '?amount=' + $scope.amountBtc;
|
var protocol = 'bitcoin';
|
||||||
|
if ($scope.wallet.coin == 'bch') protocol += 'cash';
|
||||||
|
return protocol + ':' + $scope.address + '?amount=' + $scope.amountBtc;
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
var defaults = configService.getDefaults();
|
var defaults = configService.getDefaults();
|
||||||
|
var config = configService.getSync();
|
||||||
var errors = bwcService.getErrors();
|
var errors = bwcService.getErrors();
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
|
|
@ -15,9 +16,14 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
$scope.formData.bwsurl = defaults.bws.url;
|
$scope.formData.bwsurl = defaults.bws.url;
|
||||||
$scope.formData.derivationPath = derivationPathHelper.default;
|
$scope.formData.derivationPath = derivationPathHelper.default;
|
||||||
$scope.formData.account = 1;
|
$scope.formData.account = 1;
|
||||||
|
$scope.formData.coin = $stateParams.coin;
|
||||||
$scope.importErr = false;
|
$scope.importErr = false;
|
||||||
$scope.isCopay = appConfigService.name == 'copay';
|
$scope.isCopay = appConfigService.name == 'copay';
|
||||||
$scope.fromHardwareWallet = { value: false };
|
$scope.fromHardwareWallet = {
|
||||||
|
value: false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config.cashSupport) $scope.enableCash = true;
|
||||||
|
|
||||||
if ($stateParams.code)
|
if ($stateParams.code)
|
||||||
$scope.processWalletInfo($stateParams.code);
|
$scope.processWalletInfo($stateParams.code);
|
||||||
|
|
@ -59,6 +65,15 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.switchTestnetOff = function() {
|
||||||
|
$scope.formData.testnetEnabled = false;
|
||||||
|
$scope.setDerivationPath();
|
||||||
|
$scope.resizeView();
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.processWalletInfo = function(code) {
|
$scope.processWalletInfo = function(code) {
|
||||||
if (!code) return;
|
if (!code) return;
|
||||||
|
|
||||||
|
|
@ -203,6 +218,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||||||
var opts = {};
|
var opts = {};
|
||||||
opts.bwsurl = $scope.formData.bwsurl;
|
opts.bwsurl = $scope.formData.bwsurl;
|
||||||
|
opts.coin = $scope.formData.coin;
|
||||||
_importBlob(evt.target.result, opts);
|
_importBlob(evt.target.result, opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,6 +244,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
} else {
|
} else {
|
||||||
var opts = {};
|
var opts = {};
|
||||||
opts.bwsurl = $scope.formData.bwsurl;
|
opts.bwsurl = $scope.formData.bwsurl;
|
||||||
|
opts.coin = $scope.formData.coin;
|
||||||
_importBlob(backupText, opts);
|
_importBlob(backupText, opts);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -253,6 +270,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
opts.account = pathData.account;
|
opts.account = pathData.account;
|
||||||
opts.networkName = pathData.networkName;
|
opts.networkName = pathData.networkName;
|
||||||
opts.derivationStrategy = pathData.derivationStrategy;
|
opts.derivationStrategy = pathData.derivationStrategy;
|
||||||
|
opts.coin = $scope.formData.coin;
|
||||||
|
|
||||||
var words = $scope.formData.words || null;
|
var words = $scope.formData.words || null;
|
||||||
|
|
||||||
|
|
@ -279,7 +297,7 @@ angular.module('copayApp.controllers').controller('importController',
|
||||||
$log.warn('This wont work for Intel TEE wallets');
|
$log.warn('This wont work for Intel TEE wallets');
|
||||||
|
|
||||||
var id = $scope.formData.seedSourceAll.id;
|
var id = $scope.formData.seedSourceAll.id;
|
||||||
var isMultisig = opts.derivationStrategy =='BIP48';
|
var isMultisig = opts.derivationStrategy == 'BIP48';
|
||||||
var account = opts.account;
|
var account = opts.account;
|
||||||
opts.entropySourcePath = 'm/' + hwWallet.getEntropyPath(id, isMultisig, account);
|
opts.entropySourcePath = 'm/' + hwWallet.getEntropyPath(id, isMultisig, account);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,14 @@ angular.module('copayApp.controllers').controller('joinController',
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
var defaults = configService.getDefaults();
|
var defaults = configService.getDefaults();
|
||||||
|
var config = configService.getSync();
|
||||||
$scope.formData = {};
|
$scope.formData = {};
|
||||||
$scope.formData.bwsurl = defaults.bws.url;
|
$scope.formData.bwsurl = defaults.bws.url;
|
||||||
$scope.formData.derivationPath = derivationPathHelper.default;
|
$scope.formData.derivationPath = derivationPathHelper.default;
|
||||||
$scope.formData.account = 1;
|
$scope.formData.account = 1;
|
||||||
$scope.formData.secret = null;
|
$scope.formData.secret = null;
|
||||||
|
$scope.formData.coin = data.stateParams.coin;
|
||||||
|
if (config.cashSupport) $scope.enableCash = true;
|
||||||
resetPasswordFields();
|
resetPasswordFields();
|
||||||
updateSeedSourceSelect();
|
updateSeedSourceSelect();
|
||||||
});
|
});
|
||||||
|
|
@ -103,7 +106,8 @@ angular.module('copayApp.controllers').controller('joinController',
|
||||||
var opts = {
|
var opts = {
|
||||||
secret: $scope.formData.secret,
|
secret: $scope.formData.secret,
|
||||||
myName: $scope.formData.myName,
|
myName: $scope.formData.myName,
|
||||||
bwsurl: $scope.formData.bwsurl
|
bwsurl: $scope.formData.bwsurl,
|
||||||
|
coin: $scope.formData.coin
|
||||||
}
|
}
|
||||||
|
|
||||||
var setSeed = $scope.formData.seedSource.id == 'set';
|
var setSeed = $scope.formData.seedSource.id == 'set';
|
||||||
|
|
@ -137,6 +141,11 @@ angular.module('copayApp.controllers').controller('joinController',
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.formData.seedSource.id == walletService.externalSource.ledger.id || $scope.formData.seedSource.id == walletService.externalSource.trezor.id || $scope.formData.seedSource.id == walletService.externalSource.intelTEE.id) {
|
if ($scope.formData.seedSource.id == walletService.externalSource.ledger.id || $scope.formData.seedSource.id == walletService.externalSource.trezor.id || $scope.formData.seedSource.id == walletService.externalSource.intelTEE.id) {
|
||||||
|
if ($scope.formData.coin == 'bch') {
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Hardware wallets are not yet supported with Bitcoin Cash'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var account = $scope.formData.account;
|
var account = $scope.formData.account;
|
||||||
if (!account || account < 1) {
|
if (!account || account < 1) {
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number'));
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number'));
|
||||||
|
|
|
||||||
24
src/js/controllers/mercadoLibre.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('mercadoLibreController',
|
||||||
|
function($scope, $timeout, $log, mercadoLibreService, externalLinkService, popupService) {
|
||||||
|
|
||||||
|
$scope.openExternalLink = function(url) {
|
||||||
|
externalLinkService.open(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function() {
|
||||||
|
mercadoLibreService.getPendingGiftCards(function(err, gcds) {
|
||||||
|
if (err) $log.error(err);
|
||||||
|
$scope.giftCards = gcds;
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
$scope.network = mercadoLibreService.getNetwork();
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
});
|
||||||
100
src/js/controllers/mercadoLibreCards.js
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('mercadoLibreCardsController',
|
||||||
|
function($scope, $timeout, $ionicModal, $log, $ionicScrollDelegate, lodash, mercadoLibreService, platformInfo, externalLinkService, popupService, ongoingProcess) {
|
||||||
|
|
||||||
|
$scope.openExternalLink = function(url) {
|
||||||
|
externalLinkService.open(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateGiftCards = function(cb) {
|
||||||
|
mercadoLibreService.getPendingGiftCards(function(err, gcds) {
|
||||||
|
if (err) {
|
||||||
|
popupService.showAlert('Could not get gift cards', err);
|
||||||
|
if (cb) return cb();
|
||||||
|
else return;
|
||||||
|
}
|
||||||
|
$scope.giftCards = gcds;
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$digest();
|
||||||
|
$ionicScrollDelegate.resize();
|
||||||
|
if (cb) return cb();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.updatePendingGiftCards = lodash.debounce(function() {
|
||||||
|
updateGiftCards(function() {
|
||||||
|
var index = 0;
|
||||||
|
var gcds = $scope.giftCards;
|
||||||
|
lodash.forEach(gcds, function(dataFromStorage) {
|
||||||
|
if (dataFromStorage.status == 'PENDING') {
|
||||||
|
$log.debug("Creating / Updating gift card");
|
||||||
|
|
||||||
|
mercadoLibreService.createGiftCard(dataFromStorage, function(err, giftCard) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
popupService.showAlert('Error creating gift card', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giftCard.status != 'PENDING') {
|
||||||
|
var newData = {};
|
||||||
|
|
||||||
|
if (!giftCard.status) dataFromStorage.status = null; // Fix error from server
|
||||||
|
|
||||||
|
var cardStatus = giftCard.cardStatus;
|
||||||
|
if (cardStatus && (cardStatus != 'active' && cardStatus != 'inactive' && cardStatus != 'expired'))
|
||||||
|
giftCard.status = 'FAILURE';
|
||||||
|
|
||||||
|
lodash.merge(newData, dataFromStorage, giftCard);
|
||||||
|
|
||||||
|
mercadoLibreService.savePendingGiftCard(newData, null, function(err) {
|
||||||
|
$log.debug("Saving new gift card");
|
||||||
|
updateGiftCards();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 1000, {
|
||||||
|
'leading': true
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.openCardModal = function(card) {
|
||||||
|
$scope.card = card;
|
||||||
|
|
||||||
|
$ionicModal.fromTemplateUrl('views/modals/mercadolibre-card-details.html', {
|
||||||
|
scope: $scope
|
||||||
|
}).then(function(modal) {
|
||||||
|
$scope.mercadoLibreCardDetailsModal = modal;
|
||||||
|
$scope.mercadoLibreCardDetailsModal.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on('modal.hidden', function() {
|
||||||
|
$scope.updatePendingGiftCards();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
$scope.invoiceId = data.stateParams.invoiceId;
|
||||||
|
updateGiftCards(function() {
|
||||||
|
if ($scope.invoiceId) {
|
||||||
|
var card = lodash.find($scope.giftCards, {
|
||||||
|
invoiceId: $scope.invoiceId
|
||||||
|
});
|
||||||
|
if (lodash.isEmpty(card)) {
|
||||||
|
popupService.showAlert(null, 'Card not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.openCardModal(card);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.afterEnter", function(event, data) {
|
||||||
|
$scope.updatePendingGiftCards();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -18,14 +18,14 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
|
||||||
var value = lodash.find($scope.feeLevels[$scope.network], {
|
var value = lodash.find($scope.feeLevels[$scope.network], {
|
||||||
level: 'superEconomy'
|
level: 'superEconomy'
|
||||||
});
|
});
|
||||||
return parseInt((value.feePerKB / 1000).toFixed());
|
return parseInt((value.feePerKb / 1000).toFixed());
|
||||||
};
|
};
|
||||||
|
|
||||||
var getMaxRecommended = function() {
|
var getMaxRecommended = function() {
|
||||||
var value = lodash.find($scope.feeLevels[$scope.network], {
|
var value = lodash.find($scope.feeLevels[$scope.network], {
|
||||||
level: 'urgent'
|
level: 'urgent'
|
||||||
});
|
});
|
||||||
return parseInt((value.feePerKB / 1000).toFixed());
|
return parseInt((value.feePerKb / 1000).toFixed());
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.ok = function() {
|
$scope.ok = function() {
|
||||||
|
|
@ -61,7 +61,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
|
||||||
// If no custom fee
|
// If no custom fee
|
||||||
if (value) {
|
if (value) {
|
||||||
$scope.customFeePerKB = null;
|
$scope.customFeePerKB = null;
|
||||||
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed();
|
$scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
|
||||||
$scope.avgConfirmationTime = value.nbBlocks * 10;
|
$scope.avgConfirmationTime = value.nbBlocks * 10;
|
||||||
} else {
|
} else {
|
||||||
$scope.avgConfirmationTime = null;
|
$scope.avgConfirmationTime = null;
|
||||||
|
|
@ -102,7 +102,7 @@ angular.module('copayApp.controllers').controller('feeLevelsController', functio
|
||||||
|
|
||||||
$scope.feeOpts = feeService.feeOpts;
|
$scope.feeOpts = feeService.feeOpts;
|
||||||
$scope.loadingFee = true;
|
$scope.loadingFee = true;
|
||||||
feeService.getFeeLevels(function(err, levels) {
|
feeService.getFeeLevels($scope.coin, function(err, levels) {
|
||||||
$scope.loadingFee = false;
|
$scope.loadingFee = false;
|
||||||
if (err || lodash.isEmpty(levels)) {
|
if (err || lodash.isEmpty(levels)) {
|
||||||
showErrorAndClose(null, err);
|
showErrorAndClose(null, err);
|
||||||
|
|
|
||||||
21
src/js/controllers/modals/mercadoLibreCardDetails.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('mercadoLibreCardDetailsController', function($scope, mercadoLibreService, externalLinkService) {
|
||||||
|
|
||||||
|
$scope.remove = function() {
|
||||||
|
mercadoLibreService.savePendingGiftCard($scope.card, {
|
||||||
|
remove: true
|
||||||
|
}, function(err) {
|
||||||
|
$scope.close();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.close = function() {
|
||||||
|
$scope.mercadoLibreCardDetailsModal.hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.openExternalLink = function(url) {
|
||||||
|
externalLinkService.open(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -23,7 +23,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
};
|
};
|
||||||
|
|
||||||
function displayFeeValues() {
|
function displayFeeValues() {
|
||||||
txFormatService.formatAlternativeStr($scope.tx.fee, function(v) {
|
txFormatService.formatAlternativeStr($scope.wallet.coin, $scope.tx.fee, function(v) {
|
||||||
$scope.tx.feeFiatStr = v;
|
$scope.tx.feeFiatStr = v;
|
||||||
});
|
});
|
||||||
$scope.tx.feeRateStr = ($scope.tx.fee / ($scope.tx.amount + $scope.tx.fee) * 100).toFixed(2) + '%';
|
$scope.tx.feeRateStr = ($scope.tx.fee / ($scope.tx.amount + $scope.tx.fee) * 100).toFixed(2) + '%';
|
||||||
|
|
@ -31,17 +31,23 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
};
|
};
|
||||||
|
|
||||||
function applyButtonText() {
|
function applyButtonText() {
|
||||||
$scope.buttonText = $scope.isCordova && !$scope.isWindowsPhoneApp ? gettextCatalog.getString('Slide') + ' ' : gettextCatalog.getString('Click') + ' ';
|
|
||||||
|
|
||||||
var lastSigner = lodash.filter($scope.tx.actions, {
|
var lastSigner = lodash.filter($scope.tx.actions, {
|
||||||
type: 'accept'
|
type: 'accept'
|
||||||
}).length == $scope.tx.requiredSignatures - 1;
|
}).length == $scope.tx.requiredSignatures - 1;
|
||||||
|
|
||||||
if (lastSigner) {
|
if (lastSigner) {
|
||||||
$scope.buttonText += gettextCatalog.getString('to send');
|
if ($scope.isCordova && !$scope.isWindowsPhoneApp) {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Slide to send');
|
||||||
|
} else {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Click to send');
|
||||||
|
}
|
||||||
$scope.successText = gettextCatalog.getString('Payment Sent');
|
$scope.successText = gettextCatalog.getString('Payment Sent');
|
||||||
} else {
|
} else {
|
||||||
$scope.buttonText += gettextCatalog.getString('to accept');
|
if ($scope.isCordova && !$scope.isWindowsPhoneApp) {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Slide to accept');
|
||||||
|
} else {
|
||||||
|
$scope.buttonText = gettextCatalog.getString('Click to accept');
|
||||||
|
}
|
||||||
$scope.successText = gettextCatalog.getString('Payment Accepted');
|
$scope.successText = gettextCatalog.getString('Payment Accepted');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -219,7 +225,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
copayerId: $scope.wallet.credentials.copayerId
|
copayerId: $scope.wallet.credentials.copayerId
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.tx = txFormatService.processTx(tx);
|
$scope.tx = txFormatService.processTx($scope.wallet.coin, tx);
|
||||||
|
|
||||||
if (!action && tx.status == 'pending')
|
if (!action && tx.status == 'pending')
|
||||||
$scope.tx.pendingForUs = true;
|
$scope.tx.pendingForUs = true;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ angular.module('copayApp.controllers').controller('tourController',
|
||||||
rateService.whenAvailable(function() {
|
rateService.whenAvailable(function() {
|
||||||
var localCurrency = 'USD';
|
var localCurrency = 'USD';
|
||||||
var btcAmount = 1;
|
var btcAmount = 1;
|
||||||
var rate = rateService.toFiat(btcAmount * 1e8, localCurrency);
|
var rate = rateService.toFiat(btcAmount * 1e8, localCurrency, 'btc');
|
||||||
$scope.localCurrencySymbol = '$';
|
$scope.localCurrencySymbol = '$';
|
||||||
$scope.localCurrencyPerBtc = $filter('formatFiatAmount')(parseFloat(rate.toFixed(2), 10));
|
$scope.localCurrencyPerBtc = $filter('formatFiatAmount')(parseFloat(rate.toFixed(2), 10));
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ angular.module('copayApp.controllers').controller('paperWalletController',
|
||||||
$scope.balanceSat = balance;
|
$scope.balanceSat = balance;
|
||||||
if ($scope.balanceSat <= 0)
|
if ($scope.balanceSat <= 0)
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not funds found'));
|
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not funds found'));
|
||||||
var config = configService.getSync().wallet.settings;
|
$scope.balance = txFormatService.formatAmountStr($scope.wallet.coin, balance);
|
||||||
$scope.balance = txFormatService.formatAmount(balance) + ' ' + config.unitName;
|
|
||||||
}
|
}
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
|
|
@ -60,9 +59,9 @@ angular.module('copayApp.controllers').controller('paperWalletController',
|
||||||
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, null, function(err, testTx) {
|
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, null, function(err, testTx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var rawTxLength = testTx.serialize().length;
|
var rawTxLength = testTx.serialize().length;
|
||||||
feeService.getCurrentFeeRate('livenet', function(err, feePerKB) {
|
feeService.getCurrentFeeRate('btc', 'livenet', function(err, feePerKb) {
|
||||||
var opts = {};
|
var opts = {};
|
||||||
opts.fee = Math.round((feePerKB * rawTxLength) / 2000);
|
opts.fee = Math.round((feePerKb * rawTxLength) / 2000);
|
||||||
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, opts, function(err, tx) {
|
$scope.wallet.buildTxFromPrivateKey($scope.privateKey, destinationAddress, opts, function(err, tx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
$scope.wallet.broadcastRawTx({
|
$scope.wallet.broadcastRawTx({
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('preferencesController',
|
angular.module('copayApp.controllers').controller('preferencesController',
|
||||||
function($scope, $rootScope, $timeout, $log, $ionicHistory, configService, profileService, fingerprintService, walletService, platformInfo) {
|
function($scope, $rootScope, $timeout, $log, $ionicHistory, configService, profileService, fingerprintService, walletService, platformInfo, externalLinkService, gettextCatalog) {
|
||||||
var wallet;
|
var wallet;
|
||||||
var walletId;
|
var walletId;
|
||||||
|
|
||||||
|
|
@ -58,6 +58,16 @@ angular.module('copayApp.controllers').controller('preferencesController',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.openWikiSpendingPassword = function() {
|
||||||
|
var url = 'https://github.com/bitpay/copay/wiki/COPAY---FAQ#what-the-spending-password-does';
|
||||||
|
var optIn = true;
|
||||||
|
var title = null;
|
||||||
|
var message = gettextCatalog.getString('Read more in our Wiki');
|
||||||
|
var okText = gettextCatalog.getString('Open');
|
||||||
|
var cancelText = gettextCatalog.getString('Go Back');
|
||||||
|
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||||
|
};
|
||||||
|
|
||||||
$scope.touchIdChange = function() {
|
$scope.touchIdChange = function() {
|
||||||
var newStatus = $scope.touchIdEnabled.value;
|
var newStatus = $scope.touchIdEnabled.value;
|
||||||
walletService.setTouchId(wallet, !!newStatus, function(err) {
|
walletService.setTouchId(wallet, !!newStatus, function(err) {
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,9 @@ angular.module('copayApp.controllers').controller('preferencesAltCurrencyControl
|
||||||
$scope.findCurrency = function(search) {
|
$scope.findCurrency = function(search) {
|
||||||
if (!search) init();
|
if (!search) init();
|
||||||
$scope.altCurrencyList = lodash.filter(completeAlternativeList, function(item) {
|
$scope.altCurrencyList = lodash.filter(completeAlternativeList, function(item) {
|
||||||
var val = item.name;
|
var val = item.name
|
||||||
return lodash.includes(val.toLowerCase(), search.toLowerCase());
|
var val2 = item.isoCode;
|
||||||
|
return lodash.includes(val.toLowerCase(), search.toLowerCase()) || lodash.includes(val2.toLowerCase(), search.toLowerCase());
|
||||||
});
|
});
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
|
|
|
||||||
42
src/js/controllers/preferencesCash.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.controllers').controller('preferencesCashController', function($scope, $log, $timeout, appConfigService, configService, gettextCatalog, externalLinkService) {
|
||||||
|
var updateConfig = function() {
|
||||||
|
|
||||||
|
var config = configService.getSync();
|
||||||
|
$scope.appName = appConfigService.nameCase;
|
||||||
|
|
||||||
|
$scope.cashSupport = {
|
||||||
|
value: config.cashSupport
|
||||||
|
};
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cashSupportChange = function() {
|
||||||
|
var opts = {
|
||||||
|
cashSupport: $scope.cashSupport.value
|
||||||
|
};
|
||||||
|
configService.set(opts, function(err) {
|
||||||
|
if (err) $log.debug(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$scope.openBitcoinCashWeb = function() {
|
||||||
|
var url = 'https://www.bitcoincash.org/';
|
||||||
|
var optIn = true;
|
||||||
|
var title = null;
|
||||||
|
var message = gettextCatalog.getString('Open bitcoincash.org?');
|
||||||
|
var okText = gettextCatalog.getString('Open');
|
||||||
|
var cancelText = gettextCatalog.getString('Go Back');
|
||||||
|
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
updateConfig();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -17,8 +17,7 @@ angular.module('copayApp.controllers').controller('preferencesDeleteWalletContro
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$scope.alias = lodash.isEqual($scope.wallet.name, $scope.wallet.credentials.walletName) ? null : $scope.wallet.name + ' ';
|
$scope.walletName = $scope.wallet.name;
|
||||||
$scope.walletName = $scope.wallet.credentials.walletName;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.showDeletePopup = function() {
|
$scope.showDeletePopup = function() {
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,12 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
|
var coin = 'btc'; // TODO: only BTC in preferences
|
||||||
$scope.network = $scope.network || 'livenet';
|
$scope.network = $scope.network || 'livenet';
|
||||||
$scope.feeOpts = feeService.feeOpts;
|
$scope.feeOpts = feeService.feeOpts;
|
||||||
$scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel();
|
$scope.currentFeeLevel = $scope.feeLevel || feeService.getCurrentFeeLevel();
|
||||||
$scope.loadingFee = true;
|
$scope.loadingFee = true;
|
||||||
feeService.getFeeLevels(function(err, levels) {
|
feeService.getFeeLevels(coin, function(err, levels) {
|
||||||
$scope.loadingFee = false;
|
$scope.loadingFee = false;
|
||||||
if (err) {
|
if (err) {
|
||||||
//Error is already formatted
|
//Error is already formatted
|
||||||
|
|
@ -66,7 +67,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.feePerSatByte = (value.feePerKB / 1000).toFixed();
|
$scope.feePerSatByte = (value.feePerKb / 1000).toFixed();
|
||||||
$scope.avgConfirmationTime = value.nbBlocks * 10;
|
$scope.avgConfirmationTime = value.nbBlocks * 10;
|
||||||
$scope.invalidCustomFeeEntered = false;
|
$scope.invalidCustomFeeEntered = false;
|
||||||
setMinWarning();
|
setMinWarning();
|
||||||
|
|
@ -97,7 +98,7 @@ angular.module('copayApp.controllers').controller('preferencesFeeController', fu
|
||||||
var value = lodash.find($scope.feeLevels[$scope.network], {
|
var value = lodash.find($scope.feeLevels[$scope.network], {
|
||||||
level: 'superEconomy'
|
level: 'superEconomy'
|
||||||
});
|
});
|
||||||
return parseInt((value.feePerKB / 1000).toFixed());
|
return parseInt((value.feePerKb / 1000).toFixed());
|
||||||
};
|
};
|
||||||
|
|
||||||
var setMinWarning = function() {
|
var setMinWarning = function() {
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('preferencesUnitController', function($scope, $log, configService, $ionicHistory, gettextCatalog, walletService, profileService) {
|
|
||||||
|
|
||||||
var config = configService.getSync();
|
|
||||||
$scope.unitList = [{
|
|
||||||
name: 'bits (1,000,000 bits = 1BTC)',
|
|
||||||
shortName: 'bits',
|
|
||||||
value: 100,
|
|
||||||
decimals: 2,
|
|
||||||
code: 'bit',
|
|
||||||
}, {
|
|
||||||
name: 'BTC',
|
|
||||||
shortName: 'BTC',
|
|
||||||
value: 100000000,
|
|
||||||
decimals: 8,
|
|
||||||
code: 'btc',
|
|
||||||
}];
|
|
||||||
|
|
||||||
$scope.save = function(newUnit) {
|
|
||||||
var opts = {
|
|
||||||
wallet: {
|
|
||||||
settings: {
|
|
||||||
unitName: newUnit.shortName,
|
|
||||||
unitToSatoshi: newUnit.value,
|
|
||||||
unitDecimals: newUnit.decimals,
|
|
||||||
unitCode: newUnit.code,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
configService.set(opts, function(err) {
|
|
||||||
if (err) $log.warn(err);
|
|
||||||
|
|
||||||
$ionicHistory.goBack();
|
|
||||||
walletService.updateRemotePreferences(profileService.getWallets())
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data){
|
|
||||||
$scope.currentUnit = config.wallet.settings.unitCode;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('sellCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, appConfigService, configService, txFormatService) {
|
angular.module('copayApp.controllers').controller('sellCoinbaseController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicScrollDelegate, $ionicConfig, lodash, coinbaseService, popupService, profileService, ongoingProcess, walletService, appConfigService, configService, txFormatService) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
var amount;
|
var amount;
|
||||||
var currency;
|
var currency;
|
||||||
|
|
||||||
|
|
@ -34,6 +35,51 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
|
||||||
}, onSendStatusChange);
|
}, onSendStatusChange);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var processPaymentInfo = function() {
|
||||||
|
ongoingProcess.set('connectingCoinbase', true);
|
||||||
|
coinbaseService.init(function(err, res) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var accessToken = res.accessToken;
|
||||||
|
|
||||||
|
coinbaseService.sellPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, s) {
|
||||||
|
$scope.sellPrice = s.data || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.paymentMethods = [];
|
||||||
|
$scope.selectedPaymentMethodId = { value : null };
|
||||||
|
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
|
||||||
|
if (err) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var hasPrimary;
|
||||||
|
var pm;
|
||||||
|
for(var i = 0; i < p.data.length; i++) {
|
||||||
|
pm = p.data[i];
|
||||||
|
if (pm.allow_sell) {
|
||||||
|
$scope.paymentMethods.push(pm);
|
||||||
|
}
|
||||||
|
if (pm.allow_sell && pm.primary_sell) {
|
||||||
|
hasPrimary = true;
|
||||||
|
$scope.selectedPaymentMethodId.value = pm.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lodash.isEmpty($scope.paymentMethods)) {
|
||||||
|
ongoingProcess.set('connectingCoinbase', false);
|
||||||
|
showErrorAndBack('No payment method available to sell');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
|
||||||
|
$scope.sellRequest();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var checkTransaction = lodash.throttle(function(count, txp) {
|
var checkTransaction = lodash.throttle(function(count, txp) {
|
||||||
$log.warn('Check if transaction has been received by Coinbase. Try ' + count + '/5');
|
$log.warn('Check if transaction has been received by Coinbase. Try ' + count + '/5');
|
||||||
// TX amount in BTC
|
// TX amount in BTC
|
||||||
|
|
@ -125,14 +171,9 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
|
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
|
||||||
var parsedAmount = txFormatService.parseAmount(
|
amount = data.stateParams.amount;
|
||||||
data.stateParams.amount,
|
currency = data.stateParams.currency;
|
||||||
data.stateParams.currency);
|
|
||||||
|
|
||||||
amount = parsedAmount.amount;
|
|
||||||
currency = parsedAmount.currency;
|
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
|
||||||
|
|
||||||
$scope.priceSensitivity = coinbaseService.priceSensitivity;
|
$scope.priceSensitivity = coinbaseService.priceSensitivity;
|
||||||
$scope.selectedPriceSensitivity = { data: coinbaseService.selectedPriceSensitivity };
|
$scope.selectedPriceSensitivity = { data: coinbaseService.selectedPriceSensitivity };
|
||||||
|
|
@ -143,57 +184,14 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
|
||||||
onlyComplete: true,
|
onlyComplete: true,
|
||||||
network: $scope.network,
|
network: $scope.network,
|
||||||
hasFunds: true,
|
hasFunds: true,
|
||||||
minAmount: parsedAmount.amountSat
|
coin: coin
|
||||||
});
|
});
|
||||||
|
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
showErrorAndBack('Insufficient funds');
|
showErrorAndBack('Insufficient funds');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$scope.wallet = $scope.wallets[0]; // Default first wallet
|
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
|
||||||
|
|
||||||
ongoingProcess.set('connectingCoinbase', true);
|
|
||||||
coinbaseService.init(function(err, res) {
|
|
||||||
if (err) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var accessToken = res.accessToken;
|
|
||||||
|
|
||||||
coinbaseService.sellPrice(accessToken, coinbaseService.getAvailableCurrency(), function(err, s) {
|
|
||||||
$scope.sellPrice = s.data || null;
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.paymentMethods = [];
|
|
||||||
$scope.selectedPaymentMethodId = { value : null };
|
|
||||||
coinbaseService.getPaymentMethods(accessToken, function(err, p) {
|
|
||||||
if (err) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var hasPrimary;
|
|
||||||
var pm;
|
|
||||||
for(var i = 0; i < p.data.length; i++) {
|
|
||||||
pm = p.data[i];
|
|
||||||
if (pm.allow_sell) {
|
|
||||||
$scope.paymentMethods.push(pm);
|
|
||||||
}
|
|
||||||
if (pm.allow_sell && pm.primary_sell) {
|
|
||||||
hasPrimary = true;
|
|
||||||
$scope.selectedPaymentMethodId.value = pm.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lodash.isEmpty($scope.paymentMethods)) {
|
|
||||||
ongoingProcess.set('connectingCoinbase', false);
|
|
||||||
showErrorAndBack('No payment method available to sell');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!hasPrimary) $scope.selectedPaymentMethodId.value = $scope.paymentMethods[0].id;
|
|
||||||
$scope.sellRequest();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.sellRequest = function() {
|
$scope.sellRequest = function() {
|
||||||
|
|
@ -306,6 +304,15 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func
|
||||||
|
|
||||||
$scope.onWalletSelect = function(wallet) {
|
$scope.onWalletSelect = function(wallet) {
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
var parsedAmount = txFormatService.parseAmount(
|
||||||
|
coin,
|
||||||
|
amount,
|
||||||
|
currency);
|
||||||
|
|
||||||
|
amount = parsedAmount.amount;
|
||||||
|
currency = parsedAmount.currency;
|
||||||
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
processPaymentInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goBackHome = function() {
|
$scope.goBackHome = function() {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('sellGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, txFormatService) {
|
angular.module('copayApp.controllers').controller('sellGlideraController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, glideraService, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, txFormatService) {
|
||||||
|
|
||||||
|
var coin = 'btc';
|
||||||
var amount;
|
var amount;
|
||||||
var currency;
|
var currency;
|
||||||
|
|
||||||
|
|
@ -35,39 +36,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
var processPaymentInfo = function() {
|
||||||
$ionicConfig.views.swipeBackEnabled(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
|
||||||
$ionicConfig.views.swipeBackEnabled(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
|
||||||
$scope.isFiat = data.stateParams.currency != 'bits' && data.stateParams.currency != 'BTC' ? true : false;
|
|
||||||
var parsedAmount = txFormatService.parseAmount(
|
|
||||||
data.stateParams.amount,
|
|
||||||
data.stateParams.currency);
|
|
||||||
|
|
||||||
amount = parsedAmount.amount;
|
|
||||||
currency = parsedAmount.currency;
|
|
||||||
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
|
||||||
|
|
||||||
$scope.network = glideraService.getNetwork();
|
|
||||||
$scope.wallets = profileService.getWallets({
|
|
||||||
m: 1, // Only 1-signature wallet
|
|
||||||
onlyComplete: true,
|
|
||||||
network: $scope.network,
|
|
||||||
hasFunds: true,
|
|
||||||
minAmount: parsedAmount.amountSat
|
|
||||||
});
|
|
||||||
|
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
|
||||||
showErrorAndBack('Insufficient funds');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$scope.wallet = $scope.wallets[0]; // Default first wallet
|
|
||||||
|
|
||||||
ongoingProcess.set('connectingGlidera', true);
|
ongoingProcess.set('connectingGlidera', true);
|
||||||
glideraService.init(function(err, data) {
|
glideraService.init(function(err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -91,6 +60,35 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
|
||||||
$scope.sellInfo = sell;
|
$scope.sellInfo = sell;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeLeave", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
|
$ionicConfig.views.swipeBackEnabled(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
|
$scope.isFiat = data.stateParams.currency != 'BTC' ? true : false;
|
||||||
|
amount = data.stateParams.amount;
|
||||||
|
currency = data.stateParams.currency;
|
||||||
|
|
||||||
|
$scope.network = glideraService.getNetwork();
|
||||||
|
$scope.wallets = profileService.getWallets({
|
||||||
|
m: 1, // Only 1-signature wallet
|
||||||
|
onlyComplete: true,
|
||||||
|
network: $scope.network,
|
||||||
|
hasFunds: true,
|
||||||
|
coin: coin
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
|
showErrorAndBack('Insufficient funds');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.onWalletSelect($scope.wallets[0]); // Default first wallet
|
||||||
});
|
});
|
||||||
|
|
||||||
var ask2FaCode = function(mode, cb) {
|
var ask2FaCode = function(mode, cb) {
|
||||||
|
|
@ -231,6 +229,15 @@ angular.module('copayApp.controllers').controller('sellGlideraController', funct
|
||||||
|
|
||||||
$scope.onWalletSelect = function(wallet) {
|
$scope.onWalletSelect = function(wallet) {
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
var parsedAmount = txFormatService.parseAmount(
|
||||||
|
coin,
|
||||||
|
amount,
|
||||||
|
currency);
|
||||||
|
|
||||||
|
amount = parsedAmount.amount;
|
||||||
|
currency = parsedAmount.currency;
|
||||||
|
$scope.amountUnitStr = parsedAmount.amountUnitStr;
|
||||||
|
processPaymentInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goBackHome = function() {
|
$scope.goBackHome = function() {
|
||||||
|
|
|
||||||
|
|
@ -206,14 +206,24 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateAllWallets = function() {
|
var updateAllWallets = function() {
|
||||||
$scope.wallets = profileService.getWallets();
|
var wallets = [];
|
||||||
if (lodash.isEmpty($scope.wallets)) return;
|
$scope.walletsBtc = profileService.getWallets({coin: 'btc'});
|
||||||
|
$scope.walletsBch = profileService.getWallets({coin: 'bch'});
|
||||||
|
|
||||||
var i = $scope.wallets.length;
|
lodash.each($scope.walletsBtc, function(wBtc) {
|
||||||
|
wallets.push(wBtc);
|
||||||
|
});
|
||||||
|
|
||||||
|
lodash.each($scope.walletsBch, function(wBch) {
|
||||||
|
wallets.push(wBch);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lodash.isEmpty(wallets)) return;
|
||||||
|
|
||||||
|
var i = wallets.length;
|
||||||
var j = 0;
|
var j = 0;
|
||||||
var timeSpan = 60 * 60 * 24 * 7;
|
|
||||||
|
|
||||||
lodash.each($scope.wallets, function(wallet) {
|
lodash.each(wallets, function(wallet) {
|
||||||
walletService.getStatus(wallet, {}, function(err, status) {
|
walletService.getStatus(wallet, {}, function(err, status) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
||||||
|
|
||||||
$scope.requestSpecificAmount = function() {
|
$scope.requestSpecificAmount = function() {
|
||||||
$state.go('tabs.paymentRequest.amount', {
|
$state.go('tabs.paymentRequest.amount', {
|
||||||
id: $scope.wallet.credentials.walletId
|
id: $scope.wallet.credentials.walletId,
|
||||||
|
coin: $scope.wallet.coin
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -123,8 +124,13 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var setProtocolHandler = function() {
|
||||||
|
$scope.protocolHandler = walletService.getProtocolHandler($scope.wallet);
|
||||||
|
}
|
||||||
|
|
||||||
$scope.onWalletSelect = function(wallet) {
|
$scope.onWalletSelect = function(wallet) {
|
||||||
$scope.wallet = wallet;
|
$scope.wallet = wallet;
|
||||||
|
setProtocolHandler();
|
||||||
$scope.setAddress();
|
$scope.setAddress();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -136,6 +142,8 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
||||||
|
|
||||||
$scope.shareAddress = function() {
|
$scope.shareAddress = function() {
|
||||||
if (!$scope.isCordova) return;
|
if (!$scope.isCordova) return;
|
||||||
window.plugins.socialsharing.share('bitcoin:' + $scope.addr, null, null, null);
|
var protocol = 'bitcoin';
|
||||||
|
if ($scope.wallet.coin == 'bch') protocol += 'cash';
|
||||||
|
window.plugins.socialsharing.share(protocol + ':' + $scope.addr, null, null, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, bwcError, gettextCatalog, scannerService) {
|
angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, bwcError, gettextCatalog, scannerService, bitcoreCash) {
|
||||||
|
|
||||||
var originalList;
|
var originalList;
|
||||||
var CONTACTS_SHOW_LIMIT;
|
var CONTACTS_SHOW_LIMIT;
|
||||||
|
|
@ -76,6 +76,8 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
||||||
color: v.color,
|
color: v.color,
|
||||||
name: v.name,
|
name: v.name,
|
||||||
recipientType: 'wallet',
|
recipientType: 'wallet',
|
||||||
|
coin: v.coin,
|
||||||
|
network: v.network,
|
||||||
getAddress: function(cb) {
|
getAddress: function(cb) {
|
||||||
walletService.getAddress(v, false, cb);
|
walletService.getAddress(v, false, cb);
|
||||||
},
|
},
|
||||||
|
|
@ -85,6 +87,14 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var getCoin = function(address) {
|
||||||
|
var cashAddress = bitcoreCash.Address.isValid(address, 'livenet');
|
||||||
|
if (cashAddress) {
|
||||||
|
return 'bch';
|
||||||
|
}
|
||||||
|
return 'btc';
|
||||||
|
};
|
||||||
|
|
||||||
var updateContactsList = function(cb) {
|
var updateContactsList = function(cb) {
|
||||||
addressbookService.list(function(err, ab) {
|
addressbookService.list(function(err, ab) {
|
||||||
if (err) $log.error(err);
|
if (err) $log.error(err);
|
||||||
|
|
@ -99,6 +109,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
||||||
address: k,
|
address: k,
|
||||||
email: lodash.isObject(v) ? v.email : null,
|
email: lodash.isObject(v) ? v.email : null,
|
||||||
recipientType: 'contact',
|
recipientType: 'contact',
|
||||||
|
coin: getCoin(k),
|
||||||
getAddress: function(cb) {
|
getAddress: function(cb) {
|
||||||
return cb(null, k);
|
return cb(null, k);
|
||||||
},
|
},
|
||||||
|
|
@ -186,7 +197,8 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
||||||
toAddress: addr,
|
toAddress: addr,
|
||||||
toName: item.name,
|
toName: item.name,
|
||||||
toEmail: item.email,
|
toEmail: item.email,
|
||||||
toColor: item.color
|
toColor: item.color,
|
||||||
|
coin: item.coin
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
|
||||||
$scope.currentLanguageName = uxLanguage.getCurrentLanguageName();
|
$scope.currentLanguageName = uxLanguage.getCurrentLanguageName();
|
||||||
$scope.feeOpts = feeService.feeOpts;
|
$scope.feeOpts = feeService.feeOpts;
|
||||||
$scope.currentFeeLevel = feeService.getCurrentFeeLevel();
|
$scope.currentFeeLevel = feeService.getCurrentFeeLevel();
|
||||||
$scope.wallets = profileService.getWallets();
|
$scope.walletsBtc = profileService.getWallets({ coin: 'btc' });
|
||||||
|
$scope.walletsBch = profileService.getWallets({ coin: 'bch' });
|
||||||
$scope.buyAndSellServices = buyAndSellService.getLinked();
|
$scope.buyAndSellServices = buyAndSellService.getLinked();
|
||||||
|
|
||||||
configService.whenAvailable(function(config) {
|
configService.whenAvailable(function(config) {
|
||||||
$scope.unitName = config.wallet.settings.unitName;
|
|
||||||
$scope.selectedAlternative = {
|
$scope.selectedAlternative = {
|
||||||
name: config.wallet.settings.alternativeName,
|
name: config.wallet.settings.alternativeName,
|
||||||
isoCode: config.wallet.settings.alternativeIsoCode
|
isoCode: config.wallet.settings.alternativeIsoCode
|
||||||
|
|
@ -26,6 +26,11 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
|
||||||
}, 10);
|
}, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.cashSupport = {
|
||||||
|
value: config.cashSupport
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// TODO move this to a generic service
|
// TODO move this to a generic service
|
||||||
bitpayCardService.getCards(function(err, cards) {
|
bitpayCardService.getCards(function(err, cards) {
|
||||||
if (err) $log.error(err);
|
if (err) $log.error(err);
|
||||||
|
|
@ -63,6 +68,8 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.enter", function(event, data) {
|
$scope.$on("$ionicView.enter", function(event, data) {
|
||||||
updateConfig();
|
updateConfig();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
angular.module('copayApp.controllers').controller('topUpController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, bitpayService, bitpayCardService, payproService, bwcError, txFormatService, sendMaxService, gettextCatalog) {
|
angular.module('copayApp.controllers').controller('topUpController', function($scope, $log, $state, $timeout, $ionicHistory, $ionicConfig, lodash, popupService, profileService, ongoingProcess, walletService, configService, platformInfo, bitpayService, bitpayCardService, payproService, bwcError, txFormatService, sendMaxService, gettextCatalog) {
|
||||||
|
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
var coin = 'btc';
|
||||||
var cardId;
|
var cardId;
|
||||||
var useSendMax;
|
var useSendMax;
|
||||||
var amount;
|
var amount;
|
||||||
|
|
@ -36,7 +37,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
|
||||||
};
|
};
|
||||||
|
|
||||||
var satToFiat = function(sat, cb) {
|
var satToFiat = function(sat, cb) {
|
||||||
txFormatService.toFiat(sat, $scope.currencyIsoCode, function(value) {
|
txFormatService.toFiat(coin, sat, $scope.currencyIsoCode, function(value) {
|
||||||
return cb(value);
|
return cb(value);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -218,7 +219,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
|
||||||
// Save TX in memory
|
// Save TX in memory
|
||||||
createdTx = ctxp;
|
createdTx = ctxp;
|
||||||
|
|
||||||
$scope.totalAmountStr = txFormatService.formatAmountStr(ctxp.amount);
|
$scope.totalAmountStr = txFormatService.formatAmountStr(coin, ctxp.amount);
|
||||||
|
|
||||||
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
|
setTotalAmount(parsedAmount.amountSat, invoiceFeeSat, ctxp.fee);
|
||||||
|
|
||||||
|
|
@ -256,7 +257,8 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
|
||||||
$scope.wallets = profileService.getWallets({
|
$scope.wallets = profileService.getWallets({
|
||||||
onlyComplete: true,
|
onlyComplete: true,
|
||||||
network: bitpayService.getEnvironment().network,
|
network: bitpayService.getEnvironment().network,
|
||||||
hasFunds: true
|
hasFunds: true,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
|
|
||||||
if (lodash.isEmpty($scope.wallets)) {
|
if (lodash.isEmpty($scope.wallets)) {
|
||||||
|
|
@ -319,7 +321,7 @@ angular.module('copayApp.controllers').controller('topUpController', function($s
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var parsedAmount = txFormatService.parseAmount(a, c);
|
var parsedAmount = txFormatService.parseAmount(coin, a, c);
|
||||||
initializeTopUp(wallet, parsedAmount);
|
initializeTopUp(wallet, parsedAmount);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
var txId;
|
var txId;
|
||||||
var listeners = [];
|
var listeners = [];
|
||||||
var config = configService.getSync();
|
var config = configService.getSync();
|
||||||
|
var blockexplorerUrl;
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
txId = data.stateParams.txid;
|
txId = data.stateParams.txid;
|
||||||
|
|
@ -15,6 +16,12 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
$scope.isShared = $scope.wallet.credentials.n > 1;
|
$scope.isShared = $scope.wallet.credentials.n > 1;
|
||||||
$scope.txsUnsubscribedForNotifications = config.confirmedTxsNotifications ? !config.confirmedTxsNotifications.enabled : true;
|
$scope.txsUnsubscribedForNotifications = config.confirmedTxsNotifications ? !config.confirmedTxsNotifications.enabled : true;
|
||||||
|
|
||||||
|
if ($scope.wallet.coin == 'bch') {
|
||||||
|
blockexplorerUrl = 'bch-insight.bitpay.com';
|
||||||
|
} else {
|
||||||
|
blockexplorerUrl = 'insight.bitpay.com';
|
||||||
|
}
|
||||||
|
|
||||||
txConfirmNotification.checkIfEnabled(txId, function(res) {
|
txConfirmNotification.checkIfEnabled(txId, function(res) {
|
||||||
$scope.txNotification = {
|
$scope.txNotification = {
|
||||||
value: res
|
value: res
|
||||||
|
|
@ -40,6 +47,16 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.readMore = function() {
|
||||||
|
var url = 'https://github.com/bitpay/copay/wiki/COPAY---FAQ#amount-too-low-to-spend';
|
||||||
|
var optIn = true;
|
||||||
|
var title = null;
|
||||||
|
var message = gettextCatalog.getString('Read more in our Wiki');
|
||||||
|
var okText = gettextCatalog.getString('Open');
|
||||||
|
var cancelText = gettextCatalog.getString('Go Back');
|
||||||
|
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||||
|
};
|
||||||
|
|
||||||
function updateMemo() {
|
function updateMemo() {
|
||||||
walletService.getTxNote($scope.wallet, $scope.btx.txid, function(err, note) {
|
walletService.getTxNote($scope.wallet, $scope.btx.txid, function(err, note) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -102,8 +119,8 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not available at this time'));
|
return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Transaction not available at this time'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.btx = txFormatService.processTx(tx);
|
$scope.btx = txFormatService.processTx($scope.wallet.coin, tx);
|
||||||
txFormatService.formatAlternativeStr(tx.fees, function(v) {
|
txFormatService.formatAlternativeStr($scope.wallet.coin, tx.fees, function(v) {
|
||||||
$scope.btx.feeFiatStr = v;
|
$scope.btx.feeFiatStr = v;
|
||||||
$scope.btx.feeRateStr = ($scope.btx.fees / ($scope.btx.amount + $scope.btx.fees) * 100).toFixed(2) + '%';
|
$scope.btx.feeRateStr = ($scope.btx.fees / ($scope.btx.amount + $scope.btx.fees) * 100).toFixed(2) + '%';
|
||||||
});
|
});
|
||||||
|
|
@ -121,7 +138,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
$scope.$digest();
|
$scope.$digest();
|
||||||
});
|
});
|
||||||
|
|
||||||
feeService.getFeeLevels(function(err, levels) {
|
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
walletService.getLowAmount($scope.wallet, levels, function(err, amount) {
|
walletService.getLowAmount($scope.wallet, levels, function(err, amount) {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
|
|
@ -168,10 +185,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
|
||||||
|
|
||||||
$scope.viewOnBlockchain = function() {
|
$scope.viewOnBlockchain = function() {
|
||||||
var btx = $scope.btx;
|
var btx = $scope.btx;
|
||||||
var url = 'https://blockchain.info/tx/' + btx.txid;
|
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + blockexplorerUrl + '/tx/' + btx.txid;
|
||||||
if ($scope.getShortNetworkName() == 'test') {
|
|
||||||
url = "https://test-insight.bitpay.com/tx/" + btx.txid;
|
|
||||||
}
|
|
||||||
var optIn = true;
|
var optIn = true;
|
||||||
var title = null;
|
var title = null;
|
||||||
var message = gettextCatalog.getString('View Transaction on Insight');
|
var message = gettextCatalog.getString('View Transaction on Insight');
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
var analyzeUtxos = function() {
|
var analyzeUtxos = function() {
|
||||||
if (analyzeUtxosDone) return;
|
if (analyzeUtxosDone) return;
|
||||||
|
|
||||||
feeService.getFeeLevels(function(err, levels) {
|
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
|
walletService.getLowUtxos($scope.wallet, levels, function(err, resp) {
|
||||||
if (err || !resp) return;
|
if (err || !resp) return;
|
||||||
|
|
@ -156,9 +156,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
|
|
||||||
var updateTxHistory = function(cb) {
|
var updateTxHistory = function(cb) {
|
||||||
if (!cb) cb = function() {};
|
if (!cb) cb = function() {};
|
||||||
if ($scope.updatingTxHistory) return;
|
|
||||||
|
|
||||||
$scope.updatingTxHistory = true;
|
|
||||||
$scope.updateTxHistoryError = false;
|
$scope.updateTxHistoryError = false;
|
||||||
$scope.updatingTxHistoryProgress = 0;
|
$scope.updatingTxHistoryProgress = 0;
|
||||||
|
|
||||||
|
|
@ -171,7 +169,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
feeService.getFeeLevels(function(err, levels) {
|
feeService.getFeeLevels($scope.wallet.coin, function(err, levels) {
|
||||||
walletService.getTxHistory($scope.wallet, {
|
walletService.getTxHistory($scope.wallet, {
|
||||||
progressFn: progressFn,
|
progressFn: progressFn,
|
||||||
feeLevels: levels,
|
feeLevels: levels,
|
||||||
|
|
@ -184,7 +182,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
}
|
}
|
||||||
$scope.completeTxHistory = txHistory;
|
$scope.completeTxHistory = txHistory;
|
||||||
$scope.showHistory();
|
$scope.showHistory();
|
||||||
$scope.$apply();
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
return cb();
|
return cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -356,6 +356,8 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
|
||||||
if (!$scope.wallet) return;
|
if (!$scope.wallet) return;
|
||||||
$scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1;
|
$scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1;
|
||||||
|
|
||||||
|
$scope.updatingTxHistory = true;
|
||||||
|
|
||||||
addressbookService.list(function(err, ab) {
|
addressbookService.list(function(err, ab) {
|
||||||
if (err) $log.error(err);
|
if (err) $log.error(err);
|
||||||
$scope.addressbook = ab || {};
|
$scope.addressbook = ab || {};
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.directives')
|
angular.module('copayApp.directives')
|
||||||
.directive('validAddress', ['$rootScope', 'bitcore',
|
.directive('validAddress', ['$rootScope', 'bitcore', 'bitcoreCash',
|
||||||
function($rootScope, bitcore) {
|
function($rootScope, bitcore, bitcoreCash) {
|
||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
link: function(scope, elem, attrs, ctrl) {
|
link: function(scope, elem, attrs, ctrl) {
|
||||||
|
// Bitcoin address
|
||||||
var URI = bitcore.URI;
|
var URI = bitcore.URI;
|
||||||
var Address = bitcore.Address
|
var Address = bitcore.Address
|
||||||
|
|
||||||
|
// Bitcoin Cash address
|
||||||
|
var URICash = bitcoreCash.URI;
|
||||||
|
var AddressCash = bitcoreCash.Address
|
||||||
|
|
||||||
var validator = function(value) {
|
var validator = function(value) {
|
||||||
|
|
||||||
// Regular url
|
// Regular url
|
||||||
|
|
@ -16,8 +22,8 @@ angular.module('copayApp.directives')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bip21 uri
|
// Bip21 uri
|
||||||
|
var uri, isAddressValidLivenet, isAddressValidTestnet;
|
||||||
if (/^bitcoin:/.test(value)) {
|
if (/^bitcoin:/.test(value)) {
|
||||||
var uri, isAddressValidLivenet, isAddressValidTestnet;
|
|
||||||
var isUriValid = URI.isValid(value);
|
var isUriValid = URI.isValid(value);
|
||||||
if (isUriValid) {
|
if (isUriValid) {
|
||||||
uri = new URI(value);
|
uri = new URI(value);
|
||||||
|
|
@ -26,6 +32,14 @@ angular.module('copayApp.directives')
|
||||||
}
|
}
|
||||||
ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet || isAddressValidTestnet));
|
ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet || isAddressValidTestnet));
|
||||||
return value;
|
return value;
|
||||||
|
} else if (/^bitcoincash:/.test(value)) {
|
||||||
|
var isUriValid = URICash.isValid(value);
|
||||||
|
if (isUriValid) {
|
||||||
|
uri = new URICash(value);
|
||||||
|
isAddressValidLivenet = AddressCash.isValid(uri.address.toString(), 'livenet')
|
||||||
|
}
|
||||||
|
ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet));
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value == 'undefined') {
|
if (typeof value == 'undefined') {
|
||||||
|
|
@ -33,10 +47,11 @@ angular.module('copayApp.directives')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular Address
|
// Regular Address: try Bitcoin and Bitcoin Cash
|
||||||
var regularAddressLivenet = Address.isValid(value, 'livenet');
|
var regularAddressLivenet = Address.isValid(value, 'livenet');
|
||||||
var regularAddressTestnet = Address.isValid(value, 'testnet');
|
var regularAddressTestnet = Address.isValid(value, 'testnet');
|
||||||
ctrl.$setValidity('validAddress', (regularAddressLivenet || regularAddressTestnet));
|
var regularAddressCashLivenet = AddressCash.isValid(value, 'livenet');
|
||||||
|
ctrl.$setValidity('validAddress', (regularAddressLivenet || regularAddressTestnet || regularAddressCashLivenet));
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,10 @@ angular.module('copayApp.filters', [])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter('formatFiatAmount', ['$filter', '$locale', 'configService',
|
.filter('formatFiatAmount', ['$filter', '$locale', 'configService',
|
||||||
function(filter, locale, configService) {
|
function(filter, locale) {
|
||||||
var numberFilter = filter('number');
|
var numberFilter = filter('number');
|
||||||
var formats = locale.NUMBER_FORMATS;
|
var formats = locale.NUMBER_FORMATS;
|
||||||
var config = configService.getSync().wallet.settings;
|
|
||||||
return function(amount) {
|
return function(amount) {
|
||||||
if (!config) return amount;
|
|
||||||
|
|
||||||
var fractionSize = 2;
|
var fractionSize = 2;
|
||||||
var value = numberFilter(amount, fractionSize);
|
var value = numberFilter(amount, fractionSize);
|
||||||
|
|
|
||||||
107
src/js/routes.js
|
|
@ -287,7 +287,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.state('tabs.send.amount', {
|
.state('tabs.send.amount', {
|
||||||
url: '/amount/:recipientType/:toAddress/:toName/:toEmail/:toColor',
|
url: '/amount/:recipientType/:toAddress/:toName/:toEmail/:toColor/:coin/:fixedUnit',
|
||||||
views: {
|
views: {
|
||||||
'tab-send@tabs': {
|
'tab-send@tabs': {
|
||||||
controller: 'amountController',
|
controller: 'amountController',
|
||||||
|
|
@ -296,7 +296,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.send.confirm', {
|
.state('tabs.send.confirm', {
|
||||||
url: '/confirm/:recipientType/:toAddress/:toName/:toAmount/:toEmail/:toColor/:description/:useSendMax',
|
url: '/confirm/:recipientType/:toAddress/:toName/:toAmount/:toEmail/:toColor/:description/:coin/:useSendMax',
|
||||||
views: {
|
views: {
|
||||||
'tab-send@tabs': {
|
'tab-send@tabs': {
|
||||||
controller: 'confirmController',
|
controller: 'confirmController',
|
||||||
|
|
@ -329,6 +329,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
'tab-home@tabs': {
|
'tab-home@tabs': {
|
||||||
templateUrl: 'views/add.html'
|
templateUrl: 'views/add.html'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
coin: 'btc'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.add.join', {
|
.state('tabs.add.join', {
|
||||||
|
|
@ -374,6 +377,16 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.state('tabs.preferencesCash', {
|
||||||
|
url: '/preferencesCash',
|
||||||
|
views: {
|
||||||
|
'tab-settings@tabs': {
|
||||||
|
controller: 'preferencesCashController',
|
||||||
|
templateUrl: 'views/preferencesCash.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
.state('tabs.notifications', {
|
.state('tabs.notifications', {
|
||||||
url: '/notifications',
|
url: '/notifications',
|
||||||
views: {
|
views: {
|
||||||
|
|
@ -392,15 +405,6 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.unit', {
|
|
||||||
url: '/unit',
|
|
||||||
views: {
|
|
||||||
'tab-settings@tabs': {
|
|
||||||
controller: 'preferencesUnitController',
|
|
||||||
templateUrl: 'views/preferencesUnit.html'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('tabs.fee', {
|
.state('tabs.fee', {
|
||||||
url: '/fee',
|
url: '/fee',
|
||||||
views: {
|
views: {
|
||||||
|
|
@ -474,6 +478,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Wallet preferences
|
* Wallet preferences
|
||||||
|
|
@ -589,6 +594,16 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.state('tabs.preferencesCash.scan', {
|
||||||
|
url: '/cashScan',
|
||||||
|
views: {
|
||||||
|
'tab-settings@tabs': {
|
||||||
|
controller: 'cashScanController',
|
||||||
|
templateUrl: 'views/cashScan.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Addressbook
|
* Addressbook
|
||||||
|
|
@ -676,12 +691,12 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
abstract: true,
|
abstract: true,
|
||||||
params: {
|
params: {
|
||||||
id: null,
|
id: null,
|
||||||
nextStep: 'tabs.paymentRequest.confirm'
|
nextStep: 'tabs.paymentRequest.confirm',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
.state('tabs.paymentRequest.amount', {
|
.state('tabs.paymentRequest.amount', {
|
||||||
url: '/amount',
|
url: '/amount/:coin',
|
||||||
views: {
|
views: {
|
||||||
'tab-receive@tabs': {
|
'tab-receive@tabs': {
|
||||||
controller: 'amountController',
|
controller: 'amountController',
|
||||||
|
|
@ -690,7 +705,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.paymentRequest.confirm', {
|
.state('tabs.paymentRequest.confirm', {
|
||||||
url: '/confirm/:amount/:currency',
|
url: '/confirm/:amount/:currency/:coin',
|
||||||
views: {
|
views: {
|
||||||
'tab-receive@tabs': {
|
'tab-receive@tabs': {
|
||||||
controller: 'customAmountController',
|
controller: 'customAmountController',
|
||||||
|
|
@ -923,6 +938,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
controllerAs: 'glidera',
|
controllerAs: 'glidera',
|
||||||
templateUrl: 'views/glidera.html'
|
templateUrl: 'views/glidera.html'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
coin: 'btc',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.buyandsell.glidera.amount', {
|
.state('tabs.buyandsell.glidera.amount', {
|
||||||
|
|
@ -976,6 +994,9 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
controllerAs: 'coinbase',
|
controllerAs: 'coinbase',
|
||||||
templateUrl: 'views/coinbase.html'
|
templateUrl: 'views/coinbase.html'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
coin: 'btc',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.preferences.coinbase', {
|
.state('tabs.preferences.coinbase', {
|
||||||
|
|
@ -1026,36 +1047,54 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
abstract: true
|
abstract: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Mercado Libre Gift Card
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/* Explore Bitcoin.com */
|
.state('tabs.giftcards.mercadoLibre', {
|
||||||
.state('tabs.bitcoin-com', {
|
url: '/mercadoLibre',
|
||||||
url: '/bitcoincom',
|
|
||||||
views: {
|
views: {
|
||||||
'tab-home@tabs': {
|
'tab-home@tabs': {
|
||||||
controller: 'bitcoincomController',
|
controller: 'mercadoLibreController',
|
||||||
templateUrl: 'views/bitcoincom.html'
|
templateUrl: 'views/mercadoLibre.html'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.state('tabs.giftcards.mercadoLibre.cards', {
|
||||||
/* buy.Bitcoin.com */
|
url: '/cards',
|
||||||
.state('tabs.buyandsell.bitcoindotcom', {
|
|
||||||
url: '/buyBitcoindotcom',
|
|
||||||
views: {
|
views: {
|
||||||
'tab-home@tabs': {
|
'tab-home@tabs': {
|
||||||
controller: 'buyBitcoindotcomController',
|
controller: 'mercadoLibreCardsController',
|
||||||
templateUrl: 'views/buyBitcoindotcom.html'
|
templateUrl: 'views/mercadoLibreCards.html'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
invoiceId: null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.state('tabs.giftcards.mercadoLibre.amount', {
|
||||||
/* Price Chart */
|
url: '/amount',
|
||||||
.state('tabs.pricechart', {
|
|
||||||
url: '/pricechart',
|
|
||||||
views: {
|
views: {
|
||||||
'tab-home@tabs': {
|
'tab-home@tabs': {
|
||||||
controller: 'pricechartController',
|
controller: 'amountController',
|
||||||
templateUrl: 'views/pricechart.html'
|
templateUrl: 'views/amount.html'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
nextStep: 'tabs.giftcards.mercadoLibre.buy',
|
||||||
|
currency: 'BRL',
|
||||||
|
coin: 'btc',
|
||||||
|
fixedUnit: 1,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.state('tabs.giftcards.mercadoLibre.buy', {
|
||||||
|
url: '/buy/:amount/:currency',
|
||||||
|
views: {
|
||||||
|
'tab-home@tabs': {
|
||||||
|
controller: 'buyMercadoLibreController',
|
||||||
|
templateUrl: 'views/buyMercadoLibre.html'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -1098,7 +1137,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
params: {
|
params: {
|
||||||
nextStep: 'tabs.giftcards.amazon.buy',
|
nextStep: 'tabs.giftcards.amazon.buy',
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
forceCurrency: true
|
coin: 'btc',
|
||||||
|
fixedUnit: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('tabs.giftcards.amazon.buy', {
|
.state('tabs.giftcards.amazon.buy', {
|
||||||
|
|
@ -1138,6 +1178,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
params: {
|
params: {
|
||||||
id: null,
|
id: null,
|
||||||
currency: 'USD',
|
currency: 'USD',
|
||||||
|
coin: 'btc',
|
||||||
useSendMax: null
|
useSendMax: null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -1169,7 +1210,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.run(function($rootScope, $state, $location, $log, $timeout, startupService, fingerprintService, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, configService, emailService, /* plugins START HERE => */ glideraService, buydotbitcoindotcomService, amazonService, bitpayCardService, applicationService) {
|
.run(function($rootScope, $state, $location, $log, $timeout, startupService, ionicToast, fingerprintService, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, configService, emailService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService, bitpayCardService, applicationService, mercadoLibreService) {
|
||||||
|
|
||||||
uxLanguage.init();
|
uxLanguage.init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,19 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.services').factory('addressbookService', function(bitcore, storageService, lodash) {
|
angular.module('copayApp.services').factory('addressbookService', function($log, bitcore, bitcoreCash, storageService, lodash) {
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
||||||
|
var getNetwork = function(address) {
|
||||||
|
var network;
|
||||||
|
try {
|
||||||
|
network = (new bitcore.Address(address)).network.name;
|
||||||
|
} catch(e) {
|
||||||
|
$log.warn('No valid bitcoin address. Trying bitcoin cash...');
|
||||||
|
network = (new bitcoreCash.Address(address)).network.name;
|
||||||
|
}
|
||||||
|
return network;
|
||||||
|
};
|
||||||
|
|
||||||
root.get = function(addr, cb) {
|
root.get = function(addr, cb) {
|
||||||
storageService.getAddressbook('testnet', function(err, ab) {
|
storageService.getAddressbook('testnet', function(err, ab) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
@ -35,7 +46,8 @@ angular.module('copayApp.services').factory('addressbookService', function(bitco
|
||||||
};
|
};
|
||||||
|
|
||||||
root.add = function(entry, cb) {
|
root.add = function(entry, cb) {
|
||||||
var network = (new bitcore.Address(entry.address)).network.name;
|
var network = getNetwork(entry.address);
|
||||||
|
if (lodash.isEmpty(network)) return cb('Not valid bitcoin address');
|
||||||
storageService.getAddressbook(network, function(err, ab) {
|
storageService.getAddressbook(network, function(err, ab) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (ab) ab = JSON.parse(ab);
|
if (ab) ab = JSON.parse(ab);
|
||||||
|
|
@ -53,7 +65,8 @@ angular.module('copayApp.services').factory('addressbookService', function(bitco
|
||||||
};
|
};
|
||||||
|
|
||||||
root.remove = function(addr, cb) {
|
root.remove = function(addr, cb) {
|
||||||
var network = (new bitcore.Address(addr)).network.name;
|
var network = getNetwork(addr);
|
||||||
|
if (lodash.isEmpty(network)) return cb('Not valid bitcoin address');
|
||||||
storageService.getAddressbook(network, function(err, ab) {
|
storageService.getAddressbook(network, function(err, ab) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (ab) ab = JSON.parse(ab);
|
if (ab) ab = JSON.parse(ab);
|
||||||
|
|
|
||||||
6
src/js/services/bitcoreCash.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
'use strict';
|
||||||
|
angular.module('copayApp.services')
|
||||||
|
.factory('bitcoreCash', function bitcoreFactory(bwcService) {
|
||||||
|
var bitcoreCash = bwcService.getBitcoreCash();
|
||||||
|
return bitcoreCash;
|
||||||
|
});
|
||||||
|
|
@ -53,6 +53,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $
|
||||||
'wallet:sells:create,' +
|
'wallet:sells:create,' +
|
||||||
'wallet:transactions:read,' +
|
'wallet:transactions:read,' +
|
||||||
'wallet:transactions:send,' +
|
'wallet:transactions:send,' +
|
||||||
|
'wallet:transactions:send:bypass-2fa,' +
|
||||||
'wallet:payment-methods:read';
|
'wallet:payment-methods:read';
|
||||||
|
|
||||||
// NW has a bug with Window Object
|
// NW has a bug with Window Object
|
||||||
|
|
@ -169,9 +170,9 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $
|
||||||
var _getNetAmount = function(amount, cb) {
|
var _getNetAmount = function(amount, cb) {
|
||||||
// Fee Normal for a single transaction (450 bytes)
|
// Fee Normal for a single transaction (450 bytes)
|
||||||
var txNormalFeeKB = 450 / 1000;
|
var txNormalFeeKB = 450 / 1000;
|
||||||
feeService.getFeeRate(null, 'normal', function(err, feePerKB) {
|
feeService.getFeeRate('btc', 'livenet', 'normal', function(err, feePerKb) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
var feeBTC = (feePerKB * txNormalFeeKB / 100000000).toFixed(8);
|
var feeBTC = (feePerKb * txNormalFeeKB / 100000000).toFixed(8);
|
||||||
|
|
||||||
return cb(null, amount - feeBTC, feeBTC);
|
return cb(null, amount - feeBTC, feeBTC);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
||||||
bannedUntil: null,
|
bannedUntil: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
// External services
|
cashSupport: false,
|
||||||
|
|
||||||
recentTransactions: {
|
recentTransactions: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
|
@ -141,6 +142,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
||||||
configCache.hideNextSteps = defaultConfig.hideNextSteps;
|
configCache.hideNextSteps = defaultConfig.hideNextSteps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!configCache.cashSupport) {
|
||||||
|
configCache.cashSupport = defaultConfig.cashSupport;
|
||||||
|
}
|
||||||
|
|
||||||
if (!configCache.recentTransactions) {
|
if (!configCache.recentTransactions) {
|
||||||
configCache.recentTransactions = defaultConfig.recentTransactions;
|
configCache.recentTransactions = defaultConfig.recentTransactions;
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +157,14 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
||||||
configCache.bitpayAccount = defaultConfig.bitpayAccount;
|
configCache.bitpayAccount = defaultConfig.bitpayAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configCache.wallet.settings.unitCode == 'bit') {
|
||||||
|
// Convert to BTC. Bits will be disabled
|
||||||
|
configCache.wallet.settings.unitName = defaultConfig.wallet.settings.unitName;
|
||||||
|
configCache.wallet.settings.unitToSatoshi = defaultConfig.wallet.settings.unitToSatoshi;
|
||||||
|
configCache.wallet.settings.unitDecimals = defaultConfig.wallet.settings.unitDecimals;
|
||||||
|
configCache.wallet.settings.unitCode = defaultConfig.wallet.settings.unitCode;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
configCache = lodash.clone(defaultConfig);
|
configCache = lodash.clone(defaultConfig);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
||||||
|
|
||||||
var cache = {
|
var cache = {
|
||||||
updateTs: 0,
|
updateTs: 0,
|
||||||
|
coin: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
root.getCurrentFeeLevel = function() {
|
root.getCurrentFeeLevel = function() {
|
||||||
|
|
@ -24,20 +25,20 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
root.getFeeRate = function(network, feeLevel, cb) {
|
root.getFeeRate = function(coin, network, feeLevel, cb) {
|
||||||
|
|
||||||
if (feeLevel == 'custom') return cb();
|
if (feeLevel == 'custom') return cb();
|
||||||
|
|
||||||
network = network || 'livenet';
|
network = network || 'livenet';
|
||||||
|
|
||||||
root.getFeeLevels(function(err, levels, fromCache) {
|
root.getFeeLevels(coin, function(err, levels, fromCache) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
var feeLevelRate = lodash.find(levels[network], {
|
var feeLevelRate = lodash.find(levels[network], {
|
||||||
level: feeLevel
|
level: feeLevel
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!feeLevelRate || !feeLevelRate.feePerKB) {
|
if (!feeLevelRate || !feeLevelRate.feePerKb) {
|
||||||
return cb({
|
return cb({
|
||||||
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
|
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
|
||||||
feeLevel: feeLevel
|
feeLevel: feeLevel
|
||||||
|
|
@ -45,34 +46,35 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var feeRate = feeLevelRate.feePerKB;
|
var feeRate = feeLevelRate.feePerKb;
|
||||||
|
|
||||||
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKB / 1000).toFixed() + ' SAT/B');
|
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKb / 1000).toFixed() + ' SAT/B');
|
||||||
|
|
||||||
return cb(null, feeRate);
|
return cb(null, feeRate);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
root.getCurrentFeeRate = function(network, cb) {
|
root.getCurrentFeeRate = function(coin, network, cb) {
|
||||||
return root.getFeeRate(network, root.getCurrentFeeLevel(), cb);
|
return root.getFeeRate(coin, network, root.getCurrentFeeLevel(), cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
root.getFeeLevels = function(cb) {
|
root.getFeeLevels = function(coin, cb) {
|
||||||
|
coin = coin || 'btc';
|
||||||
|
|
||||||
if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
|
if (cache.coin == coin && cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
|
||||||
return cb(null, cache.data, true);
|
return cb(null, cache.data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var walletClient = bwcService.getClient();
|
var walletClient = bwcService.getClient();
|
||||||
var unitName = configService.getSync().wallet.settings.unitName;
|
|
||||||
|
|
||||||
walletClient.getFeeLevels('livenet', function(errLivenet, levelsLivenet) {
|
walletClient.getFeeLevels(coin, 'livenet', function(errLivenet, levelsLivenet) {
|
||||||
walletClient.getFeeLevels('testnet', function(errTestnet, levelsTestnet) {
|
walletClient.getFeeLevels('btc', 'testnet', function(errTestnet, levelsTestnet) {
|
||||||
if (errLivenet || errTestnet) {
|
if (errLivenet || errTestnet) {
|
||||||
return cb(gettextCatalog.getString('Could not get dynamic fee'));
|
return cb(gettextCatalog.getString('Could not get dynamic fee'));
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.updateTs = Date.now();
|
cache.updateTs = Date.now();
|
||||||
|
cache.coin = coin;
|
||||||
cache.data = {
|
cache.data = {
|
||||||
'livenet': levelsLivenet,
|
'livenet': levelsLivenet,
|
||||||
'testnet': levelsTestnet
|
'testnet': levelsTestnet
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ angular.module('copayApp.services')
|
||||||
};
|
};
|
||||||
|
|
||||||
root.add = function(level, msg) {
|
root.add = function(level, msg) {
|
||||||
|
msg = msg.replace('/xpriv.*/', 'xpriv[Hidden]');
|
||||||
logs.push({
|
logs.push({
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
level: level,
|
level: level,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, $rootScope, payproService, scannerService, appConfigService, popupService, gettextCatalog) {
|
angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, appConfigService, popupService, gettextCatalog) {
|
||||||
|
|
||||||
var root = {};
|
var root = {};
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function goSend(addr, amount, message) {
|
function goSend(addr, amount, message, coin) {
|
||||||
$state.go('tabs.send', {}, {
|
$state.go('tabs.send', {}, {
|
||||||
'reload': true,
|
'reload': true,
|
||||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||||
|
|
@ -57,18 +57,20 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
$state.transitionTo('tabs.send.confirm', {
|
$state.transitionTo('tabs.send.confirm', {
|
||||||
toAmount: amount,
|
toAmount: amount,
|
||||||
toAddress: addr,
|
toAddress: addr,
|
||||||
description: message
|
description: message,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$state.transitionTo('tabs.send.amount', {
|
$state.transitionTo('tabs.send.amount', {
|
||||||
toAddress: addr
|
toAddress: addr,
|
||||||
|
coin: coin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
// data extensions for Payment Protocol with non-backwards-compatible request
|
// data extensions for Payment Protocol with non-backwards-compatible request
|
||||||
if ((/^bitcoin:\?r=[\w+]/).exec(data)) {
|
if ((/^bitcoin(cash)?:\?r=[\w+]/).exec(data)) {
|
||||||
data = decodeURIComponent(data.replace('bitcoin:?r=', ''));
|
data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, ''));
|
||||||
$state.go('tabs.send', {}, {
|
$state.go('tabs.send', {}, {
|
||||||
'reload': true,
|
'reload': true,
|
||||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||||
|
|
@ -82,27 +84,97 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
|
|
||||||
data = sanitizeUri(data);
|
data = sanitizeUri(data);
|
||||||
|
|
||||||
// BIP21
|
// Bitcoin URL
|
||||||
if (bitcore.URI.isValid(data)) {
|
if (bitcore.URI.isValid(data)) {
|
||||||
var parsed = new bitcore.URI(data);
|
var coin = 'btc';
|
||||||
|
var parsed = new bitcore.URI(data);
|
||||||
|
|
||||||
var addr = parsed.address ? parsed.address.toString() : '';
|
var addr = parsed.address ? parsed.address.toString() : '';
|
||||||
var message = parsed.message;
|
var message = parsed.message;
|
||||||
|
|
||||||
var amount = parsed.amount ? parsed.amount : '';
|
var amount = parsed.amount ? parsed.amount : '';
|
||||||
|
|
||||||
if (parsed.r) {
|
if (parsed.r) {
|
||||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (addr && amount) goSend(addr, amount, message);
|
if (addr && amount) goSend(addr, amount, message, coin);
|
||||||
else popupService.showAlert(gettextCatalog.getString('Error'), err);
|
else popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||||
} else handlePayPro(details);
|
} else handlePayPro(details);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
goSend(addr, amount, message);
|
goSend(addr, amount, message, coin);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
// Cash URI
|
||||||
|
} else if (bitcoreCash.URI.isValid(data)) {
|
||||||
|
var coin = 'bch';
|
||||||
|
var parsed = new bitcoreCash.URI(data);
|
||||||
|
|
||||||
|
var addr = parsed.address ? parsed.address.toString() : '';
|
||||||
|
var message = parsed.message;
|
||||||
|
|
||||||
|
var amount = parsed.amount ? parsed.amount : '';
|
||||||
|
|
||||||
|
// paypro not yet supported on cash
|
||||||
|
if (parsed.r) {
|
||||||
|
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||||
|
if (err) {
|
||||||
|
if (addr && amount)
|
||||||
|
goSend(addr, amount, message, coin);
|
||||||
|
else
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||||
|
}
|
||||||
|
handlePayPro(details, coin);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
goSend(addr, amount, message, coin);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Cash URI with bitcoin core address version number?
|
||||||
|
} else if (bitcore.URI.isValid(data.replace(/^bitcoincash:/,'bitcoin:'))) {
|
||||||
|
$log.debug('Handling bitcoincash URI with legacy address');
|
||||||
|
var coin = 'bch';
|
||||||
|
var parsed = new bitcore.URI(data.replace(/^bitcoincash:/,'bitcoin:'));
|
||||||
|
|
||||||
|
var oldAddr = parsed.address ? parsed.address.toString() : '';
|
||||||
|
if (!oldAddr) return false;
|
||||||
|
|
||||||
|
var addr = '';
|
||||||
|
|
||||||
|
var a = bitcore.Address(oldAddr).toObject();
|
||||||
|
addr = bitcoreCash.Address.fromObject(a).toString();
|
||||||
|
|
||||||
|
// Translate address
|
||||||
|
$log.debug('address transalated to:' + addr);
|
||||||
|
popupService.showConfirm(
|
||||||
|
gettextCatalog.getString('Bitcoin cash Payment'),
|
||||||
|
gettextCatalog.getString('Payment address was translated to new Bitcoin Cash address format: ' + addr),
|
||||||
|
gettextCatalog.getString('OK'),
|
||||||
|
gettextCatalog.getString('Cancel'),
|
||||||
|
function(ret) {
|
||||||
|
if (!ret) return false;
|
||||||
|
|
||||||
|
var message = parsed.message;
|
||||||
|
var amount = parsed.amount ? parsed.amount : '';
|
||||||
|
|
||||||
|
// paypro not yet supported on cash
|
||||||
|
if (parsed.r) {
|
||||||
|
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||||
|
if (err) {
|
||||||
|
if (addr && amount)
|
||||||
|
goSend(addr, amount, message, coin);
|
||||||
|
else
|
||||||
|
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||||
|
}
|
||||||
|
handlePayPro(details, coin);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
goSend(addr, amount, message, coin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Plain URL
|
// Plain URL
|
||||||
} else if (/^https?:\/\//.test(data)) {
|
} else if (/^https?:\/\//.test(data)) {
|
||||||
|
|
||||||
|
|
@ -127,6 +199,16 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
} else {
|
} else {
|
||||||
goToAmountPage(data);
|
goToAmountPage(data);
|
||||||
}
|
}
|
||||||
|
} else if (bitcoreCash.Address.isValid(data, 'livenet')) {
|
||||||
|
if ($state.includes('tabs.scan')) {
|
||||||
|
root.showMenu({
|
||||||
|
data: data,
|
||||||
|
type: 'bitcoinAddress',
|
||||||
|
coin: 'bch',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
goToAmountPage(data, 'bch');
|
||||||
|
}
|
||||||
} else if (data && data.indexOf(appConfigService.name + '://glidera') === 0) {
|
} else if (data && data.indexOf(appConfigService.name + '://glidera') === 0) {
|
||||||
var code = getParameterByName('code', data);
|
var code = getParameterByName('code', data);
|
||||||
$ionicHistory.nextViewOptions({
|
$ionicHistory.nextViewOptions({
|
||||||
|
|
@ -236,29 +318,29 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function goToAmountPage(toAddress) {
|
function goToAmountPage(toAddress, coin) {
|
||||||
$state.go('tabs.send', {}, {
|
$state.go('tabs.send', {}, {
|
||||||
'reload': true,
|
'reload': true,
|
||||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||||
});
|
});
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
$state.transitionTo('tabs.send.amount', {
|
$state.transitionTo('tabs.send.amount', {
|
||||||
toAddress: toAddress
|
toAddress: toAddress,
|
||||||
|
coin: coin,
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePayPro(payProDetails) {
|
function handlePayPro(payProDetails, coin) {
|
||||||
var stateParams = {
|
var stateParams = {
|
||||||
toAmount: payProDetails.amount,
|
toAmount: payProDetails.amount,
|
||||||
toAddress: payProDetails.toAddress,
|
toAddress: payProDetails.toAddress,
|
||||||
description: payProDetails.memo,
|
description: payProDetails.memo,
|
||||||
paypro: payProDetails
|
paypro: payProDetails,
|
||||||
|
coin: coin,
|
||||||
};
|
};
|
||||||
scannerService.pausePreview();
|
scannerService.pausePreview();
|
||||||
$state.go('tabs.send', {}, {
|
$state.go('tabs.send', {}, {
|
||||||
|
|
|
||||||
183
src/js/services/mercadoLibreService.js
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
'use strict';
|
||||||
|
angular.module('copayApp.services').factory('mercadoLibreService', function($http, $log, lodash, moment, storageService, configService, platformInfo, nextStepsService, homeIntegrationsService) {
|
||||||
|
var root = {};
|
||||||
|
var credentials = {};
|
||||||
|
|
||||||
|
// Not used yet
|
||||||
|
var availableCountries = [{
|
||||||
|
'country': 'Brazil',
|
||||||
|
'currency': 'BRL',
|
||||||
|
'name': 'Mercado Livre',
|
||||||
|
'url': 'https://www.mercadolivre.com.br'
|
||||||
|
}];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Development: 'testnet'
|
||||||
|
* Production: 'livenet'
|
||||||
|
*/
|
||||||
|
credentials.NETWORK = 'livenet';
|
||||||
|
//credentials.NETWORK = 'testnet';
|
||||||
|
|
||||||
|
if (credentials.NETWORK == 'testnet') {
|
||||||
|
credentials.BITPAY_API_URL = "https://test.bitpay.com";
|
||||||
|
} else {
|
||||||
|
credentials.BITPAY_API_URL = "https://bitpay.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
var homeItem = {
|
||||||
|
name: 'mercadoLibre',
|
||||||
|
title: 'Vales-Presente do Mercado Livre Brasil',
|
||||||
|
icon: 'icon-ml',
|
||||||
|
sref: 'tabs.giftcards.mercadoLibre',
|
||||||
|
};
|
||||||
|
|
||||||
|
var nextStepItem = {
|
||||||
|
name: 'mercadoLibre',
|
||||||
|
title: 'Comprar um Vale-Presente Mercado Livre',
|
||||||
|
icon: 'icon-ml',
|
||||||
|
sref: 'tabs.giftcards.mercadoLibre',
|
||||||
|
};
|
||||||
|
|
||||||
|
var _getBitPay = function(endpoint) {
|
||||||
|
return {
|
||||||
|
method: 'GET',
|
||||||
|
url: credentials.BITPAY_API_URL + endpoint,
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _postBitPay = function(endpoint, data) {
|
||||||
|
return {
|
||||||
|
method: 'POST',
|
||||||
|
url: credentials.BITPAY_API_URL + endpoint,
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json'
|
||||||
|
},
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
root.getNetwork = function() {
|
||||||
|
return credentials.NETWORK;
|
||||||
|
};
|
||||||
|
|
||||||
|
root.savePendingGiftCard = function(gc, opts, cb) {
|
||||||
|
var network = root.getNetwork();
|
||||||
|
storageService.getMercadoLibreGiftCards(network, function(err, oldGiftCards) {
|
||||||
|
if (lodash.isString(oldGiftCards)) {
|
||||||
|
oldGiftCards = JSON.parse(oldGiftCards);
|
||||||
|
}
|
||||||
|
if (lodash.isString(gc)) {
|
||||||
|
gc = JSON.parse(gc);
|
||||||
|
}
|
||||||
|
var inv = oldGiftCards || {};
|
||||||
|
inv[gc.invoiceId] = gc;
|
||||||
|
if (opts && (opts.error || opts.status)) {
|
||||||
|
inv[gc.invoiceId] = lodash.assign(inv[gc.invoiceId], opts);
|
||||||
|
}
|
||||||
|
if (opts && opts.remove) {
|
||||||
|
delete(inv[gc.invoiceId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inv = JSON.stringify(inv);
|
||||||
|
|
||||||
|
|
||||||
|
storageService.setMercadoLibreGiftCards(network, inv, function(err) {
|
||||||
|
|
||||||
|
homeIntegrationsService.register(homeItem);
|
||||||
|
nextStepsService.unregister(nextStepItem.name);
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.getPendingGiftCards = function(cb) {
|
||||||
|
var network = root.getNetwork();
|
||||||
|
storageService.getMercadoLibreGiftCards(network, function(err, giftCards) {
|
||||||
|
var _gcds = giftCards ? JSON.parse(giftCards) : null;
|
||||||
|
return cb(err, _gcds);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.createBitPayInvoice = function(data, cb) {
|
||||||
|
var dataSrc = {
|
||||||
|
currency: data.currency,
|
||||||
|
amount: data.amount,
|
||||||
|
clientId: data.uuid
|
||||||
|
};
|
||||||
|
|
||||||
|
$http(_postBitPay('/mercado-libre-gift/pay', dataSrc)).then(function(data) {
|
||||||
|
$log.info('BitPay Create Invoice: SUCCESS');
|
||||||
|
return cb(null, data.data);
|
||||||
|
}, function(data) {
|
||||||
|
$log.error('BitPay Create Invoice: ERROR', JSON.stringify(data.data));
|
||||||
|
return cb(data.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.getBitPayInvoice = 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', JSON.stringify(data.data));
|
||||||
|
return cb(data.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
root.createGiftCard = function(data, cb) {
|
||||||
|
var dataSrc = {
|
||||||
|
"clientId": data.uuid,
|
||||||
|
"invoiceId": data.invoiceId,
|
||||||
|
"accessKey": data.accessKey
|
||||||
|
};
|
||||||
|
|
||||||
|
$http(_postBitPay('/mercado-libre-gift/redeem', dataSrc)).then(function(data) {
|
||||||
|
var status = data.data.status == 'new' ? 'PENDING' : (data.data.status == 'paid') ? 'PENDING' : data.data.status;
|
||||||
|
data.data.status = status;
|
||||||
|
$log.info('Mercado Libre Gift Card Create/Update: ' + status);
|
||||||
|
return cb(null, data.data);
|
||||||
|
}, function(data) {
|
||||||
|
$log.error('Mercado Libre Gift Card Create/Update: ERROR', JSON.stringify(data.data));
|
||||||
|
return cb(data.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disabled for now *
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
root.cancelGiftCard = function(data, cb) {
|
||||||
|
|
||||||
|
var dataSrc = {
|
||||||
|
"clientId": data.uuid,
|
||||||
|
"invoiceId": data.invoiceId,
|
||||||
|
"accessKey": data.accessKey
|
||||||
|
};
|
||||||
|
|
||||||
|
$http(_postBitPay('/mercado-libre-gift/cancel', dataSrc)).then(function(data) {
|
||||||
|
$log.info('Mercado Libre Gift Card Cancel: SUCCESS');
|
||||||
|
return cb(null, data.data);
|
||||||
|
}, function(data) {
|
||||||
|
$log.error('Mercado Libre Gift Card Cancel: ' + data.data.message);
|
||||||
|
return cb(data.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
var register = function() {
|
||||||
|
storageService.getMercadoLibreGiftCards(root.getNetwork(), function(err, giftCards) {
|
||||||
|
if (giftCards) {
|
||||||
|
homeIntegrationsService.register(homeItem);
|
||||||
|
} else {
|
||||||
|
nextStepsService.register(nextStepItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Hide Mercado Libre
|
||||||
|
// register();
|
||||||
|
return root;
|
||||||
|
});
|
||||||
|
|
@ -45,7 +45,8 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
'cancelingGiftCard': 'Canceling Gift Card...',
|
'cancelingGiftCard': 'Canceling Gift Card...',
|
||||||
'creatingGiftCard': 'Creating Gift Card...',
|
'creatingGiftCard': 'Creating Gift Card...',
|
||||||
'buyingGiftCard': 'Buying Gift Card...',
|
'buyingGiftCard': 'Buying Gift Card...',
|
||||||
'topup': gettext('Top up in progress...')
|
'topup': gettext('Top up in progress...'),
|
||||||
|
'duplicatingWallet': gettext('Duplicating wallet...'),
|
||||||
};
|
};
|
||||||
|
|
||||||
root.clear = function() {
|
root.clear = function() {
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,10 @@ angular.module('copayApp.services').factory('openURLService', function($rootScop
|
||||||
|
|
||||||
// This event is sent to an existent instance of Copay (only for standalone apps)
|
// This event is sent to an existent instance of Copay (only for standalone apps)
|
||||||
gui.App.on('open', function(pathData) {
|
gui.App.on('open', function(pathData) {
|
||||||
if (pathData.indexOf('bitcoin:') != -1) {
|
if (pathData.indexOf(/^bitcoin(cash)?:/) != -1) {
|
||||||
$log.debug('Bitcoin URL found');
|
$log.debug('Bitcoin URL found');
|
||||||
handleOpenURL({
|
handleOpenURL({
|
||||||
url: pathData.substring(pathData.indexOf('bitcoin:'))
|
url: pathData.substring(pathData.indexOf(/^bitcoin(cash)?:/))
|
||||||
});
|
});
|
||||||
} else if (pathData.indexOf(appConfigService.name + '://') != -1) {
|
} else if (pathData.indexOf(appConfigService.name + '://') != -1) {
|
||||||
$log.debug(appConfigService.name + ' URL found');
|
$log.debug(appConfigService.name + ' URL found');
|
||||||
|
|
@ -84,6 +84,7 @@ angular.module('copayApp.services').factory('openURLService', function($rootScop
|
||||||
if (navigator.registerProtocolHandler) {
|
if (navigator.registerProtocolHandler) {
|
||||||
$log.debug('Registering Browser handlers base:' + base);
|
$log.debug('Registering Browser handlers base:' + base);
|
||||||
navigator.registerProtocolHandler('bitcoin', url, 'Copay Bitcoin Handler');
|
navigator.registerProtocolHandler('bitcoin', url, 'Copay Bitcoin Handler');
|
||||||
|
navigator.registerProtocolHandler('web+bitcoincash', url, 'Copay Bitcoin Cash Handler');
|
||||||
navigator.registerProtocolHandler('web+copay', url, 'Copay Wallet Handler');
|
navigator.registerProtocolHandler('web+copay', url, 'Copay Wallet Handler');
|
||||||
navigator.registerProtocolHandler('web+bitpay', url, 'BitPay Wallet Handler');
|
navigator.registerProtocolHandler('web+bitpay', url, 'BitPay Wallet Handler');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, $state) {
|
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, $state, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, appConfigService) {
|
||||||
|
|
||||||
|
|
||||||
var isChromeApp = platformInfo.isChromeApp;
|
var isChromeApp = platformInfo.isChromeApp;
|
||||||
|
|
@ -89,6 +89,7 @@ angular.module('copayApp.services')
|
||||||
wallet.copayerId = wallet.credentials.copayerId;
|
wallet.copayerId = wallet.credentials.copayerId;
|
||||||
wallet.m = wallet.credentials.m;
|
wallet.m = wallet.credentials.m;
|
||||||
wallet.n = wallet.credentials.n;
|
wallet.n = wallet.credentials.n;
|
||||||
|
wallet.coin = wallet.credentials.coin;
|
||||||
|
|
||||||
root.updateWalletSettings(wallet);
|
root.updateWalletSettings(wallet);
|
||||||
root.wallet[walletId] = wallet;
|
root.wallet[walletId] = wallet;
|
||||||
|
|
@ -222,11 +223,12 @@ angular.module('copayApp.services')
|
||||||
return ((config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url);
|
return ((config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var client = bwcService.getClient(JSON.stringify(credentials), {
|
var client = bwcService.getClient(JSON.stringify(credentials), {
|
||||||
bwsurl: getBWSURL(credentials.walletId),
|
bwsurl: getBWSURL(credentials.walletId),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var skipKeyValidation = shouldSkipValidation(credentials.walletId);
|
var skipKeyValidation = shouldSkipValidation(credentials.walletId);
|
||||||
if (!skipKeyValidation)
|
if (!skipKeyValidation)
|
||||||
root.runValidation(client, 500);
|
root.runValidation(client, 500);
|
||||||
|
|
@ -328,6 +330,7 @@ angular.module('copayApp.services')
|
||||||
passphrase: opts.passphrase,
|
passphrase: opts.passphrase,
|
||||||
account: opts.account || 0,
|
account: opts.account || 0,
|
||||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||||
|
coin: opts.coin
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
|
@ -336,7 +339,12 @@ angular.module('copayApp.services')
|
||||||
}
|
}
|
||||||
} else if (opts.extendedPrivateKey) {
|
} else if (opts.extendedPrivateKey) {
|
||||||
try {
|
try {
|
||||||
walletClient.seedFromExtendedPrivateKey(opts.extendedPrivateKey);
|
walletClient.seedFromExtendedPrivateKey(opts.extendedPrivateKey, {
|
||||||
|
network: network,
|
||||||
|
account: opts.account || 0,
|
||||||
|
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||||
|
coin: opts.coin,
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
$log.warn(ex);
|
$log.warn(ex);
|
||||||
return cb(gettextCatalog.getString('Could not create using the specified extended private key'));
|
return cb(gettextCatalog.getString('Could not create using the specified extended private key'));
|
||||||
|
|
@ -346,6 +354,7 @@ angular.module('copayApp.services')
|
||||||
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
||||||
account: opts.account || 0,
|
account: opts.account || 0,
|
||||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||||
|
coin: opts.coin
|
||||||
});
|
});
|
||||||
walletClient.credentials.hwInfo = opts.hwInfo;
|
walletClient.credentials.hwInfo = opts.hwInfo;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
|
@ -360,6 +369,7 @@ angular.module('copayApp.services')
|
||||||
passphrase: opts.passphrase,
|
passphrase: opts.passphrase,
|
||||||
language: lang,
|
language: lang,
|
||||||
account: 0,
|
account: 0,
|
||||||
|
coin: opts.coin
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$log.info('Error creating recovery phrase: ' + e.message);
|
$log.info('Error creating recovery phrase: ' + e.message);
|
||||||
|
|
@ -369,6 +379,7 @@ angular.module('copayApp.services')
|
||||||
network: network,
|
network: network,
|
||||||
passphrase: opts.passphrase,
|
passphrase: opts.passphrase,
|
||||||
account: 0,
|
account: 0,
|
||||||
|
coin: opts.coin
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return cb(e);
|
return cb(e);
|
||||||
|
|
@ -380,7 +391,11 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
// Creates a wallet on BWC/BWS
|
// Creates a wallet on BWC/BWS
|
||||||
var doCreateWallet = function(opts, cb) {
|
var doCreateWallet = function(opts, cb) {
|
||||||
$log.debug('Creating Wallet:', opts);
|
var showOpts = lodash.clone(opts);
|
||||||
|
if (showOpts.extendedPrivateKey) showOpts.extendedPrivateKey='[hidden]';
|
||||||
|
if (showOpts.mnemonic) showOpts.mnemonic='[hidden]';
|
||||||
|
|
||||||
|
$log.debug('Creating Wallet:', showOpts);
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
seedWallet(opts, function(err, walletClient) {
|
seedWallet(opts, function(err, walletClient) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
@ -392,6 +407,7 @@ angular.module('copayApp.services')
|
||||||
network: opts.networkName,
|
network: opts.networkName,
|
||||||
singleAddress: opts.singleAddress,
|
singleAddress: opts.singleAddress,
|
||||||
walletPrivKey: opts.walletPrivKey,
|
walletPrivKey: opts.walletPrivKey,
|
||||||
|
coin: opts.coin
|
||||||
}, function(err, secret) {
|
}, function(err, secret) {
|
||||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb);
|
if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb);
|
||||||
return cb(null, walletClient, secret);
|
return cb(null, walletClient, secret);
|
||||||
|
|
@ -435,7 +451,9 @@ angular.module('copayApp.services')
|
||||||
seedWallet(opts, function(err, walletClient) {
|
seedWallet(opts, function(err, walletClient) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
walletClient.joinWallet(opts.secret, opts.myName || 'me', {}, function(err) {
|
walletClient.joinWallet(opts.secret, opts.myName || 'me', {
|
||||||
|
coin: opts.coin
|
||||||
|
}, function(err) {
|
||||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Could not join wallet'), cb);
|
if (err) return bwcError.cb(err, gettextCatalog.getString('Could not join wallet'), cb);
|
||||||
addAndBindWalletClient(walletClient, {
|
addAndBindWalletClient(walletClient, {
|
||||||
bwsurl: opts.bwsurl
|
bwsurl: opts.bwsurl
|
||||||
|
|
@ -495,7 +513,9 @@ angular.module('copayApp.services')
|
||||||
var walletId = client.credentials.walletId
|
var walletId = client.credentials.walletId
|
||||||
|
|
||||||
if (!root.profile.addWallet(JSON.parse(client.export())))
|
if (!root.profile.addWallet(JSON.parse(client.export())))
|
||||||
return cb(gettextCatalog.getString('Wallet already in Copay'));
|
return cb(gettextCatalog.getString("Wallet already in {{appName}}", {
|
||||||
|
appName: appConfigService.nameCase
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
var skipKeyValidation = shouldSkipValidation(walletId);
|
var skipKeyValidation = shouldSkipValidation(walletId);
|
||||||
|
|
@ -621,6 +641,7 @@ angular.module('copayApp.services')
|
||||||
entropySourcePath: opts.entropySourcePath,
|
entropySourcePath: opts.entropySourcePath,
|
||||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||||
account: opts.account || 0,
|
account: opts.account || 0,
|
||||||
|
coin: opts.coin
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err instanceof errors.NOT_AUTHORIZED)
|
if (err instanceof errors.NOT_AUTHORIZED)
|
||||||
|
|
@ -642,6 +663,7 @@ angular.module('copayApp.services')
|
||||||
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
||||||
account: opts.account || 0,
|
account: opts.account || 0,
|
||||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||||
|
coin: opts.coin
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
|
|
@ -682,6 +704,7 @@ angular.module('copayApp.services')
|
||||||
opts.m = 1;
|
opts.m = 1;
|
||||||
opts.n = 1;
|
opts.n = 1;
|
||||||
opts.networkName = 'livenet';
|
opts.networkName = 'livenet';
|
||||||
|
opts.coin = 'btc';
|
||||||
root.createWallet(opts, cb);
|
root.createWallet(opts, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -747,6 +770,12 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
var ret = lodash.values(root.wallet);
|
var ret = lodash.values(root.wallet);
|
||||||
|
|
||||||
|
if (opts.coin) {
|
||||||
|
ret = lodash.filter(ret, function(x) {
|
||||||
|
return (x.credentials.coin == opts.coin);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.network) {
|
if (opts.network) {
|
||||||
ret = lodash.filter(ret, function(x) {
|
ret = lodash.filter(ret, function(x) {
|
||||||
return (x.credentials.network == opts.network);
|
return (x.credentials.network == opts.network);
|
||||||
|
|
@ -767,12 +796,14 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
if (opts.hasFunds) {
|
if (opts.hasFunds) {
|
||||||
ret = lodash.filter(ret, function(w) {
|
ret = lodash.filter(ret, function(w) {
|
||||||
|
if (!w.status) return;
|
||||||
return (w.status.availableBalanceSat > 0);
|
return (w.status.availableBalanceSat > 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.minAmount) {
|
if (opts.minAmount) {
|
||||||
ret = lodash.filter(ret, function(w) {
|
ret = lodash.filter(ret, function(w) {
|
||||||
|
if (!w.status) return;
|
||||||
return (w.status.availableBalanceSat > opts.minAmount);
|
return (w.status.availableBalanceSat > opts.minAmount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -857,7 +888,7 @@ angular.module('copayApp.services')
|
||||||
x.types = [x.type];
|
x.types = [x.type];
|
||||||
|
|
||||||
if (x.data && x.data.amount)
|
if (x.data && x.data.amount)
|
||||||
x.amountStr = txFormatService.formatAmountStr(x.data.amount);
|
x.amountStr = txFormatService.formatAmountStr(x.wallet.coin, x.data.amount);
|
||||||
|
|
||||||
x.action = function() {
|
x.action = function() {
|
||||||
// TODO?
|
// TODO?
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,10 @@ var RateService = function(opts) {
|
||||||
self._isAvailable = false;
|
self._isAvailable = false;
|
||||||
self._rates = {};
|
self._rates = {};
|
||||||
self._alternatives = [];
|
self._alternatives = [];
|
||||||
|
self._ratesBCH = {};
|
||||||
self._queued = [];
|
self._queued = [];
|
||||||
|
|
||||||
self._fetchCurrencies();
|
self.updateRates();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,14 +40,20 @@ RateService.singleton = function(opts) {
|
||||||
return _instance;
|
return _instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype._fetchCurrencies = function() {
|
RateService.prototype.updateRates = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var backoffSeconds = 5;
|
var backoffSeconds = 5;
|
||||||
var updateFrequencySeconds = 5 * 60;
|
var updateFrequencySeconds = 5 * 60;
|
||||||
var rateServiceUrl = 'https://bitpay.com/api/rates';
|
var rateServiceUrl = 'https://bitpay.com/api/rates';
|
||||||
|
var bchRateServiceUrl = 'https://api.kraken.com/0/public/Ticker?pair=BCHUSD,BCHEUR';
|
||||||
|
|
||||||
|
|
||||||
|
function getBTC(cb, tries) {
|
||||||
|
tries = tries || 0;
|
||||||
|
if (!self.httprequest) return;
|
||||||
|
if (tries > 5) return cb('could not get BTC rates');
|
||||||
|
|
||||||
var retrieve = function() {
|
|
||||||
//log.info('Fetching exchange rates');
|
//log.info('Fetching exchange rates');
|
||||||
self.httprequest.get(rateServiceUrl).success(function(res) {
|
self.httprequest.get(rateServiceUrl).success(function(res) {
|
||||||
self.lodash.each(res, function(currency) {
|
self.lodash.each(res, function(currency) {
|
||||||
|
|
@ -57,27 +64,64 @@ RateService.prototype._fetchCurrencies = function() {
|
||||||
rate: currency.rate
|
rate: currency.rate
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return cb();
|
||||||
|
}).error(function() {
|
||||||
|
//log.debug('Error fetching exchange rates', err);
|
||||||
|
setTimeout(function() {
|
||||||
|
backoffSeconds *= 1.5;
|
||||||
|
getBTC(cb, tries++);
|
||||||
|
}, backoffSeconds * 1000);
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBCH(cb, tries) {
|
||||||
|
tries = tries || 0;
|
||||||
|
if (!self.httprequest) return;
|
||||||
|
if (tries > 5) return cb('could not get BCH rates');
|
||||||
|
|
||||||
|
function retry(tries) {
|
||||||
|
//log.debug('Error fetching exchange rates', err);
|
||||||
|
setTimeout(function() {
|
||||||
|
backoffSeconds *= 1.5;
|
||||||
|
getBTC(cb, tries++);
|
||||||
|
}, backoffSeconds * 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.httprequest.get(bchRateServiceUrl).success(function(res) {
|
||||||
|
self.lodash.each(res.result, function(data, paircode) {
|
||||||
|
var code = paircode.substr(3,3);
|
||||||
|
var rate =data.c[0];
|
||||||
|
self._ratesBCH[code] = rate;
|
||||||
|
})
|
||||||
|
return cb();
|
||||||
|
}).error(function() {
|
||||||
|
return retry(tries);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getBTC(function(err) {
|
||||||
|
if (err) return;
|
||||||
|
getBCH(function(err) {
|
||||||
|
if (err) return;
|
||||||
|
|
||||||
self._isAvailable = true;
|
self._isAvailable = true;
|
||||||
self.lodash.each(self._queued, function(callback) {
|
self.lodash.each(self._queued, function(callback) {
|
||||||
setTimeout(callback, 1);
|
setTimeout(callback, 1);
|
||||||
});
|
});
|
||||||
setTimeout(retrieve, updateFrequencySeconds * 1000);
|
setTimeout( self.updateRates , updateFrequencySeconds * 1000);
|
||||||
}).error(function(err) {
|
})
|
||||||
//log.debug('Error fetching exchange rates', err);
|
})
|
||||||
setTimeout(function() {
|
|
||||||
backoffSeconds *= 1.5;
|
|
||||||
retrieve();
|
|
||||||
}, backoffSeconds * 1000);
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
retrieve();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype.getRate = function(code) {
|
RateService.prototype.getRate = function(code, chain) {
|
||||||
return this._rates[code];
|
if (chain == 'bch')
|
||||||
|
return this._ratesBCH[code];
|
||||||
|
else
|
||||||
|
return this._rates[code];
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype.getAlternatives = function() {
|
RateService.prototype.getAlternatives = function() {
|
||||||
|
|
@ -90,25 +134,25 @@ RateService.prototype.isAvailable = function() {
|
||||||
|
|
||||||
RateService.prototype.whenAvailable = function(callback) {
|
RateService.prototype.whenAvailable = function(callback) {
|
||||||
if (this.isAvailable()) {
|
if (this.isAvailable()) {
|
||||||
setTimeout(callback, 1);
|
setTimeout(callback, 10);
|
||||||
} else {
|
} else {
|
||||||
this._queued.push(callback);
|
this._queued.push(callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype.toFiat = function(satoshis, code) {
|
RateService.prototype.toFiat = function(satoshis, code, chain) {
|
||||||
if (!this.isAvailable()) {
|
if (!this.isAvailable()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return satoshis * this.SAT_TO_BTC * this.getRate(code);
|
return satoshis * this.SAT_TO_BTC * this.getRate(code, chain);
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype.fromFiat = function(amount, code) {
|
RateService.prototype.fromFiat = function(amount, code, chain) {
|
||||||
if (!this.isAvailable()) {
|
if (!this.isAvailable()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return amount / this.getRate(code) * this.BTC_TO_SAT;
|
return amount / this.getRate(code, chain) * this.BTC_TO_SAT;
|
||||||
};
|
};
|
||||||
|
|
||||||
RateService.prototype.listAlternatives = function(sort) {
|
RateService.prototype.listAlternatives = function(sort) {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ angular.module('copayApp.services').service('sendMaxService', function(feeServic
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
this.getInfo = function(wallet, cb) {
|
this.getInfo = function(wallet, cb) {
|
||||||
feeService.getCurrentFeeRate(wallet.credentials.network, function(err, feePerKb) {
|
feeService.getCurrentFeeRate(wallet.coin, wallet.credentials.network, function(err, feePerKb) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
var config = configService.getSync().wallet;
|
var config = configService.getSync().wallet;
|
||||||
|
|
|
||||||
|
|
@ -610,5 +610,17 @@ angular.module('copayApp.services')
|
||||||
storage.remove('txConfirmNotif-' + txid, cb);
|
storage.remove('txConfirmNotif-' + txid, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.setMercadoLibreGiftCards = function(network, gcs, cb) {
|
||||||
|
storage.set('mercadoLibreGiftCards-' + network, gcs, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
root.getMercadoLibreGiftCards = function(network, cb) {
|
||||||
|
storage.get('mercadoLibreGiftCards-' + network, cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
root.removeMercadoLibreGiftCards = function(network, cb) {
|
||||||
|
storage.remove('MercadoLibreGiftCards-' + network, cb);
|
||||||
|
};
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
|
|
||||||
|
|
||||||
root.formatAmount = function(satoshis, fullPrecision) {
|
root.formatAmount = function(satoshis, fullPrecision) {
|
||||||
var config = configService.getSync().wallet.settings;
|
var config = configService.getDefaults().wallet.settings;
|
||||||
if (config.unitCode == 'sat') return satoshis;
|
if (config.unitCode == 'sat') return satoshis;
|
||||||
|
|
||||||
//TODO : now only works for english, specify opts to change thousand separator and decimal separator
|
//TODO : now only works for english, specify opts to change thousand separator and decimal separator
|
||||||
|
|
@ -17,16 +17,15 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
return this.Utils.formatAmount(satoshis, config.unitCode, opts);
|
return this.Utils.formatAmount(satoshis, config.unitCode, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
root.formatAmountStr = function(satoshis) {
|
root.formatAmountStr = function(coin, satoshis) {
|
||||||
if (isNaN(satoshis)) return;
|
if (isNaN(satoshis)) return;
|
||||||
var config = configService.getSync().wallet.settings;
|
return root.formatAmount(satoshis) + ' ' + (coin).toUpperCase();
|
||||||
return root.formatAmount(satoshis) + ' ' + config.unitName;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
root.toFiat = function(satoshis, code, cb) {
|
root.toFiat = function(coin, satoshis, code, cb) {
|
||||||
if (isNaN(satoshis)) return;
|
if (isNaN(satoshis)) return;
|
||||||
var val = function() {
|
var val = function() {
|
||||||
var v1 = rateService.toFiat(satoshis, code);
|
var v1 = rateService.toFiat(satoshis, code, coin);
|
||||||
if (!v1) return null;
|
if (!v1) return null;
|
||||||
|
|
||||||
return v1.toFixed(2);
|
return v1.toFixed(2);
|
||||||
|
|
@ -43,10 +42,10 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
root.formatToUSD = function(satoshis, cb) {
|
root.formatToUSD = function(coin, satoshis, cb) {
|
||||||
if (isNaN(satoshis)) return;
|
if (isNaN(satoshis)) return;
|
||||||
var val = function() {
|
var val = function() {
|
||||||
var v1 = rateService.toFiat(satoshis, 'USD');
|
var v1 = rateService.toFiat(satoshis, 'USD', coin);
|
||||||
if (!v1) return null;
|
if (!v1) return null;
|
||||||
|
|
||||||
return v1.toFixed(2);
|
return v1.toFixed(2);
|
||||||
|
|
@ -63,12 +62,12 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
root.formatAlternativeStr = function(satoshis, cb) {
|
root.formatAlternativeStr = function(coin, satoshis, cb) {
|
||||||
if (isNaN(satoshis)) return;
|
if (isNaN(satoshis)) return;
|
||||||
var config = configService.getSync().wallet.settings;
|
var config = configService.getSync().wallet.settings;
|
||||||
|
|
||||||
var val = function() {
|
var val = function() {
|
||||||
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode)).toFixed(2));
|
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode, coin)).toFixed(2));
|
||||||
v1 = $filter('formatFiatAmount')(v1);
|
v1 = $filter('formatFiatAmount')(v1);
|
||||||
if (!v1) return null;
|
if (!v1) return null;
|
||||||
|
|
||||||
|
|
@ -86,7 +85,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
root.processTx = function(tx) {
|
root.processTx = function(coin, tx) {
|
||||||
if (!tx || tx.action == 'invalid')
|
if (!tx || tx.action == 'invalid')
|
||||||
return tx;
|
return tx;
|
||||||
|
|
||||||
|
|
@ -101,17 +100,17 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
tx.hasMultiplesOutputs = true;
|
tx.hasMultiplesOutputs = true;
|
||||||
}
|
}
|
||||||
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
|
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
|
||||||
o.amountStr = root.formatAmountStr(o.amount);
|
o.amountStr = root.formatAmountStr(coin, o.amount);
|
||||||
o.alternativeAmountStr = root.formatAlternativeStr(o.amount);
|
o.alternativeAmountStr = root.formatAlternativeStr(coin, o.amount);
|
||||||
return total + o.amount;
|
return total + o.amount;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
tx.toAddress = tx.outputs[0].toAddress;
|
tx.toAddress = tx.outputs[0].toAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.amountStr = root.formatAmountStr(tx.amount);
|
tx.amountStr = root.formatAmountStr(coin, tx.amount);
|
||||||
tx.alternativeAmountStr = root.formatAlternativeStr(tx.amount);
|
tx.alternativeAmountStr = root.formatAlternativeStr(coin, tx.amount);
|
||||||
tx.feeStr = root.formatAmountStr(tx.fee || tx.fees);
|
tx.feeStr = root.formatAmountStr(coin, tx.fee || tx.fees);
|
||||||
|
|
||||||
if (tx.amountStr) {
|
if (tx.amountStr) {
|
||||||
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
||||||
|
|
@ -145,8 +144,6 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
|
|
||||||
lodash.each(txps, function(tx) {
|
lodash.each(txps, function(tx) {
|
||||||
|
|
||||||
tx = txFormatService.processTx(tx);
|
|
||||||
|
|
||||||
// no future transactions...
|
// no future transactions...
|
||||||
if (tx.createdOn > now)
|
if (tx.createdOn > now)
|
||||||
tx.createdOn = now;
|
tx.createdOn = now;
|
||||||
|
|
@ -157,6 +154,8 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx = txFormatService.processTx(tx.wallet.coin, tx);
|
||||||
|
|
||||||
var action = lodash.find(tx.actions, {
|
var action = lodash.find(tx.actions, {
|
||||||
copayerId: tx.wallet.copayerId
|
copayerId: tx.wallet.copayerId
|
||||||
});
|
});
|
||||||
|
|
@ -180,7 +179,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
return txps;
|
return txps;
|
||||||
};
|
};
|
||||||
|
|
||||||
root.parseAmount = function(amount, currency) {
|
root.parseAmount = function(coin, amount, currency) {
|
||||||
var config = configService.getSync().wallet.settings;
|
var config = configService.getSync().wallet.settings;
|
||||||
var satToBtc = 1 / 100000000;
|
var satToBtc = 1 / 100000000;
|
||||||
var unitToSatoshi = config.unitToSatoshi;
|
var unitToSatoshi = config.unitToSatoshi;
|
||||||
|
|
@ -189,21 +188,21 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
||||||
var alternativeIsoCode = config.alternativeIsoCode;
|
var alternativeIsoCode = config.alternativeIsoCode;
|
||||||
|
|
||||||
// If fiat currency
|
// If fiat currency
|
||||||
if (currency != 'bits' && currency != 'BTC' && currency != 'sat') {
|
if (currency != 'BCH' && currency != 'BTC' && currency != 'sat') {
|
||||||
amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency;
|
amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency;
|
||||||
amountSat = rateService.fromFiat(amount, currency).toFixed(0);
|
amountSat = rateService.fromFiat(amount, currency, coin).toFixed(0);
|
||||||
} else if (currency == 'sat') {
|
} else if (currency == 'sat') {
|
||||||
amountSat = amount;
|
amountSat = amount;
|
||||||
amountUnitStr = root.formatAmountStr(amountSat);
|
amountUnitStr = root.formatAmountStr(coin, amountSat);
|
||||||
// convert sat to BTC
|
// convert sat to BTC or BCH
|
||||||
amount = (amountSat * satToBtc).toFixed(8);
|
amount = (amountSat * satToBtc).toFixed(8);
|
||||||
currency = 'BTC';
|
currency = (coin).toUpperCase();
|
||||||
} else {
|
} else {
|
||||||
amountSat = parseInt((amount * unitToSatoshi).toFixed(0));
|
amountSat = parseInt((amount * unitToSatoshi).toFixed(0));
|
||||||
amountUnitStr = root.formatAmountStr(amountSat);
|
amountUnitStr = root.formatAmountStr(coin, amountSat);
|
||||||
// convert unit to BTC
|
// convert unit to BTC or BCH
|
||||||
amount = (amountSat * satToBtc).toFixed(8);
|
amount = (amountSat * satToBtc).toFixed(8);
|
||||||
currency = 'BTC';
|
currency = (coin).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ angular.module('copayApp.services')
|
||||||
}, {
|
}, {
|
||||||
name: 'Italiano',
|
name: 'Italiano',
|
||||||
isoCode: 'it',
|
isoCode: 'it',
|
||||||
|
}, {
|
||||||
|
name: 'Nederlands',
|
||||||
|
isoCode: 'nl',
|
||||||
}, {
|
}, {
|
||||||
name: 'Polski',
|
name: 'Polski',
|
||||||
isoCode: 'pl',
|
isoCode: 'pl',
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
root.getStatus = function(wallet, opts, cb) {
|
root.getStatus = function(wallet, opts, cb) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
var walletId = wallet.id;
|
||||||
|
|
||||||
function processPendingTxps(status) {
|
function processPendingTxps(status) {
|
||||||
var txps = status.pendingTxps;
|
var txps = status.pendingTxps;
|
||||||
|
|
@ -130,7 +130,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
lodash.each(txps, function(tx) {
|
lodash.each(txps, function(tx) {
|
||||||
|
|
||||||
tx = txFormatService.processTx(tx);
|
tx = txFormatService.processTx(wallet.coin, tx);
|
||||||
|
|
||||||
// no future transactions...
|
// no future transactions...
|
||||||
if (tx.createdOn > now)
|
if (tx.createdOn > now)
|
||||||
|
|
@ -213,14 +213,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
// Selected unit
|
// Selected unit
|
||||||
cache.unitToSatoshi = config.settings.unitToSatoshi;
|
cache.unitToSatoshi = config.settings.unitToSatoshi;
|
||||||
cache.satToUnit = 1 / cache.unitToSatoshi;
|
cache.satToUnit = 1 / cache.unitToSatoshi;
|
||||||
cache.unitName = config.settings.unitName;
|
|
||||||
|
|
||||||
//STR
|
//STR
|
||||||
cache.totalBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat) + ' ' + cache.unitName;
|
cache.totalBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.totalBalanceSat);
|
||||||
cache.lockedBalanceStr = txFormatService.formatAmount(cache.lockedBalanceSat) + ' ' + cache.unitName;
|
cache.lockedBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.lockedBalanceSat);
|
||||||
cache.availableBalanceStr = txFormatService.formatAmount(cache.availableBalanceSat) + ' ' + cache.unitName;
|
cache.availableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.availableBalanceSat);
|
||||||
cache.spendableBalanceStr = txFormatService.formatAmount(cache.spendableAmount) + ' ' + cache.unitName;
|
cache.spendableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.spendableAmount);
|
||||||
cache.pendingBalanceStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName;
|
cache.pendingBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.pendingAmount);
|
||||||
|
|
||||||
cache.alternativeName = config.settings.alternativeName;
|
cache.alternativeName = config.settings.alternativeName;
|
||||||
cache.alternativeIsoCode = config.settings.alternativeIsoCode;
|
cache.alternativeIsoCode = config.settings.alternativeIsoCode;
|
||||||
|
|
@ -238,11 +237,11 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
rateService.whenAvailable(function() {
|
rateService.whenAvailable(function() {
|
||||||
|
|
||||||
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode);
|
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode, wallet.coin);
|
||||||
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode);
|
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode, wallet.coin);
|
||||||
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode);
|
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode, wallet.coin);
|
||||||
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode);
|
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode, wallet.coin);
|
||||||
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode);
|
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode, wallet.coin);
|
||||||
|
|
||||||
cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative);
|
cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative);
|
||||||
cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative);
|
cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative);
|
||||||
|
|
@ -260,6 +259,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
};
|
};
|
||||||
|
|
||||||
function cacheStatus(status) {
|
function cacheStatus(status) {
|
||||||
|
if (status.wallet && status.wallet.scanStatus == 'running') return;
|
||||||
|
|
||||||
wallet.cachedStatus = status || {};
|
wallet.cachedStatus = status || {};
|
||||||
var cache = wallet.cachedStatus;
|
var cache = wallet.cachedStatus;
|
||||||
cache.statusUpdatedOn = Date.now();
|
cache.statusUpdatedOn = Date.now();
|
||||||
|
|
@ -304,6 +305,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
cacheStatus(status);
|
cacheStatus(status);
|
||||||
|
|
||||||
|
wallet.scanning = status.wallet && status.wallet.scanStatus == 'running';
|
||||||
|
|
||||||
return cb(null, status);
|
return cb(null, status);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -366,7 +369,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
wallet.hasUnsafeConfirmed = false;
|
wallet.hasUnsafeConfirmed = false;
|
||||||
|
|
||||||
lodash.each(txs, function(tx) {
|
lodash.each(txs, function(tx) {
|
||||||
tx = txFormatService.processTx(tx);
|
tx = txFormatService.processTx(wallet.coin, tx);
|
||||||
|
|
||||||
// no future transactions...
|
// no future transactions...
|
||||||
if (tx.time > now)
|
if (tx.time > now)
|
||||||
|
|
@ -400,7 +403,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
var LIMIT = 50;
|
var LIMIT = 50;
|
||||||
var requestLimit = FIRST_LIMIT;
|
var requestLimit = FIRST_LIMIT;
|
||||||
var walletId = wallet.credentials.walletId;
|
var walletId = wallet.credentials.walletId;
|
||||||
var config = configService.getSync().wallet.settings;
|
|
||||||
|
|
||||||
var opts = opts || {};
|
var opts = opts || {};
|
||||||
var progressFn = opts.progressFn || function() {};
|
var progressFn = opts.progressFn || function() {};
|
||||||
|
|
@ -414,18 +416,16 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
var fixTxsUnit = function(txs) {
|
var fixTxsUnit = function(txs) {
|
||||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||||
|
|
||||||
var cacheUnit = txs[0].amountStr.split(' ')[1];
|
var cacheCoin = txs[0].amountStr.split(' ')[1];
|
||||||
|
|
||||||
if (cacheUnit == config.unitName)
|
if (cacheCoin == 'bits') {
|
||||||
return;
|
|
||||||
|
|
||||||
var name = ' ' + config.unitName;
|
$log.debug('Fixing Tx Cache Unit to: ' + wallet.coin)
|
||||||
|
lodash.each(txs, function(tx) {
|
||||||
$log.debug('Fixing Tx Cache Unit to:' + name)
|
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount);
|
||||||
lodash.each(txs, function(tx) {
|
tx.feeStr = txFormatService.formatAmountStr(wallet.coin, tx.fees);
|
||||||
tx.amountStr = txFormatService.formatAmount(tx.amount) + name;
|
});
|
||||||
tx.feeStr = txFormatService.formatAmount(tx.fees) + name;
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
getSavedTxs(walletId, function(err, txsFromLocal) {
|
getSavedTxs(walletId, function(err, txsFromLocal) {
|
||||||
|
|
@ -788,7 +788,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
//prefs.email (may come from arguments)
|
//prefs.email (may come from arguments)
|
||||||
prefs.email = config.emailNotifications.email;
|
prefs.email = config.emailNotifications.email;
|
||||||
prefs.language = uxLanguage.getCurrentLanguage();
|
prefs.language = uxLanguage.getCurrentLanguage();
|
||||||
prefs.unit = walletSettings.unitCode;
|
// prefs.unit = walletSettings.unitCode; // TODO: remove, not used
|
||||||
|
|
||||||
updateRemotePreferencesFor(lodash.clone(clients), prefs, function(err) {
|
updateRemotePreferencesFor(lodash.clone(clients), prefs, function(err) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
@ -820,13 +820,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
$log.debug('Scanning wallet ' + wallet.id);
|
$log.debug('Scanning wallet ' + wallet.id);
|
||||||
if (!wallet.isComplete()) return;
|
if (!wallet.isComplete()) return;
|
||||||
|
|
||||||
wallet.updating = true;
|
wallet.scanning = true;
|
||||||
ongoingProcess.set('scanning', true);
|
|
||||||
wallet.startScan({
|
wallet.startScan({
|
||||||
includeCopayerBranches: true,
|
includeCopayerBranches: true,
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
wallet.updating = false;
|
|
||||||
ongoingProcess.set('scanning', false);
|
|
||||||
return cb(err);
|
return cb(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -926,7 +923,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
root.getMinFee = function(wallet, feeLevels, nbOutputs) {
|
root.getMinFee = function(wallet, feeLevels, nbOutputs) {
|
||||||
var lowLevelRate = (lodash.find(feeLevels[wallet.network], {
|
var lowLevelRate = (lodash.find(feeLevels[wallet.network], {
|
||||||
level: 'normal',
|
level: 'normal',
|
||||||
}).feePerKB / 1000).toFixed(0);
|
}).feePerKb / 1000).toFixed(0);
|
||||||
|
|
||||||
var size = root.getEstimatedTxSize(wallet, nbOutputs);
|
var size = root.getEstimatedTxSize(wallet, nbOutputs);
|
||||||
return size * lowLevelRate;
|
return size * lowLevelRate;
|
||||||
|
|
@ -935,15 +932,17 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
|
|
||||||
// Approx utxo amount, from which the uxto is economically redeemable
|
// Approx utxo amount, from which the uxto is economically redeemable
|
||||||
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
||||||
var minFee = root.getMinFee(wallet,feeLevels, nbOutputs);
|
var minFee = root.getMinFee(wallet, feeLevels, nbOutputs);
|
||||||
return parseInt( minFee / LOW_AMOUNT_RATIO);
|
return parseInt(minFee / LOW_AMOUNT_RATIO);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
root.getLowUtxos = function(wallet, levels, cb) {
|
root.getLowUtxos = function(wallet, levels, cb) {
|
||||||
|
|
||||||
wallet.getUtxos({}, function(err, resp) {
|
wallet.getUtxos({
|
||||||
|
coin: wallet.coin
|
||||||
|
}, function(err, resp) {
|
||||||
if (err || !resp || !resp.length) return cb();
|
if (err || !resp || !resp.length) return cb();
|
||||||
|
|
||||||
var minFee = root.getMinFee(wallet, levels, resp.length);
|
var minFee = root.getMinFee(wallet, levels, resp.length);
|
||||||
|
|
@ -959,7 +958,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
||||||
|
|
||||||
return cb(err, {
|
return cb(err, {
|
||||||
allUtxos: resp || [],
|
allUtxos: resp || [],
|
||||||
lowUtxos: lowUtxos || [],
|
lowUtxos: lowUtxos || [],
|
||||||
warning: minFee / balance > TOTAL_LOW_WARNING_RATIO,
|
warning: minFee / balance > TOTAL_LOW_WARNING_RATIO,
|
||||||
minFee: minFee,
|
minFee: minFee,
|
||||||
|
|
@ -1236,5 +1235,38 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.getProtocolHandler = function(wallet) {
|
||||||
|
if (wallet.coin== 'bch') return 'bitcoincash';
|
||||||
|
else return 'bitcoin';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
root.copyCopayers = function(wallet, newWallet, cb) {
|
||||||
|
var c = wallet.credentials;
|
||||||
|
|
||||||
|
var walletPrivKey = bitcore.PrivateKey.fromString(c.walletPrivKey);
|
||||||
|
|
||||||
|
var copayer = 1,
|
||||||
|
i = 0,
|
||||||
|
l = c.publicKeyRing.length;
|
||||||
|
var mainErr = null;
|
||||||
|
|
||||||
|
lodash.each(c.publicKeyRing, function(item) {
|
||||||
|
var name = item.copayerName || ('copayer ' + copayer++);
|
||||||
|
newWallet._doJoinWallet(newWallet.credentials.walletId, walletPrivKey, item.xPubKey, item.requestPubKey, name, {
|
||||||
|
coin: newWallet.credentials.coin,
|
||||||
|
}, function(err) {
|
||||||
|
//Ignore error is copayer already in wallet
|
||||||
|
if (err && !(err instanceof errors.COPAYER_IN_WALLET)) {
|
||||||
|
mainErr = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++i == l) {
|
||||||
|
return cb(mainErr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.amount {
|
.amount {
|
||||||
|
.icon-toggle {
|
||||||
|
font-size: 1.2em;
|
||||||
|
width: auto;
|
||||||
|
margin: 0.8em auto;
|
||||||
|
border: 1px solid $v-subtle-gray;
|
||||||
|
color: $v-dark-gray;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
@media(max-height: 280px) {
|
||||||
|
margin: 0.1em auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
&__editable {
|
&__editable {
|
||||||
&--minimize {
|
&--minimize {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
|
|
@ -187,7 +200,7 @@
|
||||||
&__result {
|
&__result {
|
||||||
color: $v-light-gray;
|
color: $v-light-gray;
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
margin-bottom: -.9em;
|
//margin-bottom: -.9em; TODO matias
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@media(max-height: 480px) {
|
@media(max-height: 480px) {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
@ -196,7 +209,6 @@
|
||||||
&__result-equiv {
|
&__result-equiv {
|
||||||
color: $v-mid-gray;
|
color: $v-mid-gray;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
margin-top: 2rem;
|
|
||||||
@media(max-height: 480px) {
|
@media(max-height: 480px) {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
|
||||||
43
src/sass/views/cashScan.scss
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#cash-scan {
|
||||||
|
.comment {
|
||||||
|
color: #667;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
color: $v-dark-gray;
|
||||||
|
padding-top: 1.3rem;
|
||||||
|
padding-bottom: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
font-size: 17px;
|
||||||
|
color: $v-dark-gray;
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-disabled {
|
||||||
|
color: $v-light-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.supported {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.wallet-content {
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.duplicate-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
padding-top: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -99,6 +99,9 @@
|
||||||
i {
|
i {
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
span {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.toggle-unconfirmed {
|
.toggle-unconfirmed {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,17 @@ wallet-selector {
|
||||||
padding-right: .75rem;
|
padding-right: .75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subheader {
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #EFEFEF;
|
||||||
|
.wallet-coin-logo {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wallet-selector {
|
.wallet-selector {
|
||||||
.wallet {
|
.wallet {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
@import "coinbase";
|
@import "coinbase";
|
||||||
@import "glidera";
|
@import "glidera";
|
||||||
@import "amazon";
|
@import "amazon";
|
||||||
|
@import "mercadolibre";
|
||||||
|
|
||||||
#coinbase, #glidera {
|
#coinbase, #glidera {
|
||||||
.button-small {
|
.button-small {
|
||||||
|
|
|
||||||
202
src/sass/views/integrations/mercadolibre.scss
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
#mercadolibre {
|
||||||
|
$item-lateral-padding: 20px;
|
||||||
|
$item-vertical-padding: 10px;
|
||||||
|
$item-border-color: #EFEFEF;
|
||||||
|
$item-label-color: #6C6C6E;
|
||||||
|
@extend .deflash-blue;
|
||||||
|
.icon-amazon {
|
||||||
|
background-image: url("../img/mercado-libre/icon-ml.svg");
|
||||||
|
}
|
||||||
|
.spinner svg {
|
||||||
|
stroke: black;
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-bottom-for-cta {
|
||||||
|
bottom: 92px;
|
||||||
|
}
|
||||||
|
.head {
|
||||||
|
padding: 30px $item-lateral-padding 4rem;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
|
.sending-label {
|
||||||
|
display: flex;
|
||||||
|
font-size: 18px;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1.8rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-right: 1rem;
|
||||||
|
height: 35px;
|
||||||
|
width: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-icon-svg {
|
||||||
|
padding: 0 7px 0 0;
|
||||||
|
margin-right: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-icon-svg > .bg {
|
||||||
|
height: 28px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.amount-label{
|
||||||
|
line-height: 30px;
|
||||||
|
.amount{
|
||||||
|
font-size: 38px;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
|
||||||
|
> .unit {
|
||||||
|
font-family: "Roboto-Light";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alternative {
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: "Roboto-Light";
|
||||||
|
color: #9B9B9B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
border-color: $item-border-color;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
.badge {
|
||||||
|
border-radius: 0;
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
color: #4A4A4A;
|
||||||
|
padding-top: $item-vertical-padding;
|
||||||
|
padding-bottom: $item-vertical-padding;
|
||||||
|
padding-left: $item-lateral-padding;
|
||||||
|
|
||||||
|
&:not(.item-icon-right) {
|
||||||
|
padding-right: $item-lateral-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: $item-label-color;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.capitalized {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wallet .big-icon-svg > .bg {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
padding: 2px;
|
||||||
|
box-shadow: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-amount {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.single-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 17px;
|
||||||
|
padding-bottom: 17px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item-divider {
|
||||||
|
padding-top: 1.2rem;
|
||||||
|
color: $item-label-color;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.wallet {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: .2rem 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
~ .bp-arrow-right {
|
||||||
|
top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> i {
|
||||||
|
padding: 0;
|
||||||
|
position: static;
|
||||||
|
|
||||||
|
> img {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
padding: 2px;
|
||||||
|
margin-right: .7rem;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#meli-list-cards {
|
||||||
|
img.item-logo {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#meli-card {
|
||||||
|
.card-head {
|
||||||
|
margin: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
.date {
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.amount {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card-status {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
.card-status-desc {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: $v-text-secondary-color;
|
||||||
|
}
|
||||||
|
.redeem-pin {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
.button-redeem {
|
||||||
|
margin-top: 10px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 12px;
|
||||||
|
color: $v-text-accent-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.card-remove {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
.button-remove {
|
||||||
|
margin-top: 10px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 12px;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,11 @@
|
||||||
.icon-amazon {
|
.icon-amazon {
|
||||||
background-image: url("../img/icon-amazon.svg");
|
background-image: url("../img/icon-amazon.svg");
|
||||||
}
|
}
|
||||||
|
.icon-ml {
|
||||||
|
background-image: url("../img/mercado-libre/icon-ml.svg");
|
||||||
|
background-position: center;
|
||||||
|
background-size: 85%;
|
||||||
|
}
|
||||||
.bg {
|
.bg {
|
||||||
&.wallet {
|
&.wallet {
|
||||||
padding: .25rem
|
padding: .25rem
|
||||||
|
|
@ -54,6 +59,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.wallet-coin-logo {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
.wallet-details__item.item {
|
.wallet-details__item.item {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@
|
||||||
.has-comment {
|
.has-comment {
|
||||||
border-bottom: 0 none;
|
border-bottom: 0 none;
|
||||||
}
|
}
|
||||||
|
.scan-label {
|
||||||
|
cursor: pointer;
|
||||||
|
cursor: hand;
|
||||||
|
color: $link-color;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
.comment {
|
.comment {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
@ -34,6 +40,9 @@
|
||||||
width: 20px;
|
width: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&-explanation, &-button-group {
|
&-explanation, &-button-group {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
|
|
@ -137,6 +146,14 @@
|
||||||
.log-level {
|
.log-level {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.alt-currency-radio {
|
||||||
|
.item-content {
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
.radio-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#tab-settings {
|
#tab-settings {
|
||||||
|
|
@ -149,6 +166,13 @@
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
& > .bch {
|
||||||
|
background-color: #9b9bab;
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
& > .bch-enabled {
|
||||||
|
background-color: #ff9900 !important;
|
||||||
|
}
|
||||||
&.circle{
|
&.circle{
|
||||||
left:8px;
|
left:8px;
|
||||||
.bg {
|
.bg {
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,4 @@
|
||||||
@import "includes/pin";
|
@import "includes/pin";
|
||||||
@import "includes/logOptions";
|
@import "includes/logOptions";
|
||||||
@import "includes/checkBar";
|
@import "includes/checkBar";
|
||||||
|
@import "cashScan";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,22 @@
|
||||||
#wallet-backup-phrase {
|
#wallet-backup-phrase {
|
||||||
|
.comment {
|
||||||
|
color: #667;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
.item {
|
||||||
|
color: $v-dark-gray;
|
||||||
|
padding-top: 1.3rem;
|
||||||
|
padding-bottom: 1.3rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.heading {
|
||||||
|
font-size: 17px;
|
||||||
|
color: $v-dark-gray;
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
h3 {
|
h3 {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,27 @@
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background: #f8f8f9;
|
background: #f8f8f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__no-transaction {
|
||||||
|
color: $v-mid-gray;
|
||||||
|
font-size: 12.5px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__no-update-history {
|
||||||
|
color: $v-error-color;
|
||||||
|
font-size: 12.5px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__updating-history {
|
||||||
|
color: $v-mid-gray;
|
||||||
|
font-size: 12.5px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#walletDetails {
|
#walletDetails {
|
||||||
|
|
@ -177,10 +198,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
&.collapsible {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__balance {
|
&__balance {
|
||||||
-webkit-transform: scale3d(1, 1, 1) translateY(45px);
|
-webkit-transform: scale3d(1, 1, 1) translateY(45px);
|
||||||
transform: scale3d(1, 1, 1) translateY(45px);
|
transform: scale3d(1, 1, 1) translateY(45px);
|
||||||
|
|
@ -198,8 +215,21 @@
|
||||||
&__button-balance {
|
&__button-balance {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid rgba(255,255,255,0.25);
|
border: 1px solid rgba(255,255,255,0.25);
|
||||||
|
margin-top: 10px;
|
||||||
|
i.icon {
|
||||||
|
margin-right: 7px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__error {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 35px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.no-alternative {
|
||||||
|
padding-top: 45px;
|
||||||
}
|
}
|
||||||
.item.item-footer {
|
.item.item-footer {
|
||||||
font-weight: lighter;
|
font-weight: lighter;
|
||||||
|
|
@ -237,6 +267,17 @@
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width:95%;
|
width:95%;
|
||||||
|
|
||||||
|
.actions{
|
||||||
|
float: right;
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wallet-not-backed-up-warning {
|
.wallet-not-backed-up-warning {
|
||||||
|
|
|
||||||
18
www/img/bitcoin-cash-logo.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="49px" height="33px" viewBox="0 0 49 33" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group 4</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Home/Overview" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Group-4" transform="translate(0.000000, -6.000000)" fill-rule="nonzero">
|
||||||
|
<g id="element-icon-bitcoin" transform="translate(24.500000, 22.000000) rotate(-26.000000) translate(-24.500000, -22.000000) translate(8.000000, 6.000000)">
|
||||||
|
<g id="bitcoin" transform="translate(0.000000, -0.000000)">
|
||||||
|
<path d="M32.1867932,19.8608311 C30.0167764,28.4289206 21.2022608,33.6584288 12.4778868,31.5222983 C3.77643011,29.3856664 -1.5352984,20.7067588 0.634718392,12.1386692 C2.80422591,3.57108109 11.6192507,-1.65842708 20.3207074,0.477703406 C29.0450815,2.59177057 34.3563007,11.2932429 32.1867932,19.8608311" id="Shape" fill="#09C286"></path>
|
||||||
|
<path d="M20.8680125,13.6901518 C20.3834958,15.7120375 17.1993056,14.7348781 16.1611297,14.4850856 L17.0381466,10.8958545 C18.0529285,11.1456469 21.3754035,11.5776651 20.8680125,13.6901518 L20.8680125,13.6901518 Z M20.3601017,19.4829825 C19.8298366,21.7091043 15.9994508,20.5507429 14.7767218,20.255394 L15.7228811,16.3027353 C16.9684843,16.5980842 20.9137609,17.1432255 20.3601017,19.4829825 Z M24.4670572,13.6901518 C24.7670209,11.5090745 23.0826493,10.3732354 20.7754761,9.60082384 L21.4908141,6.64784689 L19.6681577,6.21634063 L18.9762137,9.1012389 C18.4916969,8.98760381 18.0071801,8.87396871 17.5226634,8.78336775 L18.2146074,5.89795761 L16.3690768,5.46645136 L15.6537387,8.41994018 C15.2612385,8.32882735 14.8692582,8.26074867 14.4767581,8.16963584 L11.9621576,7.57944995 L11.500515,9.48770061 C11.500515,9.48770061 12.8620487,9.78253763 12.8157805,9.80557177 C13.5539927,9.98728555 13.6922776,10.4643482 13.6694034,10.8277758 L12.8620487,14.1897367 C12.9077971,14.2127709 12.9774594,14.2127709 13.0466018,14.2578154 C12.9774594,14.2352931 12.9311911,14.2352931 12.8620487,14.2127709 L11.7542105,18.914807 C11.6621939,19.1420772 11.4313726,19.4599483 10.9239817,19.3468251 C10.9468558,19.3693474 9.58584199,19.0284421 9.58584199,19.0284421 L8.70882504,21.0958842 L11.0851407,21.6410256 C11.5239091,21.7546607 11.9621576,21.8452617 12.377532,21.9588968 L11.6621939,24.9349079 L13.4848503,25.3664141 L14.2001884,22.4134371 C14.7075794,22.5495945 15.1920961,22.6632296 15.6537387,22.7768647 L14.9384006,25.7073194 L16.7610571,26.1388257 L17.4763951,23.1633264 C20.590923,23.7084678 22.9209704,23.4581634 23.8671298,20.664378 C24.6287361,18.4377443 23.7979873,17.1657478 22.1370098,16.3252576 C23.3597388,16.052431 24.2362359,15.2805313 24.4670572,13.6901518 L24.4670572,13.6901518 Z" id="Shape" fill="#FFFFFF"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path d="M15.921528,5.99999821 L0,5.99999821 L0,37.9999982 L15.913948,37.9999982 C8.54220902,34.2663545 4.45416261,25.9154102 6.54600075,17.6560011 C7.87168946,12.4207324 11.4030305,8.29337503 15.921528,5.99999821 Z M32.6737493,5.99999821 L49,5.99999821 L49,37.9999982 L32.6621291,37.9999982 C37.1847176,35.7065678 40.716075,31.5790477 42.0420849,26.3434332 C44.1319349,18.09042 40.0515857,9.72697744 32.6737493,5.99999821 Z" id="Combined-Shape" fill="#09C286"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
12
www/img/icon-bch.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
|
<g id="Fondo" transform="matrix(0.0814451,-0.0296277,0.0296277,0.0814451,-44.594,-27.3805)">
|
||||||
|
<g transform="matrix(10.8433,3.94452,-3.94452,10.8433,375.543,472.796)">
|
||||||
|
<use xlink:href="#_Image1" x="7.552" y="5.557" width="23.603px" height="28.885px" transform="matrix(0.983467,0,0,0.996049,0,0)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<image id="_Image1" width="24px" height="29px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAdCAYAAACwuqxLAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACgUlEQVRIia2WzYuPURTHP88Y7zNEaWJKppnEUKRkM5shdlIipSSDSLazQFYkK/EXeMnChsWUkvK2mCJvWXgpZczGa6EmJn7Mx+K50zzu3OeZ35Tv6t5zzj3fc8859wUmAbVJbZjMmnqcZuo69ZT6XN31v5wuV+eE+XXH8FptrNfXP9tVZ6n7gD7gLrA6qO4BhnEHME1dpk6bbORz1duFaC8E0hXq24L8g/pJfa9eVddMhuSk/+KY+shqDKqb6nE+Q92hfpvAYQrP1QWxz0ydAiwAFgMHgJ6KGPqBH8AMoAvIIn17lmVv4qh71C8VkT1Rj6ob1Jawplk9H9kNq5tTaTlU4fyPurcknV3mxR7FV7UptmsErgNbw3YXAcsK+gZgeUm6BoH5hfltoJa0DHXAvMAxHqvtkf0ctS/scETtj23KiFrUOwmS3UG/VD2nDiXqdDOQ7hkNuIzkeILggflZeFdRr1HU1MtVBN2OPwcjCUfPzHt/MKH/re4vI5hufvxTeKGeUDeqbcF+ieNbVvWjOrOM5HBiwX21s8R+ZmIXI2pz2ePRD7yJZJ1Aa4l9E3nbFjEEtCYJsix7CtyKxM3k10MKs4G5kWwgy7JXVc/fvYSsW11YFKjzgHPAvKIYKO+ksLBNfZioxc6gX6+eVV8m8n9Jba4kCE5OJwgG1BuhS2L8VI9Y75OqbjHv6Sr8iebTiz4m+oJ8B4ZLdDXgM3AGGCjIe9X4nRgX+VTzCyzObS2KvCPY3yzIfxRTVNamNfLrNwN+AV+Ba0Av8KWwdlUYXwHeAxeBbYz9QCp3sTYUc3tB1mB+Y46iz/DbU1snTE09UHvN2/eguvK/OI0IZsedUoW/zudIHkrmZMIAAAAASUVORK5CYII="/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,93 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
<svg width="100%" height="100%" viewBox="0 0 51 51" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
<path id="coin" d="M25.5,51C39.6,51 51,39.6 51,25.5C51,11.4 39.5,0 25.5,0C11.5,0 0,11.4 0,25.5C0,39.6 11.4,51 25.5,51Z" style="fill:url(#_Linear1);fill-rule:nonzero;"/>
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
<g id="BitPay.-Bitcoin_Symbol" transform="matrix(0.939973,0.341249,-0.341249,0.939973,10.2185,-7.19166)">
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
<path d="M33.5,19.1C32.9,16.1 30.2,15.3 27,15.2L26.5,11L24,11.2L24.5,15.4C23.8,15.5 23.2,15.5 22.5,15.6L22,11.4L19.5,11.6L20,15.9C19.5,15.9 18.9,16 18.4,16.1L15,16.4L15.3,19.2C15.3,19.2 17.1,19 17.1,19.1C18.1,19 18.5,19.6 18.6,20.1L19.1,25C19.2,25 19.3,25 19.4,25C19.3,25 19.2,25 19.1,25L19.9,31.8C19.9,32.1 19.7,32.7 19.1,32.7L17.3,32.9L17.2,36L20.4,35.7C21,35.7 21.6,35.6 22.2,35.6L22.7,39.9L25.2,39.7L24.7,35.4C25.4,35.4 26.1,35.3 26.7,35.3L27.2,39.5L29.7,39.3L29.2,35C33.4,34.4 36.2,33 36.1,28.9C36,25.6 34.4,24.2 31.9,23.8C33.2,22.8 34,21.4 33.5,19.1ZM31,28.7C31.4,31.9 26,32 24.3,32.2L23.7,26.5C25.5,26.3 30.7,25.3 31,28.7ZM23.5,23.8L23,18.6C24.4,18.5 28.8,17.6 29.1,20.7C29.3,23.6 24.9,23.7 23.5,23.8Z" style="fill:white;fill-rule:nonzero;"/>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
</g>
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
<defs>
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-17.5917,-30.4347,30.4347,-17.5917,30.8557,34.8191)"><stop offset="0" style="stop-color:rgb(255,162,75);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(247,137,28);stop-opacity:1"/></linearGradient>
|
||||||
version="1.1"
|
</defs>
|
||||||
id="Layer_1"
|
</svg>
|
||||||
x="0px"
|
|
||||||
y="0px"
|
|
||||||
viewBox="0 0 51 51"
|
|
||||||
style="enable-background:new 0 0 51 51;"
|
|
||||||
xml:space="preserve"
|
|
||||||
sodipodi:docname="icon-bitcoin.svg"
|
|
||||||
inkscape:version="0.92.1 r15371"><metadata
|
|
||||||
id="metadata23"><rdf:RDF><cc:Work
|
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1"
|
|
||||||
objecttolerance="10"
|
|
||||||
gridtolerance="10"
|
|
||||||
guidetolerance="10"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1015"
|
|
||||||
id="namedview21"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="15.54902"
|
|
||||||
inkscape:cx="25.5"
|
|
||||||
inkscape:cy="25.5"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="Layer_1" /><style
|
|
||||||
type="text/css"
|
|
||||||
id="style2">
|
|
||||||
.st0{fill:url(#coin_1_);}
|
|
||||||
.st1{filter:url(#Adobe_OpacityMaskFilter);}
|
|
||||||
.st2{fill:#FFFFFF;}
|
|
||||||
.st3{mask:url(#mask-3);fill:#FFFFFF;}
|
|
||||||
</style><linearGradient
|
|
||||||
id="coin_1_"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
x1="-273.8224"
|
|
||||||
y1="413.966"
|
|
||||||
x2="-274.172"
|
|
||||||
y2="414.57"
|
|
||||||
gradientTransform="matrix(50.3194 0 0 -50.3886 13809.4346 20893.9863)"><stop
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#FFA24B"
|
|
||||||
id="stop4" /><stop
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#F7891C"
|
|
||||||
id="stop6" /></linearGradient><path
|
|
||||||
id="coin"
|
|
||||||
class="st0"
|
|
||||||
d="M25.5,51c14.1,0,25.5-11.4,25.5-25.5S39.5,0,25.5,0S0,11.4,0,25.5S11.4,51,25.5,51z"
|
|
||||||
style="fill:#fab915;fill-opacity:1" /><defs
|
|
||||||
id="defs13"><filter
|
|
||||||
id="Adobe_OpacityMaskFilter"
|
|
||||||
filterUnits="userSpaceOnUse"
|
|
||||||
x="15"
|
|
||||||
y="11"
|
|
||||||
width="21"
|
|
||||||
height="28.7"><feColorMatrix
|
|
||||||
type="matrix"
|
|
||||||
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"
|
|
||||||
id="feColorMatrix10" /></filter></defs><mask
|
|
||||||
maskUnits="userSpaceOnUse"
|
|
||||||
x="15"
|
|
||||||
y="11"
|
|
||||||
width="21"
|
|
||||||
height="28.7"
|
|
||||||
id="mask-3"><g
|
|
||||||
class="st1"
|
|
||||||
id="g16"><path
|
|
||||||
id="path-2"
|
|
||||||
class="st2"
|
|
||||||
d="M26.2,50.4c13.9,0,25.2-11.3,25.2-25.2S40.1,0,26.2,0S1,11.3,1,25.2S12.3,50.4,26.2,50.4z" /></g></mask><g
|
|
||||||
transform="matrix(2.7667404,0,0,2.7667404,-215.6998,-317.27681)"
|
|
||||||
aria-label=""
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:125%;font-family:icomoon;-inkscape-font-specification:icomoon;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="text4487"><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
d="m 89.710383,123.60521 v -0.0207 q 0.506429,-0.24804 0.785482,-0.7338 0.289388,-0.48576 0.289388,-1.11621 0,-0.69247 -0.330729,-1.1989 -0.33073,-0.50642 -0.847494,-0.74414 -0.320394,-0.14469 -0.682129,-0.19637 -0.3514,-0.0517 -0.816487,-0.0517 H 87.78802 v -0.7028 q 0,-0.10336 -0.07235,-0.1757 -0.07235,-0.0724 -0.1757,-0.0724 H 86.8165 q -0.103353,0 -0.1757,0.0724 -0.07235,0.0723 -0.07235,0.1757 v 0.7028 h -0.806152 v -0.7028 q 0,-0.10336 -0.07235,-0.1757 -0.07235,-0.0724 -0.1757,-0.0724 h -0.7028 q -0.113688,0 -0.186035,0.0724 -0.06201,0.0723 -0.06201,0.1757 v 0.7028 h -0.74414 q -0.06201,0 -0.113688,0.0517 -0.04134,0.0413 -0.04134,0.11369 v 0.68213 q 0,0.0724 0.04134,0.12402 0.05168,0.0413 0.113688,0.0413 h 0.74414 v 6.57324 h -0.692464 q -0.08268,0 -0.144694,0.062 -0.05168,0.0517 -0.05168,0.13436 v 0.59944 q 0,0.0827 0.05168,0.1447 0.06201,0.0517 0.144694,0.0517 h 0.692464 v 0.68213 q 0,0.11369 0.06201,0.1757 0.07235,0.0724 0.186035,0.0724 h 0.72347 q 0.103353,0 0.165365,-0.0724 0.07235,-0.062 0.07235,-0.1757 v -0.68213 h 0.816487 v 0.68213 q 0,0.11369 0.07235,0.1757 0.07235,0.0724 0.1757,0.0724 h 0.72347 q 0.103353,0 0.1757,-0.0724 0.07235,-0.062 0.07235,-0.1757 v -0.68213 h 0.475423 q 0.3514,0 0.661459,-0.0207 0.320394,-0.031 0.620117,-0.14469 0.661458,-0.21704 1.126546,-0.81649 0.465088,-0.60978 0.465088,-1.47794 -0.01034,-0.71314 -0.382406,-1.28158 -0.361735,-0.57877 -1.064534,-0.77515 z m -1.601969,-3.0489 q 0.279052,0 0.485758,0.0413 0.217041,0.0413 0.392741,0.13436 0.279053,0.15502 0.423747,0.45475 0.144694,0.29972 0.144694,0.67179 0,0.57878 -0.3514,0.94051 -0.341065,0.36174 -0.919841,0.36174 h -2.511474 v -2.60449 h 2.335775 z m 0.971516,6.44921 q -0.175699,0.0827 -0.382405,0.10336 -0.206706,0.0207 -0.382406,0.0207 h -2.54248 v -2.97657 h 2.645833 q 0.682129,0 1.085205,0.40308 0.403076,0.39274 0.403076,1.0542 0,0.49609 -0.227376,0.86816 -0.217041,0.37207 -0.599447,0.5271 z"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.26458332px"
|
|
||||||
id="path4527" /></g></svg>
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 1.8 KiB |
12
www/img/icon-btc.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
|
<g id="Fondo" transform="matrix(0.0814603,0.0295859,-0.0295859,0.0814603,0.874237,-57.7095)">
|
||||||
|
<g transform="matrix(10.8453,-3.93895,3.93895,10.8453,217.833,629.321)">
|
||||||
|
<use xlink:href="#_Image1" x="7.557" y="5.56" width="22.579px" height="28.881px" transform="matrix(0.981703,0,0,0.995881,0,0)"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<image id="_Image1" width="23px" height="29px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAdCAYAAABBsffGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACiElEQVRIia3VPYhfRRQF8PM2myya1SxBcLUQP+JXYQpBkJUlGgu1EoRgIyxkUUQUEU0hKQ1io6K9YBRBC0Fj4UdhghYWURHBQtFI0oioWUVFs5vkZ/Hers/J/N9/F7zdO+/MuWfu3JmbbDAwg/PXw50YIzRVgfcmOYqnMY9mowaDObyE23AptmAT3vFvvIFpTOKadSfCgZ7IKbyI+7HUw+/puIs40SV+AJOD5cBr+NXoOI0bO/4HPfyPQfFekgX8PZDgczzZuV6N/esqD+7uHG4k1ppgsFuSzCXZVGBHkrw/gr+c5AVsH+f6ShytONuDi3ArnsJXFc4hbBsSv6+y6CNcUvB24kiFuzBUll0V7HDTND/0gaZpvkzySJIzBXe+Kq5tsdsL+M8kH48wMpvk9wK7YZTzuSRXFNjmJM/jGVzbmZjCTOd8puC/W3M9hTfHtNvPOIm38CPOFP//wo6a+G7n3sxf8MWYhP3Ei2hq1/SWJGUbvZ1kf5Lr057FniRX9/4vJTmU5HiSl5Mcb5pG6fpiHK64WSh4O/Eqzvbc7sOWitkEE7i3IvwZrqrwp/Fhj7eCJ0rS5TiG1/F1RfzZqpt27aMF91tc0Cc8NHA4Z8uS9NZN4r2Cv4z5Vc5EkukkJ5OcGmHwYW1v7+5EV5/ThSR3FNzNaQ81SbL27uKuJI8luSnJhTn3xfwpybHOhCQ3Jyln7HKS2aZplqo2tTPzt95WywsyKk7j8RG7XxM/UCx6TnsLVwaEV3BwnPA2/22vg9iqnf7f9/AT2sP+Bp9gL4YHj/ZduROvaKf8rg7fV5RnB7ZjdlBwRJIGl2Fr993fzXfWM903kOg6PIhPsfi/CFcSnTe2tr34BwJIUvoJiuf+AAAAAElFTkSuQmCC"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
13
www/img/icon-text-testnet-white.svg
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="57px" height="16px" viewBox="0 0 57 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group 2 Copy</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Group-2-Copy">
|
||||||
|
<rect id="Rectangle" stroke="#FBFBFB" x="0.5" y="0.5" width="56" height="15" rx="2"></rect>
|
||||||
|
<path d="M9.75390625,4.55761719 L7.41601562,4.55761719 L7.41601562,13 L5.48144531,13 L5.48144531,4.55761719 L3.20507812,4.55761719 L3.20507812,3.046875 L9.75390625,3.046875 L9.75390625,4.55761719 Z M15.6669922,8.60449219 L12.625,8.60449219 L12.625,11.4960938 L16.2685547,11.4960938 L16.2685547,13 L10.6972656,13 L10.6972656,3.046875 L16.2548828,3.046875 L16.2548828,4.55761719 L12.625,4.55761719 L12.625,7.10058594 L15.6669922,7.10058594 L15.6669922,8.60449219 Z M21.8808594,10.4160156 C21.8808594,10.0195293 21.7794606,9.7062186 21.5766602,9.47607422 C21.3738597,9.24592984 21.0104193,9.02148547 20.4863281,8.80273438 C19.4654897,8.44270653 18.6975937,8.03483301 18.1826172,7.57910156 C17.6676407,7.12337012 17.4101562,6.48535566 17.4101562,5.66503906 C17.4101562,4.84927978 17.7040986,4.18506116 18.2919922,3.67236328 C18.8798858,3.15966541 19.6295527,2.90332031 20.5410156,2.90332031 C21.5071663,2.90332031 22.2841767,3.17675508 22.8720703,3.72363281 C23.4599639,4.27051055 23.7447918,5.00422717 23.7265625,5.92480469 L23.7128906,5.96582031 L21.8398438,5.96582031 C21.8398438,5.45084378 21.7247733,5.06005993 21.4946289,4.79345703 C21.2644845,4.52685414 20.9352235,4.39355469 20.5068359,4.39355469 C20.1376935,4.39355469 19.850587,4.51546102 19.6455078,4.75927734 C19.4404287,5.00309367 19.3378906,5.30728984 19.3378906,5.671875 C19.3378906,6.00911627 19.4541004,6.28710828 19.6865234,6.50585938 C19.9189465,6.72461047 20.3177055,6.96386589 20.8828125,7.22363281 C21.8444058,7.54264482 22.5724259,7.9459611 23.0668945,8.43359375 C23.5613631,8.9212264 23.8085938,9.57746983 23.8085938,10.4023438 C23.8085938,11.2545616 23.5192086,11.9244767 22.9404297,12.4121094 C22.3616508,12.899742 21.5937548,13.1435547 20.6367188,13.1435547 C19.6933547,13.1435547 18.8867221,12.8803737 18.2167969,12.3540039 C17.5468717,11.8276341 17.2233072,11.0266981 17.2460938,9.95117188 L17.2597656,9.91015625 L19.1396484,9.91015625 C19.1396484,10.5345083 19.266112,10.9833971 19.519043,11.2568359 C19.7719739,11.5302748 20.1445288,11.6669922 20.6367188,11.6669922 C21.0514344,11.6669922 21.3624664,11.553061 21.5698242,11.3251953 C21.777182,11.0973296 21.8808594,10.7942727 21.8808594,10.4160156 Z M31.0478516,4.55761719 L28.7099609,4.55761719 L28.7099609,13 L26.7753906,13 L26.7753906,4.55761719 L24.4990234,4.55761719 L24.4990234,3.046875 L31.0478516,3.046875 L31.0478516,4.55761719 Z M39.0458984,13 L37.1181641,13 L33.9599609,6.64941406 L33.9189453,6.65625 L33.9189453,13 L31.9912109,13 L31.9912109,3.046875 L33.9189453,3.046875 L37.0771484,9.40429688 L37.1181641,9.39746094 L37.1181641,3.046875 L39.0458984,3.046875 L39.0458984,13 Z M45.546875,8.60449219 L42.5048828,8.60449219 L42.5048828,11.4960938 L46.1484375,11.4960938 L46.1484375,13 L40.5771484,13 L40.5771484,3.046875 L46.1347656,3.046875 L46.1347656,4.55761719 L42.5048828,4.55761719 L42.5048828,7.10058594 L45.546875,7.10058594 L45.546875,8.60449219 Z M53.3603516,4.55761719 L51.0224609,4.55761719 L51.0224609,13 L49.0878906,13 L49.0878906,4.55761719 L46.8115234,4.55761719 L46.8115234,3.046875 L53.3603516,3.046875 L53.3603516,4.55761719 Z" id="TESTNET" fill="#FFFFFF"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
7
www/img/icon-wallet-testnet.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
|
<g id="flask" transform="matrix(1.27778,0,0,1.27778,7.86111,8)">
|
||||||
|
<path d="M13.358,7.26C13.563,7.465 13.78,7.69 14.009,7.937C14.237,8.183 14.571,8.552 15.011,9.044C15.45,9.536 15.854,10.034 16.224,10.538C16.593,11.042 16.959,11.58 17.322,12.151C17.686,12.722 17.973,13.295 18.184,13.869C18.395,14.443 18.5,14.962 18.5,15.425C18.5,16.134 18.248,16.74 17.744,17.244C17.24,17.748 16.634,18 15.925,18L3.075,18C2.366,18 1.76,17.748 1.256,17.244C0.752,16.74 0.5,16.134 0.5,15.425C0.5,14.962 0.605,14.443 0.816,13.869C1.027,13.295 1.314,12.722 1.678,12.151C2.041,11.58 2.407,11.042 2.776,10.538C3.146,10.034 3.55,9.536 3.989,9.044C4.429,8.552 4.763,8.183 4.991,7.937C5.22,7.69 5.437,7.465 5.642,7.26L5.642,1.925L4.675,1.925C4.587,1.925 4.512,1.894 4.451,1.833C4.389,1.771 4.358,1.696 4.358,1.608L4.358,0.316C4.358,0.229 4.389,0.154 4.451,0.092C4.512,0.031 4.587,0 4.675,0L14.325,0C14.413,0 14.488,0.031 14.549,0.092C14.611,0.154 14.642,0.229 14.642,0.316L14.642,1.608C14.642,1.696 14.611,1.771 14.549,1.833C14.488,1.894 14.413,1.925 14.325,1.925L13.358,1.925L13.358,7.26ZM5,1.283L14,1.283L14,0.642L5,0.642L5,1.283ZM12.717,1.925L6.283,1.925L6.283,4.14C6.705,4.011 7.105,3.926 7.483,3.885C7.861,3.844 8.168,3.838 8.406,3.867C8.643,3.896 8.863,3.948 9.065,4.021C9.267,4.094 9.408,4.156 9.487,4.206C9.566,4.255 9.632,4.304 9.685,4.351C9.737,4.392 9.806,4.437 9.891,4.487C9.976,4.537 10.124,4.601 10.335,4.68C10.546,4.759 10.763,4.811 10.985,4.834C11.208,4.857 11.478,4.835 11.794,4.768C12.11,4.701 12.418,4.576 12.717,4.395L12.717,1.925ZM15.925,17.358C16.458,17.358 16.914,17.169 17.292,16.792C17.669,16.414 17.858,15.958 17.858,15.425C17.858,14.897 17.688,14.273 17.349,13.553C17.009,12.832 16.615,12.161 16.167,11.54C15.718,10.919 15.228,10.295 14.694,9.668C14.161,9.041 13.747,8.574 13.451,8.266C13.155,7.958 12.942,7.746 12.813,7.629C12.749,7.564 12.717,7.485 12.717,7.392L12.717,5.124C12.242,5.353 11.753,5.467 11.249,5.467C10.903,5.467 10.566,5.413 10.238,5.304C9.91,5.196 9.679,5.101 9.544,5.019C9.409,4.937 9.321,4.875 9.28,4.834C9.233,4.799 9.192,4.77 9.157,4.746C9.122,4.723 9.012,4.679 8.828,4.614C8.643,4.55 8.45,4.51 8.248,4.496C8.045,4.481 7.767,4.496 7.413,4.54C7.058,4.583 6.682,4.673 6.283,4.808L6.283,7.392C6.283,7.485 6.251,7.564 6.187,7.629C6.058,7.746 5.845,7.958 5.549,8.266C5.253,8.574 4.839,9.041 4.306,9.668C3.772,10.295 3.282,10.919 2.833,11.54C2.385,12.161 1.991,12.832 1.651,13.553C1.312,14.273 1.142,14.897 1.142,15.425C1.142,15.958 1.331,16.414 1.708,16.792C2.086,17.169 2.542,17.358 3.075,17.358L15.925,17.358ZM9.825,6.425C10.358,6.425 10.812,6.614 11.187,6.992C11.563,7.37 11.75,7.825 11.75,8.358C11.75,8.892 11.563,9.346 11.187,9.721C10.812,10.096 10.358,10.283 9.825,10.283C9.292,10.283 8.836,10.096 8.458,9.721C8.081,9.346 7.892,8.892 7.892,8.358C7.892,7.825 8.081,7.37 8.458,6.992C8.836,6.614 9.292,6.425 9.825,6.425ZM9.825,9.642C10.177,9.642 10.479,9.517 10.73,9.268C10.982,9.019 11.108,8.716 11.108,8.358C11.108,8.001 10.982,7.696 10.73,7.444C10.479,7.192 10.177,7.066 9.825,7.066C9.468,7.066 9.163,7.192 8.911,7.444C8.659,7.696 8.533,8.001 8.533,8.358C8.533,8.716 8.659,9.019 8.911,9.268C9.163,9.517 9.468,9.642 9.825,9.642ZM7.892,10.925C8.249,10.925 8.552,11.051 8.801,11.303C9.05,11.555 9.175,11.859 9.175,12.217C9.175,12.568 9.05,12.87 8.801,13.122C8.552,13.374 8.249,13.5 7.892,13.5C7.534,13.5 7.231,13.374 6.982,13.122C6.733,12.87 6.608,12.568 6.608,12.217C6.608,11.859 6.733,11.555 6.982,11.303C7.231,11.051 7.534,10.925 7.892,10.925ZM7.892,12.858C8.073,12.858 8.226,12.795 8.349,12.669C8.472,12.543 8.533,12.393 8.533,12.217C8.533,12.035 8.472,11.881 8.349,11.755C8.226,11.629 8.073,11.566 7.892,11.566C7.716,11.566 7.565,11.629 7.439,11.755C7.313,11.881 7.25,12.035 7.25,12.217C7.25,12.393 7.313,12.543 7.439,12.669C7.565,12.795 7.716,12.858 7.892,12.858ZM10.783,13.5C11.053,13.5 11.281,13.594 11.469,13.781C11.656,13.969 11.75,14.197 11.75,14.467C11.75,14.73 11.656,14.956 11.469,15.144C11.281,15.331 11.053,15.425 10.783,15.425C10.52,15.425 10.294,15.331 10.106,15.144C9.919,14.956 9.825,14.73 9.825,14.467C9.825,14.197 9.919,13.969 10.106,13.781C10.294,13.594 10.52,13.5 10.783,13.5ZM10.783,14.783C10.871,14.783 10.947,14.752 11.012,14.691C11.076,14.629 11.108,14.555 11.108,14.467C11.108,14.373 11.076,14.295 11.012,14.234C10.947,14.172 10.871,14.142 10.783,14.142C10.695,14.142 10.621,14.172 10.559,14.234C10.498,14.295 10.467,14.373 10.467,14.467C10.467,14.555 10.498,14.629 10.559,14.691C10.621,14.752 10.695,14.783 10.783,14.783Z" style="fill:white;"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
24
www/img/mercado-libre/24px.svg
Normal file
|
After Width: | Height: | Size: 31 KiB |
2311
www/img/mercado-libre/giftcard-pt.svg
Normal file
|
After Width: | Height: | Size: 63 KiB |
1
www/img/mercado-libre/icon-ml.svg
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
www/img/mercado-libre/meli-card-24px.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |