diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ed48a909..80cb2241a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - [#384](https://github.com/poanetwork/nifty-wallet/pull/384) - (Fix) placement of HW Connect button title - [#383](https://github.com/poanetwork/nifty-wallet/pull/383) - (Chore) Replace POA-ETH Binance link to POA-BTC - [#382](https://github.com/poanetwork/nifty-wallet/pull/382) - (Fix) replace vulnerable npm dependencies with newer versions of packages, update chromedriver to match the latest Google Chrome release +- [#381](https://github.com/poanetwork/nifty-wallet/pull/381) - (Feature) Add RNS integration +- [#381](https://github.com/poanetwork/nifty-wallet/pull/381) - (Fix) ENS/RNS integration when sending tokens ## 5.1.0 Tue May 12 2020 diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index bd2c76df5..c69efac36 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -355,6 +355,9 @@ "ensNameNotFound": { "message": "ENS name not found" }, + "rnsNameNotFound": { + "message": "RNS name not found" + }, "enterPassword": { "message": "Enter password" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index b763e5f3b..a74acb258 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -349,6 +349,9 @@ "ensNameNotFound": { "message": "Nom ENS inconnu" }, + "rnsNameNotFound": { + "message": "Nom RNS inconnu" + }, "enterPassword": { "message": "Entrez votre mot de passe" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index fa235d75e..061d5fc9c 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -313,6 +313,9 @@ "ensNameNotFound": { "message": "Nou pa jwenn non ENS ou a" }, + "rnsNameNotFound": { + "message": "Nou pa jwenn non RNS ou a" + }, "enterPassword": { "message": "Mete modpas" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index d1a18daa2..7bc5c1178 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -352,6 +352,9 @@ "ensNameNotFound": { "message": "Nome ENS non trovato" }, + "rnsNameNotFound": { + "message": "Nome RNS non trovato" + }, "enterPassword": { "message": "Inserisci password" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index c2e34270e..b6fcce865 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -349,6 +349,9 @@ "ensNameNotFound": { "message": "ENS 이름을 찾을 수 없습니다" }, + "rnsNameNotFound": { + "message": "RNS 이름을 찾을 수 없습니다" + }, "enterPassword": { "message": "비밀번호를 입력해주세요" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index d3a74782e..7012c962b 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -313,6 +313,9 @@ "ensNameNotFound": { "message": "Nie znaleziono nazwy ENS" }, + "rnsNameNotFound": { + "message": "Nie znaleziono nazwy RNS" + }, "enterPassword": { "message": "Wpisz hasło" }, diff --git a/old-ui/app/components/ens-input.js b/old-ui/app/components/ens-input.js index 42b575076..e5f285ff0 100644 --- a/old-ui/app/components/ens-input.js +++ b/old-ui/app/components/ens-input.js @@ -5,11 +5,15 @@ const debounce = require('debounce') const copyToClipboard = require('copy-to-clipboard') const ENS = require('ethjs-ens') const networkMap = require('ethjs-ens/lib/network-map.json') +const RNSRegistryData = require('@rsksmart/rns-registry/RNSRegistryData.json'); const ensRE = /.+\..+$/ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const log = require('loglevel') -const { isValidENSAddress } = require('../util') - +const { isValidENSAddress, isValidRNSAddress } = require('../util') +const { + RSK_CODE, + RSK_TESTNET_CODE, +} = require('../../../app/scripts/controllers/network/enums') module.exports = EnsInput @@ -24,7 +28,8 @@ EnsInput.prototype.render = function () { function onInputChange () { const network = this.props.network const networkHasEnsSupport = getNetworkEnsSupport(network) - if (!networkHasEnsSupport) return + const networkHasRnsSupport = getNetworkRnsSupport(network) + if (!networkHasEnsSupport && !networkHasRnsSupport) return const recipient = document.querySelector('input[name="address"]').value if (recipient.match(ensRE) === null) { @@ -81,20 +86,27 @@ EnsInput.prototype.render = function () { EnsInput.prototype.componentDidMount = function () { const network = this.props.network const networkHasEnsSupport = getNetworkEnsSupport(network) + const networkHasRnsSupport = getNetworkRnsSupport(network) + this.setState({ ensResolution: ZERO_ADDRESS }) if (networkHasEnsSupport) { const provider = global.ethereumProvider this.ens = new ENS({ provider, network }) - this.checkName = debounce(this.lookupEnsName.bind(this), 200) + this.checkName = debounce(this.lookupEnsName.bind(this, 'ENS'), 200) + } else if (networkHasRnsSupport) { + const registryAddress = getRnsRegistryAddress(network); + const provider = global.ethereumProvider + this.ens = new ENS({ provider, network, registryAddress }) + this.checkName = debounce(this.lookupEnsName.bind(this, 'RNS'), 200) } } -EnsInput.prototype.lookupEnsName = function () { +EnsInput.prototype.lookupEnsName = function (nameService) { const recipient = document.querySelector('input[name="address"]').value const { ensResolution } = this.state - log.info(`ENS attempting to resolve name: ${recipient}`) + log.info(`${nameService} attempting to resolve name: ${recipient}`) this.ens.lookup(recipient.trim()) .then((address) => { if (address === ZERO_ADDRESS) throw new Error('No address has been set for this name.') @@ -116,9 +128,12 @@ EnsInput.prototype.lookupEnsName = function () { ensFailure: true, toError: null, } - if (isValidENSAddress(recipient) && reason.message === 'ENS name not defined.') { - setStateObj.hoverText = 'ENS name not found' - setStateObj.toError = 'ensNameNotFound' + if ( + (isValidENSAddress(recipient) || isValidRNSAddress(recipient)) + && reason.message === 'ENS name not defined.' + ) { + setStateObj.hoverText = `${nameService} name not found` + setStateObj.toError = `${nameService.toLowerCase()}NameNotFound` setStateObj.ensFailure = false } else { log.error(reason) @@ -198,3 +213,19 @@ EnsInput.prototype.ensIconContents = function (recipient) { function getNetworkEnsSupport (network) { return Boolean(networkMap[network]) } + +function getNetworkRnsSupport (network) { + return (network == RSK_CODE || network == RSK_TESTNET_CODE); +} + +function getRnsRegistryAddress (network) { + if (network == RSK_CODE) { + return RNSRegistryData.address.rskMainnet; + } + + if (network == RSK_TESTNET_CODE) { + return RNSRegistryData.address.rskTestnet; + }; + + return; +} diff --git a/old-ui/app/components/send/send-token.js b/old-ui/app/components/send/send-token.js index 4eb0bb80d..347434896 100644 --- a/old-ui/app/components/send/send-token.js +++ b/old-ui/app/components/send/send-token.js @@ -63,7 +63,7 @@ class SendTransactionScreen extends PersistentForm { this.recipientDidChange.bind(this)} + onChange={this.recipientDidChange.bind(this)} network={network} identities={identities} addressBook={addressBook} diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 182e053a7..9514262f5 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -67,6 +67,7 @@ module.exports = { isAllOneCase, isValidAddress, isValidENSAddress, + isValidRNSAddress, numericBalance, parseBalance, formatBalance, @@ -139,6 +140,10 @@ function isValidENSAddress (address) { return address.match(/^.{7,}\.(eth|test)$/) } +function isValidRNSAddress (address) { + return address.match(/^[a-z0-9]+\.rsk$/) +} + function isInvalidChecksumAddress (address, network) { const prefixed = ethUtil.addHexPrefix(address) if (address === '0x0000000000000000000000000000000000000000') return false diff --git a/package-lock.json b/package-lock.json index a143593e9..a02b551ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1966,6 +1966,14 @@ "react-lifecycles-compat": "^3.0.4" } }, + "@rsksmart/rns-registry": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@rsksmart/rns-registry/-/rns-registry-1.0.4.tgz", + "integrity": "sha512-phhzFT2URDi+buxychLvaKPtSytGvXh+HVJUUwvyAHDjvBPXiBSLr7OTnaciVYjVnTns++lwcMoVdgqQMVt3xQ==", + "requires": { + "minimist": "^1.2.3" + } + }, "@rsksmart/rsk-contract-metadata": { "version": "github:rsksmart/rsk-contract-metadata#d7913739e5ee93dac8667043e2c17b0ef339c206", "from": "github:rsksmart/rsk-contract-metadata#master" diff --git a/package.json b/package.json index 3af8d30b3..97a3fdceb 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "dependencies": { "@babel/runtime": "^7.5.5", "@material-ui/core": "^4.1.1", + "@rsksmart/rns-registry": "^1.0.4", "@rsksmart/rsk-contract-metadata": "github:rsksmart/rsk-contract-metadata#master", "@rsksmart/rsk-testnet-contract-metadata": "github:rsksmart/rsk-testnet-contract-metadata#master", "@zxing/library": "^0.8.0",