Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration ENS with IPFS #4405

Merged
merged 17 commits into from
Jul 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions app/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<html>
<head>
<title>MetaMask</title>
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
img{
display: block;
}
html, body{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.app{
position: relative;
width: 100%;
height: auto;
overflow: hidden;
}
img{
display: block;
width: 100%;
height: auto;
}
h2{
display: block;
width: 100%;
overflow: hidden;
position: absolute;
bottom: 20%;
left: 0;
color: #1b243d;
text-align: center;
}
h2 > a{
color: #1b243d;
}
</style>
</head>
<body>
<div class="app">
<img src="./images/404.png" alt="">
<h2>Powered by <a href="https://www.portal.network/">Portal Network</a></h2>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure how I felt about this at first, but you know, getting credit for what you do seems pretty fair. I'm fine leaving it up, at least for a while. The same way we link to 409H for the phishing detector.

</div>
</body>
</html>
79 changes: 79 additions & 0 deletions app/error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<html>
<head>
<title>MetaMask Error</title>
<link href="https://fonts.googleapis.com/css?family=Rokkitt" rel="stylesheet">
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
img{
display: block;
}
html, body{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
@keyframes logoAmin{
from {transform: scale(1);}
50%{transform: scale(1.1);}
to {transform: scale(1);}
}
.errorBox{
width: 70%;
height: auto;
overflow: hidden;
background-image: url("./images/deadface.png");
background-repeat: no-repeat;
background-position: 100% 50%;
background-size: auto 90%;
padding: 5px;
}
.errorBox > img{
width: 100px;
height: auto;
margin-bottom: 25px;
animation: logoAmin 1s infinite linear;
}
.errorBox > h1, .errorBox > h2{
letter-spacing: 2px;
}
.errorBox > h1{
color: #9b9b9b;
font-size: 40px;
}
.errorBox > h2{
color: #1b243d;
font-size: 20px;
padding-top: 5px;
}
.errorBox > h2 >a{
color: #1b243d;
}
.errorBox > h2 >a:hover{
color: #44588e;
}

.errorBox > h1 > span{
color: #33559f;
}

</style>
</head>
<body>
<div class="errorBox">
<img src="./images/logo.png" alt="">
<h1><span id="name"></span> not found</h1>
<h2>Powered by <a href="https://www.portal.network/">Portal Network</a></h2>
</div>
<script>
let index = location.href.lastIndexOf("?name=")
let name = location.href.slice(index + 6)
document.getElementById("name").innerHTML = name
</script>
</body>
</html>
Binary file added app/images/404.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/cancel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/deadface.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions app/images/loginglogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/pw-128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/pw-48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/pw128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions app/loading.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<html>
<head>
<title>MetaMask Loading</title>
<style>
#div-logo {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 256px;
}
#logo {
width: 100%;
animation: pulse 1s ease-in-out infinite;
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
transform: scale(0.95, 0.95);
}
100% {
opacity: 1;
}
}
</style>
</head>
<body>
<div id="div-logo">
<img id="logo" src="./images/loginglogo.svg">
</div>
</body>
</html>
7 changes: 5 additions & 2 deletions app/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@
"unlimitedStorage",
"clipboardWrite",
"http://localhost:8545/",
"https://*.infura.io/"
"https://*.infura.io/",
"activeTab",
"webRequest",
"*://*.eth/"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to appear in permissions dialog for Chrome as "eth websites" without an indication it's talking about a TLD. Leaving the user wondering "What is an eth website?"

],
"web_accessible_resources": [
"inpage.js"
Expand All @@ -72,4 +75,4 @@
"*"
]
}
}
}
5 changes: 5 additions & 0 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics')
const EdgeEncryptor = require('./edge-encryptor')
const getFirstPreferredLangCode = require('./lib/get-first-preferred-lang-code')
const getObjStructure = require('./lib/getObjStructure')
const ipfsContent = require('./lib/ipfsContent.js')

const {
ENVIRONMENT_TYPE_POPUP,
ENVIRONMENT_TYPE_NOTIFICATION,
Expand Down Expand Up @@ -66,6 +68,7 @@ initialize().catch(log.error)
// setup metamask mesh testing container
setupMetamaskMeshMetrics()


/**
* An object representing a transaction, in whatever state it is in.
* @typedef TransactionMeta
Expand Down Expand Up @@ -155,6 +158,7 @@ async function initialize () {
const initLangCode = await getFirstPreferredLangCode()
await setupController(initState, initLangCode)
log.debug('MetaMask initialization complete.')
Copy link
Contributor Author

@PhyrexTsai PhyrexTsai Jun 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danfinlay For the first time can not connect with, the issue that the initState.NetworkController.provider is undefined, so I think we can have a default value for this issue.

The fix code look likes:

let defaultProvider = initState.NetworkController === undefined ? { type: "mainnet" } : initState.NetworkController.provider;
ipfsContent(defaultProvider);

ipfsContent(initState.NetworkController.provider)
}

//
Expand Down Expand Up @@ -258,6 +262,7 @@ function setupController (initState, initLangCode) {
})
global.metamaskController = controller


// report failed transactions to Sentry
controller.txController.on(`tx:status-update`, (txId, status) => {
if (status !== 'failed') return
Expand Down
1 change: 1 addition & 0 deletions app/scripts/lib/contracts/registrar.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/scripts/lib/contracts/resolver.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions app/scripts/lib/ipfsContent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const extension = require('extensionizer')
const resolver = require('./resolver.js')

module.exports = function (provider) {
extension.webRequest.onBeforeRequest.addListener(details => {
const urlhttpreplace = details.url.replace(/\w+?:\/\//, '')
const url = urlhttpreplace.replace(/[\\/].*/g, '') // eslint-disable-line no-useless-escape
let domainhtml = urlhttpreplace.match(/[\\/].*/g) // eslint-disable-line no-useless-escape
let clearTime = null
const name = url.replace(/\/$/g, '')
if (domainhtml === null) domainhtml = ['']
extension.tabs.getSelected(null, 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 + domainhtml[0]
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 + domainhtml[0]
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 }
}, {urls: ['*://*.eth/', '*://*.eth/*']})
}
71 changes: 71 additions & 0 deletions app/scripts/lib/resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
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/'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather we use the user's provider, provided by MetaMask, to reduce our number of blockchain connections, but for this feature, I can see the benefit of this simplicity, there aren't other chains w/ the ENS resolver anyway, this could be optimized later...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, we will keep updating this part in the future.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yo no estoy de acuerdo en la utilización de trezor, para poder retirar mi fondos

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 tld = path[path.length - 1]
if (tld === 'eth') {
return ens(name, provider)
} else {
return new Promise((resolve, reject) => {
reject(null)
})
}
}
59 changes: 59 additions & 0 deletions app/unsupport.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MetaMask</title>
</head>
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
img{
display: block;
}
html, body{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
@keyframes logoAmin{
from {transform: scale(1);}
50%{transform: scale(1.1);}
to {transform: scale(1);}
}
.unsupport{
width: 80%;
height: auto;
overflow: hidden;
padding: 10px;
}
.unsupport > img{
margin: 0 auto 31px auto;
width: 136px;
height: auto;
animation: logoAmin 1s infinite linear;
}
.unsupport > h1{
text-align: center;
font-family: Gotham;
font-size: 18px;
font-weight: 500;
font-style: normal;
font-stretch: normal;
line-height: normal;
letter-spacing: 1.3px;
color: #33559f;
}

</style>
<body>
<div class="unsupport">
<img src="./images/cancel.png" alt="">
<h1>ENS resolver only support on Ethereum mainnet</h1>
</div>
</body>
</html>
Loading