diff options
Diffstat (limited to 'app/scripts/lib')
-rw-r--r-- | app/scripts/lib/ens-ipfs/contracts/registrar.js (renamed from app/scripts/lib/contracts/registrar.js) | 0 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/contracts/resolver.js (renamed from app/scripts/lib/contracts/resolver.js) | 0 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/resolver.js | 54 | ||||
-rw-r--r-- | app/scripts/lib/ens-ipfs/setup.js | 63 | ||||
-rw-r--r-- | app/scripts/lib/ipfsContent.js | 46 | ||||
-rw-r--r-- | app/scripts/lib/reportFailedTxToSentry.js | 6 | ||||
-rw-r--r-- | app/scripts/lib/resolver.js | 71 | ||||
-rw-r--r-- | app/scripts/lib/setupFetchDebugging.js | 10 | ||||
-rw-r--r-- | app/scripts/lib/setupSentry.js (renamed from app/scripts/lib/setupRaven.js) | 75 |
9 files changed, 162 insertions, 163 deletions
diff --git a/app/scripts/lib/contracts/registrar.js b/app/scripts/lib/ens-ipfs/contracts/registrar.js index 99ca24458..99ca24458 100644 --- a/app/scripts/lib/contracts/registrar.js +++ b/app/scripts/lib/ens-ipfs/contracts/registrar.js diff --git a/app/scripts/lib/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js index 1bf3f90ce..1bf3f90ce 100644 --- a/app/scripts/lib/contracts/resolver.js +++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js new file mode 100644 index 000000000..fe2dc1134 --- /dev/null +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -0,0 +1,54 @@ +const namehash = require('eth-ens-namehash') +const multihash = require('multihashes') +const Eth = require('ethjs-query') +const EthContract = require('ethjs-contract') +const registrarAbi = require('./contracts/registrar') +const resolverAbi = require('./contracts/resolver') + +module.exports = resolveEnsToIpfsContentId + + +async function resolveEnsToIpfsContentId ({ provider, name }) { + const eth = new Eth(provider) + const hash = namehash.hash(name) + const contract = new EthContract(eth) + // lookup registrar + const chainId = Number.parseInt(await eth.net_version(), 10) + const registrarAddress = getRegistrarForChainId(chainId) + if (!registrarAddress) { + throw new Error(`EnsIpfsResolver - no known ens-ipfs registrar for chainId "${chainId}"`) + } + const Registrar = contract(registrarAbi).at(registrarAddress) + // lookup resolver + const resolverLookupResult = await Registrar.resolver(hash) + const resolverAddress = resolverLookupResult[0] + if (hexValueIsEmpty(resolverAddress)) { + throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`) + } + const Resolver = contract(resolverAbi).at(resolverAddress) + // lookup content id + const contentLookupResult = await Resolver.content(hash) + const contentHash = contentLookupResult[0] + if (hexValueIsEmpty(contentHash)) { + throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`) + } + const nonPrefixedHex = contentHash.slice(2) + const buffer = multihash.fromHexString(nonPrefixedHex) + const contentId = multihash.toB58String(multihash.encode(buffer, 'sha2-256')) + return contentId +} + +function hexValueIsEmpty(value) { + return [undefined, null, '0x', '0x0', '0x0000000000000000000000000000000000000000000000000000000000000000'].includes(value) +} + +function getRegistrarForChainId (chainId) { + switch (chainId) { + // mainnet + case 1: + return '0x314159265dd8dbb310642f98f50c066173c1259b' + // ropsten + case 3: + return '0x112234455c3a32fd11230c42e7bccd4a84e02010' + } +} diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js new file mode 100644 index 000000000..45eb1ce14 --- /dev/null +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -0,0 +1,63 @@ +const urlUtil = require('url') +const extension = require('extensionizer') +const resolveEnsToIpfsContentId = require('./resolver.js') + +const supportedTopLevelDomains = ['eth'] + +module.exports = setupEnsIpfsResolver + +function setupEnsIpfsResolver({ provider }) { + + // install listener + const urlPatterns = supportedTopLevelDomains.map(tld => `*://*.${tld}/*`) + extension.webRequest.onErrorOccurred.addListener(webRequestDidFail, { urls: urlPatterns }) + + // return api object + return { + // uninstall listener + remove () { + extension.webRequest.onErrorOccurred.removeListener(webRequestDidFail) + }, + } + + async function webRequestDidFail (details) { + const { tabId, url } = details + // ignore requests that are not associated with tabs + if (tabId === -1) return + // parse ens name + const urlData = urlUtil.parse(url) + const { hostname: name, path, search } = urlData + const domainParts = name.split('.') + const topLevelDomain = domainParts[domainParts.length - 1] + // if unsupported TLD, abort + if (!supportedTopLevelDomains.includes(topLevelDomain)) return + // otherwise attempt resolve + attemptResolve({ tabId, name, path, search }) + } + + async function attemptResolve({ tabId, name, path, search }) { + extension.tabs.update(tabId, { url: `loading.html` }) + try { + const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name }) + let url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}` + try { + // check if ipfs gateway has result + const response = await fetch(url, { method: 'HEAD' }) + // if failure, redirect to 404 page + if (response.status !== 200) { + extension.tabs.update(tabId, { url: '404.html' }) + return + } + // otherwise redirect to the correct page + extension.tabs.update(tabId, { url }) + } catch (err) { + console.warn(err) + // if HEAD fetch failed, redirect so user can see relevant error page + extension.tabs.update(tabId, { url }) + } + } catch (err) { + console.warn(err) + extension.tabs.update(tabId, { url: `error.html?name=${name}` }) + } + } +} diff --git a/app/scripts/lib/ipfsContent.js b/app/scripts/lib/ipfsContent.js deleted file mode 100644 index 8b08453c4..000000000 --- a/app/scripts/lib/ipfsContent.js +++ /dev/null @@ -1,46 +0,0 @@ -const extension = require('extensionizer') -const resolver = require('./resolver.js') - -module.exports = function (provider) { - function ipfsContent (details) { - const name = details.url.substring(7, details.url.length - 1) - let clearTime = null - if (/^.+\.eth$/.test(name) === false) return - - extension.tabs.query({active: true}, tab => { - extension.tabs.update(tab.id, { url: 'loading.html' }) - - clearTime = setTimeout(() => { - return extension.tabs.update(tab.id, { url: '404.html' }) - }, 60000) - - resolver.resolve(name, provider).then(ipfsHash => { - clearTimeout(clearTime) - let url = 'https://ipfs.infura.io/ipfs/' + ipfsHash - return fetch(url, { method: 'HEAD' }).then(response => response.status).then(statusCode => { - if (statusCode !== 200) return extension.tabs.update(tab.id, { url: '404.html' }) - extension.tabs.update(tab.id, { url: url }) - }) - .catch(err => { - url = 'https://ipfs.infura.io/ipfs/' + ipfsHash - extension.tabs.update(tab.id, {url: url}) - return err - }) - }) - .catch(err => { - clearTimeout(clearTime) - const url = err === 'unsupport' ? 'unsupport' : 'error' - extension.tabs.update(tab.id, {url: `${url}.html?name=${name}`}) - }) - }) - return { cancel: true } - } - - extension.webRequest.onErrorOccurred.addListener(ipfsContent, {urls: ['*://*.eth/'], types: ['main_frame']}) - - return { - remove () { - extension.webRequest.onErrorOccurred.removeListener(ipfsContent) - }, - } -} diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js index df5661e59..de4d57145 100644 --- a/app/scripts/lib/reportFailedTxToSentry.js +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -7,10 +7,10 @@ module.exports = reportFailedTxToSentry // for sending to sentry // -function reportFailedTxToSentry ({ raven, txMeta }) { +function reportFailedTxToSentry ({ sentry, txMeta }) { const errorMessage = 'Transaction Failed: ' + extractEthjsErrorMessage(txMeta.err.message) - raven.captureMessage(errorMessage, { + sentry.captureMessage(errorMessage, { // "extra" key is required by Sentry - extra: txMeta, + extra: { txMeta }, }) } diff --git a/app/scripts/lib/resolver.js b/app/scripts/lib/resolver.js deleted file mode 100644 index ff0fed161..000000000 --- a/app/scripts/lib/resolver.js +++ /dev/null @@ -1,71 +0,0 @@ -const namehash = require('eth-ens-namehash') -const multihash = require('multihashes') -const HttpProvider = require('ethjs-provider-http') -const Eth = require('ethjs-query') -const EthContract = require('ethjs-contract') -const registrarAbi = require('./contracts/registrar') -const resolverAbi = require('./contracts/resolver') - -function ens (name, provider) { - const eth = new Eth(new HttpProvider(getProvider(provider.type))) - const hash = namehash.hash(name) - const contract = new EthContract(eth) - const Registrar = contract(registrarAbi).at(getRegistrar(provider.type)) - return new Promise((resolve, reject) => { - if (provider.type === 'mainnet' || provider.type === 'ropsten') { - Registrar.resolver(hash).then((address) => { - if (address === '0x0000000000000000000000000000000000000000') { - reject(null) - } else { - const Resolver = contract(resolverAbi).at(address['0']) - return Resolver.content(hash) - } - }).then((contentHash) => { - if (contentHash['0'] === '0x0000000000000000000000000000000000000000000000000000000000000000') reject(null) - if (contentHash.ret !== '0x') { - const hex = contentHash['0'].substring(2) - const buf = multihash.fromHexString(hex) - resolve(multihash.toB58String(multihash.encode(buf, 'sha2-256'))) - } else { - reject(null) - } - }) - } else { - return reject('unsupport') - } - }) -} - -function getProvider (type) { - switch (type) { - case 'mainnet': - return 'https://mainnet.infura.io/' - case 'ropsten': - return 'https://ropsten.infura.io/' - default: - return 'http://localhost:8545/' - } -} - -function getRegistrar (type) { - switch (type) { - case 'mainnet': - return '0x314159265dd8dbb310642f98f50c066173c1259b' - case 'ropsten': - return '0x112234455c3a32fd11230c42e7bccd4a84e02010' - default: - return '0x0000000000000000000000000000000000000000' - } -} - -module.exports.resolve = function (name, provider) { - const path = name.split('.') - const topLevelDomain = path[path.length - 1] - if (topLevelDomain === 'eth' || topLevelDomain === 'test') { - return ens(name, provider) - } else { - return new Promise((resolve, reject) => { - reject(null) - }) - } -} diff --git a/app/scripts/lib/setupFetchDebugging.js b/app/scripts/lib/setupFetchDebugging.js index dd87b65a6..c1ef22d21 100644 --- a/app/scripts/lib/setupFetchDebugging.js +++ b/app/scripts/lib/setupFetchDebugging.js @@ -2,7 +2,7 @@ module.exports = setupFetchDebugging // // This is a utility to help resolve cases where `window.fetch` throws a -// `TypeError: Failed to Fetch` without any stack or context for the request +// `TypeError: Failed to Fetch` without any stack or context for the request // https://github.com/getsentry/sentry-javascript/pull/1293 // @@ -17,9 +17,11 @@ function setupFetchDebugging() { try { return await originalFetch.call(window, ...args) } catch (err) { - console.warn('FetchDebugger - fetch encountered an Error', err) - console.warn('FetchDebugger - overriding stack to point of original call') - err.stack = initialStack + if (!err.stack) { + console.warn('FetchDebugger - fetch encountered an Error without a stack', err) + console.warn('FetchDebugger - overriding stack to point of original call') + err.stack = initialStack + } throw err } } diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupSentry.js index e6e511640..69042bc19 100644 --- a/app/scripts/lib/setupRaven.js +++ b/app/scripts/lib/setupSentry.js @@ -1,58 +1,55 @@ -const Raven = require('raven-js') +const Sentry = require('@sentry/browser') const METAMASK_DEBUG = process.env.METAMASK_DEBUG const extractEthjsErrorMessage = require('./extractEthjsErrorMessage') -const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' -const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' +const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' +const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' -module.exports = setupRaven +module.exports = setupSentry -// Setup raven / sentry remote error reporting -function setupRaven (opts) { - const { release } = opts - let ravenTarget +// Setup sentry remote error reporting +function setupSentry (opts) { + const { release, getState } = opts + let sentryTarget // detect brave const isBrave = Boolean(window.chrome.ipcRenderer) if (METAMASK_DEBUG) { - console.log('Setting up Sentry Remote Error Reporting: DEV') - ravenTarget = DEV + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV') + sentryTarget = SENTRY_DSN_DEV } else { - console.log('Setting up Sentry Remote Error Reporting: PROD') - ravenTarget = PROD + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_PROD') + sentryTarget = SENTRY_DSN_PROD } - const client = Raven.config(ravenTarget, { + Sentry.init({ + dsn: sentryTarget, + debug: METAMASK_DEBUG, release, - transport: function (opts) { - opts.data.extra.isBrave = isBrave - const report = opts.data + beforeSend: (report) => rewriteReport(report), + }) - try { - // handle error-like non-error exceptions - rewriteErrorLikeExceptions(report) - // simplify certain complex error messages (e.g. Ethjs) - simplifyErrorMessages(report) - // modify report urls - rewriteReportUrls(report) - } catch (err) { - console.warn(err) - } - // make request normally - client._makeRequest(opts) - }, + Sentry.configureScope(scope => { + scope.setExtra('isBrave', isBrave) }) - client.install() - return Raven -} + function rewriteReport(report) { + try { + // simplify certain complex error messages (e.g. Ethjs) + simplifyErrorMessages(report) + // modify report urls + rewriteReportUrls(report) + // append app state + if (getState) { + const appState = getState() + report.extra.appState = appState + } + } catch (err) { + console.warn(err) + } + return report + } -function rewriteErrorLikeExceptions (report) { - // handle errors that lost their error-ness in serialization (e.g. dnode) - rewriteErrorMessages(report, (errorMessage) => { - if (!errorMessage.includes('Non-Error exception captured with keys:')) return errorMessage - if (!(report.extra && report.extra.__serialized__ && report.extra.__serialized__.message)) return errorMessage - return `Non-Error Exception: ${report.extra.__serialized__.message}` - }) + return Sentry } function simplifyErrorMessages (report) { |