diff --git a/Gruntfile.js b/Gruntfile.js index 342cc85e7..eb4bb2eb0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -163,7 +163,7 @@ module.exports = function(grunt) { }, bitanalytics: { src: [ - 'bitanalytics/bitanalytics-0.1.0.js' + 'bitanalytics/bitanalytics.js' ], dest: 'www/lib/bitanalytics.js' }, diff --git a/app-template/bitcoincom/appConfig.json b/app-template/bitcoincom/appConfig.json index fefcb9a4f..084a586ce 100644 --- a/app-template/bitcoincom/appConfig.json +++ b/app-template/bitcoincom/appConfig.json @@ -24,9 +24,9 @@ "windowsAppId": "804636ee-b017-4cad-8719-e58ac97ffa5c", "pushSenderId": "1036948132229", "description": "A Secure Bitcoin Wallet", - "version": "4.13.0", - "fullVersion": "4.13-rc1", - "androidVersion": "413000", + "version": "4.13.2", + "fullVersion": "4.13-rc3", + "androidVersion": "413200", "_extraCSS": "", "_enabledExtensions": { "coinbase": false, diff --git a/app-template/bitcoincom/css/bitcoin.com.css b/app-template/bitcoincom/css/bitcoin.com.css index e9b316761..cb20ff48d 100644 --- a/app-template/bitcoincom/css/bitcoin.com.css +++ b/app-template/bitcoincom/css/bitcoin.com.css @@ -268,5 +268,33 @@ div.onboarding-topic { display: block; float: left; max-height: 100%; - max-width: 100%; + max-width: 100%; +} + +.bitpay-banner { + background: #1A3A8B; + padding: 10px; + box-shadow: 0px 5px 10px 0px #cccccc; + height: 5em; +} + +.bitpay-logo { + display: block; + max-height: 100%; + width: 100%; + height: 4em; +} + +.egifter-banner { + background: #1A3A8B; + padding: 10px; + box-shadow: 0px 5px 10px 0px #cccccc; + height: 5em; + text-align: center; +} + +.egifter-logo { + max-height: 100%; + max-width: 100%; + height: 4em; } diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 1c7f5a30a..2f8e3db04 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -72,7 +72,7 @@ - + diff --git a/bitanalytics/bitanalytics-0.1.0.js b/bitanalytics/bitanalytics.js similarity index 97% rename from bitanalytics/bitanalytics-0.1.0.js rename to bitanalytics/bitanalytics.js index db149e481..d04b2a0bd 100644 --- a/bitanalytics/bitanalytics-0.1.0.js +++ b/bitanalytics/bitanalytics.js @@ -6256,7 +6256,6 @@ var ClickAction = /** @class */ (function (_super) { // Add event listener to all the elements found for (var i = 0; i < elements.length; i++) { var element = elements[i]; - console.log('init ' + this.name); element.addEventListener('click', this.listener); } }; @@ -6276,7 +6275,7 @@ var ClickAction = /** @class */ (function (_super) { }(action_1.default)); exports.default = ClickAction; -},{"../action":4,"../log-event":15,"../log-event-handlers":14}],6:[function(require,module,exports){ +},{"../action":4,"../log-event":16,"../log-event-handlers":15}],6:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; @@ -6315,7 +6314,7 @@ var BitAnalytics = /** @class */ (function () { exports.default = BitAnalytics; BitAnalytics.main(); -},{"./action-factory":2,"./action-handlers":3,"./channels/adjust-channel":9,"./channels/mixpanel-channel":12,"./log-event":15,"./log-event-handlers":14}],7:[function(require,module,exports){ +},{"./action-factory":2,"./action-handlers":3,"./channels/adjust-channel":9,"./channels/mixpanel-channel":12,"./log-event":16,"./log-event-handlers":15}],7:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; @@ -6413,7 +6412,6 @@ var AdjustChannel = /** @class */ (function (_super) { _this.eventTypes = config.eventTypes; var os = _this.adjustedOs(config.os); _this.advertisingId = _this.getAdvertisingId(os); - console.log('Advertising ID for adjust: ' + _this.advertisingId); // TODO: Different initialisation for Cordova. var sessionParams = { app_version: config.appVersion, @@ -6560,11 +6558,10 @@ var FirebaseChannel = /** @class */ (function (_super) { var keys = Object.keys(params); var keysLength = keys.length; var sanitized = {}; - for (var i = 0; i < keysLength; i++) { - var key = keys[i]; + keys.map(function (key) { var cleanKey = key.replace('-', '_').replace(/[\W]+/g, ''); sanitized[cleanKey] = params[key]; - } + }); return sanitized; }; return FirebaseChannel; @@ -6588,13 +6585,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); var channel_1 = __importDefault(require("../channel")); +var ga_1 = __importDefault(require("../external-libs/ga")); var GoogleAnalyticsChannel = /** @class */ (function (_super) { __extends(GoogleAnalyticsChannel, _super); function GoogleAnalyticsChannel(name, config) { var _this = _super.call(this, name) || this; - _this.dataLayer = null; _this.gaInstance = null; - _this.trackingId = ''; _this.eventLabels = ['id']; if (!config.trackingId) { throw new Error('[BitAnalytics] Google Analytics config is missing tracking ID.'); @@ -6602,8 +6598,12 @@ var GoogleAnalyticsChannel = /** @class */ (function (_super) { if (config.eventLabels) { _this.eventLabels = config.eventLabels; } - _this.trackingId = config.trackingId; - _this.setUpGa(); + _this.gaInstance = new ga_1.default({ + trackID: config.trackingId, + appVersion: config.appVersion, + appName: config.appName || 'App' + }); + _this.isReady = true; return _this; } /** @@ -6612,49 +6612,26 @@ var GoogleAnalyticsChannel = /** @class */ (function (_super) { * */ GoogleAnalyticsChannel.prototype.postEvent = function (name, params) { - // Default Google Analytics Events - // https://developers.google.com/analytics/devguides/collection/gtagjs/events - // Useful to convert to these, or start with these? if (this.isReady) { - params.event_category = name; + var category = name; + var action = name; + var label = name; + var value = params['value'] || ''; for (var _i = 0, _a = this.eventLabels; _i < _a.length; _i++) { var eventLabel = _a[_i]; if (params[eventLabel]) { - params.event_label = params[eventLabel]; + label = params[eventLabel]; break; } } - this.gtag('event', name, params); + this.gaInstance.event(category, action, label, value); } }; - /** - * - * Private methods - * - */ - /** - * Mimics function in the tracking snippet - */ - GoogleAnalyticsChannel.prototype.gtag = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - console.log(arguments); - window.dataLayer.push(arguments); - }; - GoogleAnalyticsChannel.prototype.setUpGa = function () { - // From what GA recommends to insert into page - window.dataLayer = window.dataLayer || []; - this.gtag('js', new Date()); - this.gtag('config', this.trackingId); - this.isReady = true; - }; return GoogleAnalyticsChannel; }(channel_1.default)); exports.default = GoogleAnalyticsChannel; -},{"../channel":8}],12:[function(require,module,exports){ +},{"../channel":8,"../external-libs/ga":14}],12:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || @@ -6677,7 +6654,7 @@ var MixpanelChannel = /** @class */ (function (_super) { function MixpanelChannel(name, config) { var _this = _super.call(this, name) || this; if (!config.token) { - throw new DOMException('[BitAnalytics] Config incorrect.'); + throw new Error('[BitAnalytics] Config incorrect.'); } _this.mixpanelInstance = mixpanel; mixpanel.init(config.token, config.config); @@ -6746,6 +6723,207 @@ exports.default = MixpanelChannel; },{}],14:[function(require,module,exports){ "use strict"; +/* + * name: nwjs-analytics -Node-Webkit Google Analytics integration + * version: 1.0.2 + * github: https://github.com/Daaru00/nwjs-analytics + */ +function GA(opt) { + this.apiVersion = opt.apiVersion || '1'; + this.trackID = opt.trackID || 'UA-XXXXXXXX-X'; + this.clientID = opt.clientID || null; + this.userID = opt.userID || null; + this.appName = opt.appName || 'App'; + this.appVersion = opt.appVersion || '1.0.0'; + this.debug = opt.debug || false; + this.performanceTracking = opt.performanceTracking || true; + this.errorTracking = opt.errorTracking || true; + this.userLanguage = opt.userLanguage || "en"; + this.currency = opt.currency || "EUR"; + this.lastScreenName = opt.lastScreenName || ''; +} +GA.prototype.sendRequest = function (data, callback) { + var ga = this; + if (!this.clientID || this.clientID == null) + this.clientID = this.generateClientID(); + if (!this.userID || this.userID == null) + this.userID = this.generateClientID(); + var postData = "v=" + this.apiVersion + + "&an=" + this.appName + + "&av=" + this.appVersion + + "&tid=" + this.trackID + + "&cid=" + this.clientID + + "&sr=" + this.getScreenResolution() + + "&vp=" + this.getViewportSize(); + Object.keys(data).forEach(function (key) { + var val = data[key]; + if (typeof val != "undefined") + postData += "&" + key + "=" + val; + }); + var http = new XMLHttpRequest(); + var url = "https://www.google-analytics.com"; + if (!this.debug) + url += "/collect"; + else + url += "/debug/collect"; + http.open("GET", url + "?" + postData, true); + http.onreadystatechange = function () { + if (ga.debug) + console.log(http.response); + if (http.readyState == 4 && http.status == 200) { + if (callback) + callback(true); + } + else { + if (callback) + callback(false); + } + }; + http.send(); +}; +GA.prototype.generateClientID = function () { + var id = ""; + var possibilities = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (var i = 0; i < 5; i++) + id += possibilities.charAt(Math.floor(Math.random() * possibilities.length)); + return id; +}; +GA.prototype.getScreenResolution = function () { + return screen.width + "x" + screen.height; +}; +GA.prototype.getColorDept = function () { + return screen.colorDepth + "-bits"; +}; +GA.prototype.getUserAgent = function () { + return navigator.userAgent; +}; +GA.prototype.getViewportSize = function () { + return window.screen.availWidth + "x" + window.screen.availHeight; +}; +/* + * Measurement Protocol + * [https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide] + */ +GA.prototype.screenView = function (screename) { + var data = { + 't': 'screenview', + 'cd': screename + }; + this.sendRequest(data); + this.lastScreenName = screename; +}; +GA.prototype.event = function (category, action, label, value) { + var data = { + 't': 'event', + 'ec': category, + 'ea': action, + }; + if (label) { + data['el'] = label; + } + if (value) { + data['ev'] = value; + } + if (this.lastScreenName) { + data['cd'] = this.lastScreenName; + } + this.sendRequest(data); +}; +GA.prototype.exception = function (msg, fatal) { + var data = { + 't': 'exception', + 'exd': msg, + 'exf': fatal || 0 + }; + this.sendRequest(data); +}; +GA.prototype.timing = function (category, variable, time, label) { + var data = { + 't': 'timing', + 'utc': category, + 'utv': variable, + 'utt': time, + 'utl': label, + }; + this.sendRequest(data); +}, + GA.prototype.ecommerce = { + transactionID: false, + generateTransactionID: function () { + var id = ""; + var possibilities = "0123456789"; + for (var i = 0; i < 5; i++) + id += possibilities.charAt(Math.floor(Math.random() * possibilities.length)); + return id; + }, + transaction: function (total, items) { + var t_id = ""; + if (!this.ecommerce.transactionID) + t_id = this.ecommerce.generateTransactionID(); + else + t_id = this.ecommerce.transactionID; + var data = { + 't': 'transaction', + 'ti': t_id, + 'tr': total, + 'cu': this.currency, + }; + this.sendRequest(data); + items.forEach(function (item) { + var data = { + 't': 'item', + 'ti': t_id, + 'in': item.name, + 'ip': item.price, + 'iq': item.qty, + 'ic': item.id, + 'cu': this.currency + }; + this.sendRequest(data); + }); + } + }, + GA.prototype.custom = function (data) { + this.sendRequest(data); + }; +module.exports = GA; +/* + * Performance Tracking + */ +/*window.addEventListener("load", function() { + + if(ga.performanceTracking) { + setTimeout(function() { + var timing = window.performance.timing; + var userTime = timing.loadEventEnd - timing.navigationStart; + ga.timing("performance", "pageload", userTime); + }, 0); + } + +}, false);*/ +/* + * Error Reporting + */ +/*window.onerror = function (msg, url, lineNo, columnNo, error) { + var message = [ + 'Message: ' + msg, + 'Line: ' + lineNo, + 'Column: ' + columnNo, + 'Error object: ' + JSON.stringify(error) + ].join(' - '); + + if(ga.errorTracking) + { + setTimeout(function() { + ga.exception(message.toString()); + }, 0); + } + + return false; +};*/ + +},{}],15:[function(require,module,exports){ +"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -6857,7 +7035,7 @@ var LogEventHandlers = /** @class */ (function () { _this.channels.push(channel); } catch (error) { - console.log('[BitAnalytics] ' + error.name + ': ' + error.message); + console.log(error.message); } }); }; @@ -6865,7 +7043,7 @@ var LogEventHandlers = /** @class */ (function () { }()); exports.default = LogEventHandlers; -},{"./channel-factory":7}],15:[function(require,module,exports){ +},{"./channel-factory":7}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var LogEvent = /** @class */ (function () { diff --git a/i18n/po/ca/template-ca.po b/i18n/po/ca/template-ca.po index 515fcd814..088cd870b 100644 --- a/i18n/po/ca/template-ca.po +++ b/i18n/po/ca/template-ca.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Catalan\n" "Language: ca\n" -"PO-Revision-Date: 2018-07-04 09:26\n" +"PO-Revision-Date: 2018-07-27 08:43\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Compra & ven bitcoins" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Compra bitcoins" @@ -619,10 +620,14 @@ msgstr "S'està connectant a Glidera..." msgid "Connection reset by peer" msgstr "Connexió reiniciada per un parell" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contactes" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Adreces utilitzades freqüentment desades" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Continua" @@ -823,7 +828,7 @@ msgstr "Crea una cartera compartida" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Crea una cartera bitcoin" @@ -2533,6 +2538,14 @@ msgstr "Cerca transaccions" msgid "Search or enter bitcoin address" msgstr "Cerca o introdueix l'adreça bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Porta-retalls" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Teniu el porta-retalls buit" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Cerca transaccions" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Envia per correu electrònic" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Envia des de" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Enviat a" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Enganxa des del porta-retalls" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Enganxa l'adreça" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Transferència de cartera a cartera" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Escaneja el codi QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envia bitcoins més ràpid!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envia bitcoins més ràpid!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Deseu adreces utilitzades freqüentment i envieu-los bitcoins d'un sol toc" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Afegiu el primer contacte" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "La vostra cartera bitcoin és buida" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Per començar, compreu Bitcoin Cash (BCH) o Bitcoin Core (BTC), o compartiu la vostra adreça." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Podeu rebre bitcoins des de qualsevol cartera o servei." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Per començar, heu de crear una cartera bitcoin i obtenir uns quants bitcoins." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Compra Bitcoins ara" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Mostra la meva adreça" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Envia import màxim" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transaccions descarregades" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-de-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Comunitat" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Reddit de Bitcoin Cash" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Twitter de Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Explora Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Jocs de Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Notícies" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Xarxa minera" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Eines" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Gràfiques de preus del bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash gratis" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Les vostres carteres bitcoin ja estan a punt!" + diff --git a/i18n/po/cs/template-cs.po b/i18n/po/cs/template-cs.po index 14fe7faf2..5a3702736 100644 --- a/i18n/po/cs/template-cs.po +++ b/i18n/po/cs/template-cs.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Czech\n" "Language: cs\n" -"PO-Revision-Date: 2018-07-04 09:26\n" +"PO-Revision-Date: 2018-07-27 08:43\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Koupit & prodat Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Koupit Bitcoin" @@ -619,10 +620,14 @@ msgstr "Připojování ke Glidera..." msgid "Connection reset by peer" msgstr "Připojení přerušeno druhou stranou" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Kontakty" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Uložené, často používané adresy" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Pokračovat" @@ -823,7 +828,7 @@ msgstr "Vytvořit sdílenou peněženku" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Vytvořit Bitcoin peněženku" @@ -2533,6 +2538,14 @@ msgstr "Vyhledávání transakcí" msgid "Search or enter bitcoin address" msgstr "Vyhledat nebo zadat Bitcoin adresu" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Schránka" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Vaše schránka je prázdná" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Vyhledávání transakcí" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Poslat e-mailem" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Odeslat z" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Odeslat" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Vložit ze schránky" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Vložit adresu" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Převod mezi peněženkami" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Skenovat QR kód" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Odesílejte Bitcoin rychleji!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Odesílejte Bitcoin rychleji!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Uložte si často používané adresy a posílejte jim Bitcoin jedním kliknutím" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Přidat váš první kontakt" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Vaše Bitcoin peněženka je prázdná" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Chcete-li začít, nakupte Bitcoin Cash (BCH) nebo Bitcoin Core (BTC), nebo sdílejte svou adresu." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Můžete přijímat Bitcoin z jakékoliv peněženky nebo služby." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Chcete-li začít, budete muset vytvořit Bitcoin peněženku a Bitcoin získat." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Koupit Bitcoin" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Zobrazit mou adresu" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Odeslat maximální částku" @@ -3030,7 +3104,7 @@ msgstr "Chcete-li začít, nakupte Bitcoin nebo sdílejte svou adresu. Můžete #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Chcete-li začít, budete muset vytvořit Bitcoin peněženku a Bitcoin získat." +msgstr "Chcete-li začít, budete potřebovat vytvořit Bitcoin peněženku a získat Bitcoin." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transakcí staženo" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-z-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Komunita" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Prohlédnout Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash hry" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Novinky" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Těžební pool" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Nástroje" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Grafy cen Bitcoinu" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash zdarma" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Vaše Bitcoin peněženka je připravena!" + diff --git a/i18n/po/de/template-de.po b/i18n/po/de/template-de.po index 7b3a50d69..18d8ca0f4 100644 --- a/i18n/po/de/template-de.po +++ b/i18n/po/de/template-de.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: German\n" "Language: de\n" -"PO-Revision-Date: 2018-07-04 03:57\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -79,7 +79,7 @@ msgstr "Kontonummer" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "" +msgstr "Sofortige Transaktionen mit niedrigen Gebühren" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -226,7 +226,7 @@ msgstr "Betrag zu hoch" #: www/views/includes/walletHistory.html:31 msgid "Amount too low to spend" -msgstr "Betrag ist zu niedrig zum ausgeben" +msgstr "Betrag ist zu niedrig zum Ausgeben" #: src/js/controllers/tab-home.js:147 msgid "An update to this app is available. For your security, please update to the latest version." @@ -384,7 +384,7 @@ msgstr "Bitcoin-Netzwerk Gebührenübersicht" #: www/views/tab-home.html:83 #: www/views/tab-settings.html:107 msgid "Bitcoin Core Wallets" -msgstr "Bitcoin Core Brieftaschen" +msgstr "Bitcoin Core Wallets" #: src/js/services/incomingData.js:151 msgid "Bitcoin cash Payment" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Kaufe & Verkaufe Bitcoins" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Kaufe Bitcoins" @@ -547,7 +548,7 @@ msgstr "Schließen" #: www/views/includes/cash.html:2 #: www/views/preferencesInformation.html:17 msgid "Coin" -msgstr "" +msgstr "Münze" #: www/views/preferences.html:22 msgid "Color" @@ -563,7 +564,7 @@ msgstr "Beenden Sie den Backupvorgang um diese Option zu nutzen" #: www/views/bitpayCard.html:93 msgid "Completed" -msgstr "" +msgstr "Abgeschlossen" #: src/js/controllers/buyAmazon.js:311 #: src/js/controllers/buyMercadoLibre.js:305 @@ -584,7 +585,7 @@ msgstr "Bestätigen & Beenden" #: www/views/buyAmazon.html:90 msgid "Confirm purchase" -msgstr "" +msgstr "Kauf bestätigen" #: www/views/modals/pin.html:10 msgid "Confirm your PIN" @@ -619,10 +620,14 @@ msgstr "Verbinde mit Glidera..." msgid "Connection reset by peer" msgstr "Verbindung von Peer zurückgesetzt" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Kontakte" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Gespeicherte häufig verwendete Adressen" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Weiter" @@ -633,7 +638,7 @@ msgstr "Übersetzungen beitragen" #: src/js/controllers/confirm.js:130 msgid "Copay only supports Bitcoin Cash using new version numbers addresses" -msgstr "" +msgstr "Copay unterstützt nur Bitcoin Cash bei Adressen welche das neue Adressformat benutzen" #: src/js/services/bwcError.js:62 msgid "Copayer already in this wallet" @@ -675,7 +680,7 @@ msgstr "In die Zwischenablage kopieren" #: src/js/controllers/buyMercadoLibre.js:102 msgid "Could not access Gift Card Service" -msgstr "" +msgstr "Der Geschenkkartendienst konnte nicht erreicht werden" #: www/views/tab-import-phrase.html:2 msgid "Could not access the wallet at the server. Please check:" @@ -683,7 +688,7 @@ msgstr "Kein Zugriff auf Wallet des Servers. Überprüfen Sie bitte:" #: src/js/controllers/buyAmazon.js:102 msgid "Could not access to Amazon.com" -msgstr "" +msgstr "Auf Amazon.com konnte nicht zugegriffen werden" #: src/js/services/profileService.js:511 msgid "Could not access wallet" @@ -707,13 +712,13 @@ msgstr "Adresse konnte nicht erstellt werden" #: src/js/controllers/topup.js:92 msgid "Could not create the invoice" -msgstr "" +msgstr "Die Rechnung konnte nicht erstellt werden" #: src/js/controllers/buyAmazon.js:164 #: src/js/controllers/buyMercadoLibre.js:164 #: src/js/controllers/topup.js:142 msgid "Could not create transaction" -msgstr "" +msgstr "Transaktion konnte nicht erstellt werden" #: src/js/services/profileService.js:350 msgid "Could not create using the specified extended private key" @@ -737,7 +742,7 @@ msgstr "Zahlungsvorschlag konnte nicht gelöscht werden" #: src/js/controllers/cashScan.js:117 msgid "Could not duplicate" -msgstr "" +msgstr "Konnte nicht duplizieren" #: src/js/services/feeService.js:73 msgid "Could not get dynamic fee" @@ -749,13 +754,13 @@ msgstr "Dynamische Gebühr für den Level konnte nicht abgerufen werden: {{feeLe #: src/js/controllers/modals/feeLevels.js:112 msgid "Could not get fee levels" -msgstr "" +msgstr "Gebühren konnten nicht abgerufen werden" #: src/js/controllers/buyAmazon.js:122 #: src/js/controllers/buyMercadoLibre.js:122 #: src/js/controllers/topup.js:100 msgid "Could not get the invoice" -msgstr "" +msgstr "Konnte die Rechnung nicht erhalten" #: src/js/controllers/bitpayCard.js:66 msgid "Could not get transactions" @@ -800,7 +805,7 @@ msgstr "Zahlung kann nicht gesendet werden" #: src/js/controllers/buyMercadoLibre.js:318 #: src/js/controllers/topup.js:299 msgid "Could not send transaction" -msgstr "" +msgstr "Transaktion konnte nicht gesendet werden" #: www/views/walletDetails.html:210 msgid "Could not update transaction history" @@ -823,7 +828,7 @@ msgstr "Erstelle eine gemeinsame Wallet" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Erstelle Bitcoin-Wallet" @@ -859,7 +864,7 @@ msgstr "Aktuelle Gebühr für dieses Verfahren" #: src/js/services/feeService.js:15 msgid "Custom" -msgstr "" +msgstr "Eigene" #: www/views/customAmount.html:9 msgid "Custom Amount" @@ -867,7 +872,7 @@ msgstr "Benutzerdefinierter Betrag" #: src/js/controllers/preferencesFee.js:85 msgid "Custom Fee" -msgstr "" +msgstr "Eigene Gebühr" #: www/views/modals/mercadolibre-card-details.html:56 #: www/views/modals/txp-details.html:87 @@ -944,11 +949,11 @@ msgstr "Herunterladen" #: www/views/cashScan.html:37 msgid "Duplicate for BCH" -msgstr "Duplikat für BCH" +msgstr "Für BCH duplizieren" #: src/js/services/onGoingProcess.js:49 msgid "Duplicating wallet..." -msgstr "" +msgstr "Wallet wird dupliziert..." #: www/views/addresses.html:19 msgid "Each bitcoin wallet can generate billions of addresses from your 12-word backup. A new address is automatically generated and shown each time you receive a payment." @@ -960,7 +965,7 @@ msgstr "Wirtschaftlich" #: www/views/onboarding/collectEmail.html:27 msgid "Edit" -msgstr "" +msgstr "Bearbeiten" #: www/views/addressbook.add.html:29 #: www/views/addressbook.view.html:22 @@ -977,7 +982,7 @@ msgstr "Obergrenze für leere Adressen erreicht. Neue Adressen können nicht gen #: www/views/preferencesCash.html:17 msgid "Enable Bitcoin Cash wallet creation and operation within the App." -msgstr "" +msgstr "Bitcoin Cash-Wallet-Erstellung und Betrieb innerhalb der App aktivieren." #: www/views/tab-scan.html:19 msgid "Enable camera access in your device settings to get started." @@ -993,7 +998,7 @@ msgstr "Pushbenachrichtigungen aktivieren" #: www/views/preferencesNotifications.html:33 msgid "Enable sound" -msgstr "" +msgstr "Sound einschalten" #: www/views/tab-scan.html:18 msgid "Enable the camera to get started." @@ -1014,11 +1019,11 @@ msgstr "Eingabe des Zwei-Faktor-Authentifizierungs-Codes für das BitPay Konto" #: www/views/amount.html:4 msgid "Enter amount" -msgstr "" +msgstr "Betrag eingeben" #: www/views/modals/chooseFeeLevel.html:41 msgid "Enter custom fee" -msgstr "" +msgstr "Eigene Gebühr eingeben" #: src/js/services/walletService.js:1029 msgid "Enter new spending password" @@ -1032,7 +1037,7 @@ msgstr "Wiederherstellungsphrase eingeben (BIP39)" #: www/views/onboarding/collectEmail.html:13 msgid "Enter your email" -msgstr "" +msgstr "Ihre E-Mail Adresse eingeben" #: www/views/backup.html:69 msgid "Enter your password" @@ -1123,12 +1128,12 @@ msgstr "Fehler beim bestätigen" #: src/js/controllers/buyAmazon.js:179 msgid "Error creating gift card" -msgstr "" +msgstr "Fehler beim Erstellen der Geschenkkarte" #: src/js/controllers/buyAmazon.js:94 #: src/js/controllers/buyMercadoLibre.js:94 msgid "Error creating the invoice" -msgstr "" +msgstr "Fehler beim Erstellen der Rechnung" #: src/js/services/profileService.js:412 msgid "Error creating wallet" @@ -1136,17 +1141,17 @@ msgstr "Fehler beim Erstellen des Wallets" #: src/js/controllers/confirm.js:296 msgid "Error getting SendMax information" -msgstr "" +msgstr "Fehler beim Abrufen der SendMax Informationen" #: src/js/controllers/buyAmazon.js:136 #: src/js/controllers/buyMercadoLibre.js:136 #: src/js/controllers/topup.js:114 msgid "Error in Payment Protocol" -msgstr "" +msgstr "Fehler im Zahlungsprotokoll" #: src/js/controllers/bitpayCardIntro.js:14 msgid "Error pairing BitPay Account" -msgstr "" +msgstr "Fehler beim Paaren mit BitPay Konto" #: src/js/controllers/paperWallet.js:41 msgid "Error scanning funds:" @@ -1201,7 +1206,7 @@ msgstr "Erweiterte öffentliche Schlüssel" #: src/js/services/onGoingProcess.js:20 msgid "Extracting Wallet information..." -msgstr "" +msgstr "Wallet-Informationen extrahieren..." #: src/js/controllers/export.js:115 #: src/js/controllers/export.js:126 @@ -1222,16 +1227,16 @@ msgstr "Gebühr" #: www/views/modals/chooseFeeLevel.html:75 msgid "Fee level" -msgstr "" +msgstr "Gebührenstufe" #: src/js/controllers/modals/feeLevels.js:100 msgid "Fee level is not defined" -msgstr "" +msgstr "Gebührenstufe ist nicht definiert" #: www/views/confirm.html:79 #: www/views/modals/txp-details.html:99 msgid "Fee:" -msgstr "" +msgstr "Gebühr:" #: src/js/controllers/feedback/send.js:23 msgid "Feedback could not be submitted. Please try again later." @@ -1243,7 +1248,7 @@ msgstr "BitPay Konto abrufen..." #: src/js/services/onGoingProcess.js:21 msgid "Fetching payment information" -msgstr "" +msgstr "Zahlungsinformationen abrufen" #: www/views/export.html:14 #: www/views/import.html:16 @@ -1252,7 +1257,7 @@ msgstr "Datei/Text" #: www/views/preferencesLogs.html:17 msgid "Filter setting" -msgstr "" +msgstr "Filtereinstellungen" #: src/js/services/fingerprintService.js:43 #: src/js/services/fingerprintService.js:48 @@ -1285,7 +1290,7 @@ msgstr "Von BitPay Konto" #: www/views/tab-import-phrase.html:57 msgid "From Hardware Wallet" -msgstr "" +msgstr "Aus der Hardware-Wallet" #: www/views/tab-export-qrCode.html:5 msgid "From the destination device, go to Add wallet > Import wallet and scan this QR code" @@ -1301,7 +1306,7 @@ msgstr "Betrag gefunden:" #: www/views/topup.html:49 msgid "Funds to be added" -msgstr "" +msgstr "Hinzuzufügende Mittel" #: www/views/paperWallet.html:51 msgid "Funds transferred" @@ -1309,7 +1314,7 @@ msgstr "Betrag übermittelt" #: www/views/topup.html:103 msgid "Funds were added to debit card" -msgstr "" +msgstr "Mittel wurden auf die Debitkarte hinzugefügt" #: www/views/paperWallet.html:22 msgid "Funds will be transferred to" @@ -1317,7 +1322,7 @@ msgstr "Beträge werden überwiesen an" #: www/views/tab-receive.html:51 msgid "Generate new address" -msgstr "" +msgstr "Neue Adresse generieren" #: src/js/services/onGoingProcess.js:22 msgid "Generating .csv file..." @@ -1338,7 +1343,7 @@ msgstr "Erhalten Sie Neuigkeiten und Aktualisierungen von BitPay" #: www/views/onboarding/welcome.html:8 msgctxt "button" msgid "Get started" -msgstr "" +msgstr "Loslegen" #: www/views/bitpayCard.html:49 msgid "Get started" @@ -1355,20 +1360,20 @@ msgstr "Entgelt-Level werden abgerufen..." #: www/views/buyAmazon.html:43 #: www/views/buyMercadoLibre.html:42 msgid "Gift Card" -msgstr "Geschenk-Karte" +msgstr "Geschenkkarte" #: www/views/modals/mercadolibre-card-details.html:30 #: www/views/modals/mercadolibre-card-details.html:35 msgid "Gift Card is not available to use anymore" -msgstr "" +msgstr "Geschenkkarte kann nicht mehr verwendet werden" #: src/js/controllers/buyAmazon.js:204 msgid "Gift card expired" -msgstr "" +msgstr "Geschenkkarte ist abgelaufen" #: www/views/buyAmazon.html:111 msgid "Gift card generated and ready to use." -msgstr "" +msgstr "Geschenkkarte generiert und einsatzbereit." #: src/js/controllers/bitpayCard.js:114 #: src/js/controllers/bitpayCard.js:124 @@ -1414,7 +1419,7 @@ msgstr "Hardware-Wallet" #: src/js/controllers/create.js:180 #: src/js/controllers/join.js:145 msgid "Hardware wallets are not yet supported with Bitcoin Cash" -msgstr "" +msgstr "Bitcoin Cash unterstützt keine Hardware-Wallets" #: www/views/tab-settings.html:20 msgid "Help & Support" @@ -1531,7 +1536,7 @@ msgstr "Wenn Sie einen Screenshot erstellen, kann die Sicherung von anderen Apps #: www/views/tab-import-hardware.html:42 #: www/views/tab-import-phrase.html:80 msgid "Import" -msgstr "" +msgstr "Import" #: www/views/import.html:3 msgid "Import Wallet" @@ -1580,13 +1585,13 @@ msgstr "QR code hat falsches Format" #: src/js/services/bwcError.js:113 msgid "Incorrect network address" -msgstr "" +msgstr "Falsche Netzwerkadresse" #: src/js/controllers/confirm.js:114 #: src/js/controllers/confirm.js:306 #: src/js/services/bwcError.js:44 msgid "Insufficient confirmed funds" -msgstr "" +msgstr "Unzureichende bestätigte Mittel" #: src/js/controllers/topup.js:165 #: src/js/controllers/topup.js:177 @@ -1606,7 +1611,7 @@ msgstr "Ungültig" #: src/js/controllers/buyMercadoLibre.js:137 #: src/js/controllers/topup.js:115 msgid "Invalid URL" -msgstr "" +msgstr "Ungültige URL" #: src/js/controllers/create.js:186 #: src/js/controllers/import.js:345 @@ -1635,7 +1640,7 @@ msgstr "Einladung um eine {{appName}} Wallet zu teilen" #: www/views/mercadoLibreCards.html:20 #: www/views/modals/mercadolibre-card-details.html:48 msgid "Invoice expired" -msgstr "" +msgstr "Rechnung abgelaufen" #: src/js/controllers/feedback/send.js:79 msgid "Is there anything we could do better?" @@ -1696,7 +1701,7 @@ msgstr "Letzter Monat" #: www/views/preferencesCash.html:18 #: www/views/tx-details.html:94 msgid "Learn more" -msgstr "" +msgstr "Weitere Informationen" #: www/views/backup.html:43 msgid "Let's verify your backup phrase." @@ -1737,15 +1742,15 @@ msgstr "Zeitsperre aktiv. Bitte auf die Entfernung des Zahlungsvorschlags warten #: www/views/includes/logOptions.html:3 msgid "Log options" -msgstr "" +msgstr "Log-Optionen" #: www/views/modals/bitpay-card-confirmation.html:14 msgid "Log out" -msgstr "" +msgstr "Abmelden" #: www/views/addresses.html:87 msgid "Low amount inputs" -msgstr "" +msgstr "Zu wenige Inputs" #: www/views/includes/walletHistory.html:27 msgid "Low fees" @@ -1777,11 +1782,11 @@ msgstr "Notiz" #: www/views/mercadoLibre.html:6 msgid "Mercado Livre Brazil Gift Cards" -msgstr "" +msgstr "Mercado Livre Brazil Geschenkkarten" #: src/js/controllers/buyMercadoLibre.js:98 msgid "Mercadolibre Gift Card Service is not available at this moment. Please try back later." -msgstr "" +msgstr "Der MercadoLibre Geschenkkarten-Dienst ist aktuell nicht erreichbar. Bitte versuchen Sie es später noch einmal." #: www/views/modals/txp-details.html:131 msgid "Merchant Message" @@ -1791,7 +1796,7 @@ msgstr "Händlernachricht" #: www/views/buyMercadoLibre.html:54 #: www/views/topup.html:63 msgid "Miner Fee" -msgstr "" +msgstr "Miner-Gebühr" #: src/js/services/bwcError.js:134 msgid "Missing parameter" @@ -1828,13 +1833,13 @@ msgstr "Hinweis: Um eine Brieftasche aus einer 3rd-Party-Software zu importieren #: www/views/preferences.html:15 #: www/views/preferencesAlias.html:17 msgid "Name" -msgstr "" +msgstr "Name" #: www/views/buyAmazon.html:49 #: www/views/buyMercadoLibre.html:48 #: www/views/topup.html:56 msgid "Network Cost" -msgstr "" +msgstr "Netzwerkkosten" #: src/js/services/bwcError.js:47 msgid "Network error" @@ -1863,7 +1868,7 @@ msgstr "Keine Wallet" #: src/js/controllers/buyAmazon.js:115 #: src/js/controllers/buyMercadoLibre.js:115 msgid "No access key defined" -msgstr "" +msgstr "Kein Zugangsschlüssel definiert" #: www/views/onboarding/backupRequest.html:5 msgid "No backup, no bitcoin." @@ -1875,7 +1880,7 @@ msgstr "Noch keine Kontakte" #: www/views/preferencesLogs.html:16 msgid "No entries for this log level" -msgstr "" +msgstr "Keine Einträge für dieses Log-level" #: www/views/preferencesExternal.html:12 msgid "No hardware information available." @@ -1896,7 +1901,7 @@ msgstr "Keine aktuellen Transaktionen" #: src/js/controllers/buyAmazon.js:44 #: src/js/controllers/topup.js:47 msgid "No signing proposal: No private key" -msgstr "" +msgstr "Kein Unterzeichnungsvorschlag: Privater Schlüssel nicht vorhanden" #: www/views/walletDetails.html:204 msgid "No transactions yet" @@ -1915,7 +1920,7 @@ msgstr "Kein Wallet ausgewählt" #: src/js/controllers/confirm.js:85 #: src/js/controllers/topup.js:265 msgid "No wallets available" -msgstr "" +msgstr "Keine Wallets verfügbar" #: www/views/paperWallet.html:45 msgid "No wallets available to receive funds" @@ -1923,19 +1928,19 @@ msgstr "Keine Wallet verfügbar um Guthaben zu erhalten" #: www/views/cashScan.html:15 msgid "No wallets eligible for Bitcoin Cash support" -msgstr "" +msgstr "Keine Wallet zur Unterstützung von Bitcoin Cash geeignet" #: src/js/controllers/cashScan.js:58 msgid "Non BIP44 wallet" -msgstr "" +msgstr "Wallet ist keine BIP44-Wallet" #: www/views/cashScan.html:46 msgid "Non eligible BTC wallets" -msgstr "" +msgstr "Keine geeigneten BTC Wallets" #: src/js/services/feeService.js:12 msgid "Normal" -msgstr "" +msgstr "Normal" #: src/js/services/bwcError.js:80 msgid "Not authorized" @@ -1964,7 +1969,7 @@ msgstr "Notiz" #: www/views/backup.html:19 msgid "Note: if this BCH wallet was duplicated from a BTC wallet, they share the same recovery phrase." -msgstr "" +msgstr "Hinweis: Wenn diese BCH-Wallet aus einer BTC-Wallet dupliziert wurde, verwenden sie die selbe Wiederherstellungsphrase." #: www/views/modals/wallets.html:25 msgid "Notice: only 1-1 (single signature) wallets can be used for sell bitcoin" @@ -1977,15 +1982,15 @@ msgstr "Benachrichtigungen" #: www/views/onboarding/collectEmail.html:9 msgid "Notifications by email" -msgstr "" +msgstr "Benachrichtigungen per e-Mail" #: www/views/tx-details.html:117 msgid "Notify me if confirmed" -msgstr "" +msgstr "Benachrichtige mich sobald sie bestätigt ist" #: www/views/preferencesNotifications.html:24 msgid "Notify me when transactions are confirmed" -msgstr "" +msgstr "Benachrichtigen Sie mich, wenn Transaktionen bestätigt werden" #: www/views/includes/backupNeededPopup.html:8 msgid "Now is a good time to backup your wallet. If this device is lost, it is impossible to access your funds without a backup." @@ -2004,7 +2009,7 @@ msgstr "Jetzt ist die perfekte Zeit um Ihre Umgebung zu überprüfen. In der Nä #: src/js/services/popupService.js:72 #: www/views/modals/chooseFeeLevel.html:6 msgid "OK" -msgstr "" +msgstr "Okay" #: www/views/modals/tx-status.html:12 #: www/views/modals/tx-status.html:24 @@ -2023,7 +2028,7 @@ msgstr "Oh nein!" #: src/js/controllers/buyMercadoLibre.js:306 msgid "Ok" -msgstr "" +msgstr "Okay" #: www/views/tab-home.html:39 msgid "On this screen you can see all your wallets, accounts, and assets." @@ -2053,7 +2058,7 @@ msgstr "Öffne GitHub Projekt" #: src/js/controllers/bitpayCard.js:123 #: src/js/controllers/tx-details.js:192 msgid "Open Explorer" -msgstr "" +msgstr "Explorer öffnen" #: www/views/tab-scan.html:22 msgid "Open Settings" @@ -2069,11 +2074,11 @@ msgstr "Öffne Website" #: src/js/controllers/preferencesCash.js:32 msgid "Open bitcoincash.org?" -msgstr "" +msgstr "bitcoincash.org öffnen?" #: src/js/controllers/cashScan.js:18 msgid "Open the recovery tool." -msgstr "" +msgstr "Öffnen Sie das Recovery-Tool." #: www/views/tab-receive.html:27 msgid "Open wallet" @@ -2081,7 +2086,7 @@ msgstr "Öffne Wallet" #: www/views/includes/incomingDataMenu.html:19 msgid "Open website" -msgstr "" +msgstr "Öffne Website" #: www/views/bitpayCardIntro.html:34 msgid "Order the BitPay Card" @@ -2173,7 +2178,7 @@ msgstr "Zahlung akzeptiert. Sie wird durch Glidera übermittelt. Falls ein Probl #: src/js/services/incomingData.js:152 msgid "Payment address was translated to new Bitcoin Cash address format:" -msgstr "" +msgstr "Die Zahlungsadresse wurde auf das neue Bitcoin Cash-Adressformat übersetzt:" #: www/views/modals/txp-details.html:107 msgid "Payment details" @@ -2186,7 +2191,7 @@ msgstr "Zahlungsanforderung" #: www/views/mercadoLibreCards.html:22 #: www/views/modals/mercadolibre-card-details.html:39 msgid "Pending" -msgstr "" +msgstr "Ausstehend" #: www/views/proposals.html:4 msgid "Pending Proposals" @@ -2232,7 +2237,7 @@ msgstr "Bitte Copay aktualisieren, um diese Aktion auszuführen" #: www/views/walletDetails.html:142 #: www/views/walletDetails.html:62 msgid "Please wait" -msgstr "" +msgstr "Bitte warten" #: src/js/controllers/import.js:238 msgid "Please, select your backup file" @@ -2240,7 +2245,7 @@ msgstr "Bitte die Sicherungsdatei wählen" #: www/views/bitpayCard.html:81 msgid "Pre-Auth Holds" -msgstr "" +msgstr "Pre-Auth Holds" #: www/views/tab-settings.html:40 msgid "Preferences" @@ -2264,7 +2269,7 @@ msgstr "höchste Priorität" #: www/views/includes/incomingDataMenu.html:80 msgid "Private Key" -msgstr "" +msgstr "Privater Schlüssel" #: src/js/controllers/paperWallet.js:136 msgid "Private key encrypted. Enter password" @@ -2298,11 +2303,11 @@ msgstr "Vorschläge" #: src/js/controllers/buyAmazon.js:282 msgid "Purchase Amount is limited to {{limitPerDay}} {{currency}} per day" -msgstr "" +msgstr "Kaufbetrag beschränkt ist auf {{limitPerDay}} {{currency}} pro Tag beschränkt" #: src/js/controllers/buyMercadoLibre.js:281 msgid "Purchase amount must be a value between 50 and 2000" -msgstr "" +msgstr "Kaufbetrag muss ein Wert zwischen 50 und 2000 sein" #: www/views/onboarding/notifications.html:3 msgid "Push Notifications" @@ -2340,11 +2345,11 @@ msgstr "Mehr anzeigen" #: src/js/controllers/preferences.js:65 #: src/js/controllers/tx-details.js:54 msgid "Read more in our Wiki" -msgstr "" +msgstr "Lesen Sie mehr in unserem Wiki" #: src/js/controllers/cashScan.js:61 msgid "Read only wallet" -msgstr "" +msgstr "Schreibgeschützte Wallet" #: www/views/tab-receive.html:3 #: www/views/tabs.html:7 @@ -2353,7 +2358,7 @@ msgstr "Empfangen" #: www/views/customAmount.html:44 msgid "Receive in" -msgstr "" +msgstr "Erhalten in" #: www/views/includes/walletHistory.html:24 #: www/views/tx-details.html:18 @@ -2402,7 +2407,7 @@ msgstr "Wallet wiederherstellen..." #: www/views/modals/mercadolibre-card-details.html:22 msgid "Redeem now" -msgstr "" +msgstr "Jetzt einlösen" #: src/js/controllers/modals/txpDetails.js:63 #: src/js/controllers/tx-details.js:80 @@ -2420,7 +2425,7 @@ msgstr "Release-Informationen" #: www/views/addressbook.view.html:36 #: www/views/modals/mercadolibre-card-details.html:69 msgid "Remove" -msgstr "" +msgstr "Entfernen" #: src/js/controllers/preferencesBitpayServices.js:7 msgid "Remove BitPay Account?" @@ -2503,7 +2508,7 @@ msgstr "Adresse auf neue Beträge überprüfen" #: www/views/modals/fingerprintCheck.html:11 msgid "Scan again" -msgstr "" +msgstr "Erneut scannen" #: src/js/services/fingerprintService.js:56 msgid "Scan your fingerprint please" @@ -2511,7 +2516,7 @@ msgstr "Scannen Sie bitte Ihren Fingerabdruck" #: www/views/preferencesCash.html:23 msgid "Scan your wallets for Bitcoin Cash" -msgstr "" +msgstr "Durchsuche deine Wallet nach Bitcoin Cash" #: src/js/services/onGoingProcess.js:30 msgid "Scanning Wallet funds..." @@ -2519,7 +2524,7 @@ msgstr "Prüfe Wallet auf neue Beträge..." #: www/views/includes/walletList.html:11 msgid "Scanning funds..." -msgstr "" +msgstr "Mittel werden durchsucht..." #: www/views/includes/screenshotWarningModal.html:7 msgid "Screenshots are not secure" @@ -2533,6 +2538,14 @@ msgstr "Transaktionen durchsuchen" msgid "Search or enter bitcoin address" msgstr "Bitcoin-Adresse suchen oder eingeben" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Zwischenablage" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Ihre Zwischenablage ist leer" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Transaktionen durchsuchen" @@ -2547,7 +2560,7 @@ msgstr "Sicherheit" #: www/views/modals/mercadolibre-card-details.html:64 msgid "See invoice" -msgstr "" +msgstr "Rechnung einsehen" #: www/views/tab-import-file.html:7 msgid "Select a backup file" @@ -2591,16 +2604,77 @@ msgid "Send by email" msgstr "Per E-Mail versenden" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Senden von" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Senden an" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Aus Zwischenablage einfügen" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Adresse einfügen" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Wallet-zu-Wallet-Überweisung" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "QR-Code scannen" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Versenden Sie Bitcoin schneller!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Versenden Sie Bitcoin schneller!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Speichern Sie häufig verwendete Adressen und senden Sie ihnen Bitcoin mit nur einem Tippen" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Ihren ersten Kontakt hinzufügen" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Ihre Bitcoin-Wallet ist leer" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Um loszulegen, können sie entweder Bitcoin Cash (BCH) oder Bitcoin Core (BTC) kaufen, oder uns ihre Adresse mitteilen." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Sie können Bitcoin von jeder Wallet oder jedem Dienst erhalten." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Um loszulegen müssen Sie eine Bitcoin-Wallet erstellen und einige Bitcoins erhalten." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Bitcoin jetzt kaufen" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Meine Adresse anzeigen" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Sende max. Betrag" #: www/views/includes/incomingDataMenu.html:46 msgid "Send payment to this address" -msgstr "" +msgstr "Zahlung an diese Adresse senden" #: www/views/feedback/rateApp.html:17 msgid "Send us feedback instead" @@ -2651,11 +2725,11 @@ msgstr "Antwort des Servers konnte nicht verifiziert werden" #: src/js/controllers/buyAmazon.js:97 #: src/js/controllers/buyMercadoLibre.js:97 msgid "Service not available" -msgstr "" +msgstr "Dienst ist nicht verfügbar" #: www/views/includes/homeIntegrations.html:3 msgid "Services" -msgstr "" +msgstr "Dienste" #: www/views/preferencesLogs.html:3 msgid "Session Log" @@ -2671,7 +2745,7 @@ msgstr "Passwort einrichten" #: src/js/controllers/preferencesFee.js:85 msgid "Set your own fee in satoshis/byte" -msgstr "" +msgstr "Legen Sie Ihre eigene Gebühr in Satoshis/byte fest" #: www/views/tab-settings.html:3 #: www/views/tabs.html:19 @@ -2747,24 +2821,24 @@ msgstr "Überspringen" #: src/js/controllers/confirm.js:371 #: src/js/controllers/modals/txpDetails.js:47 msgid "Slide to accept" -msgstr "" +msgstr "Zum Akzeptieren schieben" #: www/views/buyAmazon.html:96 msgid "Slide to buy" -msgstr "" +msgstr "Zum Kaufen schieben" #: src/js/controllers/confirm.js:365 msgid "Slide to pay" -msgstr "" +msgstr "Zum Bezahlen schieben" #: src/js/controllers/confirm.js:377 #: src/js/controllers/modals/txpDetails.js:40 msgid "Slide to send" -msgstr "" +msgstr "Zum Senden schieben" #: www/views/cashScan.html:56 msgid "Some of your wallets are not eligible for Bitcoin Cash support. You can try to access BCH funds from these wallets using the" -msgstr "" +msgstr "Einige ihrer Wallets sind nicht zur Unterstützung von Bitcoin Cash geeignet. Sie können versuchen, auf BCH Mittel von diesen Wallets aus zuzugreifen indem Sie die" #: src/js/controllers/create.js:88 #: src/js/controllers/join.js:71 @@ -2785,7 +2859,7 @@ msgstr "Berechtigungscode erforderlich" #: www/views/walletDetails.html:173 msgid "Spending this balance will need significant Bitcoin network fees" -msgstr "" +msgstr "Die Ausgabe dieses Betrages wird signifikante Bitcoin-Netzwerkgebühren erfordern" #: www/views/tab-send.html:28 msgid "Start sending bitcoin" @@ -2798,11 +2872,11 @@ msgstr "Sperre des Startups" #: www/views/mercadoLibreCards.html:21 #: www/views/modals/mercadolibre-card-details.html:42 msgid "Still pending" -msgstr "" +msgstr "Noch ausstehend" #: www/views/topup.html:101 msgid "Success" -msgstr "" +msgstr "Erfolg" #: src/js/services/feeService.js:14 msgid "Super Economy" @@ -2810,7 +2884,7 @@ msgstr "Niedrigste Priorität" #: www/views/preferencesCash.html:11 msgid "Support Bitcoin Cash" -msgstr "" +msgstr "Bitcoin Cash unterstützen" #: www/views/paperWallet.html:7 msgid "Sweep" @@ -2840,7 +2914,7 @@ msgstr "Anzeigen durch tippen und halten" #: www/views/includes/walletInfo.html:3 msgid "Tap to recreate" -msgstr "" +msgstr "Zum neu erstellen tippen" #: www/views/includes/walletInfo.html:4 msgid "Tap to retry" @@ -2860,11 +2934,11 @@ msgstr "Nutzungsbedingungen" #: www/views/tab-create-personal.html:118 #: www/views/tab-import-phrase.html:68 msgid "Testnet" -msgstr "" +msgstr "Testnet" #: www/views/includes/incomingDataMenu.html:61 msgid "Text" -msgstr "" +msgstr "Text" #: src/js/controllers/feedback/send.js:27 #: src/js/controllers/feedback/send.js:76 @@ -2999,7 +3073,7 @@ msgstr "Diese Wiederherstellungsphrase entstand mit einem Passwort. Zur Wiederhe #: www/views/tx-details.html:91 msgid "This transaction amount is too small compared to current Bitcoin network fees. Spending these funds will need a Bitcoin network fee cost comparable to the funds itself." -msgstr "" +msgstr "Dieser Betrag ist zu klein im Vergleich zu den aktuellen Bitcoin-Netzwerk-Gebühren. Diese Mittel benötigen eine Bitcoin Netzwerk Gebühr mit vergleichbarer Größe zu den Mitteln." #: www/views/tx-details.html:87 msgid "This transaction could take a long time to confirm or could be dropped due to the low fees set by the sender" @@ -3034,15 +3108,15 @@ msgstr "Um loszulegen müssen Sie eine Bitcoin-Wallet erstellen und einige Bitco #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" -msgstr "" +msgstr "Zum {{reason}} müssen Sie erst Ihr BitPay-Konto hinzufügen - {{email}}" #: src/js/services/onGoingProcess.js:48 msgid "Top up in progress..." -msgstr "" +msgstr "Aufladung in Bearbeitung..." #: src/js/controllers/topup.js:206 msgid "Top up {{amountStr}} to debit card ({{cardLastNumber}})" -msgstr "" +msgstr "Laden sie {{amountStr}} auf die Debitkarte ({{cardLastNumber}}) auf" #: www/views/buyAmazon.html:61 #: www/views/buyMercadoLibre.html:60 @@ -3061,7 +3135,7 @@ msgstr "Gesamtanzahl der Copayer" #: www/views/addresses.html:81 msgid "Total wallet inputs" -msgstr "" +msgstr "Alle Wallet-Inputs" #: src/js/services/fingerprintService.js:63 #: src/js/services/fingerprintService.js:68 @@ -3074,7 +3148,7 @@ msgstr "Transaktion" #: www/views/confirm.html:126 msgid "Transaction Created" -msgstr "" +msgstr "Transaktion erstellt" #: www/views/preferencesAdvanced.html:29 #: www/views/preferencesHistory.html:3 @@ -3089,11 +3163,11 @@ msgstr "Transaktion wurde bereits übermittelt" #: src/js/controllers/buyMercadoLibre.js:301 #: src/js/controllers/topup.js:281 msgid "Transaction has not been created" -msgstr "" +msgstr "Transaktion wurde nicht erstellt" #: www/views/topup.html:104 msgid "Transaction initiated" -msgstr "" +msgstr "Transaktion eingeleitet" #: src/js/controllers/tx-details.js:119 msgid "Transaction not available at this time" @@ -3106,11 +3180,11 @@ msgstr "Transaktion konnte nicht gefunden werden" #: www/views/modals/chooseFeeLevel.html:55 msgid "Transactions without fee are not supported." -msgstr "" +msgstr "Transaktionen ohne Gebühren werden nicht unterstützt." #: src/js/controllers/paperWallet.js:109 msgid "Transfer to" -msgstr "" +msgstr "Transfer zu" #: www/views/tab-send.html:67 msgid "Transfer to Wallet" @@ -3130,7 +3204,7 @@ msgstr "Wiederherstellungsphrase eingeben (in der Regel 12 Wörter)" #: src/js/controllers/backup.js:75 msgid "Uh oh..." -msgstr "" +msgstr "Oh oh..." #: www/views/tx-details.html:100 msgid "Unconfirmed" @@ -3178,12 +3252,12 @@ msgstr "Überprüfe Wiederherstellungsphrase..." #: www/views/modals/fingerprintCheck.html:4 msgid "Verify your identity" -msgstr "" +msgstr "Bestätigen Sie Ihre Identität" #: www/views/preferencesAbout.html:14 #: www/views/preferencesExternal.html:25 msgid "Version" -msgstr "" +msgstr "Version" #: www/views/tab-export-file.html:69 msgid "View" @@ -3200,7 +3274,7 @@ msgstr "Nutzungsbedingungen anzeigen" #: src/js/controllers/bitpayCard.js:122 #: src/js/controllers/tx-details.js:191 msgid "View Transaction on Explorer.Bitcoin.com" -msgstr "" +msgstr "Transaktion auf Explorer.Bitcoin.com ansehen" #: src/js/controllers/tab-home.js:148 msgid "View Update" @@ -3212,7 +3286,7 @@ msgstr "Auf blockchain anzeigen" #: www/views/mercadoLibre.html:26 msgid "Visit mercadolivre.com.br →" -msgstr "" +msgstr "Besuchen Sie mercadolivre.com.br →" #: www/views/walletDetails.html:182 msgid "WARNING: Key derivation is not working on this device/wallet. Actions cannot be performed on this wallet." @@ -3274,7 +3348,7 @@ msgstr "Wallet-Informationen" #: www/views/addresses.html:76 msgid "Wallet Inputs" -msgstr "" +msgstr "Wallet-Inputs" #: www/views/join.html:26 msgid "Wallet Invitation" @@ -3328,7 +3402,7 @@ msgstr "Wallet exstiert bereits" #: src/js/services/profileService.js:516 msgid "Wallet already in {{appName}}" -msgstr "" +msgstr "Wallet bereits in {{appName}}" #: www/views/includes/walletActivity.html:6 msgid "Wallet created" @@ -3379,7 +3453,7 @@ msgstr "Wallet ist nicht beim Wallet-Service registiert. Neu erzeugen mit \"Neue #: www/views/backup.html:12 msgid "Wallet recovery phrase not available" -msgstr "" +msgstr "Wallet Wiederherstellungsphrase ist nicht verfügbar" #: src/js/services/bwcError.js:50 msgid "Wallet service not found" @@ -3387,7 +3461,7 @@ msgstr "Wallet-Dienst nicht gefunden" #: www/views/tab-home.html:69 msgid "Wallets" -msgstr "" +msgstr "Wallets" #: src/js/controllers/addressbookView.js:36 #: src/js/controllers/modals/txpDetails.js:153 @@ -3424,7 +3498,7 @@ msgstr "Wir sind immer auf der Suche nach Möglichkeiten um {{appName}} zu verbe #: www/views/includes/incomingDataMenu.html:6 msgid "Website" -msgstr "" +msgstr "Webseite" #: www/views/preferencesLanguage.html:16 msgid "We’re always looking for translation contributions! You can make corrections or help to make this app available in your native language by joining our community on Crowdin." @@ -3504,11 +3578,11 @@ msgstr "Sie kontrollieren Ihre Bitcoins." #: www/views/modals/chooseFeeLevel.html:64 msgid "You should not set a fee higher than {{maxFeeRecommended}} satoshis/byte." -msgstr "" +msgstr "Sie sollten keine Gebühren welche höher als {{maxFeeRecommended}} satoshis/byte sind wählen." #: www/views/modals/bitpay-card-confirmation.html:5 msgid "You will need to log back for fill in your BitPay Card." -msgstr "" +msgstr "Sie müssen sich wieder anmelden um ihre BitPay-Karte aufzufüllen." #: www/views/preferencesNotifications.html:34 msgid "You'll receive email notifications about payments sent and received from your wallets." @@ -3516,12 +3590,12 @@ msgstr "Sie erhalten E-Mail Benachrichtigungen über gesendete und empfangen Zah #: www/views/bitpayCard.html:50 msgid "Your BitPay Card is ready. Add funds to your card to start using it at stores and ATMs worldwide." -msgstr "" +msgstr "Ihre BitPay-Karte ist bereit. Fügen sie Mittel auf Ihre Karte hinzu um diesen bei Geschäften und Geldautomaten weltweit zu benutzen." #: www/views/mercadoLibre.html:57 #: www/views/mercadoLibreCards.html:6 msgid "Your Gift Cards" -msgstr "" +msgstr "Ihre Geschenkkarten" #: www/views/includes/confirmBackupPopup.html:6 msgid "Your bitcoin wallet is backed up!" @@ -3533,7 +3607,7 @@ msgstr "Ihre Bitcoin-Wallet ist fertig!" #: www/views/modals/chooseFeeLevel.html:61 msgid "Your fee is lower than recommended." -msgstr "" +msgstr "Ihre Gebühren sind niedriger als empfohlen." #: www/views/feedback/send.html:42 msgid "Your ideas, feedback, or comments" @@ -3554,11 +3628,11 @@ msgstr "Passwort" #: www/views/buyAmazon.html:102 msgid "Your purchase could not be completed" -msgstr "" +msgstr "Ihre Bestellung konnte nicht abgeschlossen werden" #: www/views/buyAmazon.html:105 msgid "Your purchase was added to the list of pending" -msgstr "" +msgstr "Ihre Bestellung wurde in die Liste der anstehenden Bestellungen hinzugefügt" #: www/views/onboarding/backupRequest.html:10 msgid "Your wallet is never saved to cloud storage or standard device backups." @@ -3580,7 +3654,7 @@ msgstr "[Guthaben versteckt]" #: www/views/walletDetails.html:141 #: www/views/walletDetails.html:61 msgid "[Scanning Funds]" -msgstr "" +msgstr "[Mittel werden durchsucht...]" #: src/js/controllers/bitpayCardIntro.js:11 msgid "add your BitPay Visa card(s)" @@ -3604,15 +3678,15 @@ msgstr "in Arbeit..." #: www/views/cashScan.html:57 msgid "recovery tool." -msgstr "" +msgstr "Wiederherstellungstool." #: src/js/controllers/buyAmazon.js:239 msgid "{{amountStr}} for Amazon.com Gift Card" -msgstr "" +msgstr "{{amountStr}} für Amazon.com Geschenkkarte" #: src/js/controllers/buyMercadoLibre.js:237 msgid "{{amountStr}} for Mercado Livre Brazil Gift Card" -msgstr "" +msgstr "{{amountStr}} für Mercado Livre Brazil Geschenkkarte" #: www/views/preferencesBwsUrl.html:21 msgid "{{appName}} depends on Bitcore Wallet Service (BWS) for blockchain information, networking and Copayer synchronization. The default configuration points to https://bws.bitpay.com (BitPay's public BWS instance)." @@ -3624,7 +3698,7 @@ msgstr "{{fee}} wird für Bitcoin-Netzwerkgebühren abgezogen werden." #: www/views/confirm.html:85 msgid "{{tx.txp[wallet.id].feeRatePerStr}} of the sending amount" -msgstr "" +msgstr "{{tx.txp[wallet.id].feeRatePerStr}} von dem sendenden Betrag" #: www/views/walletDetails.html:218 msgid "{{updatingTxHistoryProgress}} transactions downloaded" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} Transaktionen werden heruntergeladen" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-von-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Community" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Erkunden Sie Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash Spiele" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Neuigkeiten" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Mining-Pool" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Werkzeuge" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Bitcoin Preis-Charts" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Kostenloses Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Ihre Bitcoin-Wallet ist fertig!" + diff --git a/i18n/po/es-ES/template-es-ES.po b/i18n/po/es-ES/template-es-ES.po index e062b4d1e..9338825d0 100644 --- a/i18n/po/es-ES/template-es-ES.po +++ b/i18n/po/es-ES/template-es-ES.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Spanish\n" "Language: es\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Comprar & Vender Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Comprar Bitcoin" @@ -619,10 +620,14 @@ msgstr "Conectando a Glidera..." msgid "Connection reset by peer" msgstr "Conexión re establecida" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contactos" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Direcciones frecuentes guardadas" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Continuar" @@ -823,7 +828,7 @@ msgstr "Crear billetera compartida" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Crear billetera" @@ -2533,6 +2538,14 @@ msgstr "Buscar transacciones" msgid "Search or enter bitcoin address" msgstr "Buscar o introducir dirección bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Portapapeles" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Portapapeles vacío" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Buscar transacciones" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Enviar por correo electrónico" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Enviar desde" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Enviar a" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Pegar portapapeles" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Pegar dirección" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Billetera a billetera" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Escanear código QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "¡Envía Bitcoin más rápido!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "¡Envía Bitcoin más rápido!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Guardar las direcciones que usas frecuentemente y envía Bitcoin en un click" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Añadie tu primer contacto" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Tu billetera Bitcoin está vacía" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Para empezar, compra Bitcoin Cash (BCH) o Bitcoin Core (BTC), o comparte tu dirección." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Puedes recibir bitcoin desde cualquier billetera o servicio." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Para empezar, necesitarás crear una billetera y obtener bitcoins." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Comprar Bitcoin ahora" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Ver mi dirección" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Enviar la máxima cantidad" @@ -3030,7 +3104,7 @@ msgstr "Para empezar, compra bitcoin o comparte tu dirección. Puedes recibir bi #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Para empezar, necesitarás crear una billetera y obtener bitcoins." +msgstr "Para empezar, necesitarás crear una billetera y obtener Bitcoins." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transacciones descargadas" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-de-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift - Cambia BTC a BCH" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Comunidad" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Reddit de Bitcoin Cash" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Twitter de Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Explora Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Juegos de Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Noticias" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Minería en la nube" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Herramientas" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Gráfica de precios Bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash gratis" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "¡Tus billeteras Bitcoin están listas!" + diff --git a/i18n/po/fa/template-fa.po b/i18n/po/fa/template-fa.po index aa4b76892..148ac9147 100644 --- a/i18n/po/fa/template-fa.po +++ b/i18n/po/fa/template-fa.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Persian\n" "Language: fa\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "خرید & فروش بیتکوین" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "خرید بیتکوین" @@ -619,10 +620,14 @@ msgstr "در حال اتصال به Glidera..." msgid "Connection reset by peer" msgstr "ریست اتصال توسط همکار" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "تماسها" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "آدرس های ذخیره شده که اغلب مورد استفاده قرار گرفته اند" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "ادامه" @@ -823,7 +828,7 @@ msgstr "ایجاد کیف پول مشترک" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "ایجاد کیف پول بیتکوین" @@ -2533,6 +2538,14 @@ msgstr "جستجوی تراکنش ها" msgid "Search or enter bitcoin address" msgstr "جستجو و یا وارد کردن آدرس بیتکوین" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "کلیپ بورد" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "کلیپ بورد شما خالی است" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "جستجوی تراکنش ها" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "ارسال توسط ایمیل" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "ارسال از" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "ارسال به" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "جای گذاری کلیپ برد" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "جای گذاری آدرس" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "انتقال پول از کیف پول به کیف پول" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "اسکن کد QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "ارسال سریع تر بیت کوین!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "ارسال سریع تر بیت کوین!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "ذخیره آدرس های اغلب استفاده شده و ارسال بیت کوین به آنها تنها با یک ضربه" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "اولین تماس خود اضافه کنید" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "کیف پول بیت کوین شما خالی است" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "برای شروع، Bitcoin Cash (BCH) یا Bitcoin Core (BTC) بخرید و یا آدرس خود را به اشتراک بگذارید." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "شما می توانید از هر کیف پول و یا خدمات بیت کوین دریافت کنید." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "برای شروع، شما نیاز دارید که یک کیف پول ایجاد کنید و مقداری بیتکوین تهیه کنید." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "خرید بیت کوین همین الان" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "نمایش آدرس من" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "ارسال حداکثر مقدار" @@ -3030,7 +3104,7 @@ msgstr "برای شروع، بیتکوین بخرید و یا آدرس خود ر #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "برای شروع، شما نیاز دارید که یک کیف پول ایجاد کنید و مقداری بیتکوین تهیه کنید." +msgstr "برای شروع، شما نیاز دارید که یک کیف پول بیت کوین ایجاد کرده و مقداری بیت کوین تهیه کنید." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} تراکنش دانلود شد" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}} از {{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "جامعه" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "توییتر Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "کاوش Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash Games" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "اخبار" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "استخر استخراج" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "ابزارها" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "نمودارهای قیمت بیت کوین" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "رایگان Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "کیف پول بیت کوین شما آماده است!" + diff --git a/i18n/po/fr/template-fr.po b/i18n/po/fr/template-fr.po index f49b0fe55..d87845d47 100644 --- a/i18n/po/fr/template-fr.po +++ b/i18n/po/fr/template-fr.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: French\n" "Language: fr\n" -"PO-Revision-Date: 2018-07-04 09:26\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -79,7 +79,7 @@ msgstr "Numéro de compte" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "Transactions instantanées à bas frais" +msgstr "Instant transactions with low fees" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Acheter & vendre des bitcoins" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Acheter des bitcoins" @@ -619,10 +620,14 @@ msgstr "Connexion à Glidera..." msgid "Connection reset by peer" msgstr "Connexion réinitialisée par un pair" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contacts" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Adresses fréquemment utilisées enregistrées" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Continuer" @@ -823,7 +828,7 @@ msgstr "Créer un portefeuille partagé" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Créer un portefeuille bitcoin" @@ -993,7 +998,7 @@ msgstr "Autoriser les notifications" #: www/views/preferencesNotifications.html:33 msgid "Enable sound" -msgstr "Activer le son" +msgstr "Malayu" #: www/views/tab-scan.html:18 msgid "Enable the camera to get started." @@ -2533,6 +2538,14 @@ msgstr "Rechercher des transactions" msgid "Search or enter bitcoin address" msgstr "Recherchez ou saisissez une adresse bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Presse-papiers" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Votre presse-papiers est vide" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Rechercher des transactions" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Envoyer par e-mail" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Envoyer à partir de" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Envoyer à" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Coller le contenu du presse-papiers" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Coller l'adresse" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Transfert de portefeuille à portefeuille" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Numérisez le code QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envoyez des Bitcoin plus vite !" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envoyez des Bitcoin plus vite !" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Enregistrez les adresses fréquemment utilisées et envoyez-leurs des Bitcoins en un seul geste" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Ajoutez votre premier contact" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Votre portefeuille Bitcoin est vide" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Pour commencer, achetez des Bitcoins Cash (BCH) ou des Bitcoins Core (BTC), ou partagez votre adresse." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Vous pouvez recevoir des Bitcoins de n'importe quel portefeuille ou service." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Pour commencer, vous aurez besoin de créer un portefeuille bitcoin et d'obtenir quelques bitcoins." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Acheter des Bitcoins maintenant" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Afficher mon adresse" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Envoyer le montant maximal" @@ -3030,7 +3104,7 @@ msgstr "Pour commencer, achetez des bitcoins ou partagez votre adresse. Vous pou #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Pour commencer, vous aurez besoin de créer un portefeuille bitcoin et d'obtenir quelques bitcoins." +msgstr "Pour commencer, vous aurez besoin de créer un portefeuille Bitcoin et d'obtenir quelques bitcoins." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transactions téléchargées" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-sur-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Communauté" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Reddit Bitcoin Cash" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Twitter Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Explorez Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Jeux Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Nouvelles" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Coopératives de mineurs" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Outils" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Graphiques du prix du Bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash Gratuit" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Vos portefeuilles bitcoin sont prêts !" + diff --git a/i18n/po/it/template-it.po b/i18n/po/it/template-it.po index 1fcaea030..62738bf84 100644 --- a/i18n/po/it/template-it.po +++ b/i18n/po/it/template-it.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Italian\n" "Language: it\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Comprare & Vendere Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Acquista Bitcoin" @@ -619,10 +620,14 @@ msgstr "Connessione a Glidera..." msgid "Connection reset by peer" msgstr "Connessione ripristinata dall'utente" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contatti" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Indirizzi più utilizzati salvati" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Continua" @@ -823,7 +828,7 @@ msgstr "Creare portafoglio condiviso" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Creare portafoglio bitcoin" @@ -2533,6 +2538,14 @@ msgstr "Cerca Transazioni" msgid "Search or enter bitcoin address" msgstr "Cerca o inserisci indirizzo bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Appunti" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Gli appunti sono vuoti" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Ricerca transazioni" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Invia via email" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Inviata Da" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Invia a" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Incolla appunti" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Incolla indirizzo" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Trasferimento da portafoglio a portafoglio" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Scansiona codice QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Invia Bitcoin più velocemente!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Invia Bitcoin più velocemente!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Salva gli indirizzi più utilizzati e invia Bitcoin con un solo tocco" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Aggiungi il tuo primo contatto" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Il tuo portafoglio Bitcoin è vuoto" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Per iniziare, acquista Bitcoin Cash (BCH) o Bitcoin Core (BTC), oppure condividi il tuo indirizzo." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Puoi ricevere Bitcoin da qualsiasi portafoglio o servizio." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Per iniziare, è necessario che tu crei un portafoglio bitcoin e ottenerne qualcuno." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Acquista subito Bitcoin" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Visualizza il mio indirizzo" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Inviare l'importo massimo" @@ -3030,7 +3104,7 @@ msgstr "Per iniziare, acquista bitcoin o condividi il tuo indirizzo. È possibil #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Per iniziare, è necessario che tu crei un portafoglio bitcoin e ottenerne qualcuno." +msgstr "Per iniziare, devi creare un portafoglio bitcoin e ottenere qualche bitcoin." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transazioni scaricate" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-di-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Community" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash su Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com su Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Esplora Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Giochi Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "News" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Mining Pool" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Strumenti" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Tabella prezzi Bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash gratis" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "I tuoi portafogli Bitcoin sono pronti!" + diff --git a/i18n/po/ja/template-ja.po b/i18n/po/ja/template-ja.po index e7df99c1b..30668ce9d 100644 --- a/i18n/po/ja/template-ja.po +++ b/i18n/po/ja/template-ja.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Japanese\n" "Language: ja\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -406,7 +406,7 @@ msgstr "ビットコインは世界で
最も安全な仮想通貨。" #: www/views/preferencesFee.html:11 msgid "Bitcoin transactions include a fee collected by miners on the network." -msgstr "ビットコインの取引はネットワークの安全を守る「採掘者」と呼ばれる者達に送る手数料が含まれます。" +msgstr "ビットコインの取引はネットワークの安全を守る「採掘者」と呼ばれる方達に送る手数料が含まれます。" #: www/views/buyAmazon.html:108 msgid "Bought {{amountUnitStr}}" @@ -439,6 +439,7 @@ msgid "Buy & Sell Bitcoin" msgstr "ビットコインの購入&売却" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "ビットコインを購入" @@ -621,10 +622,14 @@ msgstr "Glidera に接続中…" msgid "Connection reset by peer" msgstr "接続がピアによってリセットされました" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "連絡先" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "よく使う保存済みのアドレス" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "続ける" @@ -825,7 +830,7 @@ msgstr "共有ウォレットを作成" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "ビットコインウォレット作成" @@ -995,7 +1000,7 @@ msgstr "プッシュ通知を有効化" #: www/views/preferencesNotifications.html:33 msgid "Enable sound" -msgstr "音を有効にする" +msgstr "サウンドを有効にする" #: www/views/tab-scan.html:18 msgid "Enable the camera to get started." @@ -1348,7 +1353,7 @@ msgstr "始めよう" #: www/views/addressbook.html:20 msgid "Get started by adding your first one." -msgstr "初めての連絡先を追加しましょう。" +msgstr "連絡先を追加しましょう。" #: src/js/services/onGoingProcess.js:23 msgid "Getting fee levels..." @@ -1873,7 +1878,7 @@ msgstr "バックアップは非常に重要です!" #: www/views/addressbook.html:19 msgid "No contacts yet" -msgstr "連絡先が無い" +msgstr "連絡先はありません" #: www/views/preferencesLogs.html:16 msgid "No entries for this log level" @@ -2006,7 +2011,7 @@ msgstr "今一度周りの環境をよく見てみましょう。隠しカメラ #: src/js/services/popupService.js:72 #: www/views/modals/chooseFeeLevel.html:6 msgid "OK" -msgstr "わかりました" +msgstr "OK" #: www/views/modals/tx-status.html:12 #: www/views/modals/tx-status.html:24 @@ -2535,6 +2540,14 @@ msgstr "取引を検索" msgid "Search or enter bitcoin address" msgstr "連絡先検索かビットコインアドレスを指定" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "クリップボード" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "クリップボードは空です" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "取引を検索" @@ -2593,9 +2606,70 @@ msgid "Send by email" msgstr "メールで送信" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "ここから送金" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "送金先:" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "クリップボードからペースト" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "アドレスをペースト" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "ウォレット間送金" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "QRコードを読み取る" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "ビットコイン送金をより高速に!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "ビットコイン送金をより高速に!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "よく使うアドレスを保存すればワンタップでビットコインを送金できます" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "最初の連絡先を追加" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "ビットコインウォレットが空です" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "始めるには、Bitcoin Cash (BCH) または Bitcoin Core (BTC) を購入するか、あなたのアドレスを共有してください。" + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "どのウォレットやサービスからでもビットコインを受け取ることができます。" + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "はじめに、ビットコインウォレットを作成し、ビットコインを入手する必要があります。" + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "今すぐビットコインを購入" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "自分のアドレスを表示" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "全残高を送金" @@ -3450,7 +3524,7 @@ msgstr "送金発生時のメール通知はどのメールアドレスで受け #: www/views/addresses.html:19 msgid "Why?" -msgstr "なぜ?" +msgstr "なぜですか?" #: www/views/feedback/rateApp.html:10 msgid "Would you be willing to rate {{appName}} in the app store?" @@ -3642,3 +3716,51 @@ msgstr "{{updatingTxHistoryProgress}} 個の取引ダウンロード済み" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}} の{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "コミュニティ" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Bitcoin.com を参照" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash ゲーム" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "ニュース" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "マイニングプール" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "ツール" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "ビットコインの価格チャート" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "無料 Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "ビットコインウォレットが完成しました!" + diff --git a/i18n/po/ko/template-ko.po b/i18n/po/ko/template-ko.po index cee1be7d1..6285496ae 100644 --- a/i18n/po/ko/template-ko.po +++ b/i18n/po/ko/template-ko.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Korean\n" "Language: ko\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "비트코인 구매 & 판매" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "비트코인 구매" @@ -619,10 +620,14 @@ msgstr "Glidera에 연결 중..." msgid "Connection reset by peer" msgstr "연결 실패" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "연락처" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "자주 사용하는 저장된 주소" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "계속하기" @@ -823,7 +828,7 @@ msgstr "공유 지갑 만들기" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "비트코인 지갑 만들기" @@ -2533,6 +2538,14 @@ msgstr "거래 기록 검색하기" msgid "Search or enter bitcoin address" msgstr "비트코인 주소를 찾거나 작성" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "클립보드" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "클립보드가 비어 있습니다" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "거래 기록 검색" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "이메일로 보내기" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "출처" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "보내기" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "클립보드 붙여넣기" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "주소 붙여넣기" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "지갑 간 전송" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "QR 코드 스캔" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "비트코인 속성 전송!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "비트코인 속성 전송!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "자주 사용하는 주소를 저장하고 한 번의 탭으로 저장된 주소에 비트코인 전송" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "첫 번째 연락처 추가" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "비트코인 지갑이 비어 있습니다" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "시작하려면 비트코인 캐시(BCH) 또는 비트코인 코어(BTC)를 구매하거나 주소를 공유합니다." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "지갑 또는 서비스에서 비트코인을 받을 수 있습니다." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "시작하시기 위해선 비트코인 지갑을 생성하시거나 비트코인을 구매하세요." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "지금 비트코인 구매" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "내 주소 보기" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "최대 수량 보내기" @@ -3030,7 +3104,7 @@ msgstr "시작하시려면 비트코인을 구매하시거나 주소를 등록 #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "시작하시기 위해선 비트코인 지갑을 생성하시거나 비트코인을 구매하세요." +msgstr "시작하려면 비트코인 지갑을 만들고 비트코인을 구매하십시오." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} 거래 내역 다운로드 완료" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.n}}의 {{wallet.m}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "커뮤니티" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "BCH Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com 트위터" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Bitcoin.com 탐색" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "BCH 게임" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "소식" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "채굴 풀" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "도구" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "비트코인 가격 차트" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "무료 BCH" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "비트코인 지갑이 완료되었습니다!" + diff --git a/i18n/po/nl/template-nl.po b/i18n/po/nl/template-nl.po index 754c41e21..b66d0b892 100644 --- a/i18n/po/nl/template-nl.po +++ b/i18n/po/nl/template-nl.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Dutch\n" "Language: nl\n" -"PO-Revision-Date: 2018-07-04 09:26\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Koop & Verkoop Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Bitcoin kopen" @@ -619,10 +620,14 @@ msgstr "Verbinding maken met Glidera..." msgid "Connection reset by peer" msgstr "Verbinding is gereset door peer" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contactpersonen" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Opgeslagen veelgebruikte adressen" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Ga verder" @@ -823,7 +828,7 @@ msgstr "Gedeelde Portemonnee Aanmaken" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Bitcoin portemonnee aanmaken" @@ -2533,6 +2538,14 @@ msgstr "Doorzoek Transacties" msgid "Search or enter bitcoin address" msgstr "Zoeken of bitcoin adres invullen" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Klembord" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Uw klembord is leeg" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Doorzoek transacties" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Verstuur via email" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Verzenden vanuit" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Verzenden naar" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Klembord plakken" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Adres plakken" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Portemonnee overdracht" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Scan QR-code" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Stuur Bitcoin sneller!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Stuur Bitcoin sneller!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Sla veelgebruikte adressen op en verstuur ze Bitcoin met een druk op de knop" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Uw eerste contact toevoegen" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Uw Bitcoin portemonnee is leeg" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Om aan de slag te gaan, koop Bitcoin Cash (BCH) of Bitcoin Core (BTC), of deel uw adres." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "U kunt Bitcoin ontvangen van elke portemonnee of dienst." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Om aan de slag te gaan zult u een bitcoin portemonnee moeten aanmaken en wat bitcoin moeten verkrijgen." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Bitcoin kopen" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Toon mijn adres" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Verzend maximale hoeveelheid" @@ -3030,7 +3104,7 @@ msgstr "Om aan de slag te gaan, koop bitcoin of deel uw adres. U kunt bitcoin on #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Om aan de slag te gaan zult u een bitcoin portemonnee moeten aanmaken en wat bitcoin moeten verkrijgen." +msgstr "Om aan de slag te gaan, zult u een Bitcoin-portemonnee aan moeten maken en wat Bitcoin moeten verkrijgen." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transacties gedownload" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-van-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Community" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Bitcoin.com verkennen" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash spellen" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Nieuws" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Mining Pool" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Hulpmiddelen" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Bitcoin prijs grafieken" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Gratis Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Uw bitcoin portemonnee is gereed!" + diff --git a/i18n/po/pl/template-pl.po b/i18n/po/pl/template-pl.po index ce075e00b..ef9888ca5 100644 --- a/i18n/po/pl/template-pl.po +++ b/i18n/po/pl/template-pl.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Polish\n" "Language: pl\n" -"PO-Revision-Date: 2018-07-04 03:58\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -79,7 +79,7 @@ msgstr "Numer konta" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "" +msgstr "Natychmiastowe transakcje z niskimi prowizjami" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -363,12 +363,12 @@ msgstr "Adres bitcoin" #: www/views/cashScan.html:4 msgid "Bitcoin Cash (BCH) Balances" -msgstr "" +msgstr "Salda Bitcoin Cash (BCH)" #: www/views/preferencesCash.html:3 #: www/views/tab-settings.html:47 msgid "Bitcoin Cash Support" -msgstr "" +msgstr "Wsparcie Bitcoin Cash" #: www/views/tab-home.html:98 #: www/views/tab-settings.html:115 @@ -384,7 +384,7 @@ msgstr "Polityka prowizji sieci bitcoin" #: www/views/tab-home.html:83 #: www/views/tab-settings.html:107 msgid "Bitcoin Core Wallets" -msgstr "" +msgstr "Portfele Bitcoin Core" #: src/js/services/incomingData.js:151 msgid "Bitcoin cash Payment" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Kup & sprzedaj bitcoiny" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Kup bitcoiny" @@ -619,10 +620,14 @@ msgstr "Łączenie z Gildera..." msgid "Connection reset by peer" msgstr "Połączenie zostało zresetowane" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Kontakty" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Zapisane często używane adresy" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Dalej" @@ -823,7 +828,7 @@ msgstr "Utwórz współdzielony portfel" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Utwórz portfel bitcoin" @@ -977,7 +982,7 @@ msgstr "Puste adresy osiągnęły limit. Nowe adresy nie mogą być generowane." #: www/views/preferencesCash.html:17 msgid "Enable Bitcoin Cash wallet creation and operation within the App." -msgstr "" +msgstr "Włącz tworzenie i obsługę portfela Bitcoin Cash w aplikacji." #: www/views/tab-scan.html:19 msgid "Enable camera access in your device settings to get started." @@ -993,7 +998,7 @@ msgstr "Włącz powiadomienia" #: www/views/preferencesNotifications.html:33 msgid "Enable sound" -msgstr "" +msgstr "Włącz dźwięk" #: www/views/tab-scan.html:18 msgid "Enable the camera to get started." @@ -1001,7 +1006,7 @@ msgstr "Włącz kamerę aby rozpocząć." #: www/views/tab-settings.html:49 msgid "Enabled" -msgstr "" +msgstr "Włączono" #: src/js/services/walletService.js:1047 #: src/js/services/walletService.js:1062 @@ -1586,7 +1591,7 @@ msgstr "Nieprawidłowy adres" #: src/js/controllers/confirm.js:306 #: src/js/services/bwcError.js:44 msgid "Insufficient confirmed funds" -msgstr "" +msgstr "Niewystarczające potwierdzone środki" #: src/js/controllers/topup.js:165 #: src/js/controllers/topup.js:177 @@ -1931,7 +1936,7 @@ msgstr "Nie BIP44 portfel" #: www/views/cashScan.html:46 msgid "Non eligible BTC wallets" -msgstr "" +msgstr "Niewspierane portfele BTC" #: src/js/services/feeService.js:12 msgid "Normal" @@ -2004,7 +2009,7 @@ msgstr "Nadszedł czas, aby sprawdzić swoje otoczenie. Czy jesteś w pobliżu o #: src/js/services/popupService.js:72 #: www/views/modals/chooseFeeLevel.html:6 msgid "OK" -msgstr "" +msgstr "OK" #: www/views/modals/tx-status.html:12 #: www/views/modals/tx-status.html:24 @@ -2023,7 +2028,7 @@ msgstr "O nie!" #: src/js/controllers/buyMercadoLibre.js:306 msgid "Ok" -msgstr "" +msgstr "Ok" #: www/views/tab-home.html:39 msgid "On this screen you can see all your wallets, accounts, and assets." @@ -2053,7 +2058,7 @@ msgstr "Otwórz projekt GitHub" #: src/js/controllers/bitpayCard.js:123 #: src/js/controllers/tx-details.js:192 msgid "Open Explorer" -msgstr "" +msgstr "Otwórz Explorer" #: www/views/tab-scan.html:22 msgid "Open Settings" @@ -2069,7 +2074,7 @@ msgstr "Otwórz stronę internetową" #: src/js/controllers/preferencesCash.js:32 msgid "Open bitcoincash.org?" -msgstr "" +msgstr "Otworzyć bitcoincash.org?" #: src/js/controllers/cashScan.js:18 msgid "Open the recovery tool." @@ -2240,7 +2245,7 @@ msgstr "Proszę wybrać plik kopii zapasowej" #: www/views/bitpayCard.html:81 msgid "Pre-Auth Holds" -msgstr "" +msgstr "Wstrzymanie przedautoryzacyjne" #: www/views/tab-settings.html:40 msgid "Preferences" @@ -2353,7 +2358,7 @@ msgstr "Otrzymaj" #: www/views/customAmount.html:44 msgid "Receive in" -msgstr "" +msgstr "Otrzymaj w" #: www/views/includes/walletHistory.html:24 #: www/views/tx-details.html:18 @@ -2511,7 +2516,7 @@ msgstr "Proszę zeskanować linie papilarne" #: www/views/preferencesCash.html:23 msgid "Scan your wallets for Bitcoin Cash" -msgstr "" +msgstr "Skanuj portfele w poszukiwaniu Bitcoin Cash" #: src/js/services/onGoingProcess.js:30 msgid "Scanning Wallet funds..." @@ -2533,6 +2538,14 @@ msgstr "Szukaj transakcji" msgid "Search or enter bitcoin address" msgstr "Wyszukaj lub wpisz adres bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Schowek" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Schowek jest pusty" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Szukaj transakcji" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Wyślij przez e-mail" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Wyślij z" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Wyślij do" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Wklej ze schowka" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Wklej adres" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Transfer z portfela do portfela" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Zeskanuj kod QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Przesyłaj Bitcoiny szybciej!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Przesyłaj Bitcoiny szybciej!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Zapisz często używane adresy i wyślij im Bitcoin za pomocą jednego dotknięcia" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Dodaj swój pierwszy kontakt" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Twój portfel jest pusty" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Aby zacząć, kup Bitcoin Cash (BCH) lub Bitcoin Core (BTC), albo udostępnij swój adres." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Bitcoiny można odbierać z dowolnego portfela lub usługi." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Aby rozpocząć należy utworzyć portfel i dostać trochę bitcoinów." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Kup Bitcoin teraz" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Pokaż mój adres" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Wyślij całą kwotę" @@ -2764,7 +2838,7 @@ msgstr "Przesuń, aby wysłać" #: www/views/cashScan.html:56 msgid "Some of your wallets are not eligible for Bitcoin Cash support. You can try to access BCH funds from these wallets using the" -msgstr "" +msgstr "Niektóre z twoich portfeli nie kwalifikują się do wsparcia Bitcoin Cash. Dostęp do środków BCH z tych portfeli można spróbować uzyskać, korzystając z" #: src/js/controllers/create.js:88 #: src/js/controllers/join.js:71 @@ -2785,7 +2859,7 @@ msgstr "Wymagane hasło wypłat" #: www/views/walletDetails.html:173 msgid "Spending this balance will need significant Bitcoin network fees" -msgstr "" +msgstr "Wydanie tego salda będzie wymagało znacznych opłat sieciowych Bitcoin" #: www/views/tab-send.html:28 msgid "Start sending bitcoin" @@ -2810,7 +2884,7 @@ msgstr "Super Ekonomiczna" #: www/views/preferencesCash.html:11 msgid "Support Bitcoin Cash" -msgstr "" +msgstr "Wsparcie Bitcoin Cash" #: www/views/paperWallet.html:7 msgid "Sweep" @@ -2860,7 +2934,7 @@ msgstr "Warunki użytkowania" #: www/views/tab-create-personal.html:118 #: www/views/tab-import-phrase.html:68 msgid "Testnet" -msgstr "" +msgstr "Testnet" #: www/views/includes/incomingDataMenu.html:61 msgid "Text" @@ -2999,7 +3073,7 @@ msgstr "Ta kluczowa fraza został utworzona przy użyciu hasła. Aby odzyskać p #: www/views/tx-details.html:91 msgid "This transaction amount is too small compared to current Bitcoin network fees. Spending these funds will need a Bitcoin network fee cost comparable to the funds itself." -msgstr "" +msgstr "Ta kwota transakcji jest zbyt mała w porównaniu z obecnymi opłatami sieci Bitcoin. Wydanie tych środków będzie wymagało opłaty sieciowej Bitcoin, która jest porównywalna do kosztów samych funduszy." #: www/views/tx-details.html:87 msgid "This transaction could take a long time to confirm or could be dropped due to the low fees set by the sender" @@ -3034,15 +3108,15 @@ msgstr "Aby rozpocząć należy utworzyć portfel i dostać trochę bitcoinów." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" -msgstr "" +msgstr "Aby móc wykonać czynność {{reason}}, musisz przedtem dodać swoje konto BitPay – {{email}}" #: src/js/services/onGoingProcess.js:48 msgid "Top up in progress..." -msgstr "" +msgstr "Doładowanie w trakcie..." #: src/js/controllers/topup.js:206 msgid "Top up {{amountStr}} to debit card ({{cardLastNumber}})" -msgstr "" +msgstr "Doładuj o {{amountStr}} kartę debetową ({{cardLastNumber}})" #: www/views/buyAmazon.html:61 #: www/views/buyMercadoLibre.html:60 @@ -3061,7 +3135,7 @@ msgstr "Liczba współwłaścicieli portfela" #: www/views/addresses.html:81 msgid "Total wallet inputs" -msgstr "" +msgstr "Dane wejściowe portfela łącznie" #: src/js/services/fingerprintService.js:63 #: src/js/services/fingerprintService.js:68 @@ -3200,7 +3274,7 @@ msgstr "Zobacz zasady użytkowania" #: src/js/controllers/bitpayCard.js:122 #: src/js/controllers/tx-details.js:191 msgid "View Transaction on Explorer.Bitcoin.com" -msgstr "" +msgstr "Zobacz transakcję na Explorer.Bitcoin.com" #: src/js/controllers/tab-home.js:148 msgid "View Update" @@ -3212,7 +3286,7 @@ msgstr "Zobacz na blockchainie" #: www/views/mercadoLibre.html:26 msgid "Visit mercadolivre.com.br →" -msgstr "" +msgstr "Odwiedź mercadolivre.com.br →" #: www/views/walletDetails.html:182 msgid "WARNING: Key derivation is not working on this device/wallet. Actions cannot be performed on this wallet." @@ -3274,7 +3348,7 @@ msgstr "Informacje o portfelu" #: www/views/addresses.html:76 msgid "Wallet Inputs" -msgstr "" +msgstr "Dane wejściowe portfela" #: www/views/join.html:26 msgid "Wallet Invitation" @@ -3328,7 +3402,7 @@ msgstr "Portfel już istnieje" #: src/js/services/profileService.js:516 msgid "Wallet already in {{appName}}" -msgstr "" +msgstr "Portfel już w aplikacji {{appName}}" #: www/views/includes/walletActivity.html:6 msgid "Wallet created" @@ -3508,7 +3582,7 @@ msgstr "Nie należy ustawiać opłatę wyższą niż {{maxFeeRecommended}} satos #: www/views/modals/bitpay-card-confirmation.html:5 msgid "You will need to log back for fill in your BitPay Card." -msgstr "" +msgstr "Musisz zalogować się ponownie, aby wypełnić swoją kartę BitPay." #: www/views/preferencesNotifications.html:34 msgid "You'll receive email notifications about payments sent and received from your wallets." @@ -3580,7 +3654,7 @@ msgstr "[Balans ukryty]" #: www/views/walletDetails.html:141 #: www/views/walletDetails.html:61 msgid "[Scanning Funds]" -msgstr "" +msgstr "[Skanowanie środków]" #: src/js/controllers/bitpayCardIntro.js:11 msgid "add your BitPay Visa card(s)" @@ -3612,7 +3686,7 @@ msgstr "{{amountStr}} dla karty upominkowej Amazon.com" #: src/js/controllers/buyMercadoLibre.js:237 msgid "{{amountStr}} for Mercado Livre Brazil Gift Card" -msgstr "" +msgstr "{{amountStr}} na karcie podarunkowej Mercado Livre Brazil" #: www/views/preferencesBwsUrl.html:21 msgid "{{appName}} depends on Bitcore Wallet Service (BWS) for blockchain information, networking and Copayer synchronization. The default configuration points to https://bws.bitpay.com (BitPay's public BWS instance)." @@ -3624,7 +3698,7 @@ msgstr "{{fee}} zostanie potrącone jako prowizja sieci bitcoin." #: www/views/confirm.html:85 msgid "{{tx.txp[wallet.id].feeRatePerStr}} of the sending amount" -msgstr "" +msgstr "{{tx.txp[wallet.id].feeRatePerStr}} wysyłanej kwoty" #: www/views/walletDetails.html:218 msgid "{{updatingTxHistoryProgress}} transactions downloaded" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} transakcje pobrane" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-z-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Społeczność" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Reddit Bitcoin Cash" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Twitter Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Poznaj Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Gry Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Aktualności" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Pula kopalni" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Narzędzia" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Wykresy kursu Bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Darmowa Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Twoje portfele Bitcoin są gotowe!" + diff --git a/i18n/po/pt-BR/template-pt-BR.po b/i18n/po/pt-BR/template-pt-BR.po index c83259bf9..6879b52c4 100644 --- a/i18n/po/pt-BR/template-pt-BR.po +++ b/i18n/po/pt-BR/template-pt-BR.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Portuguese, Brazilian\n" "Language: pt\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Comprar & Vender Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Comprar Bitcoin" @@ -619,10 +620,14 @@ msgstr "A conectar ao Glidera..." msgid "Connection reset by peer" msgstr "Ligação redefinida pelo mesmo nível" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Contactos" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Salvou os endereços usados com frequência" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Continuar" @@ -823,7 +828,7 @@ msgstr "Criar carteira partilhada" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Criar carteira bitcoin" @@ -2533,6 +2538,14 @@ msgstr "Procurar transações" msgid "Search or enter bitcoin address" msgstr "Procure ou digite o endereço bitcoin" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Área de transferência" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "A sua área de transferência está vazia" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Procurar transações" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Enviar por E-mail" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Enviar De" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Enviar para" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Colar na área de trabalho" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Colar endereço" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Transferência de carteira para carteira" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Digitalizar o código QR" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envie Bitcoin mais rápido!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Envie Bitcoin mais rápido!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Salvar endereços usados com frequência e enviar Bitcoin com apenas um toque" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Adicionar o seu primeiro contato" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Sua carteira de Bitcoin está vazia" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Para começar, compre Bitcoin Cash (BCH) ou Bitcoin Core (BTC) ou compartilhe o seu endereço." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Você pode receber bitcoin de qualquer carteira ou serviço." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Para começar, você precisa criar uma carteira de bitcoins e obter alguns bitcoins." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Compre Bitcoin agora" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Mostrar meu endereço" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Quantidade Máxima de envio" @@ -3030,7 +3104,7 @@ msgstr "Para começar, compre bitcoins ou compartilhe seu endereço. Você pode #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "Para começar, você precisa criar uma carteira de bitcoins e obter alguns bitcoins." +msgstr "Para começar, você precisará criar uma carteira e obter algum bitcoin." #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3636,3 +3710,51 @@ msgstr "Transações de {{updatingTxHistoryProgress}} transferidas" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-de-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Comunidade" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Twitter Bitcoin.com" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Explore Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Jogos Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Notícias" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Pool de mineração" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Ferramentas" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Gráficos de preço do Bitcoin" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash grátis" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "As suas carteiras de Bitcoin estão prontas!" + diff --git a/i18n/po/ru/template-ru.po b/i18n/po/ru/template-ru.po index 074fa9937..a9d5d2970 100644 --- a/i18n/po/ru/template-ru.po +++ b/i18n/po/ru/template-ru.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Russian\n" "Language: ru\n" -"PO-Revision-Date: 2018-07-04 09:27\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -79,7 +79,7 @@ msgstr "Номер учётной записи" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "Мгновенные транзакции с низкой оплатой" +msgstr "Мгновенные транзакции с низкой комиссией" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "Купить & продать биткойн" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "Купить биткойн" @@ -619,10 +620,14 @@ msgstr "Подключение к Glidera..." msgid "Connection reset by peer" msgstr "Соединение сброшено другой стороной" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "Контакты" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Сохраненные часто используемые адреса" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "Продолжить" @@ -823,7 +828,7 @@ msgstr "Создать общий кошелёк" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "Создать биткойн-кошелёк" @@ -2533,6 +2538,14 @@ msgstr "Поиск транзакций" msgid "Search or enter bitcoin address" msgstr "Найти или ввести биткойн-адрес" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "Буфер обмена" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "Буфер обмена пуст" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "Поиск транзакций" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "Отправить на email" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "Отправить от" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "Получатель" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "Вставить из буфера обмена" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "Вставить адрес" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "Перевод с кошелька на кошелек" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "Сканировать QR код" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Отправляйте биткойны еще быстрее!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "Отправляйте биткойны еще быстрее!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "Сохраняйте часто используемые адреса кошельков и отправляйте на них биткойны одним нажатием" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "Добавить первый контакт" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "Ваш кошелёк пуст" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "Чтобы начать работу, купите Bitcoin Cash (BCH) или Bitcoin Core (BTC), или поделитесь вашим адресом." + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "Вы можете получать биткойны с любого кошелька или сервиса." + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "Чтобы начать работу, вам нужно создать кошелёк и получить биткойн." + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "Купить биткойны сейчас" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "Показать мой адрес" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "Отправить макс. сумму" @@ -3636,3 +3710,51 @@ msgstr "{{updatingTxHistoryProgress}} транзакций загружено" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}-из-{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "Сообщество" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "Обзор Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Игры Bitcoin Cash" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "Новости" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "Пул для майнинга" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "Инструменты" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "Динамика курса биткойна" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "Bitcoin Cash бесплатно" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "Ваши кошельки готовы!" + diff --git a/i18n/po/sv-SE/template-sv-SE.po b/i18n/po/sv-SE/template-sv-SE.po index bc496d6d5..7ffdda946 100644 --- a/i18n/po/sv-SE/template-sv-SE.po +++ b/i18n/po/sv-SE/template-sv-SE.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Swedish\n" "Language: sv\n" -"PO-Revision-Date: 2018-07-04 03:58\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "" @@ -619,10 +620,14 @@ msgstr "" msgid "Connection reset by peer" msgstr "" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "" @@ -823,7 +828,7 @@ msgstr "" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "" @@ -2533,6 +2538,14 @@ msgstr "" msgid "Search or enter bitcoin address" msgstr "" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "" + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "" + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "" + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "" @@ -3636,3 +3710,51 @@ msgstr "" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "" + diff --git a/i18n/po/template.pot b/i18n/po/template.pot index 7406fcb74..7caae0168 100644 --- a/i18n/po/template.pot +++ b/i18n/po/template.pot @@ -72,6 +72,26 @@ msgstr "" msgid "Instant transactions with low fees" msgstr "" +#: www/views/walletSelector.html:49 +msgid "Insufficient funds" +msgstr "" + +#: www/views/amount.html:42 +msgid "Change Currency" +msgstr "" + +#: www/views/amount.html:49 +msgid "Available Funds" +msgstr "" + +#: www/views/amount.html:59 +msgid "Use All Available Funds" +msgstr "" + +#: www/views/amount.html:99 +msgid "Next" +msgstr "" + #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" msgstr "" @@ -197,6 +217,20 @@ msgstr "" msgid "Alternative Currency" msgstr "" +#: www/views/tab-settings.html:75 +msgid "Price Display" +msgstr "" + +#: src/js/controllers/tab-settings.js:19 +#: www/views/preferencesPriceDisplay.html:12 +msgid "Fiat" +msgstr "" + +#: src/js/controllers/tab-settings.js:19 +#: www/views/preferencesPriceDisplay.html:15 +msgid "Cryptocurrency" +msgstr "" + #: src/js/controllers/buyAmazon.js:98 msgid "Amazon.com is not available at this moment. Please try back later." msgstr "" @@ -428,6 +462,7 @@ msgid "Buy & Sell Bitcoin" msgstr "" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "" @@ -652,6 +687,7 @@ msgstr "" #: src/js/controllers/copayers.js:79 #: src/js/controllers/export.js:193 +#: src/js/controllers/confirm.js:41 #: www/views/includes/copyToClipboard.html:4 msgid "Copied to clipboard" msgstr "" @@ -1271,6 +1307,7 @@ msgstr "" #: www/views/modals/txp-details.html:74 #: www/views/topup.html:34 #: www/views/tx-details.html:52 +#: www/views/review.html:22 msgid "From" msgstr "" @@ -1331,10 +1368,6 @@ msgid "Get news and updates from BitPay" msgstr "" #: www/views/onboarding/welcome.html:8 -msgctxt "button" -msgid "Get started" -msgstr "" - #: www/views/bitpayCard.html:49 msgid "Get started" msgstr "" @@ -2158,6 +2191,10 @@ msgstr "" msgid "Payment Sent" msgstr "" +#: www/views/includes/slideToAcceptSuccess.html:12 +msgid "Share this transaction" +msgstr "" + #: www/views/modals/txp-details.html:32 msgid "Payment accepted, but not yet broadcasted" msgstr "" @@ -2175,7 +2212,7 @@ msgid "Payment details" msgstr "" #: www/views/modals/paypro.html:6 -msgid "Payment request" +msgid "Payment Request" msgstr "" #: www/views/mercadoLibreCards.html:22 @@ -2611,7 +2648,7 @@ msgid "Paste Address" msgstr "" #: www/views/tab-send.html:27 -msgid "Wallet to Wallet Transfer" +msgid "Transfer between wallets" msgstr "" #: www/views/tab-send.html:35 @@ -2622,10 +2659,6 @@ msgstr "" msgid "Send Bitcoin faster!" msgstr "" -#: www/views/tab-send.html:46 -msgid "Send Bitcoin faster!" -msgstr "" - #: www/views/tab-send.html:50 msgid "Save frequently used addresses and send them Bitcoin in just one tap" msgstr "" @@ -2647,6 +2680,8 @@ msgid "You can receive bitcoin from any wallet or service." msgstr "" #: www/views/tab-send.html:72 +#: www/views/shapeshift.html:23 +#: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." msgstr "" @@ -3051,6 +3086,14 @@ msgstr "" msgid "This bitcoin payment request has expired." msgstr "" +#: www/views/review.html:55 +msgid "Payment expires:" +msgstr "" + +#: www/views/review.html:56 +msgid "Payment request has expired" +msgstr "" + #: www/views/join.html:133 #: www/views/tab-create-personal.html:103 #: www/views/tab-create-shared.html:132 @@ -3092,10 +3135,6 @@ msgstr "" msgid "To get started, buy bitcoin or share your address. You can receive bitcoin from any wallet or service." msgstr "" -#: www/views/tab-send.html:33 -msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "" - #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" msgstr "" @@ -3108,6 +3147,26 @@ msgstr "" msgid "Top up {{amountStr}} to debit card ({{cardLastNumber}})" msgstr "" +#: www/views/shapeshift.html:30 +msgid "Start ShapeShift" +msgstr "" + +#: www/views/shapeshift.html:30 +msgid "Exchange your BTC to BCH in minutes." +msgstr "" + +#: www/views/shapeshift.html:30 +msgid "To start the process you need to add funds to your wallet." +msgstr "" + +#: www/views/shapeshift.html:30 +msgid "he process is fast and you will receive the exchanged amount in your wallet." +msgstr "" + +#: www/views/shapeshift.html:34 +msgid "This service is provided by the third-party ShapeShift, who will charge a small fee for the service. The fee will be shown before you start the transaction." +msgstr "" + #: www/views/buyAmazon.html:61 #: www/views/buyMercadoLibre.html:60 #: www/views/modals/wallet-balance.html:23 @@ -3700,16 +3759,68 @@ msgstr "" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "" + +#: src/js/controllers/amount.js:49 +msgid "Address does not contain currency information, please make sure you are sending the correct currency." +msgstr "" + #: www/views/review.html:4 msgid "Review Transaction" msgstr "" -#: www/views/review.html:14 +#: src/js/controllers/review.controller.js:36 msgid "You are sending" msgstr "" -#: www/views/review.html:22 -msgid "From:" +#: src/js/controllers/review.controller.js:66 +msgid "You are shifting" msgstr "" #: www/views/review.html:36 @@ -3720,6 +3831,13 @@ msgstr "" msgid "Add personal note" msgstr "" +#: www/views/review.html:87 +msgid "Suggested by merchant:" +msgstr "" + +#: src/js/controllers/review.controller.js:37 +msgid "Enter text here" +msgstr "" #: www/views/review.html:57 msgid "Personal note:" @@ -3727,4 +3845,8 @@ msgstr "" #: www/views/review.html:69 msgid "Less than 1 cent" +msgstr "" + +#: src/js/services/incomingData.js:129 +msgid "This invoice is no longer accepting payments" msgstr "" \ No newline at end of file diff --git a/i18n/po/vi/template-vi.po b/i18n/po/vi/template-vi.po index d965b6ee8..ef9db2029 100644 --- a/i18n/po/vi/template-vi.po +++ b/i18n/po/vi/template-vi.po @@ -11,11 +11,11 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Vietnamese\n" "Language: vi\n" -"PO-Revision-Date: 2018-07-04 03:58\n" +"PO-Revision-Date: 2018-07-27 08:44\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" -msgstr "(Đáng tin cậy)" +msgstr "(Tin cậy)" #: www/views/includes/txp.html:23 #: www/views/includes/walletHistory.html:64 @@ -28,7 +28,7 @@ msgstr "* A payment proposal can be deleted if 1) you are the creator, and no ot #: www/views/tx-details.html:82 msgid "- {{btx.feeRateStr}} of the transaction" -msgstr "{{btx.feeRateStr}} của giao dịch" +msgstr "- {{btx.feeRateStr}} of the transaction" #: www/views/modals/txp-details.html:102 msgid "- {{tx.feeRateStr}} of the transaction" @@ -41,7 +41,9 @@ msgstr "Xếp hạng 5 sao giúp chúng tôi để {{appName}} đến tay nhiề #: www/views/mercadoLibre.html:18 #: www/views/mercadoLibre.html:40 msgid "Only redeemable on Mercado Livre (Brazil)" -msgstr "Only redeemable on Mercado Livre (Brazil)" +msgstr "Only redeemable on \n" +"Mercado Livre (Brazil) #\n\n" +"2" #: src/js/controllers/feedback/send.js:27 #: www/views/feedback/complete.html:21 @@ -54,7 +56,8 @@ msgstr "A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size all #: src/js/controllers/confirm.js:395 msgid "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided." -msgstr "A total of {{amountBelowFeeStr}} were excluded. These funds come from UTXOs smaller than the network fee provided." +msgstr "Tổng cộng {{amountBelowFeeStr}} đã bị loại trừ. Số tiền này đến từ UTXOs nhỏ hơn chi phí mạng cung cấp.#\n" +"1" #: src/js/controllers/preferencesAbout.js:6 #: www/views/tab-settings.html:156 @@ -79,7 +82,7 @@ msgstr "Account Number" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "" +msgstr "2" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -124,338 +127,339 @@ msgstr "Add account" #: www/views/tab-create-personal.html:62 #: www/views/tab-create-shared.html:91 msgid "Add an optional password to secure the recovery phrase" -msgstr "" +msgstr "Add a password option to allow a secure cluster" #: www/views/includes/incomingDataMenu.html:41 msgid "Add as a contact" -msgstr "" +msgstr "Thêm như một liên hệ" #: src/js/controllers/confirm.js:424 msgid "Add description" -msgstr "" +msgstr "Thêm mô tả" #: www/views/topup.html:6 msgid "Add funds" -msgstr "" +msgstr "Nạp tiền" #: src/js/services/bitpayAccountService.js:78 msgid "Add this BitPay account ({{email}})?" -msgstr "" +msgstr "Thêm BitPay ({{email}}) tài khoản này?" #: www/views/add.html:3 msgid "Add wallet" -msgstr "" +msgstr "Thêm ví" #: www/views/addressbook.view.html:26 #: www/views/customAmount.html:28 #: www/views/modals/paypro.html:24 msgid "Address" -msgstr "" +msgstr "Địa chỉ" #: www/views/addressbook.html:6 #: www/views/tab-settings.html:13 msgid "Address Book" -msgstr "" +msgstr "Sổ địa chỉ" #: www/views/preferencesInformation.html:41 msgid "Address Type" -msgstr "" +msgstr "Loại địa chỉ" #: www/views/addresses.html:64 msgid "Addresses With Balance" -msgstr "" +msgstr "Địa chỉ với số dư" #: www/views/tab-settings.html:149 msgid "Advanced" -msgstr "" +msgstr "Nâng cao" #: www/views/advancedSettings.html:3 msgid "Advanced Settings" -msgstr "" +msgstr "Cài đặt nâng cao" #: www/views/bitpayCard.html:62 msgid "All" -msgstr "" +msgstr "Tất cả" #: www/views/allAddresses.html:3 msgid "All Addresses" -msgstr "" +msgstr "Tất cả địa chỉ" #: www/views/modals/wallet-balance.html:18 msgid "All of your bitcoin wallet balance may not be available for immediate spending." -msgstr "" +msgstr "Tất cả số dư ví bitcoin của bạn có thể không có sẵn cho chi tiêu ngay lập tức." #: www/views/tab-receive.html:25 msgid "All signing devices must be added to this multisig wallet before bitcoin addresses can be created." -msgstr "" +msgstr "All contract device will be added to this multisig before the bitcoin address has been created." #: www/views/tab-scan.html:21 msgid "Allow Camera Access" -msgstr "" +msgstr "Allow camera access" #: www/views/onboarding/notifications.html:7 msgid "Allow notifications" -msgstr "" +msgstr "Allow notification" #: www/views/onboarding/disclaimer.html:14 msgid "Almost done! Let's review." -msgstr "" +msgstr "Most as completed! We see review." #: www/views/preferencesAltCurrency.html:4 #: www/views/tab-settings.html:79 msgid "Alternative Currency" -msgstr "" +msgstr "Money Currency instead" #: src/js/controllers/buyAmazon.js:98 msgid "Amazon.com is not available at this moment. Please try back later." -msgstr "" +msgstr "Amazon.com is not available at this time. Please try again again." #: www/views/amount.html:44 #: www/views/customAmount.html:34 #: www/views/includes/output.html:7 msgid "Amount" -msgstr "" +msgstr "Quantity" #: src/js/services/bwcError.js:110 msgid "Amount below minimum allowed" -msgstr "" +msgstr "Maximum amount of the minimum amount" #: src/js/controllers/confirm.js:216 msgid "Amount too big" -msgstr "" +msgstr "Amount too large" #: www/views/includes/walletHistory.html:31 msgid "Amount too low to spend" -msgstr "" +msgstr "Amount too low for standard" #: src/js/controllers/tab-home.js:147 msgid "An update to this app is available. For your security, please update to the latest version." -msgstr "" +msgstr "Hotel have a Update for this application. To preserve your password, please please update the latest version." #: www/views/backupWarning.html:14 msgid "Anyone with your backup phrase can access or spend your bitcoin." -msgstr "" +msgstr "Każdy, kto ma Twoją kluczową là một trong những điều tuyệt vời nhất." #: www/views/addresses.html:94 msgid "Approximate Bitcoin network fee to transfer wallet's balance (with normal priority)" -msgstr "" +msgstr "La taxa approssimativa della rete Bitcoin cho mỗi lần gửi tiền theo yêu cầu của bạn" #: www/views/backupWarning.html:10 msgid "Are you being watched?" -msgstr "" +msgstr "Chúng tôi vigilen?" #: src/js/controllers/preferencesExternal.js:15 msgid "Are you being watched? Anyone with your recovery phrase can access or spend your bitcoin." -msgstr "" +msgstr "You are tracking? Bất cứ ai có thể phục hồi từ bạn, bạn có thể truy cập hoặc bitcoin chi tiêu của bạn." #: src/js/controllers/copayers.js:56 msgid "Are you sure you want to cancel and delete this wallet?" -msgstr "" +msgstr "Are you sure you want to cancel and remove this video?" #: src/js/controllers/addressbookView.js:37 msgid "Are you sure you want to delete this contact?" -msgstr "" +msgstr "Bạn có chắc chắn muốn xóa địa chỉ liên hệ này không?" #: src/js/controllers/preferencesDelete.js:25 msgid "Are you sure you want to delete this wallet?" -msgstr "" +msgstr "Are you sure you want to delete this wallet?" #: src/js/controllers/modals/txpDetails.js:154 msgid "Are you sure you want to reject this transaction?" -msgstr "" +msgstr "Are you sure you want to reject this transaction?" #: src/js/controllers/modals/txpDetails.js:171 msgid "Are you sure you want to remove this transaction?" -msgstr "" +msgstr "Are you sure you want to remove this transaction?" #: src/js/controllers/onboarding/backupRequest.js:23 msgid "Are you sure you want to skip it?" -msgstr "" +msgstr "Are you sure you want to skip it?" #: www/views/modals/bitpay-card-confirmation.html:4 msgid "Are you sure you would like to log out of your BitPay Card account?" -msgstr "" +msgstr "Bạn có chắc chắn muốn đăng xuất khỏi tài khoản Thẻ BitPay của mình không?" #: src/js/controllers/preferencesBitpayCard.js:7 #: src/js/controllers/preferencesBitpayServices.js:20 msgid "Are you sure you would like to remove your BitPay Card ({{lastFourDigits}}) from this device?" -msgstr "" +msgstr "Are you sure you would like to remove your BitPay Card ({{lastFourDigits}}) from this device?" #: www/views/includes/walletInfo.html:10 msgid "Auditable" -msgstr "" +msgstr "Auditable" #: www/views/modals/wallet-balance.html:42 msgid "Available" -msgstr "" +msgstr "Available" #: www/views/includes/available-balance.html:3 msgid "Available Balance" -msgstr "" +msgstr "Available Balance" #: www/views/modals/chooseFeeLevel.html:24 #: www/views/preferencesFee.html:15 msgid "Average confirmation time" -msgstr "" +msgstr "Average confirmation time" #: www/views/join.html:143 #: www/views/tab-create-personal.html:113 #: www/views/tab-create-shared.html:142 #: www/views/tab-import-phrase.html:51 msgid "BIP32 path for address derivation" -msgstr "" +msgstr "Đường dẫn BIP32 cho dẫn xuất địa chỉ" #: www/views/cashScan.html:25 msgid "BTC wallets" -msgstr "" +msgstr "Ví BTC" #: www/views/preferences.html:34 msgid "Backup" -msgstr "" +msgstr "Backup" #: www/views/includes/backupNeededPopup.html:7 msgid "Backup Needed" -msgstr "" +msgstr "Backup Needed" #: src/js/controllers/lockSetup.js:87 msgid "Backup all livenet wallets before using this function" -msgstr "" +msgstr "Backup all livenet wallets before using this function" #: src/js/controllers/cashScan.js:64 #: www/views/includes/walletListSettings.html:12 #: www/views/preferences.html:36 msgid "Backup needed" -msgstr "" +msgstr "Cần sao lưu" #: www/views/includes/backupNeededPopup.html:9 msgid "Backup now" -msgstr "" +msgstr "Sao lưu ngay" #: www/views/onboarding/backupRequest.html:11 #: www/views/tab-export-file.html:89 msgid "Backup wallet" -msgstr "" +msgstr "Backup wallet" #: src/js/controllers/lockSetup.js:84 msgid "Backup your wallet before using this function" -msgstr "" +msgstr "Backup your wallet before using this function" #: src/js/services/profileService.js:446 msgid "Bad wallet invitation" -msgstr "" +msgstr "Bad wallet invitation" #: www/views/preferencesInformation.html:102 msgid "Balance By Address" -msgstr "" +msgstr "Balance By Address" #: www/views/includes/confirmBackupPopup.html:7 msgid "Be sure to store your recovery phrase in a secure place. If this app is deleted, your money cannot be recovered without it." -msgstr "" +msgstr "Hãy chắc chắn lưu trữ cụm từ khôi phục của bạn ở một nơi an toàn. Nếu ứng dụng này bị xóa, tiền của bạn không thể được phục hồi mà không có nó." #: www/views/preferencesBitpayServices.html:9 msgid "BitPay Visa® Cards" -msgstr "" +msgstr "BitPay Visa & reg; thẻ" #: www/views/addressbook.add.html:38 #: www/views/includes/incomingDataMenu.html:29 msgid "Bitcoin Address" -msgstr "" +msgstr "Bitcoin Address" #: www/views/cashScan.html:4 msgid "Bitcoin Cash (BCH) Balances" -msgstr "" +msgstr "Bitcoin Cash (BCH) Balances" #: www/views/preferencesCash.html:3 #: www/views/tab-settings.html:47 msgid "Bitcoin Cash Support" -msgstr "" +msgstr "Bitcoin Cash Support" #: www/views/tab-home.html:98 #: www/views/tab-settings.html:115 msgid "Bitcoin Cash Wallets" -msgstr "" +msgstr "Bitcoin Cash Wallets" #: www/views/modals/chooseFeeLevel.html:4 #: www/views/preferencesFee.html:4 #: www/views/tab-settings.html:90 msgid "Bitcoin Network Fee Policy" -msgstr "" +msgstr "Bitcoin Network Fee Policy" #: www/views/tab-home.html:83 #: www/views/tab-settings.html:107 msgid "Bitcoin Core Wallets" -msgstr "" +msgstr "Bitcoin Core Wallets" #: src/js/services/incomingData.js:151 msgid "Bitcoin cash Payment" -msgstr "" +msgstr "Bitcoin cash Payment" #: www/views/onboarding/tour.html:31 msgid "Bitcoin is a currency." -msgstr "" +msgstr "Bitcoin is a currency." #: www/views/onboarding/disclaimer.html:15 msgid "Bitcoin is different – it cannot be safely held with a bank or web service." -msgstr "" +msgstr "–." #: www/views/onboarding/tour.html:18 msgid "Bitcoin is secure,
digital money." -msgstr "" +msgstr "Bitcoin là an toàn,
tiền kỹ thuật số." #: www/views/preferencesFee.html:11 msgid "Bitcoin transactions include a fee collected by miners on the network." -msgstr "" +msgstr "Bitcoin transactions include a fee collected by miners on the network." #: www/views/buyAmazon.html:108 msgid "Bought {{amountUnitStr}}" -msgstr "" +msgstr "Bought {{amountUnitStr}}" #: www/views/modals/txp-details.html:36 msgid "Broadcast Payment" -msgstr "" +msgstr "Broadcast Payment" #: src/js/controllers/modals/txpDetails.js:64 #: src/js/controllers/tx-details.js:81 msgid "Broadcasted" -msgstr "" +msgstr "Broadcasted" #: src/js/services/onGoingProcess.js:11 msgid "Broadcasting transaction" -msgstr "" +msgstr "Broadcasting transaction" #: www/views/unsupported.html:6 msgid "Browser unsupported" -msgstr "" +msgstr "Browser unsupported" #: www/views/buyAmazon.html:5 #: www/views/buyMercadoLibre.html:6 msgid "Buy" -msgstr "" +msgstr "Buy" #: www/views/includes/buyAndSellCard.html:3 msgid "Buy & Sell Bitcoin" -msgstr "" +msgstr "Buy & Sell Bitcoin" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" -msgstr "" +msgstr "Buy Bitcoin" #: www/views/mercadoLibre.html:22 #: www/views/mercadoLibre.html:50 msgid "Buy a Gift Card" -msgstr "" +msgstr "Buy a Gift Card" #: src/js/controllers/buyAmazon.js:334 msgid "Buy from" -msgstr "" +msgstr "Buy from" #: src/js/services/onGoingProcess.js:40 msgid "Buying Bitcoin..." -msgstr "" +msgstr "Mua Bitcoin..." #: src/js/services/onGoingProcess.js:12 msgid "Calculating fee" -msgstr "" +msgstr "Phí tính toán" #: src/js/controllers/buyAmazon.js:313 #: src/js/controllers/buyMercadoLibre.js:307 @@ -474,65 +478,65 @@ msgstr "" #: www/views/modals/bitpay-card-confirmation.html:8 #: www/views/modals/confirmation.html:13 msgid "Cancel" -msgstr "" +msgstr "Hủy bỏ" #: www/views/copayers.html:36 msgid "Cancel invitation" -msgstr "" +msgstr "Hủy lời mời" #: src/js/controllers/onboarding/tour.js:52 msgid "Cannot Create Wallet" -msgstr "" +msgstr "Không thể tạo Wallet" #: src/js/services/profileService.js:442 msgid "Cannot join the same wallet more that once" -msgstr "" +msgstr "Cannot join the same wallet more that once" #: www/views/includes/bitpayCardsCard.html:2 msgid "Cards" -msgstr "" +msgstr "Cards" #: www/views/modals/paypro.html:30 msgid "Certified by" -msgstr "" +msgstr "Certified by" #: www/views/preferencesExternal.html:19 msgid "Check installation and retry." -msgstr "" +msgstr "Check installation and retry." #: www/views/tab-import-file.html:4 msgid "Choose a backup file from your computer" -msgstr "" +msgstr "Chọn tệp sao lưu từ máy tính của bạn" #: www/views/modals/wallets.html:9 msgid "Choose your destination wallet" -msgstr "" +msgstr "Choose your destination wallet" #: www/views/modals/wallets.html:10 msgid "Choose your source wallet" -msgstr "" +msgstr "Chọn ví nguồn của bạn" #: www/views/backup.html:61 msgid "Clear" -msgstr "" +msgstr "Clear" #: www/views/preferencesHistory.html:24 msgid "Clear cache" -msgstr "" +msgstr "Clear cache" #: src/js/controllers/confirm.js:373 #: src/js/controllers/modals/txpDetails.js:49 msgid "Click to accept" -msgstr "" +msgstr "Click to accept" #: src/js/controllers/confirm.js:367 msgid "Click to pay" -msgstr "" +msgstr "Click to pay" #: src/js/controllers/confirm.js:379 #: src/js/controllers/modals/txpDetails.js:42 msgid "Click to send" -msgstr "" +msgstr "Click to send" #: www/views/customAmount.html:4 #: www/views/modals/mercadolibre-card-details.html:3 @@ -542,28 +546,28 @@ msgstr "" #: www/views/modals/wallet-balance.html:3 #: www/views/modals/wallets.html:5 msgid "Close" -msgstr "" +msgstr "Close" #: www/views/includes/cash.html:2 #: www/views/preferencesInformation.html:17 msgid "Coin" -msgstr "" +msgstr "Coin" #: www/views/preferences.html:22 msgid "Color" -msgstr "" +msgstr "Màu" #: www/views/preferencesAbout.html:21 msgid "Commit hash" -msgstr "" +msgstr "Commit hash" #: www/views/preferences.html:49 msgid "Complete the backup process to use this option" -msgstr "" +msgstr "Complete the backup process to use this option" #: www/views/bitpayCard.html:93 msgid "Completed" -msgstr "" +msgstr "Completed" #: src/js/controllers/buyAmazon.js:311 #: src/js/controllers/buyMercadoLibre.js:305 @@ -575,95 +579,99 @@ msgstr "" #: www/views/confirm.html:4 #: www/views/onboarding/collectEmail.html:32 msgid "Confirm" -msgstr "" +msgstr "Confirm" #: www/views/modals/terms.html:26 #: www/views/onboarding/disclaimer.html:44 msgid "Confirm & Finish" -msgstr "" +msgstr "Confirm & Finish" #: www/views/buyAmazon.html:90 msgid "Confirm purchase" -msgstr "" +msgstr "Confirm purchase" #: www/views/modals/pin.html:10 msgid "Confirm your PIN" -msgstr "" +msgstr "Confirm your PIN" #: src/js/services/walletService.js:1033 msgid "Confirm your new spending password" -msgstr "" +msgstr "Confirm your new spending password" #: www/views/tx-details.html:98 msgid "Confirmations" -msgstr "" +msgstr "Confirmations" #: www/views/bitpayCard.html:68 #: www/views/modals/wallet-balance.html:61 msgid "Confirming" -msgstr "" +msgstr "Xác nhận" #: www/views/bitpayCardIntro.html:37 msgid "Connect my BitPay Card" -msgstr "" +msgstr "Kết nối thẻ BitPay của tôi" #: src/js/services/onGoingProcess.js:13 msgid "Connecting to Coinbase..." -msgstr "" +msgstr "Connecting to Coinbase..." #: src/js/services/onGoingProcess.js:14 msgid "Connecting to Glidera..." -msgstr "" +msgstr "Đang kết nối với Glidera ..." #: src/js/services/bwcError.js:53 msgid "Connection reset by peer" -msgstr "" +msgstr "Đặt lại kết nối theo ngang hàng" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" -msgstr "" +msgstr "Contacts" + +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "Save the regular usage" #: www/views/onboarding/notifications.html:9 msgid "Continue" -msgstr "" +msgstr "Continue" #: www/views/preferencesLanguage.html:26 msgid "Contribute Translations" -msgstr "" +msgstr "Contribute Translations" #: src/js/controllers/confirm.js:130 msgid "Copay only supports Bitcoin Cash using new version numbers addresses" -msgstr "" +msgstr "Copay chỉ hỗ trợ Bitcoin Cash bằng cách sử dụng số phiên bản mới" #: src/js/services/bwcError.js:62 msgid "Copayer already in this wallet" -msgstr "" +msgstr "Copayer already in this wallet" #: src/js/services/bwcError.js:77 msgid "Copayer already voted on this spend proposal" -msgstr "" +msgstr "Coper is this option" #: src/js/services/bwcError.js:107 msgid "Copayer data mismatch" -msgstr "" +msgstr "Dữ liệu Copayer không khớp" #: www/views/includes/walletActivity.html:2 msgid "Copayer joined" -msgstr "" +msgstr "Copayer joined" #: www/views/preferencesInformation.html:94 msgid "Copayer {{$index}}" -msgstr "" +msgstr "Copayer {{$index}}" #: src/js/controllers/copayers.js:79 #: src/js/controllers/export.js:193 #: www/views/includes/copyToClipboard.html:4 msgid "Copied to clipboard" -msgstr "" +msgstr "Sao chép vào clipboard" #: www/views/tab-export-file.html:94 msgid "Copy this text as it is to a safe place (notepad or email)" -msgstr "" +msgstr "Copy this text as it is to a safe place (notepad or email)" #: www/views/includes/incomingDataMenu.html:51 #: www/views/includes/incomingDataMenu.html:70 @@ -671,35 +679,35 @@ msgstr "" #: www/views/includes/logOptions.html:9 #: www/views/tab-export-file.html:78 msgid "Copy to clipboard" -msgstr "" +msgstr "Sao chép vào clipboard" #: src/js/controllers/buyMercadoLibre.js:102 msgid "Could not access Gift Card Service" -msgstr "" +msgstr "Could not access Gift Card Service" #: www/views/tab-import-phrase.html:2 msgid "Could not access the wallet at the server. Please check:" -msgstr "" +msgstr "Could not access the wallet at the server. Please check:" #: src/js/controllers/buyAmazon.js:102 msgid "Could not access to Amazon.com" -msgstr "" +msgstr "Could not access to Amazon.com" #: src/js/services/profileService.js:511 msgid "Could not access wallet" -msgstr "" +msgstr "Could not access wallet" #: src/js/controllers/confirm.js:210 msgid "Could not add message to imported wallet without shared encrypting key" -msgstr "" +msgstr "Could not add message to imported wallet without shared encrypting key" #: src/js/controllers/modals/txpDetails.js:199 msgid "Could not broadcast payment" -msgstr "" +msgstr "Could not broadcast payment" #: src/js/services/bwcError.js:41 msgid "Could not build transaction" -msgstr "" +msgstr "Cannot build transaction" #: src/js/services/walletService.js:854 msgid "Could not create address" @@ -823,7 +831,7 @@ msgstr "" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "" @@ -916,7 +924,7 @@ msgstr "" #: www/views/modals/mercadolibre-card-details.html:6 #: www/views/topup.html:45 msgid "Details" -msgstr "" +msgstr "Chi tiết" #: src/js/controllers/lockSetup.js:9 #: src/js/controllers/tab-settings.js:65 @@ -2533,6 +2541,14 @@ msgstr "" msgid "Search or enter bitcoin address" msgstr "" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "" @@ -2591,9 +2607,70 @@ msgid "Send by email" msgstr "" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "" + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "" + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "" + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "" @@ -3636,3 +3713,51 @@ msgstr "" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "" + diff --git a/i18n/po/zh-CN/template-zh-CN.po b/i18n/po/zh-CN/template-zh-CN.po index 8c274b798..eb8304e89 100644 --- a/i18n/po/zh-CN/template-zh-CN.po +++ b/i18n/po/zh-CN/template-zh-CN.po @@ -11,7 +11,7 @@ msgstr "" "Last-Translator: emilold\n" "Language-Team: Chinese Simplified\n" "Language: zh\n" -"PO-Revision-Date: 2018-07-04 03:57\n" +"PO-Revision-Date: 2018-07-27 08:43\n" #: www/views/modals/paypro.html:34 msgid "(Trusted)" @@ -79,7 +79,7 @@ msgstr "帐号" #: www/views/tab-home.html:61 msgid "Instant transactions with low fees" -msgstr "" +msgstr "以较低费用进行即时交易" #: www/views/preferencesBitpayServices.html:23 msgid "Accounts" @@ -363,12 +363,12 @@ msgstr "比特币地址" #: www/views/cashScan.html:4 msgid "Bitcoin Cash (BCH) Balances" -msgstr "" +msgstr "Bitcoin Cash (BCH) 余额" #: www/views/preferencesCash.html:3 #: www/views/tab-settings.html:47 msgid "Bitcoin Cash Support" -msgstr "" +msgstr "Bitcoin Cash 支持" #: www/views/tab-home.html:98 #: www/views/tab-settings.html:115 @@ -384,7 +384,7 @@ msgstr "比特币网络手续费策略" #: www/views/tab-home.html:83 #: www/views/tab-settings.html:107 msgid "Bitcoin Core Wallets" -msgstr "" +msgstr "Bitcoin Core 钱包" #: src/js/services/incomingData.js:151 msgid "Bitcoin cash Payment" @@ -437,6 +437,7 @@ msgid "Buy & Sell Bitcoin" msgstr "购买或出售比特币" #: www/views/tab-send.html:35 +#: src/js/services/buyAndSellService.js:26 msgid "Buy Bitcoin" msgstr "购买比特币" @@ -619,10 +620,14 @@ msgstr "正在连接 Glidera..." msgid "Connection reset by peer" msgstr "连接被对方重置" -#: www/views/tab-send.html:45 +#: www/views/tab-send.html:85 msgid "Contacts" msgstr "联系人" +#: www/views/tab-send.html:86 +msgid "Saved frequently used addresses" +msgstr "保存的常用地址" + #: www/views/onboarding/notifications.html:9 msgid "Continue" msgstr "继续" @@ -653,7 +658,7 @@ msgstr "Copayer 加入" #: www/views/preferencesInformation.html:94 msgid "Copayer {{$index}}" -msgstr "" +msgstr "Copayer {{$index}}" #: src/js/controllers/copayers.js:79 #: src/js/controllers/export.js:193 @@ -823,7 +828,7 @@ msgstr "创建自己的免费钱包" #: www/views/onboarding/tour.html:51 #: www/views/tab-home.html:75 -#: www/views/tab-send.html:36 +#: www/views/tab-send.html:75 msgid "Create bitcoin wallet" msgstr "创建比特币的钱包" @@ -977,7 +982,7 @@ msgstr "已达到空地址限制。无法生成新的地址。" #: www/views/preferencesCash.html:17 msgid "Enable Bitcoin Cash wallet creation and operation within the App." -msgstr "" +msgstr "在应用内启用 Bitcoin Cash 创建和操作。" #: www/views/tab-scan.html:19 msgid "Enable camera access in your device settings to get started." @@ -993,7 +998,7 @@ msgstr "启用推式通知" #: www/views/preferencesNotifications.html:33 msgid "Enable sound" -msgstr "" +msgstr "启用声音" #: www/views/tab-scan.html:18 msgid "Enable the camera to get started." @@ -1001,7 +1006,7 @@ msgstr "使该摄像机开始。" #: www/views/tab-settings.html:49 msgid "Enabled" -msgstr "" +msgstr "已启用" #: src/js/services/walletService.js:1047 #: src/js/services/walletService.js:1062 @@ -1586,7 +1591,7 @@ msgstr "网络地址不正确" #: src/js/controllers/confirm.js:306 #: src/js/services/bwcError.js:44 msgid "Insufficient confirmed funds" -msgstr "" +msgstr "确认的资金不足" #: src/js/controllers/topup.js:165 #: src/js/controllers/topup.js:177 @@ -2011,7 +2016,7 @@ msgstr "好的" #: www/views/modals/tx-status.html:36 #: www/views/modals/tx-status.html:46 msgid "OKAY" -msgstr "" +msgstr "确定" #: www/views/modals/terms.html:15 msgid "Official English Disclaimer" @@ -2053,7 +2058,7 @@ msgstr "打开 GitHub 项目" #: src/js/controllers/bitpayCard.js:123 #: src/js/controllers/tx-details.js:192 msgid "Open Explorer" -msgstr "" +msgstr "打开浏览器" #: www/views/tab-scan.html:22 msgid "Open Settings" @@ -2069,7 +2074,7 @@ msgstr "打开网站" #: src/js/controllers/preferencesCash.js:32 msgid "Open bitcoincash.org?" -msgstr "" +msgstr "打开 bitcoincash.org?" #: src/js/controllers/cashScan.js:18 msgid "Open the recovery tool." @@ -2511,7 +2516,7 @@ msgstr "请扫描你的指纹" #: www/views/preferencesCash.html:23 msgid "Scan your wallets for Bitcoin Cash" -msgstr "" +msgstr "扫描您的 Bitcoin Cash 钱包" #: src/js/services/onGoingProcess.js:30 msgid "Scanning Wallet funds..." @@ -2533,6 +2538,14 @@ msgstr "搜索交易" msgid "Search or enter bitcoin address" msgstr "搜索或输入比特币地址" +#: src/js/controllers/tab-send.js:28 +msgid "Clipboard" +msgstr "剪贴板" + +#: src/js/controllers/tab-send.js:29 +msgid "Your Clipboard is empty" +msgstr "您的剪贴板为空" + #: www/views/modals/search.html:16 msgid "Search transactions" msgstr "搜索交易" @@ -2591,9 +2604,70 @@ msgid "Send by email" msgstr "通过电邮发送" #: src/js/controllers/confirm.js:177 +#: src/js/controllers/tab-send.js:94 msgid "Send from" msgstr "从发送" +#: src/js/controllers/tab-send.js:77 +msgid "Send to" +msgstr "发送到" + +#: www/views/tab-send.html:20 +msgid "Paste Clipboard" +msgstr "粘贴剪贴板" + +#: www/views/tab-send.html:21 +msgid "Paste Address" +msgstr "粘贴地址" + +#: www/views/tab-send.html:27 +msgid "Wallet to Wallet Transfer" +msgstr "钱包转账" + +#: www/views/tab-send.html:35 +msgid "Scan QR Code" +msgstr "扫描二维码" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "更快地发送比特币!" + +#: www/views/tab-send.html:46 +msgid "Send Bitcoin faster!" +msgstr "更快地发送比特币!" + +#: www/views/tab-send.html:50 +msgid "Save frequently used addresses and send them Bitcoin in just one tap" +msgstr "保存常用地址,只需点击一下即可将比特币发送到这些地址" + +#: www/views/tab-send.html:55 +msgid "Add your first contact" +msgstr "添加您的第一个联系人" + +#: www/views/tab-send.html:65 +msgid "Your Bitcoin wallet is empty" +msgstr "您的比特币钱包为空" + +#: www/views/tab-send.html:69 +msgid "To get started, buy Bitcoin Cash (BCH) or Bitcoin Core (BTC), or share your address." +msgstr "首先,购买 Bitcoin Cash (BCH) 或 Bitcoin Core (BTC),或者共享您的地址。" + +#: www/views/tab-send.html:70 +msgid "You can receive bitcoin from any wallet or service." +msgstr "您可以从任何钱包或服务接收比特币。" + +#: www/views/tab-send.html:72 +msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." +msgstr "若要开始,您将需要创建一个比特币的钱包,并获得一些比特币。" + +#: www/views/tab-send.html:74 +msgid "Buy Bitcoin now" +msgstr "立即购买比特币" + +#: www/views/tab-send.html:76 +msgid "Show my address" +msgstr "显示我的地址" + #: www/views/includes/itemSelector.html:8 msgid "Send max amount" msgstr "发送最大数量" @@ -2810,7 +2884,7 @@ msgstr "超级经济" #: www/views/preferencesCash.html:11 msgid "Support Bitcoin Cash" -msgstr "" +msgstr "支持 Bitcoin Cash" #: www/views/paperWallet.html:7 msgid "Sweep" @@ -2860,7 +2934,7 @@ msgstr "使用条款" #: www/views/tab-create-personal.html:118 #: www/views/tab-import-phrase.html:68 msgid "Testnet" -msgstr "" +msgstr "测试网" #: www/views/includes/incomingDataMenu.html:61 msgid "Text" @@ -3030,7 +3104,7 @@ msgstr "若要开始,请买比特币或共享您的地址。你可以从任何 #: www/views/tab-send.html:33 msgid "To get started, you'll need to create a bitcoin wallet and get some bitcoin." -msgstr "若要开始,您将需要创建一个比特币的钱包,并获得一些比特币。" +msgstr "首先,您需要创建一个比特币钱包,并获得一些比特币。" #: src/js/services/bitpayAccountService.js:73 msgid "To {{reason}} you must first add your BitPay account - {{email}}" @@ -3200,7 +3274,7 @@ msgstr "查看服务条款" #: src/js/controllers/bitpayCard.js:122 #: src/js/controllers/tx-details.js:191 msgid "View Transaction on Explorer.Bitcoin.com" -msgstr "" +msgstr "在 Explorer.Bitcoin.com 上查看交易" #: src/js/controllers/tab-home.js:148 msgid "View Update" @@ -3596,7 +3670,7 @@ msgstr "我" #: www/views/addressbook.add.html:32 msgid "name@example.com" -msgstr "" +msgstr "name@example.com" #: www/views/preferencesHistory.html:15 msgid "preparing..." @@ -3636,3 +3710,51 @@ msgstr "下载的 {{updatingTxHistoryProgress}} 交易" msgid "{{wallet.m}}-of-{{wallet.n}}" msgstr "{{wallet.m}}{{wallet.n}}" +#: src/js/services/shapeshiftService.js:8 +msgid "Shapeshift" +msgstr "Shapeshift" + +#: www/views/includes/community.html:3 +msgid "Community" +msgstr "社区" + +#: src/js/services/communityService.js:40 +msgid "Bitcoin Cash Reddit" +msgstr "Bitcoin Cash Reddit" + +#: src/js/services/communityService.js:47 +msgid "Bitcoin.com Twitter" +msgstr "Bitcoin.com Twitter" + +#: www/views/includes/nextSteps.html:3 +msgid "Explore Bitcoin.com" +msgstr "探索 Bitcoin.com" + +#: src/js/services/bitcoincomService.js:21 +msgid "Bitcoin Cash Games" +msgstr "Bitcoin Cash 游戏" + +#: src/js/services/bitcoincomService.js:28 +msgid "News" +msgstr "新闻" + +#: src/js/services/bitcoincomService.js:35 +msgid "Mining Pool" +msgstr "矿池" + +#: src/js/services/bitcoincomService.js:42 +msgid "Tools" +msgstr "工具" + +#: src/js/services/bitcoincomService.js:49 +msgid "Bitcoin Price Charts" +msgstr "比特币价格图表" + +#: src/js/services/bitcoincomService.js:56 +msgid "Free Bitcoin Cash" +msgstr "免费的 Bitcoin Cash" + +#: www/views/tab-home.html:30 +msgid "Your Bitcoin Wallets are ready!" +msgstr "您的比特币钱包已就绪!" + diff --git a/src/js/controllers/addressbookAdd.js b/src/js/controllers/addressbookAdd.js index 9529d943e..ff284b234 100644 --- a/src/js/controllers/addressbookAdd.js +++ b/src/js/controllers/addressbookAdd.js @@ -21,6 +21,9 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu $timeout(function() { var form = addressbookForm; if (data && form) { + if (data.result) { + data = data.result; + } data = data.replace(/^bitcoin(cash)?:/, ''); form.address.$setViewValue(data); form.address.$isValid = true; @@ -36,9 +39,9 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu addressbook.address = translated.legacy; } - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("contact_created", [{ "coin": $scope.addressbookEntry.coin diff --git a/src/js/controllers/addressbookView.js b/src/js/controllers/addressbookView.js index aab6fb5b4..89c1cd924 100644 --- a/src/js/controllers/addressbookView.js +++ b/src/js/controllers/addressbookView.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, $state, $timeout, lodash, addressbookService, popupService, $ionicHistory, platformInfo, gettextCatalog, configService, bitcoinCashJsService) { +angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, sendFlowService, $state, $timeout, lodash, addressbookService, popupService, $ionicHistory, platformInfo, gettextCatalog, configService, bitcoinCashJsService) { var config = configService.getSync(); var defaults = configService.getDefaults(); @@ -22,6 +22,7 @@ angular.module('copayApp.controllers').controller('addressbookViewController', f $scope.sendTo = function() { $ionicHistory.removeBackView(); + sendFlowService.clear(); $state.go('tabs.send'); $timeout(function() { var to = ''; @@ -31,12 +32,16 @@ angular.module('copayApp.controllers').controller('addressbookViewController', f } else { to = $scope.addressbookEntry.address; } - $state.transitionTo('tabs.send.amount', { + + var stateParams = { toAddress: to, toName: $scope.addressbookEntry.name, toEmail: $scope.addressbookEntry.email, coin: $scope.addressbookEntry.coin - }); + }; + + sendFlowService.pushState(stateParams); + $state.transitionTo('tabs.send.origin'); }, 100); }; diff --git a/src/js/controllers/amount.js b/src/js/controllers/amount.js index 399acde49..c2dcc6cd4 100644 --- a/src/js/controllers/amount.js +++ b/src/js/controllers/amount.js @@ -1,68 +1,167 @@ 'use strict'; -angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicModal, $ionicScrollDelegate, $ionicHistory, storageService, walletService, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, popupService, bwcError, payproService, profileService, bitcore, amazonService, nodeWebkitService) { +angular.module('copayApp.controllers').controller('amountController', amountController); + +function amountController(configService, $filter, gettextCatalog, $ionicHistory, $ionicModal, $ionicScrollDelegate, lodash, $log, nodeWebkitService, rateService, $scope, $state, $timeout, sendFlowService, shapeshiftService, txFormatService, platformInfo, profileService, walletService, $window) { + var vm = this; + + vm.allowSend = false; + vm.altCurrencyList = []; + vm.alternativeAmount = ''; + vm.alternativeUnit = ''; + vm.amount = '0'; + vm.availableFunds = ''; + // Use insufficient for logic, as when the amount is invalid, funds being + // either sufficent or insufficient doesn't make sense. + vm.fundsAreInsufficient = false; + vm.globalResult = ''; + vm.isRequestingSpecificAmount = false; + vm.listComplete = false; + vm.lastUsedPopularList = []; + vm.maxAmount = 0; + vm.minAmount = 0; + vm.thirdParty = false; + vm.unit = ''; + + vm.changeUnit = changeUnit; + vm.close = close; + vm.findCurrency = findCurrency; + vm.finish = finish; + vm.goBack = goBack; + vm.loadMore = loadMore; + vm.next = next; + vm.openPopup = openPopup; + vm.pushDigit = pushDigit; + vm.removeDigit = removeDigit; + vm.save = save; + vm.sendMax = sendMax; + vm.errorMessage = ''; + + $scope.$on('$ionicView.beforeEnter', onBeforeEnter); + $scope.$on('$ionicView.leave', onLeave); - var _id; - var unitToSatoshi; - var satToUnit; - var unitDecimals; - var satToBtc; - var SMALL_FONT_SIZE_LIMIT = 10; var LENGTH_EXPRESSION_LIMIT = 19; var LENGTH_BEFORE_COMMA_EXPRESSION_LIMIT = 8; var LENGTH_AFTER_COMMA_EXPRESSION_LIMIT = 8; - var isNW = platformInfo.isNW; - var unitIndex = 0; + var altCurrencyModal = null; var altUnitIndex = 0; + var availableFundsInCrypto = ''; + var availableFundsInFiat = ''; + var availableSatoshis = null; var availableUnits = []; var fiatCode; + var isNW = platformInfo.isNW; + var isAndroid = platformInfo.isAndroid; + var isIos = platformInfo.isIOS; + var lastUsedAltCurrencyList = []; + var passthroughParams = {}; + var satToUnit; + var unitDecimals; + var unitIndex = 0; + var unitToSatoshi; + var useSendMax = false; - var fixedUnit; - - $scope.amountModel = { amount: 0 }; - - $scope.isChromeApp = platformInfo.isChromeApp; - $scope.isAndroid = platformInfo.isAndroid; - $scope.isIos = platformInfo.isIOS; - - $scope.$on('$ionicView.leave', function() { + function onLeave() { angular.element($window).off('keydown'); - }); - - $scope.$on("$ionicView.beforeEnter", function(event, data) { + } + function onBeforeEnter(event, data) { + if (data.direction == "back") { + sendFlowService.popState(); + } + console.log('amount onBeforeEnter after back sendflow ', sendFlowService.state); + initCurrencies(); - if (data.stateParams.shapeshiftOrderId && data.stateParams.shapeshiftOrderId.length > 0) { - $scope.minShapeshiftAmount = parseFloat(data.stateParams.minShapeshiftAmount); - $scope.maxShapeshiftAmount = parseFloat(data.stateParams.maxShapeshiftAmount); - $scope.shapeshiftOrderId = data.stateParams.shapeshiftOrderId; - } + passthroughParams = sendFlowService.getStateClone(); - // To get the wallet from with the new flow - $scope.fromWalletId = data.stateParams.fromWalletId; + vm.fromWalletId = passthroughParams.fromWalletId; + vm.toWalletId = passthroughParams.toWalletId; + vm.minAmount = parseFloat(passthroughParams.minAmount); + vm.maxAmount = parseFloat(passthroughParams.maxAmount); - if (data.stateParams.noPrefix) { - $scope.showWarningMessage = data.stateParams.noPrefix != 0; - if ($scope.showWarningMessage) { - var message = 'Address doesn\'t contain currency information, please make sure you are sending the correct currency.'; - popupService.showAlert('', message, function() {}, 'Ok'); + if (passthroughParams.thirdParty) { + vm.thirdParty = passthroughParams.thirdParty; // Parse stringified JSON-object + if (vm.thirdParty) { + if (vm.thirdParty.id === 'shapeshift') { + if (!vm.thirdParty.data) { + vm.thirdParty.data = {}; + } + vm.thirdParty.data['fromWalletId'] = vm.fromWalletId; + + vm.fromWallet = profileService.getWallet(vm.fromWalletId); + vm.toWallet = profileService.getWallet(vm.toWalletId); + + shapeshiftService.getMarketData(vm.fromWallet.coin, vm.toWallet.coin, function(data) { + vm.thirdParty.data['minAmount'] = vm.minAmount = parseFloat(data.minimum); + vm.thirdParty.data['maxAmount'] = vm.maxAmount = parseFloat(data.maxLimit); + }); + } } } + vm.isRequestingSpecificAmount = !passthroughParams.fromWalletId; + var config = configService.getSync().wallet.settings; + setAvailableUnits(); + updateUnitUI(); + + var reNr = /^[1234567890\.]$/; + var reOp = /^[\*\+\-\/]$/; + + if (!isAndroid && !isIos) { + var disableKeys = angular.element($window).on('keydown', function(e) { + if (!e.key) return; + if (e.which === 8) { // you can add others here inside brackets. + if (!altCurrencyModal) { + e.preventDefault(); + vm.removeDigit(); + } + } + + if (e.key.match(reNr)) { + vm.pushDigit(e.key); + } else if (e.key.match(reOp)) { + pushOperator(e.key); + } else if (e.keyCode === 86) { + if (e.ctrlKey || e.metaKey) processClipboard(); + } else if (e.keyCode === 13) vm.finish(); + + $timeout(function() { + $scope.$apply(); + }); + }); + } + + unitToSatoshi = config.unitToSatoshi; + satToUnit = 1 / unitToSatoshi; + unitDecimals = config.unitDecimals; + + resetAmount(); + + processAmount(); + + $timeout(function() { + $ionicScrollDelegate.resize(); + }, 10); + function setAvailableUnits() { var defaults = configService.getDefaults(); var configCache = configService.getSync(); availableUnits = []; - var hasBCHWallets = profileService.getWallets({ - coin: 'bch' - }).length; + var coinFromWallet = ''; + if (passthroughParams.fromWalletId) { + var fromWallet = profileService.getWallet(passthroughParams.fromWalletId); + coinFromWallet = fromWallet.coin; + } else { + var toWallet = profileService.getWallet(passthroughParams.toWalletId); + coinFromWallet = toWallet.coin; + } - if (hasBCHWallets) { + if (coinFromWallet === 'bch') { availableUnits.push({ name: 'Bitcoin Cash', id: 'bch', @@ -70,11 +169,7 @@ angular.module('copayApp.controllers').controller('amountController', function($ }); }; - var hasBTCWallets = profileService.getWallets({ - coin: 'btc' - }).length; - - if (hasBTCWallets) { + if (coinFromWallet === 'btc') { availableUnits.push({ name: 'Bitcoin', id: 'btc', @@ -84,31 +179,11 @@ angular.module('copayApp.controllers').controller('amountController', function($ 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; + if (passthroughParams.currency) { + fiatCode = passthroughParams.currency; altUnitIndex = unitIndex unitIndex = availableUnits.length; } else { @@ -125,142 +200,53 @@ angular.module('copayApp.controllers').controller('amountController', function($ isFiat: true, }); - if (data.stateParams.fixedUnit) { - fixedUnit = true; - } - unitIndex = lodash.findIndex(availableUnits, { isFiat: true }); altUnitIndex = 0; - }; - // Go to... - _id = data.stateParams.id; // Optional (BitPay Card ID or Wallet ID) - $scope.nextStep = data.stateParams.nextStep; - - setAvailableUnits(); - updateUnitUI(); - - $scope.hasMaxAmount = true; - if ($ionicHistory.backView().stateName == 'tabs.receive') { - $scope.hasMaxAmount = false; - } - - $scope.showMenu = $ionicHistory.backView() && ($ionicHistory.backView().stateName == 'tabs.send' || $ionicHistory.backView().stateName == 'tabs.bitpayCard'); - $scope.recipientType = data.stateParams.recipientType || null; - $scope.toAddress = data.stateParams.toAddress; - $scope.displayAddress = data.stateParams.displayAddress; - $scope.toName = data.stateParams.toName; - $scope.toEmail = data.stateParams.toEmail; - $scope.toColor = data.stateParams.toColor; - - if (!$scope.nextStep && !data.stateParams.toAddress) { - $log.error('Bad params at amount') - throw ('bad params'); - } - - var reNr = /^[1234567890\.]$/; - var reOp = /^[\*\+\-\/]$/; - - if (!$scope.isAndroid && !$scope.isIos) { - var disableKeys = angular.element($window).on('keydown', function(e) { - if (!e.key) return; - if (e.which === 8) { // you can add others here inside brackets. - if (!$scope.altCurrencyModal) { - e.preventDefault(); - $scope.removeDigit(); - } - } - - if (e.key.match(reNr)) { - $scope.pushDigit(e.key); - } else if (e.key.match(reOp)) { - $scope.pushOperator(e.key); - } else if (e.keyCode === 86) { - if (e.ctrlKey || e.metaKey) processClipboard(); - } else if (e.keyCode === 13) $scope.finish(); - - $timeout(function() { - $scope.$apply(); - }); - }); - } - - $scope.specificAmount = $scope.specificAlternativeAmount = ''; - $scope.isCordova = platformInfo.isCordova; - unitToSatoshi = config.unitToSatoshi; - satToUnit = 1 / unitToSatoshi; - satToBtc = 1 / 100000000; - unitDecimals = config.unitDecimals; - - $scope.resetAmount(); - - // in SAT ALWAYS - if ($stateParams.toAmount) { - $scope.amountModel.amount = (($stateParams.toAmount) * satToUnit).toFixed(unitDecimals); - } - - $scope.processAmount(); - - $timeout(function() { - $ionicScrollDelegate.resize(); - }, 10); - }); - - $scope.goBack = function() { - if ($scope.shapeshiftOrderId) { - $state.go('tabs.send').then(function() { - $ionicHistory.clearHistory(); - $state.go('tabs.home').then(function() { - $state.transitionTo('tabs.shapeshift'); - }); - }); - } else { - $ionicHistory.goBack(); + if (passthroughParams.fromWalletId) { + var fromWallet = profileService.getWallet(passthroughParams.fromWalletId); + updateAvailableFundsFromWallet(fromWallet); + } } } + function goBack() { + $ionicHistory.goBack(); + } + function paste(value) { - $scope.amountModel.amount = value; - $scope.processAmount(); + vm.amount = value; + processAmount(); $timeout(function() { $scope.$apply(); }); - }; + } function processClipboard() { if (!isNW) return; var value = nodeWebkitService.readFromClipboard(); if (value && evaluate(value) > 0) paste(evaluate(value)); - }; + } - $scope.sendMax = function() { - $scope.useSendMax = true; - $scope.finish(); - }; - - $scope.toggleAlternative = function() { - if ($scope.amountModel.amount && isExpression($scope.amountModel.amount)) { - var amount = evaluate(format($scope.amountModel.amount)); - $scope.globalResult = '= ' + processResult(amount); - } - }; + function sendMax() { + useSendMax = true; + finish(); + } function updateUnitUI() { - $scope.unit = availableUnits[unitIndex].shortName; - $scope.alternativeUnit = availableUnits[altUnitIndex].shortName; + vm.unit = availableUnits[unitIndex].shortName; + vm.alternativeUnit = availableUnits[altUnitIndex].shortName; - $scope.processAmount(); - $log.debug('Update unit coin @amount unit:' + $scope.unit + " alternativeUnit:" + $scope.alternativeUnit); - }; + processAmount(); + $log.debug('Update unit coin @amount unit:' + vm.unit + " alternativeUnit:" + vm.alternativeUnit); + } - $scope.changeUnit = function() { + function changeUnit() { - $scope.amountModel.amount = '0'; - - if (fixedUnit) return; + vm.amount = '0'; if (!(availableUnits[unitIndex].isFiat && availableUnits.length > 2 && altUnitIndex == 0)) { unitIndex++; @@ -275,153 +261,166 @@ angular.module('copayApp.controllers').controller('amountController', function($ }); } + updateAvailableFundsStringIfNeeded(); 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() { - if ($scope.amountModel.amount && $scope.amountModel.amount.length >= SMALL_FONT_SIZE_LIMIT) $scope.smallFont = true; - else $scope.smallFont = false; - }; - - $scope.pushDigit = function(digit) { - if ($scope.amountModel.amount && digit != '.') { - var amountSplitByComma = $scope.amountModel.amount.split('.'); + function pushDigit(digit) { + if (vm.amount && digit != '.') { + var amountSplitByComma = vm.amount.split('.'); if (amountSplitByComma.length > 1 && amountSplitByComma[1].length >= LENGTH_AFTER_COMMA_EXPRESSION_LIMIT) return; if (amountSplitByComma.length == 1 && amountSplitByComma[0].length >= LENGTH_BEFORE_COMMA_EXPRESSION_LIMIT) return; } - if ($scope.amountModel.amount && $scope.amountModel.amount.length >= LENGTH_EXPRESSION_LIMIT) return; - if ($scope.amountModel.amount.indexOf('.') > -1 && digit == '.') return; - if ($scope.amountModel.amount == '0' && digit == '0') return; - if (availableUnits[unitIndex].isFiat && $scope.amountModel.amount.indexOf('.') > -1 && $scope.amountModel.amount[$scope.amountModel.amount.indexOf('.') + 2]) return; + if (vm.amount && vm.amount.length >= LENGTH_EXPRESSION_LIMIT) return; + if (vm.amount.indexOf('.') > -1 && digit == '.') return; + if (vm.amount == '0' && digit == '0') return; + if (availableUnits[unitIndex].isFiat && vm.amount.indexOf('.') > -1 && vm.amount[vm.amount.indexOf('.') + 2]) return; - if ($scope.amountModel.amount == '0' && digit != '.') { - $scope.amountModel.amount = ''; + if (vm.amount == '0' && digit != '.') { + vm.amount = ''; } - if ($scope.amountModel.amount == '' && digit == '.') { - $scope.amountModel.amount = '0'; + if (vm.amount == '' && digit == '.') { + vm.amount = '0'; } - $scope.amountModel.amount = ($scope.amountModel.amount + digit).replace('..', '.'); - checkFontSize(); - $scope.processAmount(); - }; + vm.amount = (vm.amount + digit).replace('..', '.'); + processAmount(); + } - $scope.pushOperator = function(operator) { - if (!$scope.amountModel.amount || $scope.amountModel.amount.length == 0) return; - $scope.amountModel.amount = _pushOperator($scope.amountModel.amount); + function pushOperator(operator) { + if (!vm.amount || vm.amount.length == 0) return; + vm.amount = pushOperator(vm.amount); - function _pushOperator(val) { + function pushOperator(val) { if (!isOperator(lodash.last(val))) { return val + operator; } else { return val.slice(0, -1) + operator; } - }; - }; + } + } function isOperator(val) { var regex = /[\/\-\+\x\*]/; return regex.test(val); - }; + } function isExpression(val) { var regex = /^\.?\d+(\.?\d+)?([\/\-\+\*x]\d?\.?\d+)+$/; return regex.test(val); - }; + } - $scope.removeDigit = function() { - $scope.amountModel.amount = ($scope.amountModel.amount).toString().slice(0, -1); - $scope.processAmount(); - checkFontSize(); - }; + function removeDigit() { + vm.amount = (vm.amount).toString().slice(0, -1); + processAmount(); + } - $scope.resetAmount = function() { - $scope.amountModel.amount = $scope.alternativeAmount = $scope.globalResult = ''; - $scope.allowSend = false; - checkFontSize(); - }; + function resetAmount() { + vm.amount = vm.alternativeAmount = vm.globalResult = '0'; + vm.allowSend = false; + } - $scope.openPopup = function() { + function openPopup() { $ionicModal.fromTemplateUrl('views/modals/altCurrency.html', { scope: $scope }).then(function(modal) { - $scope.altCurrencyModal = modal; - $scope.altCurrencyModal.show(); + altCurrencyModal = modal; + altCurrencyModal.show(); }); - }; + } - $scope.close = function() { - $scope.altCurrencyModal.remove(); - $scope.altCurrencyModal = false; - }; + function close() { + altCurrencyModal.remove(); + altCurrencyModal = null; + } - $scope.processAmount = function() { - var formatedValue = format($scope.amountModel.amount); + function processAmount() { + var formatedValue = format(vm.amount); var result = evaluate(formatedValue); + var amountInCrypto = 0; + if (lodash.isNumber(result)) { - $scope.globalResult = isExpression($scope.amountModel.amount) ? '= ' + processResult(result) : ''; + vm.globalResult = isExpression(vm.amount) ? '= ' + processResult(result) : ''; if (availableUnits[unitIndex].isFiat) { var a = fromFiat(result); if (a) { - $scope.alternativeAmount = txFormatService.formatAmount(a * unitToSatoshi, true); - $scope.allowSend = lodash.isNumber(a) && a > 0 - && (!$scope.shapeshiftOrderId - || (a >= $scope.minShapeshiftAmount && a <= $scope.maxShapeshiftAmount)); + amountInCrypto = a; + var amountInSatoshis = a * unitToSatoshi; + vm.fundsAreInsufficient = !!passthroughParams.fromWalletId + && availableSatoshis !== null + && availableSatoshis < amountInSatoshis; + + vm.alternativeAmount = txFormatService.formatAmount(amountInSatoshis, true); + vm.allowSend = lodash.isNumber(a) + && a > 0 + && (!vm.minAmount || a >= vm.minAmount) + && (!vm.maxAmount || a <= vm.maxAmount) + && !vm.fundsAreInsufficient; } else { if (result) { - $scope.alternativeAmount = 'N/A'; + vm.alternativeAmount = 'N/A'; } else { - $scope.alternativeAmount = null; + vm.alternativeAmount = null; } - $scope.allowSend = false; + vm.fundsAreInsufficient = false; + vm.allowSend = false; } } else { - $scope.alternativeAmount = $filter('formatFiatAmount')(toFiat(result)); - $scope.allowSend = lodash.isNumber(result) && result > 0 - && (!$scope.shapeshiftOrderId - || (result >= $scope.minShapeshiftAmount && result <= $scope.maxShapeshiftAmount)); + amountInCrypto = result; + vm.fundsAreInsufficient = passthroughParams.fromWalletId + && availableSatoshis !== null + && availableSatoshis < result * unitToSatoshi; + + vm.alternativeAmount = $filter('formatFiatAmount')(toFiat(result)); + vm.allowSend = lodash.isNumber(result) + && result > 0 + && (!vm.minAmount || result >= vm.minAmount) + && (!vm.maxAmount || result <= vm.maxAmount) + && !vm.fundsAreInsufficient; } + + } else { + vm.fundsAreInsufficient = false; } - }; + + if (vm.fundsAreInsufficient) { + vm.errorMessage = gettextCatalog.getString('Not enough available funds'); + + } else if (amountInCrypto && vm.thirdParty && vm.thirdParty.id === 'shapeshift') { + if (amountInCrypto < vm.minAmount) { + vm.errorMessage = gettextCatalog.getString('Amount is below minimum'); + + } else if (amountInCrypto > vm.maxAmount) { + vm.errorMessage = gettextCatalog.getString('Amount is above maximum'); + + } else { + vm.errorMessage = ''; + } + } else { + vm.errorMessage = ''; + } + } function processResult(val) { if (availableUnits[unitIndex].isFiat) return $filter('formatFiatAmount')(val); else return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true); - }; + } function fromFiat(val) { return parseFloat((rateService.fromFiat(val, fiatCode, availableUnits[altUnitIndex].id) * satToUnit).toFixed(unitDecimals)); - }; + } function toFiat(val) { if (!rateService.getRate(fiatCode)) return; return parseFloat((rateService.toFiat(val * unitToSatoshi, fiatCode, availableUnits[unitIndex].id)).toFixed(2)); - }; + } function evaluate(val) { var result; @@ -432,7 +431,7 @@ angular.module('copayApp.controllers').controller('amountController', function($ } if (!lodash.isFinite(result)) return 0; return result; - }; + } function format(val) { if (!val) return; @@ -442,97 +441,44 @@ angular.module('copayApp.controllers').controller('amountController', function($ if (isOperator(lodash.last(val))) result = result.slice(0, -1); return result.replace('x', '*'); - }; + } - $scope.finish = function() { + function finish() { + var unit = availableUnits[unitIndex]; + var uiAmount = evaluate(format(vm.amount)); - function finish() { - var unit = availableUnits[unitIndex]; - var _amount = evaluate(format($scope.amountModel.amount)); - var coin = unit.id; - if (unit.isFiat) { - coin = availableUnits[altUnitIndex].id; - } + var satoshis = 0; + if (unit.isFiat) { + satoshis = (fromFiat(uiAmount) * unitToSatoshi).toFixed(0); + } else { + satoshis = (uiAmount * unitToSatoshi).toFixed(0); + } - if ($scope.nextStep) { - $state.transitionTo($scope.nextStep, { - id: _id, - amount: $scope.useSendMax ? null : _amount, - currency: unit.id.toUpperCase(), - coin: coin, - useSendMax: $scope.useSendMax, - fromWalletId: $scope.fromWalletId - }); - } else { - var amount = _amount; + var confirmData = { + amount: useSendMax ? undefined : satoshis, + fromWalletId: passthroughParams.fromWalletId, + sendMax: useSendMax, + toAddress: passthroughParams.toAddress, + toWalletId: passthroughParams.toWalletId + }; - if (unit.isFiat) { - amount = (fromFiat(amount) * unitToSatoshi).toFixed(0); - } else { - amount = (amount * unitToSatoshi).toFixed(0); - } + if (vm.thirdParty) { + confirmData.thirdParty = vm.thirdParty; + } - var confirmData = { - recipientType: $scope.recipientType, - toAmount: amount, - toAddress: $scope.toAddress, - displayAddress: $scope.displayAddress || $scope.toAddress, - toName: $scope.toName, - toEmail: $scope.toEmail, - toColor: $scope.toColor, - coin: coin, - useSendMax: $scope.useSendMax, - fromWalletId: $scope.fromWalletId - }; - - if ($scope.shapeshiftOrderId) { - var shapeshiftOrderUrl = 'https://www.shapeshift.io/#/status/'; - shapeshiftOrderUrl += $scope.shapeshiftOrderId; - confirmData.description = shapeshiftOrderUrl; - confirmData.fromWalletId = $scope.fromWalletId; - - if (confirmData.useSendMax) { - var wallet = lodash.find(profileService.getWallets({ coin: coin }), - function(w) { - return w.id == $scope.fromWalletId; - }); - - var balance = parseFloat(wallet.cachedBalance.substring(0, wallet.cachedBalance.length-4)); - if (balance < $scope.minShapeshiftAmount * 1.04) { - confirmData.useSendMax = false; - confirmData.toAmount = $scope.minShapeshiftAmount * unitToSatoshi; - } else if (balance > $scope.maxShapeshiftAmount) { - confirmData.useSendMax = false; - confirmData.toAmount = $scope.maxShapeshiftAmount * unitToSatoshi * 0.99; - } - } - } - - $state.transitionTo('tabs.send.review', confirmData); - } + sendFlowService.pushState(confirmData); + if (!confirmData.fromWalletId) { + $state.transitionTo('tabs.paymentRequest.confirm', confirmData); + } else { + $state.transitionTo('tabs.send.review', confirmData); $scope.useSendMax = null; } - - if ($scope.showWarningMessage) { - var u = $scope.unit == 'BCH' || $scope.unit == 'BTC' ? $scope.unit : $scope.alternativeUnit; - var message = 'Are you sure you want to send ' + u.toUpperCase() + '?'; - popupService.showConfirm(message, '', 'Yes', 'No', function(res) { - if (!res) { - $scope.useSendMax = null; - return; - }; - finish(); - }); - } else { - finish(); - } - - }; + } // Currency - var next = 10; + var nextCurrencies = 10; var completeAlternativeList = []; var popularCurrencyList = [ @@ -546,7 +492,7 @@ angular.module('copayApp.controllers').controller('amountController', function($ {isoCode: 'CNY', order: 7}, {isoCode: 'KRW', order: 8}, {isoCode: 'HKD', order: 9}, - ] + ]; function initCurrencies() { var unusedCurrencyList = [{ @@ -562,10 +508,10 @@ angular.module('copayApp.controllers').controller('amountController', function($ }]; rateService.whenAvailable(function() { - $scope.listComplete = false; + vm.listComplete = false; var idx = lodash.indexBy(unusedCurrencyList, 'isoCode'); - var idx2 = lodash.indexBy($scope.lastUsedAltCurrencyList, 'isoCode'); + var idx2 = lodash.indexBy(lastUsedAltCurrencyList, 'isoCode'); var idx3 = lodash.indexBy(popularCurrencyList, 'isoCode'); var alternatives = rateService.listAlternatives(true); @@ -578,8 +524,10 @@ angular.module('copayApp.controllers').controller('amountController', function($ } }); - $scope.altCurrencyList = completeAlternativeList.slice(0, 10); - $scope.lastUsedPopularList = lodash.unique(lodash.union($scope.lastUsedAltCurrencyList, popularCurrencyList), 'isoCode'); + vm.altCurrencyList = completeAlternativeList.slice(0, 10); + vm.lastUsedPopularList = lodash.unique(lodash.union(lastUsedAltCurrencyList, popularCurrencyList), 'isoCode'); + + rateService.updateRates(); $timeout(function() { $scope.$apply(); @@ -587,19 +535,24 @@ angular.module('copayApp.controllers').controller('amountController', function($ }); } - $scope.loadMore = function() { + function loadMore() { $timeout(function() { - $scope.altCurrencyList = completeAlternativeList.slice(0, next); - next += 10; - $scope.listComplete = $scope.altCurrencyList.length >= completeAlternativeList.length; + vm.altCurrencyList = completeAlternativeList.slice(0, nextCurrencies); + nextCurrencies += 10; + vm.listComplete = vm.altCurrencyList.length >= completeAlternativeList.length; $scope.$broadcast('scroll.infiniteScrollComplete'); }, 100); - }; + } - $scope.findCurrency = function(search) { + function next() { + useSendMax = false; + vm.finish(); + } + + function findCurrency(search) { if (!search) initCurrencies(); - var list = lodash.unique(lodash.union(completeAlternativeList, lodash.union($scope.lastUsedAltCurrencyList, popularCurrencyList)), 'isoCode'); - $scope.altCurrencyList = lodash.filter(list, function(item) { + var list = lodash.unique(lodash.union(completeAlternativeList, lodash.union(lastUsedAltCurrencyList, popularCurrencyList)), 'isoCode'); + vm.altCurrencyList = lodash.filter(list, function(item) { var val = item.name var val2 = item.isoCode; return lodash.includes(val.toLowerCase(), search.toLowerCase()) || lodash.includes(val2.toLowerCase(), search.toLowerCase()); @@ -607,9 +560,9 @@ angular.module('copayApp.controllers').controller('amountController', function($ $timeout(function() { $scope.$apply(); }); - }; + } - $scope.save = function(newAltCurrency) { + function save(newAltCurrency) { var opts = { wallet: { settings: { @@ -629,8 +582,63 @@ angular.module('copayApp.controllers').controller('amountController', function($ availableUnits[altUnitIndex].name = newAltCurrency.isoCode; availableUnits[altUnitIndex].shortName = newAltCurrency.isoCode; fiatCode = newAltCurrency.isoCode; + updateAvailableFundsStringIfNeeded(); updateUnitUI(); - $scope.close(); + close(); }); - }; -}); + } + + function updateAvailableFundsStringIfNeeded() { + if (passthroughParams.fromWalletId && availableSatoshis !== null) { + availableFundsInFiat = ''; + vm.availableFunds = availableFundsInCrypto; + + if (availableUnits[unitIndex].isFiat) { + var coin = availableUnits[altUnitIndex].id; + txFormatService.formatAlternativeStr(coin, availableSatoshis, function formatCallback(formatted){ + if (formatted) { + availableFundsInFiat = formatted; + + $scope.$apply(function() { + vm.availableFunds = availableFundsInFiat; + }); + } + }); + } + } + } + + function updateAvailableFundsFromWallet(wallet) { + if (wallet.status && wallet.status.isValid) { + availableFundsInCrypto = wallet.status.spendableBalanceStr; + availableSatoshis = wallet.status.spendableAmount; + if (wallet.status.alternativeBalanceAvailable) { + availableFundsInFiat = wallet.status.spendableBalanceAlternative + ' ' + wallet.status.alternativeIsoCode; + } else { + availableFundsInFiat = ''; + } + + } else if (wallet.cachedStatus && wallet.status.isValid) { + + if (wallet.cachedStatus.alternativeBalanceAvailable) { + availableFundsInFiat = wallet.cachedStatus.spendableBalanceAlternative + ' ' + wallet.cachedStatus.alternativeIsoCode; + } else { + availableFundsInFiat = ''; + } + availableFundsInCrypto = wallet.cachedStatus.spendableBalanceStr; + availableSatoshis = wallet.cachedStatus.spendableAmount; + + } else { + + availableFundsInFiat = ''; + availableFundsInCrypto = ''; + availableSatoshis = null; + } + + if (availableUnits[unitIndex].isFiat) { + vm.availableFunds = availableFundsInFiat || availableFundsInCrypto; + } else { + vm.availableFunds = availableFundsInCrypto; + } + } +} diff --git a/src/js/controllers/amount.spec.js b/src/js/controllers/amount.spec.js new file mode 100644 index 000000000..ed64da836 --- /dev/null +++ b/src/js/controllers/amount.spec.js @@ -0,0 +1,101 @@ +describe('amountController', function(){ + var configCache, + configService, + $controller, + $ionicHistory, + $rootScope, + platformInfo, + profileService, + rateService, + $stateParams; + + + + beforeEach(function(){ + module('ngLodash'); + module('copayApp.controllers'); + + configCache = { + wallet: { + settings: { + + } + } + }; + + + configService = jasmine.createSpyObj(['getDefaults','getSync']); + configService.getDefaults.and.returnValue({ + bitcoinCashAlias: 'bch', + bitcoinAlias: 'btc' + }); + configService.getSync.and.returnValue(configCache); + + $ionicHistory = jasmine.createSpyObj(['backView']); + + platformInfo = { + isChromeApp: false, + isAndroid: false, + isIos: true + }; + + profileService = jasmine.createSpyObj(['getWallets']); + + rateService = jasmine.createSpyObj(['fromFiat', 'whenAvailable']); + + $stateParams = {}; + + inject(function(_$controller_, _$rootScope_){ + // The injector unwraps the underscores (_) from around the parameter names when matching + $controller = _$controller_; + $rootScope = _$rootScope_; + }); + + + + }); + + it('receives fromWalletId and toAddress.', function() { + + var backView = { + stateName: 'ignoreme' + }; + $ionicHistory.backView.and.returnValue(backView); + profileService.getWallets.and.returnValue([{}]); + rateService.fromFiat.and.returnValue(12); // satoshis or coins? + + var $scope = $rootScope.$new(); + + + var amountController = $controller('amountController', { + configService: configService, + gettextCatalog: {}, + $ionicHistory: $ionicHistory, + $ionicModal: {}, + $ionicScrollDelegate: {}, + nodeWebkitService: {}, + ongoingProcess: {}, + platformInfo: platformInfo, + profileService: profileService, + popupService: {}, + rateService: rateService, + $scope: $scope, + $state: {}, + $stateParams: $stateParams, + txFormatService: {}, + walletService: {} + }); + + var data = { + stateParams: { + fromWalletId: 'fd56c1e7-e3ac-4fd9-8afc-27b9c1b3718b', + toAddress: 'qrup46avn8t466xxwlzs4qelht7cnwvesv2e29wf7s' + } + }; + $scope.$emit('$ionicView.beforeEnter', data); + + expect($scope.fromWalletId).toBe('fd56c1e7-e3ac-4fd9-8afc-27b9c1b3718b'); + expect($scope.toAddress).toBe('qrup46avn8t466xxwlzs4qelht7cnwvesv2e29wf7s'); + }); + +}); \ No newline at end of file diff --git a/src/js/controllers/backup.js b/src/js/controllers/backup.js index 0eec71f12..6ec7089c6 100644 --- a/src/js/controllers/backup.js +++ b/src/js/controllers/backup.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('backupController', - function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, lodash, profileService, bwcService, walletService, ongoingProcess, popupService, gettextCatalog, $ionicModal, firebaseEventsService) { + function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, lodash, profileService, bwcService, walletService, ongoingProcess, popupService, gettextCatalog, $ionicModal) { if ($state.current.name == 'onboarding.backup') { $scope.onboarding = true; @@ -89,7 +89,8 @@ angular.module('copayApp.controllers').controller('backupController', $scope.setFlow(2); }) } else { - firebaseEventsService.logEvent('backed_up_wallet'); + + //firebaseEventsService.logEvent('backed_up_wallet'); openConfirmBackupModal(); } }; diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 03af26fd1..76950df73 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -1,25 +1,20 @@ 'use strict'; -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, firebaseEventsService, soundService) { +angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $timeout, $ionicScrollDelegate, $ionicLoading, ionicToast, addressbookService, gettextCatalog, walletService, platformInfo, lodash, configService, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, feeService, bitcoinCashJsService, bwcError, txConfirmNotification, soundService, clipboardService) { var countDown = null; var FEE_TOO_HIGH_LIMIT_PER = 15; var tx = {}; + var lastTxId = ""; // Config Related values var config = configService.getSync(); var walletConfig = config.wallet; - var unitToSatoshi = walletConfig.settings.unitToSatoshi; - var unitDecimals = walletConfig.settings.unitDecimals; - var satToUnit = 1 / unitToSatoshi; var configFeeLevel = walletConfig.settings.feeLevel ? walletConfig.settings.feeLevel : 'normal'; - // Platform info - var isChromeApp = platformInfo.isChromeApp; var isCordova = platformInfo.isCordova; - var isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; //custom fee flag var usingCustomFee = false; @@ -31,6 +26,16 @@ angular.module('copayApp.controllers').controller('confirmController', function( }, 10); } + $scope.shareTransaction = function() { + var explorerTxUrl = 'https://explorer.bitcoin.com/'+tx.coin+'/tx/'+lastTxId; + if (platformInfo.isCordova) { + var text = 'Take a look at this Bitcoin transaction here: '+explorerTxUrl; + window.plugins.socialsharing.share(text, null, null, null); + } else { + ionicToast.show(gettextCatalog.getString('Copied to clipboard'), 'bottom', false, 3000); + clipboardService.copyToClipboard(explorerTxUrl); + } + }; $scope.showWalletSelector = function() { $scope.walletSelector = true; @@ -45,7 +50,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( $ionicConfig.views.swipeBackEnabled(false); }); - function exitWithError(err) { $log.info('Error setting wallet selector:' + err); popupService.showAlert(gettextCatalog.getString(), bwcError.msg(err), function() { @@ -68,112 +72,108 @@ angular.module('copayApp.controllers').controller('confirmController', function( }); }; - $scope.$on("$ionicView.beforeEnter", function(event, data) { + var setWalletSelector = function(coin, network, minAmount, cb) { - function setWalletSelector(coin, network, minAmount, cb) { + // no min amount? (sendMax) => look for no empty wallets + minAmount = minAmount || 1; - // no min amount? (sendMax) => look for no empty wallets - minAmount = minAmount || 1; + $scope.wallets = profileService.getWallets({ + onlyComplete: true, + network: network, + coin: coin + }); - $scope.wallets = profileService.getWallets({ - onlyComplete: true, - network: network, - coin: coin + if (tx.fromWalletId) { + $scope.wallets = lodash.filter($scope.wallets, function (w) { + return w.id == tx.fromWalletId; }); - - if (tx.fromWalletId) { - $scope.wallets = lodash.filter($scope.wallets, function(w) { - return w.id == tx.fromWalletId; - }); - } - - - - if (!$scope.wallets || !$scope.wallets.length) { - setNoWallet(gettextCatalog.getString('No wallets available'), true); - return cb(); - } - - var filteredWallets = []; - var index = 0; - var walletsUpdated = 0; - - lodash.each($scope.wallets, function(w) { - walletService.getStatus(w, {}, function(err, status) { - if (err || !status) { - $log.error(err); - } else { - walletsUpdated++; - w.status = status; - - if (!status.availableBalanceSat) - $log.debug('No balance available in: ' + w.name); - - if (status.availableBalanceSat > minAmount) { - filteredWallets.push(w); - } - } - - if (++index == $scope.wallets.length) { - if (!walletsUpdated) - return cb('Could not update any wallet'); - - if (lodash.isEmpty(filteredWallets)) { - setNoWallet(gettextCatalog.getString('Insufficient confirmed funds'), true); - } - $scope.wallets = lodash.clone(filteredWallets); - return cb(); - } - }); - }); - }; - - // 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('Invalid address'); - 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; } + + if (!$scope.wallets || !$scope.wallets.length) { + setNoWallet(gettextCatalog.getString('No wallets available'), true); + return cb(); + } + + var filteredWallets = []; + var index = 0; + var walletsUpdated = 0; + + lodash.each($scope.wallets, function (w) { + walletService.getStatus(w, {}, function (err, status) { + if (err || !status) { + $log.error(err); + } else { + walletsUpdated++; + w.status = status; + + if (!status.availableBalanceSat) + $log.debug('No balance available in: ' + w.name); + + if (status.availableBalanceSat > minAmount) { + filteredWallets.push(w); + } + } + + if (++index == $scope.wallets.length) { + if (!walletsUpdated) + return cb('Could not update any wallet'); + + if (lodash.isEmpty(filteredWallets)) { + setNoWallet(gettextCatalog.getString('Insufficient confirmed funds'), true); + } + $scope.wallets = lodash.clone(filteredWallets); + return cb(); + } + }); + }); + }; + + $scope.getContacts = function(addr) { + addressbookService.list(function(err, ab) { + if (err) $log.error(err); + + $scope.hasContacts = lodash.isEmpty(ab) ? false : true; + if (!$scope.hasContacts) return cb(); + + var completeContacts = []; + lodash.each(ab, function(v, k) { + completeContacts.push({ + name: lodash.isObject(v) ? v.name : v, + address: k, + email: lodash.isObject(v) ? v.email : null, + recipientType: 'contact', + coin: v.coin, + displayCoin: (v.coin == 'bch' + ? (config.bitcoinCashAlias || defaults.bitcoinCashAlias) + : (config.bitcoinAlias || defaults.bitcoinAlias)).toUpperCase() + }); + }); + + return cb(); + }); + }; + + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.fromWallet = profileService.getWallet(data.stateParams.fromWalletId); // Wallet to send from + + // Grab stateParams tx = { - toAmount: parseInt(data.stateParams.toAmount), + amount: parseInt(data.stateParams.amount), sendMax: data.stateParams.useSendMax == 'true' ? true : false, fromWalletId: data.stateParams.fromWalletId, toAddress: data.stateParams.toAddress, - displayAddress: data.stateParams.displayAddress, - description: data.stateParams.description, - paypro: data.stateParams.paypro, - feeLevel: configFeeLevel, spendUnconfirmed: walletConfig.spendUnconfirmed, // Vanity tx info (not in the real tx) - recipientType: data.stateParams.recipientType || null, - toName: data.stateParams.toName, - toEmail: data.stateParams.toEmail, - toColor: data.stateParams.toColor, - network: networkName, - coin: data.stateParams.coin, + recipientType: $scope.recipientType || null, + toName: null, + toEmail: null, + toColor: null, + network: false, + coin: $scope.fromWallet.coin, txp: {}, }; @@ -182,18 +182,71 @@ angular.module('copayApp.controllers').controller('confirmController', function( tx.feeRate = parseInt(data.stateParams.requiredFeeRate); } - if (tx.coin && tx.coin == 'bch') { + if (tx.coin && tx.coin === 'bch') { tx.feeLevel = 'normal'; } + var B = data.stateParams.coin === 'bch' ? bitcoreCash : bitcore; + var networkName; + $scope.recipientType = null; + try { + if (data.stateParams.toWalletId) { // There is a toWalletId, so we presume this is a wallet-to-wallet transfer + $scope.recipientType = 'wallet'; // set transaction type to wallet-to-wallet + $ionicLoading.show(); + + var toWallet = profileService.getWallet(data.stateParams.toWalletId); + tx.toColor = toWallet.color; + tx.toName = toWallet.name; + + // We need an address to send to, so we ask the walletService to create a new address for the toWallet. + walletService.getAddress(toWallet, true, function (err, addr) { + $ionicLoading.hide(); + tx.toAddress = addr; + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + setupTx(tx); + }); + } else { // This is a Wallet-to-address transfer + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + setupTx(tx); + } + } catch (e) { + var message = gettextCatalog.getString('Invalid address'); + popupService.showAlert(null, message, function () { + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function () { + $ionicHistory.clearHistory(); + }); + }); + return; + } + }); + + var setupTx = function(tx) { + if (tx.coin === 'bch') { + tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; + } else { + tx.displayAddress = entry.address; + } + + addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact + if (!err && addr) { + tx.toName = addr.name; + tx.toEmail = addr.email; + tx.recipientType = 'contact'; + } + }); + // Other Scope vars $scope.isCordova = isCordova; - $scope.isWindowsPhoneApp = isWindowsPhoneApp; $scope.showAddress = false; - $scope.walletSelectorTitle = gettextCatalog.getString('Send from'); - setWalletSelector(tx.coin, tx.network, tx.toAmount, function(err) { + setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { if (err) { return exitWithError('Could not update wallets'); } @@ -207,7 +260,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.displayBalanceAsFiat = walletConfig.settings.priceDisplay === 'fiat'; - }); + }; function getSendMaxInfo(tx, wallet, cb) { @@ -231,7 +284,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( return setSendError(msg); } - if (tx.toAmount > Number.MAX_SAFE_INTEGER) { + if (tx.amount > Number.MAX_SAFE_INTEGER) { var msg = gettextCatalog.getString('Amount too big'); $log.warn(msg); return setSendError(msg); @@ -241,7 +294,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( txp.outputs = [{ 'toAddress': tx.toAddress, - 'amount': tx.toAmount, + 'amount': tx.amount, 'message': tx.description }]; @@ -280,13 +333,13 @@ angular.module('copayApp.controllers').controller('confirmController', function( $scope.tx = tx; function updateAmount() { - if (!tx.toAmount) return; + if (!tx.amount) return; // Amount - tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.toAmount); + tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount); tx.amountValueStr = tx.amountStr.split(' ')[0]; tx.amountUnitStr = tx.amountStr.split(' ')[1]; - txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) { + txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { var parts = v.split(' '); tx.alternativeAmountStr = v; tx.alternativeAmountValueStr = parts[0]; @@ -342,7 +395,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( } tx.sendMaxInfo = sendMaxInfo; - tx.toAmount = tx.sendMaxInfo.amount; + tx.amount = tx.sendMaxInfo.amount; updateAmount(); ongoingProcess.set('calculatingFee', false); $timeout(function() { @@ -393,7 +446,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( function useSelectedWallet() { if (!$scope.useSendMax) { - showAmount(tx.toAmount); + showAmount(tx.amount); } $scope.onWalletSelect($scope.wallet); @@ -402,19 +455,19 @@ angular.module('copayApp.controllers').controller('confirmController', function( function setButtonText(isMultisig, isPayPro) { if (isPayPro) { - if (isCordova && !isWindowsPhoneApp) { + if (isCordova) { $scope.buttonText = gettextCatalog.getString('Slide to pay'); } else { $scope.buttonText = gettextCatalog.getString('Click to pay'); } } else if (isMultisig) { - if (isCordova && !isWindowsPhoneApp) { + if (isCordova) { $scope.buttonText = gettextCatalog.getString('Slide to accept'); } else { $scope.buttonText = gettextCatalog.getString('Click to accept'); } } else { - if (isCordova && !isWindowsPhoneApp) { + if (isCordova) { $scope.buttonText = gettextCatalog.getString('Slide to send'); } else { $scope.buttonText = gettextCatalog.getString('Click to send'); @@ -422,7 +475,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( } }; - $scope.toggleAddress = function() { $scope.showAddress = !$scope.showAddress; }; @@ -612,6 +664,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( txConfirmNotification.subscribe(wallet, { txid: txp.txid }); + lastTxId = txp.txid; } }, onSendStatusChange); }; @@ -643,9 +696,9 @@ angular.module('copayApp.controllers').controller('confirmController', function( soundService.play('misc/payment_sent.mp3'); } - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("transfer_success", [{ "coin": $scope.wallet.coin, @@ -655,8 +708,6 @@ angular.module('copayApp.controllers').controller('confirmController', function( }], [channel, "adjust"]); window.BitAnalytics.LogEventHandlers.postEvent(log); - // Should be removed - firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin }); $timeout(function() { $scope.$digest(); }, 100); diff --git a/src/js/controllers/create.js b/src/js/controllers/create.js index a25300a4a..a21053e2d 100644 --- a/src/js/controllers/create.js +++ b/src/js/controllers/create.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('createController', - function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService, pushNotificationsService, firebaseEventsService, $ionicNavBarDelegate) { + function($scope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, intelTEE, derivationPathHelper, ongoingProcess, walletService, popupService, appConfigService, pushNotificationsService, $ionicNavBarDelegate) { /* For compressed keys, m*73 + n*34 <= 496 */ var COPAYER_PAIR_LIMITS = { @@ -268,7 +268,7 @@ angular.module('copayApp.controllers').controller('createController', }, 100); } else { - firebaseEventsService.logEvent('wallet_created', { coin: opts.coin }); + //firebaseEventsService.logEvent('wallet_created', { coin: opts.coin }); $state.go('tabs.home'); } } diff --git a/src/js/controllers/customAmount.js b/src/js/controllers/customAmount.js index f6b96c22c..5d22d40fb 100644 --- a/src/js/controllers/customAmount.js +++ b/src/js/controllers/customAmount.js @@ -17,7 +17,7 @@ angular.module('copayApp.controllers').controller('customAmountController', func } $scope.$on("$ionicView.beforeEnter", function(event, data) { - var walletId = data.stateParams.id; + var walletId = data.stateParams.toWalletId; if (!walletId) { showErrorAndBack('Error', 'No wallet selected'); @@ -53,17 +53,26 @@ angular.module('copayApp.controllers').controller('customAmountController', func $scope.address = bchAddresses[$scope.bchAddressType]; } - $scope.coin = data.stateParams.coin; + $scope.coin = $scope.wallet.coin; + var satoshis = parseInt(data.stateParams.amount, 10); var parsedAmount = txFormatService.parseAmount( $scope.wallet.coin, - data.stateParams.amount, - data.stateParams.currency); + satoshis, + 'sat'); // Amount in USD or BTC var amount = parsedAmount.amount; var currency = parsedAmount.currency; $scope.amountUnitStr = parsedAmount.amountUnitStr; + configService.whenAvailable(function (config) { + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + + $timeout(function () { + $scope.$apply(); + }); + }); + if (currency != 'BTC' && currency != 'BCH') { // Convert to BTC or BCH var config = configService.getSync().wallet.settings; diff --git a/src/js/controllers/preferencesNotifications.js b/src/js/controllers/preferencesNotifications.js index edfb983b5..a9a833ff7 100644 --- a/src/js/controllers/preferencesNotifications.js +++ b/src/js/controllers/preferencesNotifications.js @@ -76,9 +76,9 @@ angular.module('copayApp.controllers').controller('preferencesNotificationsContr emailService.updateEmail(opts); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("settings_email_notification_toggle", [{ "toggle": $scope.emailNotifications.value diff --git a/src/js/controllers/review.controller.js b/src/js/controllers/review.controller.js index 5bf032fbd..c1f120241 100644 --- a/src/js/controllers/review.controller.js +++ b/src/js/controllers/review.controller.js @@ -4,9 +4,10 @@ angular .module('copayApp.controllers') .controller('reviewController', reviewController); -function reviewController(addressbookService, configService, $ionicConfig, $log, profileService, $scope, txFormatService) { +function reviewController(addressbookService, bitcoinCashJsService, bitcore, bitcoreCash, bwcError, configService, feeService, gettextCatalog, $interval, $ionicHistory, $ionicModal, lodash, $log, ongoingProcess, platformInfo, popupService, profileService, $scope, sendFlowService, shapeshiftService, soundService, $state, $timeout, txConfirmNotification, txFormatService, walletService) { var vm = this; - + + vm.buttonText = ''; vm.destination = { address: '', balanceAmount: '', @@ -18,68 +19,80 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, kind: '', // 'address', 'contact', 'wallet' name: '' }; - vm.fee = { - cryptoAmount: '', - cryptoCurrencyCode: '', - description: '', - fiatAmount: '', - fiatCurrency: '', - high: false - }; - vm.fee + vm.feeCrypto = ''; vm.feeFiat = ''; + vm.fiatCurrency = ''; + vm.feeIsHigh = false; + vm.feeLessThanACent = false; + vm.isCordova = platformInfo.isCordova; + vm.notReadyMessage = ''; vm.origin = { balanceAmount: '', balanceCurrency: '', - color: '', currency: '', currencyColor: '', - name: '', }; + vm.originWallet = null; + vm.paymentExpired = false; + vm.personalNotePlaceholder = gettextCatalog.getString('Enter text here'); vm.primaryAmount = ''; vm.primaryCurrency = ''; + vm.usingMerchantFee = false; + vm.readyToSend = false; + vm.remainingTimeStr = ''; vm.secondaryAmount = ''; vm.secondaryCurrency = ''; + vm.sendingTitle = gettextCatalog.getString('You are sending'); + vm.sendStatus = ''; + vm.showAddress = true; + vm.thirdParty = false; + vm.wallet = null; + vm.memoExpanded = false; + // Functions + vm.goBack = goBack; + vm.onSuccessConfirm = onSuccessConfirm; + + var sendFlowData; var config = null; - var configFeeLevel = ''; + var countDown = null; + var defaults = {}; var coin = ''; + var countDown = null; + var usingCustomFee = false; + var usingMerchantFee = false; + var destinationWalletId = ''; var originWalletId = ''; var priceDisplayIsFiat = true; var satoshis = null; var toAddress = ''; - var destinationWalletId = ''; + var tx = {}; + var txPayproData = null; + var unitFromSat = 0; + var FEE_TOO_HIGH_LIMIT_PERCENTAGE = 15; $scope.$on("$ionicView.beforeEnter", onBeforeEnter); - $scope.$on("$ionicView.beforeLeave", onBeforeLeave); - $scope.$on("$ionicView.enter", onEnter); - function onBeforeEnter(event, data) { - - // Dummy values for testing - vm.fee = { - cryptoAmount: '0.00195823', - cryptoCurrencyCode: 'BCH', - description: 'Less than 1 cent', - fiatAmount: '', - fiatCurrency: '', - high: false - }; - - originWalletId = data.stateParams.fromWalletId; - // For testing only - //originWalletId = data.stateParams.fromWalletId || 'bf00af8f-0788-4b57-b30a-0390747407e9'; - satoshis = parseInt(data.stateParams.amount, 10); - toAddress = data.stateParams.toAddr; + console.log('walletSelector onBeforeEnter sendflow ', sendFlowService.state); + defaults = configService.getDefaults(); + sendFlowData = sendFlowService.getStateClone(); + originWalletId = sendFlowData.fromWalletId; + satoshis = parseInt(sendFlowData.amount, 10); + toAddress = sendFlowData.toAddress; + destinationWalletId = sendFlowData.toWalletId; - var originWallet = profileService.getWallet(originWalletId); - vm.origin.currency = originWallet.coin.toUpperCase(); - vm.origin.color = originWallet.color; - vm.origin.name = originWallet.name; - coin = originWallet.coin; + vm.originWallet = profileService.getWallet(originWalletId); + vm.origin.currency = vm.originWallet.coin.toUpperCase(); + coin = vm.originWallet.coin; + + if (sendFlowData.thirdParty) { + vm.thirdParty = sendFlowData.thirdParty; + handleThirdPartyInitIfBip70(); + handleThirdPartyInitIfShapeshift(); + } configService.get(function onConfig(err, configCache) { if (err) { @@ -87,32 +100,264 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, } else { config = configCache; priceDisplayIsFiat = config.wallet.settings.priceDisplay === 'fiat'; - vm.origin.currencyColor = originWallet.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor; + vm.origin.currencyColor = (vm.originWallet.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor); + console.log("coin", vm.originWallet.coin, vm.origin.currencyColor, config.bitcoinWalletColor, vm.originWallet.coin === 'btc'); + unitFromSat = 1 / config.wallet.settings.unitToSatoshi; } - - configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; - updateSendAmounts(); - getOriginWalletBalance(originWallet); + getOriginWalletBalance(vm.originWallet); handleDestinationAsAddress(toAddress, coin); - handleDestinationAsWallet(data.stateParams.toWalletId); + handleDestinationAsWallet(sendFlowData.toWalletId); + createVanityTransaction(data); }); } - - function onBeforeLeave(event, data) { - $ionicConfig.views.swipeBackEnabled(true); - } - function onEnter(event, data) { - $ionicConfig.views.swipeBackEnabled(false); + vm.approve = function() { + + if (!tx || !vm.originWallet) return; + + if (vm.paymentExpired) { + popupService.showAlert(null, gettextCatalog.getString('This bitcoin payment request has expired.', function () { + $ionicHistory.goBack(); + })); + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + + ongoingProcess.set('creatingTx', true, statusChangeHandler); + getTxp(lodash.clone(tx), vm.originWallet, false, function(err, txp) { + ongoingProcess.set('creatingTx', false, statusChangeHandler); + if (err) return; + + // confirm txs for more that 20usd, if not spending/touchid is enabled + function confirmTx(cb) { + if (walletService.isEncrypted(vm.originWallet)) + return cb(); + + var amountUsd = parseFloat(txFormatService.formatToUSD(vm.originWallet.coin, txp.amount)); + return cb(); + }; + + function publishAndSign() { + if (!vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) { + $log.info('No signing proposal: No private key'); + + return walletService.onlyPublish(vm.originWallet, txp, function(err) { + if (err) setSendError(err); + }, statusChangeHandler); + } + + walletService.publishAndSign(vm.originWallet, txp, function(err, txp) { + if (err) return setSendError(err); + if (config.confirmedTxsNotifications && config.confirmedTxsNotifications.enabled) { + txConfirmNotification.subscribe(vm.originWallet, { + txid: txp.txid + }); + } + }, statusChangeHandler); + }; + + confirmTx(function(nok) { + if (nok) { + vm.sendStatus = ''; + $timeout(function() { + $scope.$apply(); + }); + return; + } + publishAndSign(); + }); + }); }; + vm.chooseFeeLevel = function(tx, wallet) { + + if (wallet.coin == 'bch') return; + if (usingMerchantFee) return; + + var scope = $rootScope.$new(true); + scope.network = tx.network; + scope.feeLevel = tx.feeLevel; + scope.noSave = true; + scope.coin = vm.originWallet.coin; + + if (usingCustomFee) { + scope.customFeePerKB = tx.feeRate; + scope.feePerSatByte = tx.feeRate / 1000; + } + + $ionicModal.fromTemplateUrl('views/modals/chooseFeeLevel.html', { + scope: scope, + backdropClickToClose: false, + hardwareBackButtonClose: false + }).then(function(modal) { + scope.chooseFeeLevelModal = modal; + scope.openModal(); + }); + scope.openModal = function() { + scope.chooseFeeLevelModal.show(); + }; + + scope.hideModal = function(newFeeLevel, customFeePerKB) { + scope.chooseFeeLevelModal.hide(); + $log.debug('New fee level choosen:' + newFeeLevel + ' was:' + tx.feeLevel); + + usingCustomFee = newFeeLevel == 'custom' ? true : false; + + if (tx.feeLevel == newFeeLevel && !usingCustomFee) return; + + tx.feeLevel = newFeeLevel; + if (usingCustomFee) tx.feeRate = parseInt(customFeePerKB); + + updateTx(tx, vm.originWallet, { + clearCache: true, + dryRun: true + }, function() {}); + }; + }; + + function createVanityTransaction(data) { + console.log('createVanityTransaction()'); + var configFeeLevel = config.wallet.settings.feeLevel ? config.wallet.settings.feeLevel : 'normal'; + + // Grab stateParams + tx = { + amount: parseInt(sendFlowData.amount), + sendMax: sendFlowData.sendMax, + fromWalletId: sendFlowData.fromWalletId, + toAddress: sendFlowData.toAddress, + paypro: txPayproData, + + feeLevel: configFeeLevel, + spendUnconfirmed: config.wallet.spendUnconfirmed, + + // Vanity tx info (not in the real tx) + recipientType: vm.destination.kind || null, + toName: vm.destination.name || null, + toEmail: vm.destination.email || null, + toColor: vm.destination.color || null, + network: false, + coin: vm.originWallet.coin, + txp: {}, + }; + + + if (data.stateParams.requiredFeeRate) { + vm.usingMerchantFee = true; + tx.feeRate = parseInt(data.stateParams.requiredFeeRate); + } + + if (tx.coin && tx.coin === 'bch') { + tx.feeLevel = 'normal'; + } + + var B = tx.coin === 'bch' ? bitcoreCash : bitcore; + var networkName; + try { + if (vm.destination.kind === 'wallet') { // This is a wallet-to-wallet transfer + ongoingProcess.set('generatingNewAddress', true); + var toWallet = profileService.getWallet(destinationWalletId); + + // We need an address to send to, so we ask the walletService to create a new address for the toWallet. + console.log('Getting address for wallet...'); + walletService.getAddress(toWallet, true, function onWalletAddress(err, addr) { + console.log('getAddress cb called', err); + ongoingProcess.set('generatingNewAddress', false); + tx.toAddress = addr; + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + console.log('calling setupTx() for wallet.'); + setupTx(tx); + }); + } else { // This is a Wallet-to-address transfer + networkName = (new B.Address(tx.toAddress)).network.name; + tx.network = networkName; + console.log('calling setupTx() for address.'); + setupTx(tx); + } + } catch (e) { + console.error('Error setting up tx', e); + var message = gettextCatalog.getString('Invalid address'); + popupService.showAlert(null, message, function () { + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function () { + $ionicHistory.clearHistory(); + }); + }); + return; + } + } function getOriginWalletBalance(originWallet) { - var balanceText = getWalletBalanceDisplayText(originWallet); + var balanceText = getWalletBalanceDisplayText(vm.originWallet); vm.origin.balanceAmount = balanceText.amount; vm.origin.balanceCurrency = balanceText.currency; } + function getSendMaxInfo(tx, wallet, cb) { + if (!tx.sendMax) return cb(); + + //ongoingProcess.set('retrievingInputs', true); + walletService.getSendMaxInfo(wallet, { + feePerKb: tx.feeRate, + excludeUnconfirmedUtxos: !tx.spendUnconfirmed, + returnInputs: true, + }, cb); + }; + + function getTxp(tx, wallet, dryRun, cb) { + + // ToDo: use a credential's (or fc's) function for this + if (tx.description && !wallet.credentials.sharedEncryptingKey) { + var msg = gettextCatalog.getString('Could not add message to imported wallet without shared encrypting key'); + $log.warn(msg); + return setSendError(msg); + } + + if (tx.amount > Number.MAX_SAFE_INTEGER) { + var msg = gettextCatalog.getString('Amount too big'); + $log.warn(msg); + return setSendError(msg); + } + + var txp = {}; + + txp.outputs = [{ + 'toAddress': tx.toAddress, + 'amount': tx.amount, + 'message': vm.memo + }]; + + if (tx.sendMaxInfo) { + txp.inputs = tx.sendMaxInfo.inputs; + txp.fee = tx.sendMaxInfo.fee; + } else { + if (usingCustomFee || usingMerchantFee) { + txp.feePerKb = tx.feeRate; + } else txp.feeLevel = tx.feeLevel; + } + + txp.message = vm.memo; + + if (tx.paypro) { + txp.payProUrl = tx.paypro.url; + } + txp.excludeUnconfirmedUtxos = !tx.spendUnconfirmed; + txp.dryRun = dryRun; + walletService.createTx(wallet, txp, function(err, ctxp) { + if (err) { + setSendError(err); + return cb(err); + } + return cb(null, ctxp); + }); + }; + function getWalletBalanceDisplayText(wallet) { var balanceCryptoAmount = ''; var balanceCryptoCurrencyCode = ''; @@ -153,6 +398,10 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, }; } + function goBack() { + $ionicHistory.goBack(); + } + function handleDestinationAsAddress(address, originCoin) { if (!address) { return; @@ -161,21 +410,24 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, // Check if the recipient is a contact addressbookService.get(originCoin + address, function(err, contact) { if (!err && contact) { - console.log('destination is contact'); - handleDestinationAsContact(contact); + handleDestinationAsAddressOfContact(contact); } else { - console.log('destination is address'); - vm.destination.address = address; + if (originCoin === 'bch') { + vm.destination.address = bitcoinCashJsService.readAddress(address).cashaddr; + } else { + vm.destination.address = address; + } vm.destination.kind = 'address'; } }); } - function handleDestinationAsContact(contact) { + function handleDestinationAsAddressOfContact(contact) { vm.destination.kind = 'contact'; vm.destination.name = contact.name; - vm.destination.color = contact.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor; + vm.destination.email = contact.email; + vm.destination.color = contact.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; vm.destination.currency = contact.coin.toUpperCase(); vm.destination.currencyColor = vm.destination.color; } @@ -186,7 +438,6 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, return; } - console.log('destination is wallet'); var destinationWallet = profileService.getWallet(destinationWalletId); vm.destination.coin = destinationWallet.coin; vm.destination.color = destinationWallet.color; @@ -194,8 +445,8 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, vm.destination.kind = 'wallet'; vm.destination.name = destinationWallet.name; - if (config) { - vm.destination.currencyColor = vm.destination.coin === 'btc' ? config.bitcoinWalletColor : config.bitcoinCashWalletColor; + if (defaults) { + vm.destination.currencyColor = vm.destination.coin === 'btc' ? defaults.bitcoinWalletColor : defaults.bitcoinCashWalletColor; } var balanceText = getWalletBalanceDisplayText(destinationWallet); @@ -203,6 +454,108 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, vm.destination.balanceCurrency = balanceText.currency; } + function handleThirdPartyInitIfBip70() { + if (vm.thirdParty.id === 'bip70') { + vm.sendingTitle = gettextCatalog.getString('You are paying'); + vm.memo = vm.thirdParty.memo; + vm.memoExpanded = !!vm.memo; + vm.destination.name = vm.thirdParty.name; + + txPayproData = { + caTrusted: vm.thirdParty.caTrusted, + domain: vm.thirdParty.domain, + expires: vm.thirdParty.expires, + toAddress: toAddress, + url: vm.thirdParty.url, + verified: vm.thirdParty.verified, + }; + } + } + + function handleThirdPartyInitIfShapeshift() { + if (vm.thirdParty.id === 'shapeshift') { + vm.sendingTitle = gettextCatalog.getString('You are shifting'); + if (!vm.thirdParty.data) { + vm.thirdParty.data = {}; + } + + var toWallet = profileService.getWallet(destinationWalletId); + vm.destination.name = toWallet.name; + vm.destination.color = toWallet.color; + vm.destination.currency = toWallet.coin.toUpperCase(); + + + ongoingProcess.set('connectingShapeshift', true); + walletService.getAddress(vm.originWallet, false, function onReturnWalletAddress(err, returnAddr) { + if (err) { + ongoingProcess.set('connectingShapeshift', false); + popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { + $ionicHistory.goBack(); + }); + return; + } + walletService.getAddress(toWallet, false, function onWithdrawalWalletAddress(err, withdrawalAddr) { + if (err) { + ongoingProcess.set('connectingShapeshift', false); + popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { + $ionicHistory.goBack(); + }); + return; + } + + shapeshiftService.shiftIt(vm.originWallet.coin, toWallet.coin, withdrawalAddr, returnAddr, function onShiftIt(err, shapeshiftData) { + if (err && err != null) { + ongoingProcess.set('connectingShapeshift', false); + popupService.showAlert(gettextCatalog.getString('Shapeshift Error'), err.toString(), function () { + $ionicHistory.goBack(); + }); + } else { + vm.memo = 'ShapeShift Order:\nhttps://www.shapeshift.io/#/status/' + shapeshiftData.orderId; + vm.memoExpanded = !!vm.memo; + tx.toAddress = shapeshiftData.toAddress; + vm.destination.address = toAddress; + vm.destination.kind = 'shapeshift'; + } + }); + }); + }); + } + } + + function startExpirationTimer(expirationTime) { + vm.paymentExpired = false; + setExpirationTime(); + + countDown = $interval(function() { + setExpirationTime(); + }, 1000); + + function setExpirationTime() { + console.log('setExpirationTime()'); + var now = Math.floor(Date.now() / 1000); + + if (now > expirationTime) { + setExpiredValues(); + return; + } + + var totalSecs = expirationTime - now; + var m = Math.floor(totalSecs / 60); + var s = totalSecs % 60; + vm.remainingTimeStr = m + ":" + ('0' + s).slice(-2); + }; + + function setExpiredValues() { + vm.paymentExpired = true; + vm.remainingTimeStr = gettextCatalog.getString('Expired'); + vm.readyToSend = false; + if (countDown) $interval.cancel(countDown); + $timeout(function() { + $scope.$apply(); + }); + }; + }; + function updateSendAmounts() { if (typeof satoshis !== 'number') { return; @@ -246,4 +599,315 @@ function reviewController(addressbookService, configService, $ionicConfig, $log, }); } + function onSuccessConfirm() { + vm.sendStatus = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $state.go('tabs.send').then(function() { + $ionicHistory.clearHistory(); + $state.transitionTo('tabs.home'); + }); + }; + + function setButtonText(isMultisig, isPayPro) { + if (isPayPro) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to pay'); + } else { + vm.buttonText = gettextCatalog.getString('Click to pay'); + } + } else if (isMultisig) { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to accept'); + } else { + vm.buttonText = gettextCatalog.getString('Click to accept'); + } + } else { + if (vm.isCordova) { + vm.buttonText = gettextCatalog.getString('Slide to send'); + } else { + vm.buttonText = gettextCatalog.getString('Click to send'); + } + } + } + + function setNotReady(msg, criticalError) { + vn.readyToSend = false; + vm.notReadyMessage = msg; + $scope.criticalError = criticalError; + $log.warn('Not ready to make the payment:' + msg); + $timeout(function() { + $scope.$apply(); + }); + }; + + function setSendError(msg) { + $scope.sendStatus = ''; + vm.readyToSend = false; + $timeout(function() { + $scope.$apply(); + }); + popupService.showAlert(gettextCatalog.getString('Error at confirm'), bwcError.msg(msg), function () { + $ionicHistory.goBack(); + }); + }; + + function setupTx(tx) { + if (tx.coin === 'bch') { + tx.displayAddress = bitcoinCashJsService.readAddress(tx.toAddress).cashaddr; + } else { + tx.displayAddress = tx.toAddress; + } + + addressbookService.get(tx.coin+tx.toAddress, function(err, addr) { // Check if the recipient is a contact + if (!err && addr) { + tx.toName = addr.name; + tx.toEmail = addr.email; + tx.recipientType = 'contact'; + } + }); + + vm.showAddress = false; + + + setButtonText(vm.originWallet.credentials.m > 1, !!tx.paypro); + + if (tx.paypro) + startExpirationTimer(tx.paypro.expires); + + updateTx(tx, vm.originWallet, { + dryRun: true + }, function(err) { + $timeout(function() { + $scope.$apply(); + }, 10); + + }); + + // setWalletSelector(tx.coin, tx.network, tx.amount, function(err) { + // if (err) { + // return exitWithError('Could not update wallets'); + // } + // + // if (vm.wallets.length > 1) { + // vm.showWalletSelector(); + // } else if (vm.wallets.length) { + // setWallet(vm.wallets[0], tx); + // } + // }); + } + + function showSendMaxWarning(wallet, sendMaxInfo) { + var feeAlternative = '', + msg = ''; + + function verifyExcludedUtxos() { + var warningMsg = []; + 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.", { + amountBelowFeeStr: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.amountBelowFee) + })); + } + + if (sendMaxInfo.utxosAboveMaxSize > 0) { + warningMsg.push(gettextCatalog.getString("A total of {{amountAboveMaxSizeStr}} were excluded. The maximum size allowed for a transaction was exceeded.", { + amountAboveMaxSizeStr: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.amountAboveMaxSize) + })); + } + return warningMsg.join('\n'); + }; + + feeAlternative = txFormatService.formatAlternativeStr(vm.originWallet.coin, sendMaxInfo.fee); + if (feeAlternative) { + msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee), + feeAlternative: feeAlternative + }); + } else { + msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", { + fee: txFormatService.formatAmountStr(vm.originWallet.coin, sendMaxInfo.fee) + }); + } + + var warningMsg = verifyExcludedUtxos(); + + if (!lodash.isEmpty(warningMsg)) + msg += '\n' + warningMsg; + + popupService.showAlert(null, msg, function() {}); + }; + + function statusChangeHandler(processName, showName, isOn) { + $log.debug('statusChangeHandler: ', processName, showName, isOn); + if ( + ( + processName === 'broadcastingTx' || + ((processName === 'signingTx') && vm.originWallet.m > 1) || + (processName == 'sendingTx' && !vm.originWallet.canSign() && !vm.originWallet.isPrivKeyExternal()) + ) && !isOn) { + vm.sendStatus = 'success'; + + if ($state.current.name === "tabs.send.review") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device. + soundService.play('misc/payment_sent.mp3'); + } + + var channel = "firebase"; + if (platformInfo.isNW) { + channel = "ga"; + } + // When displaying Fiat, if the formatting fails, the crypto will be the primary amount. + var amount = unitFromSat * satoshis; + var log = new window.BitAnalytics.LogEvent("transfer_success", [{ + "coin": vm.originWallet.coin, + "type": "outgoing", + "amount": amount, + "fees": vm.feeCrypto + }], [channel, "adjust"]); + window.BitAnalytics.LogEventHandlers.postEvent(log); + + $timeout(function() { + $scope.$digest(); + }, 100); + } else if (showName) { + vm.sendStatus = showName; + } + }; + + function updateTx(tx, wallet, opts, cb) { + ongoingProcess.set('calculatingFee', true); + + if (opts.clearCache) { + tx.txp = {}; + } + + // $scope.tx = tx; + + // function updateAmount() { + // if (!tx.amount) return; + // + // // Amount + // tx.amountStr = txFormatService.formatAmountStr(originWallet.coin, tx.amount); + // tx.amountValueStr = tx.amountStr.split(' ')[0]; + // tx.amountUnitStr = tx.amountStr.split(' ')[1]; + // txFormatService.formatAlternativeStr(wallet.coin, tx.amount, function(v) { + // var parts = v.split(' '); + // tx.alternativeAmountStr = v; + // tx.alternativeAmountValueStr = parts[0]; + // tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : ''; + // }); + // } + // + // updateAmount(); + // refresh(); + + var feeServiceLevel = usingMerchantFee && vm.originWallet.coin == 'btc' ? 'urgent' : tx.feeLevel; + feeService.getFeeRate(vm.originWallet.coin, tx.network, feeServiceLevel, function(err, feeRate) { + if (err) { + ongoingProcess.set('calculatingFee', false); + return cb(err); + } + + var msg; + if (usingCustomFee) { + msg = gettextCatalog.getString('Custom'); + tx.feeLevelName = msg; + } else if (usingMerchantFee) { + $log.info('Using Merchant Fee:' + tx.feeRate + ' vs. Urgent level:' + feeRate); + msg = gettextCatalog.getString('Suggested by Merchant'); + tx.feeLevelName = msg; + } else { + tx.feeLevelName = feeService.feeOpts[tx.feeLevel]; + tx.feeRate = feeRate; + } + + getSendMaxInfo(lodash.clone(tx), wallet, function(err, sendMaxInfo) { + if (err) { + ongoingProcess.set('calculatingFee', false); + var msg = gettextCatalog.getString('Error getting SendMax information'); + return setSendError(msg); + } + + if (sendMaxInfo) { + + $log.debug('Send max info', sendMaxInfo); + + if (tx.sendMax && sendMaxInfo.amount == 0) { + ongoingProcess.set('calculatingFee', false); + setNotReady(gettextCatalog.getString('Insufficient confirmed funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee'), function () { + $ionicHistory.goBack(); + }); + return cb('no_funds'); + } + + tx.sendMaxInfo = sendMaxInfo; + tx.amount = tx.sendMaxInfo.amount; + satoshis = tx.amount; + updateSendAmounts(); + ongoingProcess.set('calculatingFee', false); + $timeout(function() { + showSendMaxWarning(wallet, sendMaxInfo); + }, 200); + } + + // txp already generated for this wallet? + if (tx.txp[wallet.id]) { + ongoingProcess.set('calculatingFee', false); + vm.readyToSend = true; + updateSendAmounts(); + $scope.$apply(); + return cb(); + } + + console.log('calling getTxp() from getSendMaxInfo cb.'); + getTxp(lodash.clone(tx), wallet, opts.dryRun, function(err, txp) { + ongoingProcess.set('calculatingFee', false); + if (err) { + if (err.message == 'Insufficient funds') { + setNotReady(gettextCatalog.getString('Insufficient funds')); + popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Not enough funds for fee')); + return cb('no_funds'); + } else + return cb(err); + } + + txp.feeStr = txFormatService.formatAmountStr(wallet.coin, txp.fee); + txFormatService.formatAlternativeStr(wallet.coin, txp.fee, function(v) { + // txp.alternativeFeeStr = v; + // if (txp.alternativeFeeStr.substring(0, 4) == '0.00') + // txp.alternativeFeeStr = '< ' + txp.alternativeFeeStr; + vm.feeFiat = v; + vm.fiatCurrency = config.wallet.settings.alternativeIsoCode; + if (v.substring(0, 1) === "<") { + vm.feeLessThanACent = true; + } + + console.log("fiat", vm.feeFiat); + + }); + + var per = (txp.fee / (txp.amount + txp.fee) * 100); + var perString = per.toFixed(2); + txp.feeRatePerStr = (perString == '0.00' ? '< ' : '') + perString + '%'; + txp.feeToHigh = per > FEE_TOO_HIGH_LIMIT_PERCENTAGE; + vm.feeCrypto = (unitFromSat * txp.fee).toFixed(8); + vm.feeIsHigh = txp.feeToHigh; + console.log("crypto", vm.feeCrypto); + + + tx.txp[wallet.id] = txp; + $log.debug('Confirm. TX Fully Updated for wallet:' + wallet.id, tx); + vm.readyToSend = true; + updateSendAmounts(); + console.log('readyToSend:', vm.readyToSend); + $scope.$apply(); + + return cb(); + }); + }); + }); + } + } diff --git a/src/js/controllers/shapeshift.js b/src/js/controllers/shapeshift.js index a58fc20b6..3538ebe1a 100644 --- a/src/js/controllers/shapeshift.js +++ b/src/js/controllers/shapeshift.js @@ -1,7 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('shapeshiftController', function($scope, $interval, profileService, walletService, popupService, lodash, $ionicNavBarDelegate) { - +angular.module('copayApp.controllers').controller('shapeshiftController', function($scope, sendFlowService, $state, $timeout, $ionicHistory, profileService, walletService, popupService, lodash, $ionicNavBarDelegate) { var walletsBtc = []; var walletsBch = []; @@ -16,24 +15,9 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi } function showToWallets() { - $scope.toWallets = $scope.fromWallet.coin == 'btc' ? walletsBch : walletsBtc; + $scope.toWallets = $scope.fromWallet.coin === 'btc' ? walletsBch : walletsBtc; $scope.onToWalletSelect($scope.toWallets[0]); - $scope.singleToWallet = $scope.toWallets.length == 1; - } - - $scope.onFromWalletSelect = function(wallet) { - $scope.fromWallet = wallet; - showToWallets(); - generateAddress(wallet, function(addr) { - $scope.fromWalletAddress = addr; - }); - }; - - $scope.onToWalletSelect = function(wallet) { - $scope.toWallet = wallet; - generateAddress(wallet, function(addr) { - $scope.toWalletAddress = addr; - }); + $scope.singleToWallet = $scope.toWallets.length === 1; } $scope.$on("$ionicView.beforeEnter", function(event, data) { @@ -42,15 +26,15 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi $scope.fromWallets = lodash.filter(walletsBtc.concat(walletsBch), function(w) { return w.status.balance.availableAmount > 0; }); - if ($scope.fromWallets.length == 0) return; - $scope.onFromWalletSelect($scope.fromWallets[0]); - $scope.onToWalletSelect($scope.toWallets[0]); - $scope.singleFromWallet = $scope.fromWallets.length == 1; - $scope.singleToWallet = $scope.toWallets.length == 1; + + $scope.singleFromWallet = $scope.fromWallets.length === 1; $scope.fromWalletSelectorTitle = 'From'; $scope.toWalletSelectorTitle = 'To'; $scope.showFromWallets = false; $scope.showToWallets = false; + $scope.walletsWithFunds = profileService.getWallets({onlyComplete: true, hasFunds: true}); + $scope.wallets = profileService.getWallets({onlyComplete: true}); + $scope.hasWallets = !lodash.isEmpty($scope.wallets); }); $scope.$on("$ionicView.enter", function(event, data) { @@ -59,9 +43,42 @@ angular.module('copayApp.controllers').controller('shapeshiftController', functi $scope.showFromWalletSelector = function() { $scope.showFromWallets = true; - } + }; $scope.showToWalletSelector = function() { $scope.showToWallets = true; + }; + + // This could probably be enhanced refactoring the routes abstract states + $scope.createWallet = function() { + $state.go('tabs.home').then(function() { + $state.go('tabs.add.create-personal'); + }); + }; + + $scope.buyBitcoin = function() { + $state.go('tabs.home').then(function() { + $state.go('tabs.buyandsell'); + }); + }; + + $scope.shapeshift = function() { + var stateParams = { + thirdParty: { + id: 'shapeshift' + } + }; + + // Starting new send flow, so ensure everything is reset + sendFlowService.clear(); + $state.go('tabs.home').then(function() { + $ionicHistory.clearHistory(); + $state.go('tabs.send').then(function() { + $timeout(function () { + sendFlowService.pushState(stateParams); + $state.transitionTo('tabs.send.origin'); + }, 60); + }); + }); } }); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index a04820ebd..318fcece2 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('tabHomeController', - function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) { + function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, communityService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, sendFlowService, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) { var wallet; var listeners = []; var notifications = []; @@ -20,7 +20,12 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.bannerUrl = ''; - $scope.$on("$ionicView.afterEnter", function() { + $scope.$on("$ionicView.beforeEnter", onBeforeEnter); + $scope.$on("$ionicView.enter", onEnter); + $scope.$on("$ionicView.afterEnter", onAfterEnter); + $scope.$on("$ionicView.leave", onLeave); + + function onAfterEnter () { startupService.ready(); bannerService.getBanner(function (banner) { @@ -28,9 +33,10 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.bannerUrl = banner.url; $scope.bannerIsLoading = false; }); - }); + }; + + function onBeforeEnter (event, data) { - $scope.$on("$ionicView.beforeEnter", function(event, data) { if (!$scope.homeTip) { storageService.getHomeTipAccepted(function(error, value) { $scope.homeTip = (value == 'accepted') ? false : true; @@ -51,9 +57,9 @@ angular.module('copayApp.controllers').controller('tabHomeController', } }); } - }); + }; - $scope.$on("$ionicView.enter", function(event, data) { + function onEnter(event, data) { $ionicNavBarDelegate.showBar(true); updateAllWallets(); @@ -97,26 +103,29 @@ angular.module('copayApp.controllers').controller('tabHomeController', } $scope.showServices = true; - pushNotificationsService.init(); - firebaseEventsService.init(); $timeout(function() { $ionicScrollDelegate.resize(); $scope.$apply(); }, 10); }); - }); + }; - $scope.$on("$ionicView.leave", function(event, data) { + function onLeave (event, data) { lodash.each(listeners, function(x) { x(); }); - }); + }; $scope.createdWithinPastDay = function(time) { return timeService.withinPastDay(time); }; + $scope.startFreshSend = function() { + sendFlowService.clear(); + $state.go('tabs.send'); + } + $scope.openExternalLink = function() { var url = 'https://github.com/Bitcoin-com/Wallet/releases/latest'; var optIn = true; @@ -205,6 +214,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', var j = 0; lodash.each(wallets, function(wallet) { + walletService.invalidateCache(wallet); // Temporary solution, to have the good balance, when we ask to reload the wallets. walletService.getStatus(wallet, {}, function(err, status) { if (err) { @@ -224,6 +234,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', cb(); } } + $scope.walletsWithFunds = profileService.getWallets({hasFunds: true}); }); }); }; diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 8f25412ec..0e80f4382 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService, soundService, clipboardService) { +angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, sendFlowService, txFormatService, soundService, clipboardService) { var listeners = []; $scope.bchAddressType = { type: 'cashaddr' }; @@ -18,10 +18,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi $scope.displayBalanceAsFiat = true; $scope.requestSpecificAmount = function() { - $state.go('tabs.paymentRequest.amount', { - id: $scope.wallet.credentials.walletId, - coin: $scope.wallet.coin + sendFlowService.pushState({ + toWalletId: $scope.wallet.credentials.walletId }); + $state.go('tabs.paymentRequest.amount'); }; $scope.setAddress = function(newAddr, copyAddress) { @@ -145,9 +145,9 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi } $scope.paymentReceivedCoin = $scope.wallet.coin; - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("transfer_success", [{ "coin": $scope.wallet.coin, @@ -159,6 +159,10 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi soundService.play('misc/payment_received.mp3'); } + // Notify new tx + $scope.$emit('bwsEvent', $scope.wallet.id); + + $scope.$apply(function () { $scope.showingPaymentReceived = true; }); @@ -233,10 +237,14 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi if (!$scope.wallets[0]) return; - // select first wallet if no wallet selected previously - var selectedWallet = checkSelectedWallet($scope.wallet, $scope.wallets); + var selectedWallet = null; + if (data.stateParams.walletId) { // from walletDetails + selectedWallet = checkSelectedWallet(profileService.getWallet(data.stateParams.walletId), $scope.wallets); + } else { + // select first wallet if no wallet selected previously + selectedWallet = checkSelectedWallet($scope.wallet, $scope.wallets); + } $scope.onWalletSelect(selectedWallet); - $scope.showShareButton = platformInfo.isCordova ? (platformInfo.isIOS ? 'iOS' : 'Android') : null; listeners = [ diff --git a/src/js/controllers/tab-send.js b/src/js/controllers/tab-send.js index 99265457d..9ac6c35cb 100644 --- a/src/js/controllers/tab-send.js +++ b/src/js/controllers/tab-send.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, $ionicLoading, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, bwcError, gettextCatalog, scannerService, configService, bitcoinCashJsService, $ionicPopup, $ionicNavBarDelegate, clipboardService) { +angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, $ionicLoading, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo, sendFlowService, bwcError, gettextCatalog, scannerService, configService, bitcoinCashJsService, $ionicPopup, $ionicNavBarDelegate, clipboardService) { var clipboardHasAddress = false; var clipboardHasContent = false; var originalList; @@ -28,6 +28,10 @@ angular.module('copayApp.controllers').controller('tabSendController', function( }; $scope.$on("$ionicView.enter", function(event, data) { + + var stateParams = sendFlowService.getStateClone(); + $scope.fromWallet = profileService.getWallet(stateParams.fromWalletId); + clipboardService.readFromClipboard(function(text) { if (text.length > 200) { text = text.substring(0, 200); @@ -55,42 +59,6 @@ angular.module('copayApp.controllers').controller('tabSendController', function( }); }); - var wallets; - var walletsBch; - var walletsBtc; - var walletToWalletFrom = false; - - $scope.onWalletSelect = function(wallet) { - if (!$scope.walletToWalletFrom) { - $scope.walletToWalletFrom = wallet; - if (wallet.coin === 'bch') { - $scope.showWalletsBch = true; - } else if (wallet.coin === 'btc') { - $scope.showWalletsBtc = true; - } - $scope.walletSelectorTitleTo = gettextCatalog.getString('Send to'); - } else { - $ionicLoading.show(); - walletService.getAddress(wallet, true, function(err, addr) { - $ionicLoading.hide(); - return $state.transitionTo('tabs.send.amount', { - displayAddress: $scope.walletToWalletFrom.coin === 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr, - recipientType: 'wallet', - fromWalletId: $scope.walletToWalletFrom.id, - toAddress: addr, - coin: $scope.walletToWalletFrom.coin - }); - }); - - } - }; - - $scope.showWalletSelector = function() { - $scope.walletToWalletFrom = false; - $scope.walletSelectorTitleFrom = gettextCatalog.getString('Send from'); - $scope.showWallets = true; - }; - $scope.findContact = function(search) { if (incomingData.redir(search)) { @@ -133,7 +101,6 @@ angular.module('copayApp.controllers').controller('tabSendController', function( }; var updateHasFunds = function() { - $scope.hasFunds = false; var index = 0; lodash.each($scope.wallets, function(w) { @@ -179,10 +146,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function( coin: v.coin, displayCoin: (v.coin == 'bch' ? (config.bitcoinCashAlias || defaults.bitcoinCashAlias) - : (config.bitcoinAlias || defaults.bitcoinAlias)).toUpperCase(), - getAddress: function(cb) { - return cb(null, k); - }, + : (config.bitcoinAlias || defaults.bitcoinAlias)).toUpperCase() }); }); originalList = completeContacts; @@ -203,39 +167,46 @@ angular.module('copayApp.controllers').controller('tabSendController', function( }; $scope.searchBlurred = function() { - if ($scope.formData.search == null || $scope.formData.search.length == 0) { + if ($scope.formData.search == null || $scope.formData.search.length === 0) { $scope.searchFocus = false; } }; - $scope.goToAmount = function(item) { - $timeout(function() { - item.getAddress(function(err, addr) { - if (err || !addr) { - //Error is already formated - return popupService.showAlert(err); - } + $scope.sendToContact = function (item) { + $timeout(function () { + var toAddress = item.address; - if (item.recipientType && item.recipientType == 'contact') { - if (addr.indexOf('bch') == 0 || addr.indexOf('btc') == 0) { - addr = addr.substring(3); - } + if (item.recipientType && item.recipientType === 'contact') { + if (toAddress.indexOf('bch') === 0 || toAddress.indexOf('btc') === 0) { + toAddress = toAddress.substring(3); } + } + + $log.debug('Got toAddress:' + toAddress + ' | ' + item.name); + + var stateParams = sendFlowService.getStateClone(); + stateParams.toAddress = toAddress, + stateParams.coin = item.coin; + sendFlowService.pushState(stateParams); + + if (!stateParams.fromWalletId) { // If we have no toAddress or fromWallet + $state.transitionTo('tabs.send.origin'); + } else { + $state.transitionTo('tabs.send.amount'); + } - $log.debug('Got toAddress:' + addr + ' | ' + item.name); - return $state.transitionTo('tabs.send.amount', { - recipientType: item.recipientType, - displayAddress: item.coin == 'bch' ? bitcoinCashJsService.translateAddresses(addr).cashaddr : addr, - toAddress: addr, - toName: item.name, - toEmail: item.email, - toColor: item.color, - coin: item.coin - }); - }); }); }; + $scope.startWalletToWalletTransfer = function() { + console.log('startWalletToWalletTransfer()'); + var params = sendFlowService.getStateClone(); + sendFlowService.pushState(params); + $state.transitionTo('tabs.send.wallet-to-wallet', { + fromWalletId: sendFlowService.fromWalletId + }); + } + // This could probably be enhanced refactoring the routes abstract states $scope.createWallet = function() { $state.go('tabs.home').then(function() { @@ -250,6 +221,8 @@ angular.module('copayApp.controllers').controller('tabSendController', function( }; $scope.$on("$ionicView.beforeEnter", function(event, data) { + console.log(data); + console.log('tab-send onBeforeEnter sendflow ', sendFlowService.state); $scope.isIOS = platformInfo.isIOS && platformInfo.isCordova; $scope.showWalletsBch = $scope.showWalletsBtc = $scope.showWallets = false; @@ -264,5 +237,9 @@ angular.module('copayApp.controllers').controller('tabSendController', function( $scope.displayBalanceAsFiat = _config.wallet.settings.priceDisplay === 'fiat'; }); + if (data.direction == "back") { + sendFlowService.clear(); + } + }); -}); +}); \ No newline at end of file diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 4d0636d53..494d63cc5 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -16,7 +16,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct isoCode: config.wallet.settings.alternativeIsoCode }; - $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay === 'crypto' ? gettextCatalog.getString('Cryptocurrency') : gettextCatalog.getString('Fiat'); // TODO move this to a generic service bitpayAccountService.getAccounts(function(err, data) { diff --git a/src/js/controllers/tabsController.js b/src/js/controllers/tabsController.js index a186879e3..b3de6c70f 100644 --- a/src/js/controllers/tabsController.js +++ b/src/js/controllers/tabsController.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('tabsController', function($rootScope, $log, $scope, $state, $stateParams, $timeout, platformInfo, incomingData, lodash, popupService, gettextCatalog, scannerService) { +angular.module('copayApp.controllers').controller('tabsController', function($rootScope, $log, $scope, $state, $stateParams, $timeout, platformInfo, incomingData, lodash, popupService, gettextCatalog, scannerService, sendFlowService) { $scope.onScan = function(data) { if (!incomingData.redir(data)) { @@ -15,6 +15,11 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro }; }; + $scope.startFreshSend = function() { + sendFlowService.clear(); + $state.go('tabs.send'); + }; + $scope.importInit = function() { $scope.fromOnboarding = $stateParams.fromOnboarding; $timeout(function() { @@ -23,7 +28,7 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro }; $scope.chooseScanner = function() { - + sendFlowService.clear(); var isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; if (!isWindowsPhoneApp) { diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 24237f6c9..ec787a5f4 100644 --- a/src/js/controllers/walletDetails.js +++ b/src/js/controllers/walletDetails.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, storageService, $ionicScrollDelegate, $window, bwcError, gettextCatalog, timeService, feeService, appConfigService, rateService) { +angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, sendFlowService, storageService, $ionicScrollDelegate, $window, bwcError, gettextCatalog, timeService, feeService, appConfigService, rateService) { var HISTORY_SHOW_LIMIT = 10; var currentTxHistoryPage = 0; @@ -12,9 +12,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.isAndroid = platformInfo.isAndroid; $scope.isIOS = platformInfo.isIOS; - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("wallet_details_open", [], [channel]); window.BitAnalytics.LogEventHandlers.postEvent(log); @@ -304,9 +304,13 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }; function refreshAmountSection(scrollPos) { + var AMOUNT_HEIGHT_BASE = 210; $scope.showBalanceButton = false; if ($scope.status) { $scope.showBalanceButton = ($scope.status.totalBalanceSat != $scope.status.spendableAmount); + if ($scope.showBalanceButton) { + AMOUNT_HEIGHT_BASE = 270; + } } if (!$scope.amountIsCollapsible) { var t = ($scope.showBalanceButton ? 15 : 45); @@ -315,16 +319,16 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun } scrollPos = scrollPos || 0; - var amountHeight = 210 - scrollPos; + var amountHeight = AMOUNT_HEIGHT_BASE - scrollPos; if (amountHeight < 80) { amountHeight = 80; } var contentMargin = amountHeight; - if (contentMargin > 210) { - contentMargin = 210; + if (contentMargin > AMOUNT_HEIGHT_BASE) { + contentMargin = AMOUNT_HEIGHT_BASE; } - var amountScale = (amountHeight / 210); + var amountScale = (amountHeight / AMOUNT_HEIGHT_BASE); if (amountScale < 0.5) { amountScale = 0.5; } @@ -342,9 +346,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun top = TOP_BALANCE_BUTTON; } - var amountTop = ((amountScale - 0.7) / 0.7) * top; - if (amountTop < -10) { - amountTop = -10; + var amountTop = ((amountScale - 0.80) / 0.80) * top; + if (amountTop < -2) { + amountTop = -2; } if (amountTop > top) { amountTop = top; @@ -353,6 +357,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun var t = amountTop; $scope.altAmountOpacity = (amountHeight - 100) / 80; + $scope.buttonsOpacity = (amountHeight - 140) / 70; $window.requestAnimationFrame(function() { $scope.amountHeight = amountHeight + 'px'; $scope.contentMargin = contentMargin + 'px'; @@ -373,6 +378,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }); $scope.$on("$ionicView.beforeEnter", function(event, data) { + sendFlowService.clear(); configService.whenAvailable(function (config) { $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; @@ -469,4 +475,36 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun function rgbToHex(r, g, b) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); } + + $scope.goToSend = function() { + sendFlowService.startSend({ + fromWalletId: $scope.wallet.id + }); + + // Go home first so that the Home tab works properly + $state.go('tabs.home').then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.send'); + }); + + }; + $scope.goToReceive = function() { + $state.go('tabs.home', { + walletId: $scope.wallet.id + }).then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.receive', { + walletId: $scope.wallet.id + }); + }); + }; + + $scope.goToBuy = function() { + $state.go('tabs.home', { + walletId: $scope.wallet.id + }).then(function () { + $ionicHistory.clearHistory(); + $state.go('tabs.buyandsell'); + }); + }; }); diff --git a/src/js/controllers/walletSelectorController.js b/src/js/controllers/walletSelectorController.js new file mode 100644 index 000000000..777871e44 --- /dev/null +++ b/src/js/controllers/walletSelectorController.js @@ -0,0 +1,210 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('walletSelectorController', function($scope, $rootScope, $state, $log, $ionicHistory, sendFlowService, configService, gettextCatalog, profileService, txFormatService) { + + var fromWalletId = ''; + var priceDisplayAsFiat = false; + var unitDecimals = 0; + var unitsFromSatoshis = 0; + + $scope.$on("$ionicView.beforeEnter", onBeforeEnter); + $scope.$on("$ionicView.enter", onEnter); + + function onBeforeEnter(event, data) { + if (data.direction == "back") { + sendFlowService.popState(); + } + console.log('walletSelector onBeforeEnter after back sendflow', sendFlowService.state); + + $scope.params = sendFlowService.getStateClone(); + + var config = configService.getSync().wallet.settings; + priceDisplayAsFiat = config.priceDisplay === 'fiat'; + unitDecimals = config.unitDecimals; + unitsFromSatoshis = 1 / config.unitToSatoshi; + + switch($state.current.name) { + case 'tabs.send.wallet-to-wallet': + $scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets'); + break; + case 'tabs.send.destination': + if ($scope.params.fromWalletId && !$scope.params.thirdParty) { + $scope.sendFlowTitle = gettextCatalog.getString('Transfer between wallets'); + } + break; + default: + if (!$scope.params.thirdParty) { + $scope.sendFlowTitle = gettextCatalog.getString('Send'); + } + // nop + } + + $scope.coin = false; // Wallets to show (for destination screen or contacts) + $scope.type = $scope.params['fromWalletId'] ? 'destination' : 'origin'; // origin || destination + fromWalletId = $scope.params['fromWalletId']; + + if ($scope.type === 'destination' && $scope.params.toAddress) { + $state.transitionTo(getNextStep($scope.params)); + } + + if ($scope.params.coin) { + $scope.coin = $scope.params.coin; // Contacts have a coin embedded + } + + if ($scope.params.amount) { // There is an amount, so presume that it is a payment request + $scope.sendFlowTitle = gettextCatalog.getString('Payment Request'); + $scope.specificAmount = $scope.specificAlternativeAmount = ''; + $scope.isPaymentRequest = true; + } + if ($scope.params.thirdParty) { + $scope.thirdParty = $scope.params.thirdParty; + } + }; + + function onEnter (event, data) { + configService.whenAvailable(function(config) { + $scope.selectedPriceDisplay = config.wallet.settings.priceDisplay; + }); + + if ($scope.thirdParty) { + // Third party services specific logic + handleThirdPartyIfShapeshift(); + } + + prepareWalletLists(); + formatRequestedAmount(); + }; + + function formatRequestedAmount() { + if ($scope.params.amount) { + var cryptoAmount = (unitsFromSatoshis * $scope.params.amount).toFixed(unitDecimals); + var cryptoCoin = $scope.coin.toUpperCase(); + + txFormatService.formatAlternativeStr($scope.coin, $scope.params.amount, function onFormatAlternativeStr(formatted){ + if (formatted) { + var fiatParts = formatted.split(' '); + var fiatAmount = fiatParts[0]; + var fiatCurrrency = fiatParts.length > 1 ? fiatParts[1] : ''; + + if (priceDisplayAsFiat) { + $scope.requestAmount = fiatAmount; + $scope.requestCurrency = fiatCurrrency; + + $scope.requestAmountSecondary = cryptoAmount; + $scope.requestCurrencySecondary = cryptoCoin; + } else { + $scope.requestAmount = cryptoAmount; + $scope.requestCurrency = cryptoCoin; + + $scope.requestAmountSecondary = fiatAmount; + $scope.requestCurrencySecondary = fiatCurrrency; + } + } + }); + } + } + + function getNextStep(params) { + if (!params.toWalletId && !params.toAddress) { // If we have no toAddress or fromWallet + return 'tabs.send.destination'; + } else if (!params.amount) { // If we have no amount + return 'tabs.send.amount'; + } else { // If we do have them + return 'tabs.send.review'; + } + } + + function handleThirdPartyIfShapeshift() { + console.log($scope.thirdParty, $scope.coin); + if ($scope.thirdParty.id === 'shapeshift' && $scope.type === 'destination') { // Shapeshift wants to know the + $scope.coin = profileService.getWallet(fromWalletId).coin; + if ($scope.coin === 'bch') { + $scope.coin = 'btc'; + } else { + $scope.coin = 'bch'; + } + } + } + + function prepareWalletLists() { + var walletsAll = []; + var walletsSufficientFunds = []; + $scope.walletsInsufficientFunds = []; // For origin screen + + if ($scope.type === 'origin') { + $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send from'); + + if ($scope.params.amount) { + + walletsAll = profileService.getWallets({coin: $scope.coin}); + + walletsAll.forEach(function forWallet(wallet){ + if (wallet.status.availableBalanceSat > $scope.params.amount) { + walletsSufficientFunds.push(wallet); + } else { + $scope.walletsInsufficientFunds.push(wallet); + } + }); + + if ($scope.coin === 'btc') { + $scope.walletsBtc = walletsSufficientFunds; + } else { + $scope.walletsBch = walletsSufficientFunds; + } + + } else if ($scope.coin) { + walletsAll = profileService.getWallets({coin: $scope.coin}); + walletsAll.forEach(function forWallet(wallet){ + if (wallet.status.availableBalanceSat > 0) { + walletsSufficientFunds.push(wallet); + } else { + $scope.walletsInsufficientFunds.push(wallet); + } + }); + + if ($scope.coin === 'btc') { + $scope.walletsBtc = walletsSufficientFunds; + } else { + $scope.walletsBch = walletsSufficientFunds; + } + } else { + $scope.walletsBch = profileService.getWallets({coin: 'bch', hasFunds: true}); + $scope.walletsBtc = profileService.getWallets({coin: 'btc', hasFunds: true}); + $scope.walletsInsufficientFunds = profileService.getWallets({coin: $scope.coin, hasNoFunds: true}); + } + + } else if ($scope.type === 'destination') { + if (!$scope.coin) { // Allow for the coin to be set by a third party + $scope.fromWallet = profileService.getWallet(fromWalletId); + $scope.coin = $scope.fromWallet.coin; // Only show wallets with the select origin wallet coin + } + $scope.headerTitle = gettextCatalog.getString('Choose a wallet to send to'); + + if ($scope.coin === 'btc') { // if no specific coin is set or coin is set btc + $scope.walletsBtc = profileService.getWallets({coin: $scope.coin}); + } else { + $scope.walletsBch = profileService.getWallets({coin: $scope.coin}); + } + } + } + + + + $scope.useWallet = function(wallet) { + var params = sendFlowService.getStateClone(); + if ($scope.type === 'origin') { // we're on the origin screen, set wallet to send from + params.fromWalletId = wallet.id; + } else { // we're on the destination screen, set wallet to send to + params.toWalletId = wallet.id; + } + sendFlowService.pushState(params); + var nextStep = getNextStep(params); + console.log('walletSelector nextStep', nextStep); + $state.transitionTo(nextStep, $scope.params); + }; + + $scope.goBack = function() { + $ionicHistory.goBack(); + } + +}); \ No newline at end of file diff --git a/src/js/directives/amount.js b/src/js/directives/amount.js deleted file mode 100644 index 9622ca09d..000000000 --- a/src/js/directives/amount.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; - -/** - * @desc amount directive that can be used to display formatted financial values - * size-equal attribute is optional, defaults to false. - * @example fee = { - * value: 12.49382901, - * currency: 'BCH' - * } - * @example - * @example - */ -angular.module('bitcoincom.directives') - .directive('amount', [ - '$timeout', - function($timeout) { - return { - restrict: 'E', - scope: { - value: '=', - currency: '=', - sizeEqual: '=' - }, - templateUrl: 'views/includes/amount.html', - controller: ['$scope', function($scope) { - $scope.displaySizeEqual = typeof $scope.sizeEqual == 'undefined' ? false : true; - - var decimalPlaces = { - '0': ['BIF', 'CLP', 'DJF', 'GNF', 'ILS', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'], - '3': ['BHD', 'IQD', 'JOD', 'KWD', 'OMR', 'TND'], - '8': ['BCH', 'BTC'] - }; - - var numberWithCommas = function(x) { - return parseFloat(x).toLocaleString(); - }; - - var buildAmount = function(start, middle, end) { - $scope.start = start; - $scope.middle = middle; - $scope.end = end; - }; - - var getDecimalPlaces = function(currency) { - if (decimalPlaces['0'].indexOf($scope.currency.toUpperCase()) > -1) return '0'; - if (decimalPlaces['3'].indexOf($scope.currency.toUpperCase()) > -1) return '3'; - if (decimalPlaces['8'].indexOf($scope.currency.toUpperCase()) > -1) return '8'; - return '2'; - }; - - var formatNumbers = function(currency, value) { - switch (getDecimalPlaces(currency)) { - case '0': - var valueFormatted = numberWithCommas(Math.round(parseFloat(value))); - buildAmount(valueFormatted, '', ''); - break; - - case '2': - var valueProcessing = parseFloat(parseFloat(value).toFixed(2)); - var valueFormatted = numberWithCommas(valueProcessing); - buildAmount(valueFormatted, '', ''); - break; - - case '3': - var valueProcessing = parseFloat(parseFloat(value).toFixed(3)); - var valueFormatted = numberWithCommas(valueProcessing); - buildAmount(valueFormatted, '', ''); - break; - - case '8': - var valueFormatted = parseFloat(value).toFixed(8); - if (parseFloat(value) == 0) { - buildAmount('0', '', ''); - } else { - buildAmount(valueFormatted, '', ''); - var start = numberWithCommas(valueFormatted.slice(0, -5)); - var middle = valueFormatted.slice(-5, -2); - var end = valueFormatted.substr(valueFormatted.length - 2); - buildAmount(start, middle, end); - } - break; - } - } - - formatNumbers($scope.currency, $scope.value); - $scope.$watchGroup(['currency', 'value'], function() { - formatNumbers($scope.currency, $scope.value); - }); - }] - }; - } -]); \ No newline at end of file diff --git a/src/js/directives/formattedAmount.js b/src/js/directives/formattedAmount.js new file mode 100644 index 000000000..5ee9be050 --- /dev/null +++ b/src/js/directives/formattedAmount.js @@ -0,0 +1,198 @@ +'use strict'; + +(function(){ +/** + * @desc amount directive that can be used to display formatted financial values + * size-equal attribute is optional, defaults to false. + * @example fee = { + * value: 12.49382901, + * currency: 'BCH' + * } + * @example + * @example + */ + angular + .module('bitcoincom.directives') + .directive('formattedAmount', function() { + return { + restrict: 'E', + scope: { + value: '@', + currency: '@', + sizeEqual: '@' + }, + templateUrl: 'views/includes/formatted-amount.html', + controller: formattedAmountController + } + }); + + function formattedAmountController($scope, uxLanguage) { + $scope.vm = {}; + var vm = $scope.vm; + + vm.currency = ''; + vm.value = ''; + + $scope.canShow = false + $scope.displaySizeEqual = !!$scope.sizeEqual; + + var decimalPlaces = { + '0': ['BIF', 'CLP', 'DJF', 'GNF', 'ILS', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'], + '3': ['BHD', 'IQD', 'JOD', 'KWD', 'OMR', 'TND'], + '8': ['BCH', 'BTC'] + }; + + $scope.$watch('value', function onFormattedAmountWatch() { + formatNumbers(); + }); + + function buildAmount(start, middle, end) { + $scope.start = start; + $scope.middle = middle; + $scope.end = end; + }; + + /** + * On Android 4.4, toLocaleString() only returns 3 fractional digits when 8 is specified. + */ + function ensureEnoughFractionDigits(localizedString, number, desiredFractionDigits) { + if (desiredFractionDigits === 0) { + // Assume it is OK + return localizedString; + } + var fractionalRe = /^-*(\d*\D)(\d+)$/; + var match = fractionalRe.exec(localizedString); + if (!match || match.length !== 3) { + // Don't know what's happening, just return what we have + return localizedString; + } + + var decimals = match[2]; + var decimalCount = decimals.length; + if (decimalCount >= desiredFractionDigits) { + // Everything is OK. + return localizedString; + } + + if (typeof number !== 'number') { + number = parseFloat(number); + } + + var fixed = number.toFixed(desiredFractionDigits); + var fixedMatch = fractionalRe.exec(fixed); + if (!fixedMatch || fixedMatch.length !== 3) { + // Don't know what's happening, just return what we have + return localizedString; + } + + // Keeps locale decimal separator. + var enough = match[1] + fixedMatch[2]; + return enough; + } + + function formatNumbers() { + // Might get "< 0.01 USD" being passed in. + // During watch, may be changed from having a separate currency value, + // to both being in value. Don't want to use previous currency value. + // Try to extract currency from value.. + if (!$scope.currency || $scope.currency.length === 0) { + var currencySplit = $scope.value.split(" "); + if (currencySplit.length >= 2) { + vm.currency = currencySplit[currencySplit.length - 1]; + } + } else { + vm.currency = $scope.currency; + } + + // Redo this when we have proper formatting for low fees + if ($scope.value.indexOf("<") === 0) { + buildAmount($scope.value, '', ''); + vm.currency = ''; + $scope.canShow = true; + return; + } + + // Remove thousands separators for parseFloat() + $scope.value = $scope.value.replace(',', ''); + + var parsed = parseFloat($scope.value); + var valueFormatted = ''; + var valueProcessing = ''; + switch (getDecimalPlaces(vm.currency)) { + case '0': + if (isNaN(parsed)) { + buildAmount('-', '', ''); + } else { + valueFormatted = localizeNumbers(Math.round(parsed), 0); + buildAmount(valueFormatted, '', ''); + } + break; + + case '3': + if (isNaN(parsed)) { + buildAmount('-' + getDecimalSeparator() + '---', '', ''); + } else { + valueProcessing = parsed.toFixed(3); + valueFormatted = localizeNumbers(valueProcessing, 3); + buildAmount(valueFormatted, '', ''); + } + break; + + case '8': + if (isNaN(parsed)) { + buildAmount('-' + getDecimalSeparator() + '---', '', ''); + } else if (parsed === 0) { + buildAmount('0', '', ''); + } else { + valueFormatted = parsed.toFixed(8); + valueFormatted = localizeNumbers(valueFormatted, 8); + var start = valueFormatted.slice(0, -5); + var middle = valueFormatted.slice(-5, -2); + var end = valueFormatted.substr(valueFormatted.length - 2); + buildAmount(start, middle, end); + + } + break; + + default: // 2 + if (isNaN(parsed)) { + buildAmount('-' + getDecimalSeparator() + '--', '', ''); + } else { + valueProcessing = parseFloat(parsed.toFixed(2)); + valueFormatted = localizeNumbers(valueProcessing, 2); + buildAmount(valueFormatted, '', ''); + } + break; + } + $scope.canShow = true; + }; + + function getDecimalPlaces(currency) { + if (decimalPlaces['0'].indexOf(currency.toUpperCase()) > -1) return '0'; + if (decimalPlaces['3'].indexOf(currency.toUpperCase()) > -1) return '3'; + if (decimalPlaces['8'].indexOf(currency.toUpperCase()) > -1) return '8'; + return '2'; + }; + + function getDecimalSeparator() { + var testNum = 1.5; + var testString = testNum.toLocaleString(uxLanguage.getCurrentLanguage()); + // Some environments let you set decimal separators that are more than one character + var separator = /^1(.+)5$/.exec(testString)[1] + return separator; + }; + + function localizeNumbers(x, minimumFractionDigits) { + var parsed = parseFloat(x); + var opts = { + minimumFractionDigits: minimumFractionDigits, + useGrouping: true + }; + var lang = uxLanguage.getCurrentLanguage(); + var localized = parsed.toLocaleString(lang, opts); + var corrected = ensureEnoughFractionDigits(localized, x, minimumFractionDigits); + return corrected; + }; + } + +})(); \ No newline at end of file diff --git a/src/js/directives/shapeshiftCoinTrader.js b/src/js/directives/shapeshiftCoinTrader.js index d5c62f431..60cc66bdf 100644 --- a/src/js/directives/shapeshiftCoinTrader.js +++ b/src/js/directives/shapeshiftCoinTrader.js @@ -111,7 +111,7 @@ angular.module('copayApp.directives').directive('shapeshiftCoinTrader', function orderId: $scope.depositInfo.orderId }; - if (incomingData.redir(sendAddress, shapeshiftData)) { + if (incomingData.redir(sendAddress, 'shapeshift', shapeshiftData)) { ongoingProcess.set('connectingShapeshift', false); return; } diff --git a/src/js/directives/slideToAcceptSuccess.js b/src/js/directives/slideToAcceptSuccess.js index fbd588bfe..ec6321b95 100644 --- a/src/js/directives/slideToAcceptSuccess.js +++ b/src/js/directives/slideToAcceptSuccess.js @@ -9,12 +9,12 @@ angular.module('copayApp.directives') scope: { isShown: '=slideSuccessShow', onConfirm: '&slideSuccessOnConfirm', - hideOnConfirm: '=slideSuccessHideOnConfirm' + hideOnConfirm: '=slideSuccessHideOnConfirm', + onShare: '=slideSuccessOnShare', }, link: function(scope, element, attrs) { - - scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP; - + scope.isCordova = platformInfo.isCordova; + scope.hasShareFunction = typeof scope.onShare === 'function'; var elm = element[0]; elm.style.display = 'none'; scope.$watch('isShown', function() { @@ -32,6 +32,9 @@ angular.module('copayApp.directives') elm.style.display = 'none'; } }; + scope.onShareButtonClick = function() { + scope.onShare(); + } } }; }); diff --git a/src/js/directives/walletBalanceDirective.js b/src/js/directives/walletBalanceDirective.js new file mode 100644 index 000000000..1fea59203 --- /dev/null +++ b/src/js/directives/walletBalanceDirective.js @@ -0,0 +1,120 @@ +'use strict'; + +(function(){ + + angular + .module('bitcoincom.directives') + .directive('walletBalance', function() { + return { + restrict: 'E', + scope: { + displayAsFiat: '@', + totalBalanceSat: '@', + // The Wallet object is sometimes not stringify()-able, so not interpolatable, + // so can't be passed to a directive. + walletStatus: '@', + walletCachedBalance: '@', + walletCachedBalanceUpdatedOn: '@', + walletCachedStatus: '@' + }, + templateUrl: 'views/includes/wallet-balance.html', + controller: walletBalanceController + } + }); + + function walletBalanceController($log, $scope, txFormatService) { + var cryptoBalanceHasBeenDisplayed = false; + + formatBalance(); + $scope.$watchGroup(['displayAsFiat', 'totalBalanceSat'], function onWalletBalanceWatch() { + formatBalance(); + }); + + function displayCryptoBalance(walletStatus, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatus) { + console.log('displayCryptoBalance()'); + + if (walletStatus && walletStatus.isValid && walletStatus.totalBalanceStr) { + setDisplay(walletStatus.totalBalanceStr, ''); + cryptoBalanceHasBeenDisplayed = true; + return; + } + + if (walletCachedBalance) { + setDisplay(walletCachedBalance, walletCachedBalanceUpdatedOn); + return; + } + + if (walletCachedStatus && walletCachedStatus.isValid && walletCachedStatus.totalBalanceStr) { + setDisplay(walletCachedStatus.totalBalanceStr, ''); + return; + } + + setDisplay('', ''); + } + + function displayFiatBalance(walletStatus, walletCachedStatus) { + var displayAmount = ''; + if (walletStatus && walletStatus.isValid && walletStatus.alternativeBalanceAvailable) { + displayAmount = walletStatus.totalBalanceAlternative + ' ' + walletStatus.alternativeIsoCode; + setDisplay(displayAmount, ''); + return; + } + + if (walletCachedStatus && walletCachedStatus.isValid && walletCachedStatus.alternativeBalanceAvailable) { + displayAmount = walletCachedStatus.totalBalanceAlternative + ' ' + walletCachedStatus.alternativeIsoCode; + setDisplay(displayAmount, ''); + return; + } + + getFiatBalance(wallet); + } + + function formatBalance() { + var displayAsFiat = $scope.displayAsFiat === 'true'; + + var walletStatusObj = null; + var walletCachedBalance = null; + var walletCachedBalanceUpdatedOn = null; + var walletCachedStatusObj = null; + + try { + walletStatusObj = JSON.parse($scope.walletStatus); + } catch (e) { + $log.warn('Failed to parse walletStatus.', e); + } + + try { + walletCachedStatusObj = JSON.parse($scope.walletCachedStatus); + } catch (e) { + $log.warn('Failed to parse walletCachedStatus.', e); + } + + if (!displayAsFiat || displayAsFiat && !cryptoBalanceHasBeenDisplayed) { + displayCryptoBalance(walletStatusObj, walletCachedBalance, walletCachedBalanceUpdatedOn, walletCachedStatusObj); + } + + if (displayAsFiat) { + displayFiatBalance(walletStatusObj, walletCachedStatusObj); + } + } + + function getFiatBalance(wallet) { + if (!(wallet.status && wallet.status.isValid)) { + $log.warn('Abandoning call to get fiat balance, because no valid wallet status.'); + return; + } + + txFormatService.formatAlternativeStr(wallet.coin, wallet.status.totalBalanceSat, function onFormatAlernativeStr(formatted) { + if (formatted) { + setDisplay(formatted, ''); + } + }); + } + + function setDisplay(amount, cachedBalanceUpdatedOn) { + $scope.displayAmount = amount; + $scope.cachedBalanceUpdatedOn = cachedBalanceUpdatedOn; + } + } +})(); + diff --git a/src/js/routes.js b/src/js/routes.js index 4807fab5c..d2b78aac3 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -236,7 +236,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }) .state('tabs.receive', { - url: '/receive', + url: '/receive/:walletId', views: { 'tab-receive': { controller: 'tabReceiveController', @@ -287,16 +287,44 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr */ .state('tabs.send.amount', { - url: '/amount/:recipientType/:toAddress/:toName/:toEmail/:toColor/:coin/:fixedUnit/:fromWalletId/:minShapeshiftAmount/:maxShapeshiftAmount/:shapeshiftOrderId/:displayAddress/:noPrefix', + url: '/amount', views: { 'tab-send@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } } }) + .state('tabs.send.wallet-to-wallet', { + url: '/wallet-to-wallet', + views: { + 'tab-send@tabs': { + controller: 'walletSelectorController', + templateUrl: 'views/walletSelector.html' + } + } + }) + .state('tabs.send.origin', { + url: '/origin', + views: { + 'tab-send@tabs': { + controller: 'walletSelectorController', + templateUrl: 'views/walletSelector.html', + } + } + }) + .state('tabs.send.destination', { + url: '/destination', + views: { + 'tab-send@tabs': { + controller: 'walletSelectorController', + templateUrl: 'views/walletSelector.html', + } + } + }) .state('tabs.send.confirm', { - url: '/confirm/:recipientType/:toAddress/:toName/:toAmount/:toEmail/:toColor/:description/:coin/:useSendMax/:fromWalletId/:displayAddress/:requiredFeeRate', + url: '/confirm', views: { 'tab-send@tabs': { controller: 'confirmController', @@ -317,7 +345,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }) .state('tabs.send.review', { - url: '/review/:amount/:fromWalletId/:sendMax/:toAddr/:toWalletId', + url: '/review/:thirdParty/:amount/:fromWalletId/:sendMax/:toAddress/:toWalletId', views: { 'tab-send@tabs': { controller: 'reviewController', @@ -708,16 +736,17 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }) .state('tabs.paymentRequest.amount', { - url: '/amount/:coin', + url: '/amount/:toWalletId', views: { 'tab-receive@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } } }) .state('tabs.paymentRequest.confirm', { - url: '/confirm/:amount/:currency/:coin', + url: '/confirm/:amount/:toWalletId', views: { 'tab-receive@tabs': { controller: 'customAmountController', @@ -858,6 +887,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } } @@ -923,6 +953,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } } @@ -981,7 +1012,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr /* Shapeshift */ .state('tabs.shapeshift', { - url: '/shapeshift', + url: '/shapeshift/:fromWalletId/:toWalletId', views: { 'tab-home@tabs': { controller: 'shapeshiftController', @@ -1042,6 +1073,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } }, @@ -1094,6 +1126,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } }, @@ -1150,6 +1183,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'amountController', + controllerAs: 'vm', templateUrl: 'views/amount.html' } } @@ -1173,7 +1207,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }); }) - .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 => */ buydotbitcoindotcomService, glideraService, amazonService, bitpayCardService, applicationService, mercadoLibreService, rateService) { + .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 => */ buydotbitcoindotcomService, pushNotificationsService, glideraService, amazonService, bitpayCardService, applicationService, mercadoLibreService, rateService) { $ionicPlatform.ready(function() { @@ -1197,9 +1231,14 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + configService.whenAvailable(function(config) { + pushNotificationsService.init(); + }); + //firebaseEventsService.init(); + + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } // Send a log to test @@ -1238,6 +1277,13 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }); window.BitAnalytics.ActionHandlers.trackAction(actionTabOpen); + var actionShapeShiftStart = new window.BitAnalytics.ActionFactory.createAction('click', { + name: 'shapeshift_start_click', + class: 'track_shapeshift_start_click', + channels: [channel] + }); + window.BitAnalytics.ActionHandlers.trackAction(actionShapeShiftStart); + // Init language uxLanguage.init(function (lang) { @@ -1277,7 +1323,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr if (screen.width < 768 && platformInfo.isCordova) screen.lockOrientation('portrait'); - if (ionic.Platform.isAndroid() && StatusBar) { + if (ionic.Platform.isAndroid() && platformInfo.isCordova && StatusBar) { StatusBar.backgroundColorByHexString('#000000'); } diff --git a/src/js/services/bitcoincomService.js b/src/js/services/bitcoincomService.js index 051123111..68fd51a8a 100644 --- a/src/js/services/bitcoincomService.js +++ b/src/js/services/bitcoincomService.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.services').factory('bitcoincomService', function(platformInfo, nextStepsService) { +angular.module('copayApp.services').factory('bitcoincomService', function(gettextCatalog, nextStepsService, platformInfo) { var root = {}; var credentials = {}; @@ -19,42 +19,42 @@ angular.module('copayApp.services').factory('bitcoincomService', function(platfo var cashGamesItem = { name: 'games', - title: 'Bitcoin Cash Games', + title: gettextCatalog.getString('Bitcoin Cash Games'), icon: 'icon-games', href: 'https://cashgames.bitcoin.com' }; var newsItem = { name: 'news', - title: 'News', + title: gettextCatalog.getString('News'), icon: 'icon-news', href: 'https://news.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=News' }; var poolItem = { name: 'pool', - title: 'Mining Pool', + title: gettextCatalog.getString('Mining Pool'), icon: 'icon-mining', href: 'https://pool.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Pool' }; var toolsItem = { name: 'tools', - title: 'Tools', + title: gettextCatalog.getString('Tools'), icon: 'icon-tools', href: 'https://tools.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Tools' }; var priceChartItem = { name: 'pricechart', - title: 'Bitcoin Price Charts', + title: gettextCatalog.getString('Bitcoin Price Charts'), icon: 'icon-chart', sref: 'tabs.pricechart', }; var faucetItem = { name: 'faucet', - title: 'Free Bitcoin Cash', + title: gettextCatalog.getString('Free Bitcoin Cash'), icon: 'icon-faucet', href: 'https://free.bitcoin.com/?utm_source=WalletApp&utm_medium=' + os + '&utm_campaign=Faucet' }; diff --git a/src/js/services/buyAndSellService.js b/src/js/services/buyAndSellService.js index 65a9a93c7..e35403131 100644 --- a/src/js/services/buyAndSellService.js +++ b/src/js/services/buyAndSellService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('buyAndSellService', function($log, servicesService, lodash, $ionicScrollDelegate, $timeout) { +angular.module('copayApp.services').factory('buyAndSellService', function(gettextCatalog, $log, servicesService, lodash, $ionicScrollDelegate, $timeout) { var root = {}; var services = []; var linkedServices = []; @@ -23,7 +23,7 @@ angular.module('copayApp.services').factory('buyAndSellService', function($log, if (linkedServices.length == 0) { servicesService.register({ - title: 'Buy Bitcoin', + title: gettextCatalog.getString('Buy Bitcoin'), name: 'buyandsell', icon: 'icon-buy-bitcoin2', sref: 'tabs.buyandsell', diff --git a/src/js/services/clipboardService.js b/src/js/services/clipboardService.js index ebd30c28c..9b1a61fbe 100644 --- a/src/js/services/clipboardService.js +++ b/src/js/services/clipboardService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('clipboardService', function ($http, $log, platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) { +angular.module('copayApp.services').factory('clipboardService', function ($http, $log, $timeout, platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) { var root = {}; root.copyToClipboard = function (data) { @@ -11,10 +11,15 @@ angular.module('copayApp.services').factory('clipboardService', function ($http, cordova.plugins.clipboard.copy(data); } else if (platformInfo.isNW) { nodeWebkitService.writeToClipboard(data); + } else if (navigator && navigator.clipboard) { + $log.debug("Use navigator clipboard.") + navigator.clipboard.writeText(data).catch(function onClipboardError(err) { + $log.debug("Clipboard writing is not supported in your browser.."); + }); } else if (clipboard.supported) { clipboard.copyText(data); } else { - // No supported + // Not supported return; } }; @@ -26,7 +31,9 @@ angular.module('copayApp.services').factory('clipboardService', function ($http, cb(text); }) } else if (platformInfo.isNW) { - cb(nodeWebkitService.readFromClipboard()); + $timeout(function() { + cb(nodeWebkitService.readFromClipboard()); + },0); } else { navigator.clipboard.readText() .then(function (text) { diff --git a/src/js/services/communityService.js b/src/js/services/communityService.js index 24cc99474..93a4afe5e 100644 --- a/src/js/services/communityService.js +++ b/src/js/services/communityService.js @@ -1,5 +1,5 @@ 'use strict' -angular.module('copayApp.services').factory('communityService', function(configService, $log, lodash) { +angular.module('copayApp.services').factory('communityService', function(configService, gettextCatalog, $log, lodash) { var root = {}; var services = []; @@ -37,14 +37,14 @@ angular.module('copayApp.services').factory('communityService', function(configS var bchRedditItem = { name: 'bchreddit', - title: 'Bitcoin Cash Reddit', + title: gettextCatalog.getString('Bitcoin Cash Reddit'), icon: 'icon-reddit-white', href: 'http://reddit.com/r/btc' }; var bitcoincomTwitterItem = { name: 'bitcoincomTwitter', - title: 'Bitcoin.com Twitter', + title: gettextCatalog.getString('Bitcoin.com Twitter'), icon: 'icon-twitter-white', href: 'https://twitter.com/BTCTN' }; diff --git a/src/js/services/firebaseEventsService.js b/src/js/services/firebaseEventsService.js index d81e682d7..d6ce6f1cc 100644 --- a/src/js/services/firebaseEventsService.js +++ b/src/js/services/firebaseEventsService.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.services').factory('firebaseEventsService', function firebaseEventsService($log, $state, $ionicHistory, sjcl, platformInfo, lodash, appConfigService, profileService, configService) { +angular.module('copayApp.services').factory('firebaseEventsService', function firebaseEventsService($log, platformInfo) { var root = {}; var useEvents = platformInfo.isCordova && !platformInfo.isWP; diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index 1bb87b49c..9fad8b0f5 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) { +angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, sendFlowService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) { var root = {}; @@ -8,7 +8,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat $rootScope.$broadcast('incomingDataMenu.showMenu', data); }; - root.redir = function(data, shapeshiftData) { + root.redir = function(data, serviceId, serviceData) { var originalAddress = null; var noPrefixInAddress = 0; @@ -75,35 +75,41 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat return true; } - function goSend(addr, amount, message, coin, shapeshiftData) { + function goSend(addr, amount, message, coin, serviceId, serviceData) { $state.go('tabs.send', {}, { 'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true }); // Timeout is required to enable the "Back" button $timeout(function() { + var params = sendFlowService.getStateClone(); + if (amount) { - $state.transitionTo('tabs.send.confirm', { - toAmount: amount, - toAddress: addr, - displayAddress: originalAddress ? originalAddress : addr, - description: message, - coin: coin - }); + params.amount = amount; + } + + if (addr) { + params.toAddress = addr; + params.displayAddress = originalAddress ? originalAddress : addr; + } + + if (coin) { + params.coin = coin; + } + + if (noPrefixInAddress) { + params.noPrefixInAddress = noPrefixInAddress; + } + + if (serviceId) { + params.thirdParty = []; + params.thirdParty.id = serviceId; + params.thirdParty.data = serviceData; + sendFlowService.pushState(params); + $state.transitionTo('tabs.send.amount'); } else { - var params = { - toAddress: addr, - coin: coin, - displayAddress: originalAddress ? originalAddress : addr, - noPrefix: noPrefixInAddress - }; - if (shapeshiftData) { - params['fromWalletId'] = shapeshiftData.fromWalletId; - params['minShapeshiftAmount'] = shapeshiftData.minAmount; - params['maxShapeshiftAmount'] = shapeshiftData.maxAmount; - params['shapeshiftOrderId'] = shapeshiftData.orderId; - } - $state.transitionTo('tabs.send.amount', params); + sendFlowService.pushState(params); + $state.transitionTo('tabs.send.origin'); } }, 100); } @@ -112,15 +118,20 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat var coin = data.indexOf('bitcoincash') >= 0 ? 'bch' : 'btc'; data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, '')); if (coin == 'bch') { - payproService.getPayProDetailsViaHttp(data, function(err, details) { + payproService.getPayProDetailsViaHttp(data, function onGetPayProDetailsViaHttp(err, details) { if (err) { - popupService.showAlert(gettextCatalog.getString('Error'), err) + var message = err.toString(); + if (typeof err.data === 'string') { + // i.e. 'This invoice is no longer accepting payments' + message = gettextCatalog.getString(err.data); + } + popupService.showAlert(gettextCatalog.getString('Error'), message) } else { - handlePayPro(createBchPayProObject(details), coin); + handlePayPro(details, coin); } }); } else { - payproService.getPayProDetails(data, coin, function(err, details) { + payproService.getPayProDetails(data, coin, function onGetPayProDetails(err, details) { if (err) { popupService.showAlert(gettextCatalog.getString('Error'), err); } else { @@ -146,12 +157,12 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat if (parsed.r) { payproService.getPayProDetails(parsed.r, coin, function(err, details) { if (err) { - if (addr && amount) goSend(addr, amount, message, coin, shapeshiftData); + if (addr && amount) goSend(addr, amount, message, coin, serviceId, serviceData); else popupService.showAlert(gettextCatalog.getString('Error'), err); } else handlePayPro(details, coin); }); } else { - goSend(addr, amount, message, coin, shapeshiftData); + goSend(addr, amount, message, coin, serviceId, serviceData); } return true; // Cash URI @@ -169,14 +180,14 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat payproService.getPayProDetails(parsed.r, coin, function(err, details) { if (err) { if (addr && amount) - goSend(addr, amount, message, coin, shapeshiftData); + goSend(addr, amount, message, coin, serviceId, serviceData); else popupService.showAlert(gettextCatalog.getString('Error'), err); } handlePayPro(details, coin); }); } else { - goSend(addr, amount, message, coin, shapeshiftData); + goSend(addr, amount, message, coin, serviceId, serviceData); } return true; @@ -212,14 +223,14 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat payproService.getPayProDetails(parsed.r, coin, function(err, details) { if (err) { if (addr && amount) - goSend(addr, amount, message, coin, shapeshiftData); + goSend(addr, amount, message, coin, serviceId, serviceData); else popupService.showAlert(gettextCatalog.getString('Error'), err); } handlePayPro(details, coin); }); } else { - goSend(addr, amount, message, coin, shapeshiftData); + goSend(addr, amount, message, coin, serviceId, serviceData); } } ); @@ -377,55 +388,84 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat 'notify': $state.current.name == 'tabs.send' ? false : true }); $timeout(function() { - $state.transitionTo('tabs.send.amount', { + var stateParams = { toAddress: toAddress, coin: coin, noPrefix: 1 - }); + }; + sendFlowService.pushState(stateParams); + $state.transitionTo('tabs.send.origin'); }, 100); } - function createBchPayProObject(payProData) { - var displayAddr = payProData.outputs[0].address; - var toAddr = bitcoinCashJsService.readAddress('bitcoincash:' + displayAddr).legacy; - return { - amount: payProData.outputs[0].amount, + function handlePayPro(payProData, coin) { + + console.log(payProData); + + var toAddr = payProData.toAddress; + var amount = payProData.amount; + var paymentUrl = payProData.url; + var expires = payProData.expires; + var time = payProData.time; + + if (coin === 'bch') { + var displayAddr = payProData.outputs[0].address; + toAddr = bitcoinCashJsService.readAddress('bitcoincash:' + displayAddr).legacy; + amount = payProData.outputs[0].amount; + paymentUrl = payProData.paymentUrl; + expires = Math.floor(new Date(expires).getTime() / 1000) + time = Math.ceil(new Date(time).getTime() / 1000) + } + + var name = payProData.domain; + + if (payProData.memo.indexOf('eGifter') > -1) { + name = 'eGifter' + } else if (paymentUrl.indexOf('https://bitpay.com') > -1) { + name = 'BitPay'; + } + + var thirdPartyData = { + id: 'bip70', + amount: amount, caTrusted: true, - domain: 'bitpay.com', - expires: Math.floor(new Date(payProData.expires).getTime() / 1000), + name: name, + domain: payProData.domain, + expires: expires, memo: payProData.memo, network: 'livenet', requiredFeeRate: payProData.requiredFeeRate, selfSigned: 0, - time: Math.ceil(new Date(payProData.time).getTime() / 1000), + time: time, displayAddress: displayAddr, toAddress: toAddr, - url: payProData.paymentUrl, + url: paymentUrl, verified: true }; - } - function handlePayPro(payProDetails, coin) { var stateParams = { - toAmount: payProDetails.amount, - toAddress: payProDetails.toAddress, - description: payProDetails.memo, - paypro: payProDetails, + amount: thirdPartyData.amount, + toAddress: thirdPartyData.toAddress, coin: coin, + thirdParty: thirdPartyData }; // fee - if (payProDetails.requiredFeeRate) { - stateParams.requiredFeeRate = payProDetails.requiredFeeRate * 1024; + if (thirdPartyData.requiredFeeRate) { + stateParams.requiredFeeRate = thirdPartyData.requiredFeeRate * 1024; } + // This does not make sense, thirdPartyData gets added by stateParams below + //sendFlowService.pushState(thirdPartyData); + scannerService.pausePreview(); $state.go('tabs.send', {}, { 'reload': true, 'notify': $state.current.name == 'tabs.send' ? false : true }).then(function() { $timeout(function() { - $state.transitionTo('tabs.send.confirm', stateParams); + sendFlowService.pushState(stateParams); // Need to do more here + $state.transitionTo('tabs.send.origin'); }); }); } diff --git a/src/js/services/paypro.service.js b/src/js/services/paypro.service.js new file mode 100644 index 000000000..8f8db5f5b --- /dev/null +++ b/src/js/services/paypro.service.js @@ -0,0 +1,78 @@ +'use strict'; + +// For BIP70 Payment Protocol + +angular + .module('copayApp.services') + .factory('payproService', payproService); + +function payproService(gettextCatalog, $http, $log, ongoingProcess, platformInfo, profileService) { + + var service = { + getPayProDetails: getPayProDetails, + getPayProDetailsViaHttp: getPayProDetailsViaHttp, + broadcastBchTx: broadcastBchTx + }; + + return service; + + function getPayProDetails(uri, coin, cb, disableLoader) { + if (!cb) cb = function() {}; + + var wallet = profileService.getWallets({ + onlyComplete: true, + coin: coin + })[0]; + + if (!wallet) return cb(); + + if (platformInfo.isChromeApp) { + return cb(gettextCatalog.getString('Payment Protocol not supported on Chrome App')); + } + + $log.debug('Fetch PayPro Request...', uri); + + if (!disableLoader) ongoingProcess.set('fetchingPayPro', true); + + wallet.fetchPayPro({ + payProUrl: uri, + }, function(err, paypro) { + if (!disableLoader) ongoingProcess.set('fetchingPayPro', false); + if (err) return cb(gettextCatalog.getString('Could Not Fetch Payment: Check if it is still valid')); + else if (!paypro.verified) { + $log.warn('Failed to verify payment protocol signatures'); + return cb(gettextCatalog.getString('Payment Protocol Invalid')); + } + return cb(null, paypro); + }); + } + + function getPayProDetailsViaHttp(uri, cb) { + var config = { + headers: {'Accept': 'application/payment-request'} + }; + $http.get(uri, config).then(function onGetPayProDetailsSuccess(response) { + return cb(null, response.data); + }, function onGetPayProDetailsError(error) { + return cb(error, null); + }); + } + + function broadcastBchTx(signedTxp, cb) { + var config = { + headers: {'Content-Type': 'application/payment'} + }; + + var data = { + currency: 'BCH', + transactions: [signedTxp.raw] + }; + + $http.post(signedTxp.payProUrl, data, config).then(function(response) { + signedTxp.response = response.data; + return cb(null, signedTxp); + }, function(error) { + return cb(error.data, null); + }); + } +} diff --git a/src/js/services/payproService.js b/src/js/services/payproService.js deleted file mode 100644 index f0814cc0f..000000000 --- a/src/js/services/payproService.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -angular.module('copayApp.services').factory('payproService', - function(profileService, platformInfo, gettextCatalog, ongoingProcess, $log, $http) { - - var ret = {}; - - ret.getPayProDetails = function(uri, coin, cb, disableLoader) { - if (!cb) cb = function() {}; - - var wallet = profileService.getWallets({ - onlyComplete: true, - coin: coin - })[0]; - - if (!wallet) return cb(); - - if (platformInfo.isChromeApp) { - return cb(gettextCatalog.getString('Payment Protocol not supported on Chrome App')); - } - - $log.debug('Fetch PayPro Request...', uri); - - if (!disableLoader) ongoingProcess.set('fetchingPayPro', true); - - wallet.fetchPayPro({ - payProUrl: uri, - }, function(err, paypro) { - if (!disableLoader) ongoingProcess.set('fetchingPayPro', false); - if (err) return cb(gettextCatalog.getString('Could Not Fetch Payment: Check if it is still valid')); - else if (!paypro.verified) { - $log.warn('Failed to verify payment protocol signatures'); - return cb(gettextCatalog.getString('Payment Protocol Invalid')); - } - return cb(null, paypro); - }); - }; - - ret.getPayProDetailsViaHttp = function(uri, cb) { - var config = { - headers: {'Accept': 'application/payment-request'} - }; - $http.get(uri, config).then(function(response) { - return cb(null, response.data); - }, function(error) { - return cb(error, null); - }); - } - - ret.broadcastBchTx = function(signedTxp, cb) { - var config = { - headers: {'Content-Type': 'application/payment'} - }; - - var data = { - currency: 'BCH', - transactions: [signedTxp.raw] - }; - - $http.post(signedTxp.payProUrl, data, config).then(function(response) { - signedTxp.response = response.data; - return cb(null, signedTxp); - }, function(error) { - return cb(error.data, null); - }); - } - - return ret; - }); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index 4f8710c28..113289104 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -427,9 +427,9 @@ angular.module('copayApp.services') }, function(err, secret) { if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb); - var channel = "firebase"; - if (platformInfo.isNW) { - channel = "ga"; + var channel = "ga"; + if (platformInfo.isCordova) { + channel = "firebase"; } var log = new window.BitAnalytics.LogEvent("wallet_created", [{ "coin": opts.coin @@ -847,6 +847,13 @@ angular.module('copayApp.services') }); } + if (opts.hasNoFunds) { + ret = lodash.filter(ret, function(w) { + if (!w.status) return; + return (w.status.availableBalanceSat === 0); + }); + } + if (opts.minAmount) { ret = lodash.filter(ret, function(w) { if (!w.status) return; diff --git a/src/js/services/secureStorageService.spec.js b/src/js/services/secureStorageService.spec.js index abfa5d947..8d2842a6a 100644 --- a/src/js/services/secureStorageService.spec.js +++ b/src/js/services/secureStorageService.spec.js @@ -1,4 +1,4 @@ -describe('secureStorageService in browser', function(){ +xdescribe('secureStorageService in browser', function(){ var localStorage, sss; @@ -100,7 +100,7 @@ describe('secureStorageService in browser', function(){ }); -describe('secureStorageService on desktop', function(){ +xdescribe('secureStorageService on desktop', function(){ var desktopSss, sss; @@ -202,7 +202,7 @@ describe('secureStorageService on desktop', function(){ }); -describe('secureStorageService on mobile', function(){ +xdescribe('secureStorageService on mobile', function(){ var mobileSss, sss; diff --git a/src/js/services/sendFlowService.js b/src/js/services/sendFlowService.js new file mode 100644 index 000000000..fcb061c26 --- /dev/null +++ b/src/js/services/sendFlowService.js @@ -0,0 +1,101 @@ +'use strict'; + +(function(){ + +angular + .module('copayApp.services') + .factory('sendFlowService', sendFlowService); + + function sendFlowService($log) { + + var service = { + // A separate state variable so we can ensure it is cleared of everything, + // even other properties added that this service does not know about. (such as "coin") + state: { + amount: '', + fromWalletId: '', + sendMax: false, + thirdParty: null, + toAddress: '', + toWalletId: '' + }, + previousStates: [], + + // Functions + clear: clear, + getStateClone: getStateClone, + map: map, + popState: popState, + pushState: pushState, + startSend: startSend + }; + + return service; + + function clear() { + console.log("sendFlow clear()"); + clearCurrent(); + service.previousStates = []; + } + + function clearCurrent() { + console.log("sendFlow clearCurrent()"); + service.state = { + amount: '', + fromWalletId: '', + sendMax: false, + thirdParty: null, + toAddress: '', + toWalletId: '' + } + } + + /** + * Handy for debugging + */ + function getStateClone() { + var currentState = {}; + Object.keys(service.state).forEach(function forCurrentParam(key) { + if (typeof service.state[key] !== 'function' && key !== 'previousStates') { + currentState[key] = service.state[key]; + } + }); + return currentState; + } + + /** + * Clears all previous state + */ + function startSend(params) { + console.log('startSend()'); + clear(); + map(params); + } + + function map(params) { + Object.keys(params).forEach(function forNewParam(key) { + service.state[key] = params[key]; + }); + }; + + function popState() { + console.log('sendFlow pop'); + if (service.previousStates.length) { + var params = service.previousStates.pop(); + clearCurrent(); + map(params); + } else { + clear(); + } + }; + + function pushState(params) { + console.log('sendFlow push'); + var currentParams = getStateClone(); + service.previousStates.push(currentParams); + clearCurrent(); + map(params); + }; + }; + +})(); \ No newline at end of file diff --git a/src/js/services/servicesService.js b/src/js/services/servicesService.js index f2344dd01..316009957 100644 --- a/src/js/services/servicesService.js +++ b/src/js/services/servicesService.js @@ -1,7 +1,12 @@ 'use strict' angular.module('copayApp.services').factory('servicesService', function(configService, $log, lodash) { var root = {}; - var services = []; + var services = [{ + name: 'shapeshift', + title: 'Shapeshift', + icon: 'icon-shapeshift', + sref: 'tabs.shapeshift', + }]; root.register = function(serviceInfo) { $log.info('Adding Services entry:' + serviceInfo.name); diff --git a/src/js/services/shapeshiftService.js b/src/js/services/shapeshiftService.js index 8a9b8fcaa..1ce9672ce 100644 --- a/src/js/services/shapeshiftService.js +++ b/src/js/services/shapeshiftService.js @@ -1,19 +1,141 @@ 'use strict'; -angular.module('copayApp.services').factory('shapeshiftService', function($http, $log, lodash, moment, storageService, configService, platformInfo, servicesService) { + +angular.module('copayApp.services').factory('shapeshiftService', function ($http, $interval, $log, lodash, moment, ongoingProcess, shapeshiftApiService, storageService, configService, incomingData, platformInfo, servicesService) { var root = {}; - var credentials = {}; + root.ShiftState = 'Shift'; + root.coinIn = ''; + root.coinOut = ''; + root.withdrawalAddress = ''; + root.returnAddress = ''; + root.amount = ''; + root.marketData = {}; - var servicesItem = { - name: 'shapeshift', - title: 'Shapeshift', - icon: 'icon-shapeshift', - sref: 'tabs.shapeshift', + root.getMarketDataIn = function (coin) { + if (coin === root.coinOut) return root.getMarketData(root.coinOut, root.coinIn); + return root.getMarketData(coin, root.coinOut); + }; + root.getMarketDataOut = function (coin) { + if (coin === root.coinIn) return root.getMarketData(root.coinOut, root.coinIn); + return root.getMarketData(root.coinIn, coin); + }; + root.getMarketData = function (coinIn, coinOut, cb) { + root.coinIn = coinIn; + root.coinOut = coinOut; + if (root.coinIn === undefined || root.coinOut === undefined) return; + shapeshiftApiService + .marketInfo(root.coinIn, root.coinOut) + .then(function (marketData) { + root.marketData = marketData; + root.rateString = root.marketData.rate.toString() + ' ' + coinOut.toUpperCase() + '/' + coinIn.toUpperCase(); + if (cb) { + cb(marketData); + } + }); }; - var register = function() { - servicesService.register(servicesItem); + /*shapeshiftApiService.coins().then(function(coins){ + root.coins = coins; + root.coinIn = coins['BTC'].symbol; + root.coinOut = coins['BCH'].symbol; + root.getMarketData(root.coinIn, root.coinOut); + });*/ + + root.coins = { + 'BTC': {name: 'Bitcoin', symbol: 'BTC'}, + 'BCH': {name: 'Bitcoin Cash', symbol: 'BCH'} + }; + + function checkForError(data) { + if (data.err) return true; + return false; + } + + root.shiftIt = function (coinIn, coinOut, withdrawalAddress, returnAddress, cb) { + ongoingProcess.set('connectingShapeshift', true); + root.withdrawalAddress = withdrawalAddress; + root.returnAddress = returnAddress; + root.coinIn = coinIn; + root.coinOut = coinOut; + shapeshiftApiService.ValidateAddress(withdrawalAddress, coinOut).then(function (valid) { + var tx = ShapeShift(); + var coin; + console.log("Starting"); + tx.then(function (txData) { + console.log("Got txData", txData); + if (txData['fixedTxData']) { + txData = txData.fixedTxData; + if (checkForError(txData)) return cb(txData.err); + //console.log(txData) + var coinPair = txData.pair.split('_'); + txData.depositType = coinPair[0].toUpperCase(); + txData.withdrawalType = coinPair[1].toUpperCase(); + coin = root.coins[txData.depositType].name.toLowerCase(); + + txData.depositQR = coin + ":" + txData.deposit + "?amount=" + txData.depositAmount; + + root.txFixedPending = true; + + } else if (txData['normalTxData']) { + txData = txData.normalTxData; + if (checkForError(txData)) return cb(txData.err); + coin = root.coins[txData.depositType.toUpperCase()].name.toLowerCase(); + txData.depositQR = coin + ":" + txData.deposit; + } else if (txData['cancelTxData']) { + txData = txData.cancelTxData; + if (checkForError(txData)) return cb(txData.err); + if (root.txFixedPending) { + root.txFixedPending = false; + } + root.ShiftState = 'Shift'; + } + root.depositInfo = txData; + //console.log(root.marketData); + //console.log(root.depositInfo); + var sendAddress = txData.depositQR; + if (sendAddress && sendAddress.indexOf('bitcoin cash') >= 0) + sendAddress = sendAddress.replace('bitcoin cash', 'bitcoincash'); + + ongoingProcess.set('connectingShapeshift', false); + + root.ShiftState = 'Cancel'; + //root.GetStatus(); + //root.txInterval=$interval(root.GetStatus, 8000); + + var shapeshiftData = { + coinIn: coinIn, + coinOut: coinOut, + toWalletId: root.toWalletId, + minAmount: root.marketData.minimum, + maxAmount: root.marketData.maxLimit, + orderId: root.depositInfo.orderId, + toAddress: txData.deposit + }; + // + // if (incomingData.redir(sendAddress, 'shapeshift', shapeshiftData)) { + ongoingProcess.set('connectingShapeshift', false); + // return; + // } + cb(null, shapeshiftData); + }); + }) + }; + + function ShapeShift() { + if (parseFloat(root.amount) > 0) return shapeshiftApiService.FixedAmountTx(root); + return shapeshiftApiService.NormalTx(root); + } + + root.GetStatus = function () { + var address = root.depositInfo.deposit + shapeshiftApiService.GetStatusOfDepositToAddress(address).then(function (data) { + root.DepositStatus = data; + if (root.DepositStatus.status === 'complete') { + $interval.cancel(root.txInterval); + root.depositInfo = null; + root.ShiftState = 'Shift' + } + }); }; - register(); return root; }); diff --git a/src/js/services/storageService.spec.js b/src/js/services/storageService.spec.js index 493678b97..cc3ad285d 100644 --- a/src/js/services/storageService.spec.js +++ b/src/js/services/storageService.spec.js @@ -414,7 +414,7 @@ xdescribe('storageService on desktop', function(){ }); -describe('storageService on desktop using local storage', function(){ +xdescribe('storageService on desktop using local storage', function(){ var appConfig, localStorageServiceMock, log, @@ -614,7 +614,7 @@ describe('storageService on desktop using local storage', function(){ }); -describe('storageService on mobile', function(){ +xdescribe('storageService on mobile', function(){ var appConfig, expectedOldProfileSavedToSecure, expectedOldProfileMergedWithSecure, diff --git a/src/js/services/txFormatService.js b/src/js/services/txFormatService.js index ebcb3886a..1932ebd2a 100644 --- a/src/js/services/txFormatService.js +++ b/src/js/services/txFormatService.js @@ -201,7 +201,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter, var alternativeIsoCode = config.alternativeIsoCode; // If fiat currency - if (currency != 'BCH' && currency != 'BTC' && currency != 'sat') { + if (currency && currency.toUpperCase() != 'BCH' && currency.toUpperCase() != 'BTC' && currency != 'sat') { amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency; amountSat = rateService.fromFiat(amount, currency, coin).toFixed(0); } else if (currency == 'sat') { diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index 774fa0906..647c69734 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -343,21 +343,19 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim if (err) return cb(err); if (!txsFromServer.length) - return cb(); + return cb(null, []); - var res = lodash.takeWhile(txsFromServer, function(tx) { - return tx.txid != endingTxid; - }); - - return cb(null, res, res.length >= limit); + return cb(null, txsFromServer); }); }; var removeAndMarkSoftConfirmedTx = function(txs) { return lodash.filter(txs, function(tx) { - if (tx.confirmations >= root.SOFT_CONFIRMATION_LIMIT) - return tx; - tx.recent = true; + var isConfirm = (tx.confirmations >= root.SOFT_CONFIRMATION_LIMIT); + if (!isConfirm) { + tx.recent = true; + } + return isConfirm; }); } @@ -437,12 +435,14 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim var endingTxid = confirmedTxs[0] ? confirmedTxs[0].txid : null; var endingTs = confirmedTxs[0] ? confirmedTxs[0].time : null; + $log.debug('Confirmed TXs. Got:' + confirmedTxs.length + '/' + txsFromLocal.length); + // First update progressFn(txsFromLocal, 0); wallet.completeHistory = txsFromLocal; function getNewTxs(newTxs, skip, next) { - getTxsFromServer(wallet, skip, endingTxid, requestLimit, function(err, res, shouldContinue) { + getTxsFromServer(wallet, skip, endingTxid, requestLimit, function(err, res) { if (err) { $log.warn(bwcError.msg(err, 'Server Error')); //TODO if (err instanceof errors.CONNECTION_ERROR || (err.message && err.message.match(/5../))) { @@ -454,7 +454,22 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim return next(err); } - newTxs = newTxs.concat(processNewTxs(wallet, lodash.compact(res))); + // Check if new txs are founds, if yes, lets investigate in the 50 next + // To be sure we are not missing txs by sorting (maybe a new tx is after the "endingTxid" + var newDiscoveredTxs = res.filter(function (x) { + return confirmedTxs.filter(function (confX) { + return confX.txid == x.txid; + }).length == 0; + }); + + $log.debug('Discovering TXs. Got:' + newDiscoveredTxs.length); + + var shouldContinue = newDiscoveredTxs.length > 0; + + // If no new tx, no need to check + if (shouldContinue) { + newTxs = newTxs.concat(processNewTxs(wallet, lodash.compact(newDiscoveredTxs))); + } progressFn(newTxs.concat(txsFromLocal), newTxs.length); @@ -884,7 +899,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim var createAddress = function(wallet, cb) { $log.debug('Creating address for wallet:', wallet.id); - wallet.createAddress({}, function(err, addr) { + wallet.createAddress({}, function onWalletCreatedAddress(err, addr) { if (err) { var prefix = gettextCatalog.getString('Could not create address'); if (err instanceof errors.CONNECTION_ERROR || (err.message && err.message.match(/5../))) { @@ -902,6 +917,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim if (err) return cb(err); return cb(null, addr[0].address); }); + return; } return bwcError.cb(err, prefix, cb); } diff --git a/src/sass/buttons.scss b/src/sass/buttons.scss index a8512ae64..df0ce8945 100644 --- a/src/sass/buttons.scss +++ b/src/sass/buttons.scss @@ -55,6 +55,7 @@ .button { border-radius: 6px; &.button-full { + border-radius: 0; display: block; } &-green { @@ -72,5 +73,17 @@ &.activated { color: #FFF; } + &-outline { + @include button-style(transparent, #FFFFFF, #FFFFFF, #FFFFFF, #FFFFFF); + @include button-outline(#FFFFFF); + background: none; + box-shadow: none; + } + } + &-grey-outline { + @include button-style(transparent, #727272, #FAFAFA, #727272, #727272); + @include button-outline(#727272); + background: none; + box-shadow: none; } } \ No newline at end of file diff --git a/src/sass/components/address.scss b/src/sass/components/address-frame.scss similarity index 95% rename from src/sass/components/address.scss rename to src/sass/components/address-frame.scss index 2848deb82..b06ce8bea 100644 --- a/src/sass/components/address.scss +++ b/src/sass/components/address-frame.scss @@ -1,4 +1,4 @@ -.address { +.address-frame { background-color: #F8F8F8; border: 0.5px solid #EDEBEB; border-radius: 3px; diff --git a/src/sass/components/components.scss b/src/sass/components/components.scss index eae56e786..4d2bd695e 100644 --- a/src/sass/components/components.scss +++ b/src/sass/components/components.scss @@ -4,8 +4,9 @@ @import "header"; @import "content-frame"; -@import "address"; +@import "address-frame"; @import "action-minor"; @import "expand-content"; @import "fee-summary"; -@import "amount.scss"; +@import "formatted-amount"; +@import "wallet-balance"; diff --git a/src/sass/components/fee-summary.scss b/src/sass/components/fee-summary.scss index 404643a82..e09af4be3 100644 --- a/src/sass/components/fee-summary.scss +++ b/src/sass/components/fee-summary.scss @@ -1,7 +1,7 @@ .fee-summary { position: relative; display: flex; - justify-content: space-between; + flex-direction: column; width: 100%; padding: 5px 12px 15px; box-sizing: border-box; @@ -17,17 +17,24 @@ background: linear-gradient(to bottom, rgba(242,242,242,0) 0%,rgba(242,242,242,1) 100%); } - .fee-fiat { - &.positive { - color: #70955F; + .amount { + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; + + .fee-fiat { + &.positive { + color: #70955F; + } + + &.negative { + color: #C24633; + } } - &.negative { - color: #C24633; + .fee-crypto { + color: #A7A7A7; } } - - .fee-crypto { - color: #A7A7A7; - } } \ No newline at end of file diff --git a/src/sass/components/amount.scss b/src/sass/components/formatted-amount.scss similarity index 89% rename from src/sass/components/amount.scss rename to src/sass/components/formatted-amount.scss index 363d38a20..6678572c9 100644 --- a/src/sass/components/amount.scss +++ b/src/sass/components/formatted-amount.scss @@ -1,4 +1,6 @@ -.amount { +.formatted-amount { + display: inline-block; + .start, .middle, .end, diff --git a/src/sass/components/header.scss b/src/sass/components/header.scss index fad1f1812..d44c93b60 100644 --- a/src/sass/components/header.scss +++ b/src/sass/components/header.scss @@ -1,6 +1,9 @@ .header { padding: 29px 12px 61px; - background-color: #FAB915; + background-color: $v-bitcoin-orange; + &.btc { + background-color: $v-bitcoin-core; + } color: #FFFFFF; .title { diff --git a/src/sass/components/wallet-balance.scss b/src/sass/components/wallet-balance.scss new file mode 100644 index 000000000..faf4e8611 --- /dev/null +++ b/src/sass/components/wallet-balance.scss @@ -0,0 +1,3 @@ +.wallet-balance-directive { + display: inline-block; +} \ No newline at end of file diff --git a/src/sass/mixins/layout.scss b/src/sass/mixins/layout.scss index b03d53800..269a50320 100644 --- a/src/sass/mixins/layout.scss +++ b/src/sass/mixins/layout.scss @@ -18,3 +18,53 @@ .absolute-center{ @include absolute-center(); } + +.third-party-notice { + font-size: 12px; + margin: 0px 14px; + font-weight: 600; + color: #6F6F70; + + @media (min-width: 768px) { + text-align: center; + } +} + +@mixin empty-case() { + padding-top: 5vh; + text-align: center; + .item { + border-style: none; + } + & > .title { + font-size: 20px; + color: $v-dark-gray; + margin: 20px 10px; + } + & > .subtitle { + font-size: 1rem; + line-height: 1.5em; + font-weight: 300; + color: #6F6F70; + margin: 20px 1em 2.5em; + } + .big-icon-svg { + .bg.green { + padding: 0 10px; + box-shadow: none; + } + } + .buttons { + margin-top: 18px; + .button { + font-weight: bold; + font-size: 19px; + } + } + .button-first-contact img { + height: 19px; + width: 19px; + margin-right: 6px; + vertical-align: sub; + } +} \ No newline at end of file diff --git a/src/sass/qr.scss b/src/sass/qr.scss index 62fd12eb7..5df26e37b 100644 --- a/src/sass/qr.scss +++ b/src/sass/qr.scss @@ -5,8 +5,8 @@ qrcode { content: ""; background-size: 100% 100%; display: block; - left: 88px; - margin-top: 88px; + left: calc(50% - 22px); + margin-top: calc(50% - 22px); width: 44px; height: 44px; position:absolute; diff --git a/src/sass/shame.scss b/src/sass/shame.scss index 07ac2dedf..dbbc222d7 100644 --- a/src/sass/shame.scss +++ b/src/sass/shame.scss @@ -233,6 +233,10 @@ input[type=number] { font-size: 24px; } +.size-25 { + font-size: 25px; +} + .size-28 { font-size: 28px; } @@ -464,3 +468,7 @@ input[type=file] { .white-space-initial { white-space: initial; } + +.height-spacer { + height: 15px; +} diff --git a/src/sass/variables.scss b/src/sass/variables.scss index cb21c030a..49ee6ae89 100644 --- a/src/sass/variables.scss +++ b/src/sass/variables.scss @@ -8,7 +8,9 @@ $v-font-family-light: "Roboto-Light", sans-serif- /* Colors */ $v-bitcoin-orange: #fab915 !default; +$v-bitcoin-core: #535353 !default; +$v-off-black: #262424; $v-dark-gray: #445 !default; $v-mid-gray: #667 !default; $v-light-gray: #9b9bab !default; @@ -24,8 +26,11 @@ $v-text-accent-color: #647ce8 !default; $v-success-color: #13e5b6 !default; $v-warning-color: #ffa500 !default; +$v-warning-color-2: #b7664d; $v-error-color: #ef473a !default; +$v-background-under-card: #f2f2f2; + $v-wallet-color-map: ( 0: (color: #dd4b39, name: 'Cinnabar'), 1: (color: #f38f12, name: 'Carrot Orange'), @@ -77,6 +82,7 @@ $v-button-primary-active-bg: darken($v-accent-color, 10% $v-button-primary-active-border: transparent !default; $v-button-primary-clear-bg: none !default; $v-button-primary-clear-color: $v-accent-color !default; +$v-button-primary-disabled-bg: $v-mid-gray; $v-button-primary-outline-bg: transparent !default; $v-button-primary-outline-border: $v-accent-color !default; $v-button-primary-outline-color: $v-accent-color !default; diff --git a/src/sass/views/amount.scss b/src/sass/views/amount.scss index c712d85e5..bf4d3506a 100644 --- a/src/sass/views/amount.scss +++ b/src/sass/views/amount.scss @@ -244,6 +244,21 @@ flex-direction: column; justify-content: center; + .send-amount-header-footer { + flex: 1 1 auto; + min-height: 20px; + + .warning { + font-weight: bold; + font-size: 12px; + padding: 0 6px 6px 6px; + text-align: center; + } + &__max { + float: right; + } + } + .send-amount-tool { flex: 0 1 auto; @@ -260,6 +275,8 @@ } .primary-amount { + color: #333; + font-weight: bold; input, .unit, .primary-amount-display { font-size: 1.8em; @@ -288,7 +305,8 @@ &.very-long { input, .unit, .primary-amount-display { - font-size: 0.9em; + font-size: 1.2em; // OK for iPhone 5 / SE with BCH to 8dp + @media (min-width: 375px) { font-size: 1.3em; @@ -329,16 +347,15 @@ line-height: 1em; } - .unit { - font-weight: bold; - } - .primary-amount-display { margin-right: 5px; word-break: break-all; } } + .alternative-amount { + color: #6F6F70; + } .switch-currencies { position: absolute; right: 0; @@ -351,26 +368,60 @@ } } } + } + } - .send-amount-actions { - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; + .send-amount-extras { + display: flex; + flex: 0 0 auto; + /* So that if only one item is present, it appears on the right. */ + flex-direction: row-reverse; + font-size: 12px; + align-items: center; + justify-content: space-between; + margin: 0 14px; - .button { - flex: 1 1 auto; - line-height: 1.2em; + .available-funds { + color: #6F6F70; + text-align: left; + } - + .button { - margin-left: 10px; - } + .change-currency { + text-align: right; + } - span { - display: flex; - align-items: center; - justify-content: center; - } + .warning { + color: $v-warning-color-2; + } + + .extra { + flex: 1; + line-height: normal; + + .button { + background: none; + border: none; + border-radius: 0; + color: #000; + font-family: 'ProximaNova'; + font-size: 14px; + line-height: normal; + min-height: auto; + min-width: auto; + padding: 0; + } + + .button .icon:before { + font-size: 14px; + line-height: normal; + } + + + .button { + span { + display: flex; + align-items: center; + justify-content: center; } } } @@ -394,37 +445,58 @@ .keypad-container { position: relative; + font-size: 18px; + line-height: 2em; //flex: 0 1 196px; + @media (min-height: 667px) { + font-size: 24px; + } + + @media(max-height: 480px) { + font-size: 12px; + } + @media (min-height: 667px) { //flex: 0 1 224px; } + .sendmax { + background: $v-off-black; + + .button { + color: white; + background: black; + border: 1px solid $v-off-black; + border-radius: 0; + font-size: 0.8em; + line-height: 2em; + width: 100%; + + .available-funds-amount { + color: #C9C9C9; + } + + &:active { + background-color: $v-dark-gray; + } + } + } + .keypad { text-align: center; - font-size: 18px; font-weight: lighter; position: absolute; bottom: 0; width: 100%; - color: $v-mid-gray; + color: $v-text-primary-color; + - @media (min-height: 667px) { - font-size: 24px; - } .row { padding: 0 !important; margin: 0 !important; } - - .col { - line-height: 38px; - - @media (min-height: 667px) { - line-height: 45px; - } - } .row { &:last-child { @@ -458,23 +530,34 @@ .digit{ cursor: pointer; - border-top: 1px solid $v-subtle-gray; - border-left: 1px solid $v-subtle-gray; + background-color: #000; + border: 1px solid $v-off-black; transition: all 0.1s ease; &:active { - background-color: $v-subtle-gray; + background-color: $v-dark-gray; } } - @media(max-height: 480px) { - font-size: 12px; - - } } } + + .button-primary { + background-color: $v-primary-color; + border-radius: 0; + font-weight: bold; + } + + .button-primary[disabled] { + background-color: $v-button-primary-disabled-bg; + opacity: 1; + } } - background: #494949; + + .warning { + color: $v-warning-color-2; + } + background: $v-background-under-card; ion-content { margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */ diff --git a/src/sass/views/custom-amount.scss b/src/sass/views/custom-amount.scss index b9bf65459..17973101d 100644 --- a/src/sass/views/custom-amount.scss +++ b/src/sass/views/custom-amount.scss @@ -26,16 +26,10 @@ height: 100%; .qr-code { text-align: center; - margin-top: 24vh; - margin-bottom: 7vh; - @media(max-height: 800px) { - margin-top: 18vh; - } - @media(max-height: 700px) { - margin-top: 14vh; - } - @media(max-height: 600px) { - margin-top: 8vh; + margin-top: 6px; + qrcode canvas { + height: 30vh; + max-height: 220px; } } .info { @@ -91,5 +85,34 @@ .address-types { text-align: center; } + + .amount { + margin-top: 20vh; + margin-bottom: 4vh; + @media(max-height: 800px) { + margin-top: 12vh; + margin-bottom: 6vh; + } + @media(max-height: 700px) { + margin-top: 10vh; + margin-bottom: 4vh; + } + @media(max-height: 600px) { + margin-top: 6vh; + margin-bottom: 2vh; + + } + width: 100%; + text-align: center; + //padding-top: 30px; + display: block; + align-items: center; + justify-content: center; + + &-alternative { + line-height: 36px; + } + } + } } diff --git a/src/sass/views/includes/clickToAccept.scss b/src/sass/views/includes/clickToAccept.scss index a38455ac3..cbc7a2c75 100644 --- a/src/sass/views/includes/clickToAccept.scss +++ b/src/sass/views/includes/clickToAccept.scss @@ -8,6 +8,7 @@ click-to-accept { .click-to-accept { &__button.button.button-primary.button-standard { + border-radius: 0; height: 100%; max-width: 9999px; width: 100%; diff --git a/src/sass/views/includes/slideToAccept.scss b/src/sass/views/includes/slideToAccept.scss index 75502c6a8..24775116d 100644 --- a/src/sass/views/includes/slideToAccept.scss +++ b/src/sass/views/includes/slideToAccept.scss @@ -13,6 +13,9 @@ slide-to-accept { } .slide { + .button { + border-radius: 0; + } &__listener { height: 100%; width: 100%; diff --git a/src/sass/views/includes/slideToAcceptSuccess.scss b/src/sass/views/includes/slideToAcceptSuccess.scss index 68312c7a4..f64dd6154 100644 --- a/src/sass/views/includes/slideToAcceptSuccess.scss +++ b/src/sass/views/includes/slideToAcceptSuccess.scss @@ -12,12 +12,6 @@ slide-to-accept-success { .slide-success { $duration: 400ms; - &__windows-background { - background: $v-success-bg-color; - height: 100%; - width: 100%; - position: fixed; - } &__background { $start-radius: 5; $scale-factor: 20; @@ -40,9 +34,11 @@ slide-to-accept-success { &__content { position: relative; z-index: 1; - margin-top: -20vh; + margin-top: -10vh; > img { + width: 45vw; + max-width: 166px; margin-bottom: 1.8rem; -webkit-transform: translateY(5rem); transform: translateY(5rem); @@ -59,7 +55,7 @@ slide-to-accept-success { &__header { color: #FFFFFF; - font-size: 26px; + font-size: 29px; -webkit-transform: translateY(5rem); transform: translateY(5rem); opacity: 0; @@ -72,6 +68,26 @@ slide-to-accept-success { opacity: 1; } } + &__share { + transition: transform $duration ease, opacity $duration ease; + transition-delay: 600ms; + opacity: 0; + margin-top: 15vh; + span { + color: #FFF; + font-size: 22px; + height: 28px; + } + img { + height: 28px; + width: auto; + vertical-align: bottom; + margin-right: 4px; + } + &.reveal { + opacity: 0.79; + } + } } &__footer { @@ -98,11 +114,11 @@ slide-to-accept-success { &__btn { display: block; color: #FFFFFF; - font-size: 18px; + font-size: 22px; font-weight: 600; letter-spacing: 2.86px; - padding: 1rem 0 1.1rem; - border-top: 1px solid rgba(255, 255, 255, .45); + padding: 2rem 0 2.1rem; + border-top: 1px solid rgba(255, 255, 255, 0.25); cursor: pointer; } } diff --git a/src/sass/views/review.scss b/src/sass/views/review.scss index 67733fe22..c530a1cef 100644 --- a/src/sass/views/review.scss +++ b/src/sass/views/review.scss @@ -1,5 +1,4 @@ #view-review { - background-color: #494949; slide-to-accept, slide-to-accept-success { margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */ @@ -10,4 +9,12 @@ position: absolute; bottom: 92px; } + + .shapeshift-banner, .bitpay-banner, .egifter-banner { + box-shadow: none; + } + + .warning { + color: $v-warning-color-2; + } } \ No newline at end of file diff --git a/src/sass/views/shapeshift.scss b/src/sass/views/shapeshift.scss new file mode 100644 index 000000000..5b63c0354 --- /dev/null +++ b/src/sass/views/shapeshift.scss @@ -0,0 +1,23 @@ +#shapeshift { + .swap-image { + width: auto; + max-width: 400px; + max-height: 25vh; + } + .empty-case { + @include empty-case(); + } + .button-shapeshift { + @extend %button-standard; + + @include button-style(#243F5D, #FFF, #606060, #FFF, #FFF); + @include button-clear(#FFF); + @include button-outline(#C1C1C1); + border: 0px; + @include button-shadow(); + } +} +.header.shapeshift { + background: url(../img/shapeshiftbg.jpg) center center repeat #28394d; + opacity: 0.99; +} \ No newline at end of file diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index 66a2f1d58..55080ab7b 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -69,6 +69,30 @@ } } } + .buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + margin: 6px auto -12px; + text-align: center; + width: 100%; + >.col { + padding: 5px 10px; + margin-bottom: 0; + } + .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + max-width: 300px; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; + } + } .wallet-coin-logo { vertical-align: middle; margin-right: 5px; diff --git a/src/sass/views/tab-send.scss b/src/sass/views/tab-send.scss index a4025156f..bf77984fd 100644 --- a/src/sass/views/tab-send.scss +++ b/src/sass/views/tab-send.scss @@ -2,15 +2,15 @@ @extend .deflash-blue; &-header{ - height: 300px; + //height: 300px; width: 100%; } &-contacts { - height: calc(100vh - 300px - 50px - 44px); /* screen size - button container - bottom-tab-menu - header top */ + //height: calc(100vh - 300px - 50px - 44px); /* screen size - button container - bottom-tab-menu - header top */ &.ios { - height: calc(100vh - 300px - 50px - 44px - 18px); // Remove the notification-bar height on iOS + //height: calc(100vh - 300px - 50px - 44px - 18px); // Remove the notification-bar height on iOS } - overflow: scroll; + //overflow: scroll; } .input { @@ -88,6 +88,8 @@ &.contains-address { .address { display: inline; + border: none; + background-color: transparent; } .non-address { display: none; @@ -133,42 +135,7 @@ padding-left: 30px; } .sendTip { - padding-top: 5vh; - text-align: center; - .item { - border-style: none; - } - & > .title { - font-size: 20px; - color: $v-dark-gray; - margin: 20px 10px; - } - & > .subtitle { - font-size: 1rem; - line-height: 1.5em; - font-weight: 300; - color: #6F6F70; - margin: 20px 1em 2.5em; - } - .big-icon-svg { - .bg.green { - padding: 0 10px; - box-shadow: none; - } - } - .buttons { - margin-top: 18px; - .button { - font-weight: bold; - font-size: 19px; - } - } - .button-first-contact img { - height: 19px; - width: 19px; - margin-right: 6px; - vertical-align: sub; - } + @include empty-case(); } .item-heading { line-height: 16px; @@ -256,12 +223,12 @@ } } #tab-send-header { - height: 270px; + //height: 270px; } #tab-send-contacts { - height: calc(100vh - 270px - 50px - 44px); /* screen size - button container - bottom-tab-menu - header top */ + //height: calc(100vh - 270px - 50px - 44px); /* screen size - button container - bottom-tab-menu - header top */ &.ios { - height: calc(100vh - 270px - 50px - 44px - 18px); // Remove the notification-bar height on iOS + //height: calc(100vh - 270px - 50px - 44px - 18px); // Remove the notification-bar height on iOS } } } diff --git a/src/sass/views/views.scss b/src/sass/views/views.scss index 1e54062f9..1f25b564a 100644 --- a/src/sass/views/views.scss +++ b/src/sass/views/views.scss @@ -8,11 +8,13 @@ @import "tab-receive"; @import "tab-scan"; @import "tab-send"; +@import "wallet-origin-destination"; @import "tab-settings"; @import "wallet-colors"; @import "walletBalance"; @import "walletDetails"; @import "advancedSettings"; +@import "shapeshift"; @import "bitpayCard"; @import "bitpayCardIntro"; @import "buyandsell"; diff --git a/src/sass/views/wallet-origin-destination.scss b/src/sass/views/wallet-origin-destination.scss new file mode 100644 index 000000000..1c6016862 --- /dev/null +++ b/src/sass/views/wallet-origin-destination.scss @@ -0,0 +1,74 @@ +#wallet-origin-destination { + .header--request { + padding: 30px 24px; + width: 100%; + height: 139px; + background-color: #fff; + &__title { + width: 46px; + height: 20px; + font-size: 16px; + font-weight: 600; + letter-spacing: -0.4px; + color: #000000; + } + &__amount { + font-size: 29px; + font-weight: 600; + letter-spacing: -0.7px; + color: #000000; + margin: 11px 0 2px; + } + &__amount-alt { + opacity: 0.45; + font-size: 16px; + font-weight: 600; + letter-spacing: -0.4px; + color: #000000; + } + } + .wallets-header { + margin: 20px 14px 0px; + + .title { + font-size: 16px; + font-weight: bold; + color: $v-dark-gray; + margin-bottom: -12px; + } + } + .card { + font-size: 12px; + margin: 20px 14px 0px; + + .item-heading { + .subtitle { + font-size: 12px; + } + font-weight: 600; + + } + + &-insufficient { + .wallet { + opacity: 0.4; + + } + .item-heading { + font-size: 12px; + >div { + display: inline-block; + vertical-align: text-bottom; + } + } + &__dot { + display: inline-block; + width: 16px; + height: 16px; + background-color: #ec5959; + border-radius: 8px; + margin: 2px 6px 2px 2px; + } + } + } +} \ No newline at end of file diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index 9e651f871..858229d85 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -135,11 +135,12 @@ &.status-bar { margin-top: 20px; + margin-top: env(safe-area-inset-top); } } .bar-header { border: 0; - background: none; + background: rgb(238, 182, 64); .title, .button { color: #fff; } @@ -153,7 +154,7 @@ ion-content { &.collapsible { - margin-top: 210px; + margin-top: 230px; } padding-top: 0; @@ -190,12 +191,38 @@ transform: translateY(100px); } } + + .send-receive-buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + width: 100%; + position: absolute; + bottom: 20px; + + >.col { + padding: 5px 10px; + margin-bottom: 0; + } + .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + max-width: 300px; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; + } + } } .amount { width: 100%; text-align: center; color: #fff; - height: 210px; + height: 230px; padding-top: 40px; display: block; align-items: center; @@ -234,6 +261,7 @@ .no-alternative { padding-top: 45px; } + .item.item-footer { font-weight: lighter; } diff --git a/test/karma.conf.js b/test/karma.conf.js index 002d40c91..b4f64af73 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -17,6 +17,8 @@ module.exports = function(config) { files: [ 'node_modules/angular/angular.js', + 'bitanalytics/bitanalytics-0.1.0.js', + // From Gruntfile.js 'bower_components/qrcode-generator/js/qrcode.js', 'bower_components/qrcode-generator/js/qrcode_UTF8.js', diff --git a/www/css/bitcoin.com.css b/www/css/bitcoin.com.css index 9b69005c4..f0d7eab30 100644 --- a/www/css/bitcoin.com.css +++ b/www/css/bitcoin.com.css @@ -318,5 +318,33 @@ div.slide-success__background.fill-screen { display: block; float: left; max-height: 100%; - max-width: 100%; + max-width: 100%; +} + +.bitpay-banner { + background: #1A3A8B; + padding: 10px; + box-shadow: 0px 5px 10px 0px #cccccc; + height: 5em; +} + +.bitpay-logo { + display: block; + max-height: 100%; + width: 100%; + height: 4em; +} + +.egifter-banner { + background: #066EAA; + padding: 10px; + box-shadow: 0px 5px 10px 0px #cccccc; + height: 5em; + text-align: center; +} + +.egifter-logo { + max-height: 100%; + max-width: 100%; + height: 4em; } diff --git a/www/css/main.css b/www/css/main.css index bcc3a5acf..8602ba35d 100644 --- a/www/css/main.css +++ b/www/css/main.css @@ -10082,7 +10082,7 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm .onboarding .button.button-light.button-standard, .onboarding .button.button-white.button-standard, .onboarding .button.button-green.button-standard, -.onboarding .button.button-assertive.button-standard { +.onboarding .button.button-assertive.button-standard, #shapeshift .button-shapeshift { width: 85%; max-width: 300px; margin-left: auto; @@ -10253,6 +10253,46 @@ ion-view.deflash-blue:before, ion-view#view-amount:before, ion-view#view-confirm color: #fff; } .button-white.activated { color: #FFF; } + .button-white-outline { + border-color: #FFFFFF; + background-color: transparent; + color: #FFFFFF; + background: none; + box-shadow: none; } + .button-white-outline:hover { + color: #FFFFFF; + text-decoration: none; } + .button-white-outline.active, .button-white-outline.activated { + border-color: #FFF; + background-color: #FAFAFA; } + .button-white-outline.button-outline { + border-color: #FFFFFF; + background: transparent; + color: #FFFFFF; } + .button-white-outline.button-outline.active, .button-white-outline.button-outline.activated { + background-color: #FFFFFF; + box-shadow: none; + color: #fff; } + .button-grey-outline { + border-color: #727272; + background-color: transparent; + color: #727272; + background: none; + box-shadow: none; } + .button-grey-outline:hover { + color: #727272; + text-decoration: none; } + .button-grey-outline.active, .button-grey-outline.activated { + border-color: #727272; + background-color: #FAFAFA; } + .button-grey-outline.button-outline { + border-color: #727272; + background: transparent; + color: #727272; } + .button-grey-outline.button-outline.active, .button-grey-outline.button-outline.activated { + background-color: #727272; + box-shadow: none; + color: #fff; } .button-clear { background: none !important; } @@ -10271,8 +10311,8 @@ qrcode { content: ""; background-size: 100% 100%; display: block; - left: 88px; - margin-top: 88px; + left: calc(50% - 22px); + margin-top: calc(50% - 22px); width: 44px; height: 44px; position: absolute; } @@ -10292,6 +10332,15 @@ qrcode { top: 50%; left: 50%; } +.third-party-notice { + font-size: 12px; + margin: 0px 14px; + font-weight: 600; + color: #6F6F70; } + @media (min-width: 768px) { + .third-party-notice { + text-align: center; } } + .tabs .tab-item .icon { background-repeat: no-repeat; background-position: center; @@ -10349,7 +10398,7 @@ qrcode { padding: 10px; } #view-amount { - background: #494949; } + background: #f2f2f2; } #view-amount .recipient-label { font-size: 14px; padding-bottom: 0; @@ -10542,6 +10591,16 @@ qrcode { display: flex; flex-direction: column; justify-content: center; } + #view-amount .scroll-content .send-amount .send-amount-header-footer { + flex: 1 1 auto; + min-height: 20px; } + #view-amount .scroll-content .send-amount .send-amount-header-footer .warning { + font-weight: bold; + font-size: 12px; + padding: 0 6px 6px 6px; + text-align: center; } + #view-amount .scroll-content .send-amount .send-amount-header-footer__max { + float: right; } #view-amount .scroll-content .send-amount .send-amount-tool { flex: 0 1 auto; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input { @@ -10553,53 +10612,56 @@ qrcode { -moz-user-select: text; -ms-user-select: text; user-select: text; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { - font-size: 1.8em; } - @media (min-width: 375px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { - font-size: 2.1em; } } - @media (min-width: 414px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { - font-size: 2.4em; } } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { - font-size: 1.6em; } - @media (min-width: 375px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { - font-size: 1.8em; } } - @media (min-width: 414px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { - font-size: 2em; } } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { - font-size: 0.9em; } - @media (min-width: 375px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { - font-size: 1.3em; } } - @media (min-width: 414px) { - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { - font-size: 1.4em; } } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input { - border: 0; - padding: 0; - white-space: normal; - background: none; - line-height: 1; - box-sizing: content-box; - display: inline-block; - vertical-align: middle; - margin: 0; - height: 1em; - margin-right: 5px; - font-family: 'ProximaNova'; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { - display: inline-block; - vertical-align: middle; - line-height: 1em; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount { + color: #333; font-weight: bold; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { - margin-right: 5px; - word-break: break-all; } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { + font-size: 1.8em; } + @media (min-width: 375px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { + font-size: 2.1em; } } + @media (min-width: 414px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { + font-size: 2.4em; } } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { + font-size: 1.6em; } + @media (min-width: 375px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { + font-size: 1.8em; } } + @media (min-width: 414px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.long .primary-amount-display { + font-size: 2em; } } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { + font-size: 0.9em; } + @media (min-width: 375px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { + font-size: 1.3em; } } + @media (min-width: 414px) { + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long input, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .unit, #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount.very-long .primary-amount-display { + font-size: 1.4em; } } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount input { + border: 0; + padding: 0; + white-space: normal; + background: none; + line-height: 1; + box-sizing: content-box; + display: inline-block; + vertical-align: middle; + margin: 0; + height: 1em; + margin-right: 5px; + font-family: 'ProximaNova'; } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .unit, + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { + display: inline-block; + vertical-align: middle; + line-height: 1em; } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .primary-amount .primary-amount-display { + margin-right: 5px; + word-break: break-all; } + #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .alternative-amount { + color: #6F6F70; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .switch-currencies { position: absolute; right: 0; @@ -10608,20 +10670,40 @@ qrcode { padding: 15px; } #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-tool-input .switch-currencies img { width: 18px; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-actions { - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-actions .button { - flex: 1 1 auto; - line-height: 1.2em; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-actions .button + .button { - margin-left: 10px; } - #view-amount .scroll-content .send-amount .send-amount-tool .send-amount-actions .button span { - display: flex; - align-items: center; - justify-content: center; } + #view-amount .scroll-content .send-amount-extras { + display: flex; + flex: 0 0 auto; + /* So that if only one item is present, it appears on the right. */ + flex-direction: row-reverse; + font-size: 12px; + align-items: center; + justify-content: space-between; + margin: 0 14px; } + #view-amount .scroll-content .send-amount-extras .available-funds { + color: #6F6F70; } + #view-amount .scroll-content .send-amount-extras .warning { + color: #b7664d; } + #view-amount .scroll-content .send-amount-extras .extra, + #view-amount .scroll-content .send-amount-extras button.extra { + /*display: flex;*/ + flex: 0 1 auto; } + #view-amount .scroll-content .send-amount-extras button.extra { + background: none; + border: none; + color: #000; + font-family: 'ProximaNova'; + font-size: 14px; + line-height: normal; + min-height: auto; + min-width: auto; + padding: 0; } + #view-amount .scroll-content .send-amount-extras .button .icon:before { + font-size: 14px; + line-height: normal; } + #view-amount .scroll-content .send-amount-extras .button span { + display: flex; + align-items: center; + justify-content: center; } #view-amount .scroll-content .button.no-margin { margin: 0; } #view-amount .scroll-content .notification-warning { @@ -10633,26 +10715,39 @@ qrcode { line-height: 1.4em; margin-bottom: 20px; } #view-amount .scroll-content .keypad-container { - position: relative; } + position: relative; + font-size: 18px; + line-height: 2em; } + @media (min-height: 667px) { + #view-amount .scroll-content .keypad-container { + font-size: 24px; } } + @media (max-height: 480px) { + #view-amount .scroll-content .keypad-container { + font-size: 12px; } } + #view-amount .scroll-content .keypad-container .sendmax { + background: #262424; } + #view-amount .scroll-content .keypad-container .sendmax .button { + color: white; + background: black; + border: 1px solid #262424; + border-radius: 0; + font-size: 0.8em; + line-height: 2em; + width: 100%; } + #view-amount .scroll-content .keypad-container .sendmax .button .available-funds-amount { + color: #C9C9C9; } + #view-amount .scroll-content .keypad-container .sendmax .button:active { + background-color: #445; } #view-amount .scroll-content .keypad-container .keypad { text-align: center; - font-size: 18px; font-weight: lighter; position: absolute; bottom: 0; width: 100%; - color: #667; } - @media (min-height: 667px) { - #view-amount .scroll-content .keypad-container .keypad { - font-size: 24px; } } + color: #fff; } #view-amount .scroll-content .keypad-container .keypad .row { padding: 0 !important; margin: 0 !important; } - #view-amount .scroll-content .keypad-container .keypad .col { - line-height: 38px; } - @media (min-height: 667px) { - #view-amount .scroll-content .keypad-container .keypad .col { - line-height: 45px; } } #view-amount .scroll-content .keypad-container .keypad .row:last-child .col { padding-bottom: 10px; } #view-amount .scroll-content .keypad-container .keypad .operator { @@ -10671,14 +10766,20 @@ qrcode { background-color: #eaeaea; } #view-amount .scroll-content .keypad-container .keypad .digit { cursor: pointer; - border-top: 1px solid #f2f2f2; - border-left: 1px solid #f2f2f2; + background-color: #000; + border: 1px solid #262424; transition: all 0.1s ease; } #view-amount .scroll-content .keypad-container .keypad .digit:active { - background-color: #f2f2f2; } - @media (max-height: 480px) { - #view-amount .scroll-content .keypad-container .keypad { - font-size: 12px; } } + background-color: #445; } + #view-amount .scroll-content .button-primary { + background-color: #fab915; + border-radius: 0; + font-weight: bold; } + #view-amount .scroll-content .button-primary[disabled] { + background-color: #667; + opacity: 1; } + #view-amount .warning { + color: #b7664d; } #view-amount ion-content { margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */ @@ -10825,6 +10926,28 @@ qrcode { width: 100%; display: block; } +#tab-home .buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + margin: 6px auto -12px; + text-align: center; + width: 100%; } + #tab-home .buttons > .col { + padding: 5px 10px; + margin-bottom: 0; } + #tab-home .buttons .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + max-width: 300px; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; } + #tab-home .wallet-coin-logo { vertical-align: middle; margin-right: 5px; } @@ -11045,16 +11168,8 @@ qrcode { background-color: #fab915 !important; } #tab-send-header { - height: 300px; width: 100%; } -#tab-send-contacts { - height: calc(100vh - 300px - 50px - 44px); - /* screen size - button container - bottom-tab-menu - header top */ - overflow: scroll; } - #tab-send-contacts.ios { - height: calc(100vh - 300px - 50px - 44px - 18px); } - #tab-send .input { width: 100%; } #tab-send .input input { @@ -11118,7 +11233,9 @@ qrcode { #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-address .icon, #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-content .icon { background: url(../img/icon-clipboard-paste-white.svg); } #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-address.contains-address .address, #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-content.contains-address .address { - display: inline; } + display: inline; + border: none; + background-color: transparent; } #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-address.contains-address .non-address, #tab-send .send-wrapper .buttons .button-clipboard-paste.contains-content.contains-address .non-address { display: none; } #tab-send .send-wrapper .buttons .button span { @@ -11233,14 +11350,62 @@ qrcode { #tab-send .send-wrapper .buttons .button-qr { height: 60px; } #tab-send .send-wrapper .buttons .button-qr span { - font-size: 16px; } - #tab-send #tab-send-header { - height: 270px; } - #tab-send #tab-send-contacts { - height: calc(100vh - 270px - 50px - 44px); - /* screen size - button container - bottom-tab-menu - header top */ } - #tab-send #tab-send-contacts.ios { - height: calc(100vh - 270px - 50px - 44px - 18px); } } + font-size: 16px; } } + +#wallet-origin-destination .header--request { + padding: 30px 24px; + width: 100%; + height: 139px; + background-color: #fff; } + #wallet-origin-destination .header--request__title { + width: 46px; + height: 20px; + font-size: 16px; + font-weight: 600; + letter-spacing: -0.4px; + color: #000000; } + #wallet-origin-destination .header--request__amount { + font-size: 29px; + font-weight: 600; + letter-spacing: -0.7px; + color: #000000; + margin: 11px 0 2px; } + #wallet-origin-destination .header--request__amount-alt { + opacity: 0.45; + font-size: 16px; + font-weight: 600; + letter-spacing: -0.4px; + color: #000000; } + +#wallet-origin-destination .wallets-header { + margin: 20px 14px 0px; } + #wallet-origin-destination .wallets-header .title { + font-size: 16px; + font-weight: bold; + color: #445; + margin-bottom: -12px; } + +#wallet-origin-destination .card { + font-size: 12px; + margin: 20px 14px 0px; } + #wallet-origin-destination .card .item-heading { + font-weight: 600; } + #wallet-origin-destination .card .item-heading .subtitle { + font-size: 12px; } + #wallet-origin-destination .card-insufficient .wallet { + opacity: 0.4; } + #wallet-origin-destination .card-insufficient .item-heading { + font-size: 12px; } + #wallet-origin-destination .card-insufficient .item-heading > div { + display: inline-block; + vertical-align: text-bottom; } + #wallet-origin-destination .card-insufficient__dot { + display: inline-block; + width: 16px; + height: 16px; + background-color: #ec5959; + border-radius: 8px; + margin: 2px 6px 2px 2px; } .settings .icon-bitpay { background-image: url("../img/icon-bitpay.svg"); } @@ -11753,10 +11918,11 @@ qrcode { height: 100%; height: calc(100% - env(safe-area-inset-bottom) * 2); } #walletDetails .bp-content.status-bar { - margin-top: 20px; } + margin-top: 20px; + margin-top: env(safe-area-inset-top); } #walletDetails .bar-header { border: 0; - background: none; } + background: #eeb640; } #walletDetails .bar-header .title, #walletDetails .bar-header .button { color: #fff; } #walletDetails .bar-header .button { @@ -11768,7 +11934,7 @@ qrcode { top: 0; margin-bottom: 16px; } #walletDetails ion-content.collapsible { - margin-top: 210px; } + margin-top: 230px; } #walletDetails ion-content .scroll { background: #f8f8f9; min-height: 300px; } @@ -11793,11 +11959,32 @@ qrcode { height: 200px; -webkit-transform: translateY(100px); transform: translateY(100px); } + #walletDetails .amount-wrapper .send-receive-buttons { + display: flex; + flex-direction: row; + justify-content: space-evenly; + width: 100%; + position: absolute; + bottom: 20px; } + #walletDetails .amount-wrapper .send-receive-buttons > .col { + padding: 5px 10px; + margin-bottom: 0; } + #walletDetails .amount-wrapper .send-receive-buttons .button { + border: 2px solid; + border-radius: 47px; + padding: 0 15px 0 15px; + text-align: center; + width: 100%; + max-width: 300px; + font-size: 19px; + font-weight: bolder; + min-height: auto; + line-height: 36px; } #walletDetails .amount { width: 100%; text-align: center; color: #fff; - height: 210px; + height: 230px; padding-top: 40px; display: block; align-items: center; @@ -11911,6 +12098,73 @@ a.item { color: #667; font-size: 0.9em; } +#shapeshift .swap-image { + width: auto; + max-width: 400px; + max-height: 25vh; } + +#shapeshift .empty-case { + padding-top: 5vh; + text-align: center; } + #shapeshift .empty-case .item { + border-style: none; } + #shapeshift .empty-case > .title { + font-size: 20px; + color: #445; + margin: 20px 10px; } + #shapeshift .empty-case > .subtitle { + font-size: 1rem; + line-height: 1.5em; + font-weight: 300; + color: #6F6F70; + margin: 20px 1em 2.5em; } + #shapeshift .empty-case .big-icon-svg .bg.green { + padding: 0 10px; + box-shadow: none; } + #shapeshift .empty-case .buttons { + margin-top: 18px; } + #shapeshift .empty-case .buttons .button { + font-weight: bold; + font-size: 19px; } + #shapeshift .empty-case .button-first-contact img { + height: 19px; + width: 19px; + margin-right: 6px; + vertical-align: sub; } + +#shapeshift .button-shapeshift { + border-color: #FFF; + background-color: #243F5D; + color: #FFF; + border: 0px; + box-shadow: 0 2px 11px 0 #C1C1C1; } + #shapeshift .button-shapeshift:hover { + color: #FFF; + text-decoration: none; } + #shapeshift .button-shapeshift.active, #shapeshift .button-shapeshift.activated { + border-color: #FFF; + background-color: #606060; } + #shapeshift .button-shapeshift.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #FFF; } + #shapeshift .button-shapeshift.button-icon { + border-color: transparent; + background: none; } + #shapeshift .button-shapeshift.button-outline { + border-color: #C1C1C1; + background: transparent; + color: #C1C1C1; } + #shapeshift .button-shapeshift.button-outline.active, #shapeshift .button-shapeshift.button-outline.activated { + background-color: #C1C1C1; + box-shadow: none; + color: #fff; } + +.header.shapeshift { + background: url(../img/shapeshiftbg.jpg) center center repeat #28394d; + opacity: 0.99; } + #bitpayCard { background: white; } #bitpayCard .status-label { @@ -13790,11 +14044,6 @@ slide-to-accept-success { display: flex; align-items: center; justify-content: center; } - slide-to-accept-success .slide-success__windows-background { - background: #11D1A6; - height: 100%; - width: 100%; - position: fixed; } slide-to-accept-success .slide-success__background { height: 10vmax; width: 10vmax; @@ -13811,8 +14060,10 @@ slide-to-accept-success { slide-to-accept-success .slide-success__content { position: relative; z-index: 1; - margin-top: -20vh; } + margin-top: -10vh; } slide-to-accept-success .slide-success__content > img { + width: 45vw; + max-width: 166px; margin-bottom: 1.8rem; -webkit-transform: translateY(5rem); transform: translateY(5rem); @@ -13825,7 +14076,7 @@ slide-to-accept-success { opacity: 1; } slide-to-accept-success .slide-success__content__header { color: #FFFFFF; - font-size: 26px; + font-size: 29px; -webkit-transform: translateY(5rem); transform: translateY(5rem); opacity: 0; @@ -13835,6 +14086,22 @@ slide-to-accept-success { -webkit-transform: translateY(0); transform: translateY(0); opacity: 1; } + slide-to-accept-success .slide-success__content__share { + transition: transform 400ms ease, opacity 400ms ease; + transition-delay: 600ms; + opacity: 0; + margin-top: 15vh; } + slide-to-accept-success .slide-success__content__share span { + color: #FFF; + font-size: 22px; + height: 28px; } + slide-to-accept-success .slide-success__content__share img { + height: 28px; + width: auto; + vertical-align: bottom; + margin-right: 4px; } + slide-to-accept-success .slide-success__content__share.reveal { + opacity: 0.79; } slide-to-accept-success .slide-success__footer { position: absolute; left: 0; @@ -13857,11 +14124,11 @@ slide-to-accept-success { slide-to-accept-success .slide-success__footer__btn { display: block; color: #FFFFFF; - font-size: 18px; + font-size: 22px; font-weight: 600; letter-spacing: 2.86px; - padding: 1rem 0 1.1rem; - border-top: 1px solid rgba(255, 255, 255, 0.45); + padding: 2rem 0 2.1rem; + border-top: 1px solid rgba(255, 255, 255, 0.25); cursor: pointer; } #tx-details .action-created.action-accepted { @@ -14803,17 +15070,10 @@ account-selector { height: 100%; } #custom-amount .address .qr-code { text-align: center; - margin-top: 24vh; - margin-bottom: 7vh; } - @media (max-height: 800px) { - #custom-amount .address .qr-code { - margin-top: 18vh; } } - @media (max-height: 700px) { - #custom-amount .address .qr-code { - margin-top: 14vh; } } - @media (max-height: 600px) { - #custom-amount .address .qr-code { - margin-top: 8vh; } } + margin-top: 6px; } + #custom-amount .address .qr-code qrcode canvas { + height: 30vh; + max-height: 220px; } #custom-amount .address .info { position: absolute; width: 100%; @@ -14853,6 +15113,28 @@ account-selector { margin-left: 10px; } #custom-amount .address .address-types { text-align: center; } + #custom-amount .address .amount { + margin-top: 20vh; + margin-bottom: 4vh; + width: 100%; + text-align: center; + display: block; + align-items: center; + justify-content: center; } + @media (max-height: 800px) { + #custom-amount .address .amount { + margin-top: 12vh; + margin-bottom: 6vh; } } + @media (max-height: 700px) { + #custom-amount .address .amount { + margin-top: 10vh; + margin-bottom: 4vh; } } + @media (max-height: 600px) { + #custom-amount .address .amount { + margin-top: 6vh; + margin-bottom: 2vh; } } + #custom-amount .address .amount-alternative { + line-height: 36px; } #pin { background-color: #FAFAFA; @@ -15077,22 +15359,203 @@ log-options #check-bar .checkbox-icon { #view-review .fee-summary { position: absolute; bottom: 92px; } + #view-review .shapeshift-banner, #view-review .bitpay-banner, #view-review .egifter-banner { + box-shadow: none; } + #view-review .warning { + color: #b7664d; } .gravatar { border-radius: 3px; display: inline-block; } -(??) +.elastic { + width: 100%; + font-size: 14px; } -(??) +/* +* Extends Ionic v1 item +*/ +.item.item-compact { + padding: 11px 13px; } -(??) +.item.item-gutterless { + padding: 0; } -(??) +.item .item-content.item-content-avatar { + min-height: 69px; + padding: 13px 11px 13px 68px; } + .item .item-content.item-content-avatar > img:first-child, + .item .item-content.item-content-avatar > i:first-child { + position: absolute; + max-width: 40px; + max-height: 40px; + width: 100%; + height: 100%; + border-radius: 50%; + left: 13px; + top: 50%; + padding: 0; + transform: translate(0, -50%); } -(??) +.item .item-content.item-content-compact { + min-height: 0; + padding: 13px 11px; } -(??) +.item .item-content .highlight { + color: #FAB915; } + +.item .item-content + .item-content { + padding-top: 0; } + +/* +* Extends Ionic v1 ion-content +*/ +ion-content.bg-neutral { + background-color: #F2F2F2; } + +ion-content.padded-bottom-cta { + bottom: 92px; } + +ion-content.padded-bottom-cta-with-summary { + bottom: 134px; } + +.card.card-gutter-compact { + margin: 10px 12px; } + +.header { + padding: 29px 12px 61px; + background-color: #fab915; + color: #FFFFFF; } + .header.btc { + background-color: #535353; } + .header .title { + font-size: 18px; + font-weight: 400; + line-height: 1em; + color: #FFFFFF; + text-align: center; } + .header .title + .content { + margin-top: 23px; } + .header .content { + text-align: center; } + .header .content p { + margin: 0; + line-height: 1em; + font-size: 18px; } + .header .content p.large { + font-size: 29px; + font-weight: 600; } + .header .content p + p { + margin-top: 8px; } + +.content-frame.negative-top { + margin-top: -40px; } + .content-frame.negative-top .card:first-child { + margin-top: 0; } + +.address-frame { + background-color: #F8F8F8; + border: 0.5px solid #EDEBEB; + border-radius: 3px; + padding: 9px; + text-align: center; + font-size: 14px; + overflow: hidden; + text-overflow: ellipsis; } + .address-frame.expanded { + white-space: pre-wrap; + word-break: break-all; } + .address-frame .prefix { + color: #000000; } + .address-frame .mid { + color: #919191; } + .address-frame .suffix { + color: #000000; } + +.action-minor { + margin: 20px 14px; + font-size: 14px; } + .action-minor.mt-negative { + margin-top: 0; } + .action-minor.text-right { + text-align: right; } + .action-minor > .action-icon { + width: 15px; + height: 15px; + vertical-align: middle; + margin-right: 3px; } + .action-minor > .action-text { + vertical-align: middle; + color: #444444; } + +.expand-content-frame { + position: relative; } + .expand-content-frame .expand-content-trigger { + position: absolute; + top: 0; + transition: opacity 0.3s ease; + right: 0; } + .expand-content-frame .expand-content-trigger.expand-content-revealed { + opacity: 0; } + .expand-content-frame .expand-content { + opacity: 0; + transform-origin: 100% 0%; + transform: scale(0, 0); + transition: opacity 0.3s ease, transform 0.3s ease; } + .expand-content-frame .expand-content.expand-content-revealed { + opacity: 1; + transform: scale(1, 1); } + +.fee-summary { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + padding: 5px 12px 15px; + box-sizing: border-box; + background-color: #F2F2F2; } + .fee-summary:before { + content: ''; + position: absolute; + left: 0; + top: -15px; + width: 100%; + height: 15px; + background: linear-gradient(to bottom, rgba(242, 242, 242, 0) 0%, #f2f2f2 100%); } + .fee-summary .amount { + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; } + .fee-summary .amount .fee-fiat.positive { + color: #70955F; } + .fee-summary .amount .fee-fiat.negative { + color: #C24633; } + .fee-summary .amount .fee-crypto { + color: #A7A7A7; } + +.formatted-amount { + display: inline-block; } + .formatted-amount .start, + .formatted-amount .middle, + .formatted-amount .end, + .formatted-amount .currency { + display: inline-block; } + .formatted-amount .start { + font-size: 1em; } + .formatted-amount .middle { + font-size: 0.7857em; + margin-left: 5px; } + .formatted-amount .end { + font-size: 0.7857em; + margin-left: 5px; } + .formatted-amount.size-equal .middle, + .formatted-amount.size-equal .end { + font-size: 1em; } + .formatted-amount .currency { + font-size: 1em; + margin-left: 5px; + text-transform: uppercase; } /* This is for rules that don't yet have a home. * Our goal is to delete this file. Search the regex: /class=".*CLASS.*?"/ @@ -15275,6 +15738,9 @@ input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer .size-24 { font-size: 24px; } +.size-25 { + font-size: 25px; } + .size-28 { font-size: 28px; } @@ -15449,3 +15915,6 @@ input[type=file] { .white-space-initial { white-space: initial; } + +.height-spacer { + height: 15px; } diff --git a/www/img/bitpay_banner.svg b/www/img/bitpay_banner.svg new file mode 100644 index 000000000..cf5829899 --- /dev/null +++ b/www/img/bitpay_banner.svg @@ -0,0 +1,13 @@ + + + + Artboard + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/www/img/egifter_banner.png b/www/img/egifter_banner.png new file mode 100644 index 000000000..cb2e7c11e Binary files /dev/null and b/www/img/egifter_banner.png differ diff --git a/www/img/icon-alternative-currency-black.svg b/www/img/icon-alternative-currency-black.svg new file mode 100644 index 000000000..e9b175256 --- /dev/null +++ b/www/img/icon-alternative-currency-black.svg @@ -0,0 +1,22 @@ + + + + 3A719124-019D-470F-908A-5D61F117A295 + Created with sketchtool. + + + + + + + + + + + + + + + + + diff --git a/www/img/icon-egifter.png b/www/img/icon-egifter.png new file mode 100644 index 000000000..42ebb25c5 Binary files /dev/null and b/www/img/icon-egifter.png differ diff --git a/www/img/icon-sent-successful.svg b/www/img/icon-sent-successful.svg new file mode 100644 index 000000000..070357ddf --- /dev/null +++ b/www/img/icon-sent-successful.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/www/img/icon-share-white.svg b/www/img/icon-share-white.svg new file mode 100644 index 000000000..eeb3e7b6b --- /dev/null +++ b/www/img/icon-share-white.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/www/img/shapeshift_swap.png b/www/img/shapeshift_swap.png new file mode 100644 index 000000000..83905b751 Binary files /dev/null and b/www/img/shapeshift_swap.png differ diff --git a/www/views/amount.html b/www/views/amount.html index af4e9d55c..939937be8 100644 --- a/www/views/amount.html +++ b/www/views/amount.html @@ -1,82 +1,99 @@ - {{'Enter amount' | translate}} + {{'Enter Amount' | translate}} - + - - +
- -
-
- Minimum amount: {{minShapeshiftAmount}}
- Maximum amount: {{maxShapeshiftAmount}}
+
+
- {{ amountModel.amount || 0 }}{{unit}} + ng-class="{long: vm.amount.length > 5, 'very-long': vm.amount.length > 8}"> + + {{vm.amount || '0'}} {{vm.unit}} +
- {{globalResult}} {{unit}} +
- {{alternativeAmount || '0.00'}} {{alternativeUnit}} + {{vm.alternativeAmount || '0.00'}} {{vm.alternativeUnit}}
-
+
-
- - + +
+
+ +
+
+
+
+ Available Funds: +
+
-
+
+ +
+ +
-
7
-
8
-
9
+
7
+
8
+
9
-
4
-
5
-
6
+
4
+
5
+
6
-
1
-
2
-
3
+
1
+
2
+
3
-
.
-
0
-
+
.
+
0
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
- +
@@ -57,12 +71,6 @@ {{address}}
-
- Amount - - {{amountUnitStr}} - {{altAmountStr}} - -
diff --git a/www/views/includes/amount.html b/www/views/includes/formatted-amount.html similarity index 54% rename from www/views/includes/amount.html rename to www/views/includes/formatted-amount.html index 361dededc..45451a718 100644 --- a/www/views/includes/amount.html +++ b/www/views/includes/formatted-amount.html @@ -1,4 +1,4 @@ -
- {{start}}{{middle}}{{end}}{{currency}} +
+ {{start}}{{middle}}{{end}}{{vm.currency}}
\ No newline at end of file diff --git a/www/views/includes/slideToAcceptSuccess.html b/www/views/includes/slideToAcceptSuccess.html index 923eab25c..9995001ae 100644 --- a/www/views/includes/slideToAcceptSuccess.html +++ b/www/views/includes/slideToAcceptSuccess.html @@ -1,13 +1,16 @@
+ ng-class="{'fill-screen': fillScreen}">
- +
Payment Sent
+