From 5d9255b8623eaa732b2f1c2285288ed7cea636af Mon Sep 17 00:00:00 2001 From: Marshall Rose Date: Thu, 8 Sep 2016 11:02:46 -0700 Subject: [PATCH 1/3] add geoIP & BTC exchange information geoIP is done without any interaction-with/reporting-to brave software exchange information is downloaded for all country codes from the ledger --- app/ledger.js | 75 +++++++++++++++++++++++++++++++++++---------------- package.json | 1 + 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/app/ledger.js b/app/ledger.js index d03899bb6f6..17a9eff601d 100644 --- a/app/ledger.js +++ b/app/ledger.js @@ -32,6 +32,7 @@ const session = electron.session const acorn = require('acorn') const ledgerBalance = require('ledger-balance') const ledgerClient = require('ledger-client') +const ledgerGeoIP = require('ledger-geoip') const ledgerPublisher = require('ledger-publisher') const qr = require('qr-image') const random = require('random-lib') @@ -117,10 +118,11 @@ var init = () => { try { ledgerInfo._internal.debugP = ledgerClient.prototype.boolion(process.env.LEDGER_CLIENT_DEBUG) publisherInfo._internal.debugP = ledgerClient.prototype.boolion(process.env.LEDGER_PUBLISHER_DEBUG) + publisherInfo._internal.verboseP = ledgerClient.prototype.boolion(process.env.LEDGER_PUBLISHER_VERBOSE) appDispatcher.register(doAction) initialize(getSetting(settings.PAYMENTS_ENABLED)) - } catch (ex) { console.log('initialization failed: ' + ex.toString() + '\n' + ex.stack) } + } catch (ex) { console.log('ledger.js initialization failed: ' + ex.toString() + '\n' + ex.stack) } } var quit = () => { @@ -178,7 +180,7 @@ if (ipc) { ctx = url.parse(location, true) ctx.TLD = tldjs.getPublicSuffix(ctx.host) if (!ctx.TLD) { - console.log('\nno TLD for:' + ctx.host) + if (publisherInfo._internal.verboseP) console.log('\nno TLD for:' + ctx.host) event.returnValue = {} return } @@ -264,11 +266,11 @@ eventStore.addChangeListener(() => { request.request({ url: url, responseType: 'blob' }, (err, response, blob) => { var matchP, prefix, tail -/* - console.log('\nresponse: ' + url + - ' errP=' + (!!err) + ' blob=' + (blob || '').substr(0, 80) + '\nresponse=' + - JSON.stringify(response, null, 2)) - */ + if (publisherInfo._internal.debugP) { + console.log('\nresponse: ' + url + + ' errP=' + (!!err) + ' blob=' + (blob || '').substr(0, 80) + '\nresponse=' + + JSON.stringify(response, null, 2)) + } if (err) return console.log('response error: ' + err.toString() + '\n' + err.stack) @@ -298,20 +300,18 @@ eventStore.addChangeListener(() => { entry.faviconURL = blob updatePublisherInfo() -/* - console.log('\n' + publisher + ' synopsis=' + - JSON.stringify(underscore.extend(underscore.omit(entry, [ 'faviconURL', 'window' ]), - { faviconURL: entry.faviconURL && '... ' }), null, 2)) - */ + if (publisherInfo._internal.debugP) { + console.log('\n' + publisher + ' synopsis=' + + JSON.stringify(underscore.extend(underscore.omit(entry, [ 'faviconURL', 'window' ]), + { faviconURL: entry.faviconURL && '... ' }), null, 2)) + } }) } faviconURL = page.faviconURL || entry.protocol + '//' + url.parse(location).host + '/favicon.ico' entry.faviconURL = null -/* - console.log('request: ' + faviconURL) - */ + if (publisherInfo._internal.debugP) console.log('request: ' + faviconURL) fetch(faviconURL) } }) @@ -385,14 +385,14 @@ var enable = (onoff) => { synopsis = new (ledgerPublisher.Synopsis)() fs.readFile(pathName(synopsisPath), (err, data) => { - if (clientOptions.verboseP) console.log('\nstarting up ledger publisher integration') + if (publisherInfo._internal.verboseP) console.log('\nstarting up ledger publisher integration') if (err) { if (err.code !== 'ENOENT') console.log('synopsisPath read error: ' + err.toString()) return updatePublisherInfo() } - if (clientOptions.verboseP) console.log('\nfound ' + pathName(synopsisPath)) + if (publisherInfo._internal.verboseP) console.log('\nfound ' + pathName(synopsisPath)) try { synopsis = new (ledgerPublisher.Synopsis)(data) } catch (ex) { @@ -413,7 +413,7 @@ var enable = (onoff) => { return } - if (clientOptions.verboseP) console.log('\nfound ' + pathName(publisherPath)) + if (publisherInfo._internal.verboseP) console.log('\nfound ' + pathName(publisherPath)) try { data = JSON.parse(data) underscore.keys(data).sort().forEach((publisher) => { @@ -580,7 +580,7 @@ var visit = (location, timestamp) => { if (!synopsis) return - if (publisherInfo._internal.debugP) { + if (publisherInfo._internal.verboseP) { console.log('locations[' + currentLocation + ']=' + JSON.stringify(locations[currentLocation], null, 2) + ' duration=' + (timestamp - currentTimestamp) + ' msec') } @@ -593,7 +593,7 @@ var visit = (location, timestamp) => { publishers[publisher][currentLocation] = timestamp duration = timestamp - currentTimestamp - if (publisherInfo._internal.debugP) console.log('\nadd publisher ' + publisher + ': ' + duration + ' msec') + if (publisherInfo._internal.verboseP) console.log('\nadd publisher ' + publisher + ': ' + duration + ' msec') synopsis.addPublisher(publisher, duration) updatePublisherInfo() } @@ -670,7 +670,7 @@ var cacheRuleSet = (ruleset) => { if ((rule.consequent !== null) || (rule.dom)) return if (!rulesolver.resolve(rule.condition, ctx)) return - if (clientOptions.verboseP) console.log('\npurging ' + publisher) + if (publisherInfo._internal.verboseP) console.log('\npurging ' + publisher) delete synopsis.publishers[publisher] syncP = true }) @@ -724,7 +724,7 @@ var ledgerInfo = { */ ], -// set from ledger client's state.paymentInfo OR client's getWalletProperties + // set from ledger client's state.paymentInfo OR client's getWalletProperties // Bitcoin wallet address address: undefined, @@ -744,7 +744,15 @@ var ledgerInfo = { hasBitcoinHandler: false, - _internal: {}, + // geoIP/exchange information + countryCode: undefined, + exchangeInfo: undefined, + + _internal: { + exchangeExpiry: 0, + exchanges: {}, + geoipExpiry: 0 + }, error: null } @@ -759,6 +767,27 @@ var updateLedgerInfo = () => { underscore.extend(ledgerInfo, ledgerInfo._internal.cache || {}) } + if ((client) && (now > ledgerInfo._internal.geoipExpiry)) { + ledgerInfo._internal.geoipExpiry = now + (5 * msecs.minute) + return ledgerGeoIP.getGeoIP(client.options, (err, provider, result) => { + if (err) console.log('ledger geoip warning: ' + JSON.stringify(err, null, 2)) + if (result) ledgerInfo.countryCode = result + + ledgerInfo.exchangeInfo = ledgerInfo._internal.exchanges[ledgerInfo.countryCode] + + if (now <= ledgerInfo._internal.exchangeExpiry) return updateLedgerInfo() + + ledgerInfo._internal.exchangeExpiry = now + msecs.day + roundtrip({ path: '/v1/exchange/providers' }, client.options, (err, response, body) => { + if (err) console.log('ledger exchange error: ' + JSON.stringify(err, null, 2)) + + ledgerInfo._internal.exchanges = body + ledgerInfo.exchangeInfo = ledgerInfo._internal.exchanges[ledgerInfo.countryCode] + updateLedgerInfo() + }) + }) + } + if (ledgerInfo._internal.debugP) { console.log('\nupdateLedgerInfo: ' + JSON.stringify(underscore.omit(ledgerInfo, [ '_internal' ]), null, 2)) } diff --git a/package.json b/package.json index 3accf2b3e59..fcbaaf59969 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "l20n": "^3.5.1", "ledger-balance": "^0.8.46", "ledger-client": "^0.8.59", + "ledger-geoip": "https://github.com/brave/ledger-geoip.git", "ledger-publisher": "^0.8.58", "lru_cache": "^1.0.0", "qr-image": "^3.1.0", From 59e4385ef7b08471d7da02c8efcd254699dfaa8f Mon Sep 17 00:00:00 2001 From: Marshall Rose Date: Thu, 8 Sep 2016 11:23:10 -0700 Subject: [PATCH 2/3] update docs/state.md --- docs/state.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/state.md b/docs/state.md index 6fce9cb1d01..ed539e6ded5 100644 --- a/docs/state.md +++ b/docs/state.md @@ -435,8 +435,14 @@ WindowStore } }, hasBitcoinHandler: boolean, // brave browser has a `bitcoin:` URI handler - paymentIMG: string, // the QR code equivalent of `paymentURL` expressed as "data:image/...;base64,..." - error: { // non-null if the last updateLedgerInfo happened concurrently with an error + countryCode: // ISO3166 2-letter code for country of browser's location + exchangeInfo: { // information about corresponding "friendliest" BTC exchange (suggestions welcome!) + titleText: string, // e.g., 'Create an account on ...' + buttonText: string, // e.g., 'Create' + buttonURL: string, // where the button should take the browser + } + paymentIMG: string, // the QR code equivalent of `paymentURL` expressed as "data:image/...;base64,..." + error: { // non-null if the last updateLedgerInfo happened concurrently with an error caller: string // function in which error was handled error: object // error object returned } From eb5bdd8bafe413c795f794b7c8c83b57fff8e8eb Mon Sep 17 00:00:00 2001 From: Marshall Rose Date: Thu, 8 Sep 2016 14:14:34 -0700 Subject: [PATCH 3/3] fixes based on review --- app/ledger.js | 2 +- docs/state.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/ledger.js b/app/ledger.js index 54987a41a68..c3eb01464a7 100644 --- a/app/ledger.js +++ b/app/ledger.js @@ -786,7 +786,7 @@ var updateLedgerInfo = () => { roundtrip({ path: '/v1/exchange/providers' }, client.options, (err, response, body) => { if (err) console.log('ledger exchange error: ' + JSON.stringify(err, null, 2)) - ledgerInfo._internal.exchanges = body + ledgerInfo._internal.exchanges = body || {} ledgerInfo.exchangeInfo = ledgerInfo._internal.exchanges[ledgerInfo.countryCode] updateLedgerInfo() }) diff --git a/docs/state.md b/docs/state.md index ed539e6ded5..74114a8c138 100644 --- a/docs/state.md +++ b/docs/state.md @@ -435,7 +435,7 @@ WindowStore } }, hasBitcoinHandler: boolean, // brave browser has a `bitcoin:` URI handler - countryCode: // ISO3166 2-letter code for country of browser's location + countryCode: string, // ISO3166 2-letter code for country of browser's location exchangeInfo: { // information about corresponding "friendliest" BTC exchange (suggestions welcome!) titleText: string, // e.g., 'Create an account on ...' buttonText: string, // e.g., 'Create'