diff --git a/package.json b/package.json
index fd6d23134..4d7738179 100644
--- a/package.json
+++ b/package.json
@@ -8,14 +8,14 @@
"@buidlhub/buidlhub-ens-notifications": "^1.0.3",
"@emotion/core": "^10.0.9",
"@emotion/styled": "^10.0.9",
+ "@ensdomains/address-encoder": "^0.2.6",
+ "@ensdomains/mock": "^2.0.34",
+ "@ensdomains/react-ens-address": "^0.0.27",
+ "@ensdomains/ui": "https://github.com/buffrr/ui.git#dns-contract",
"@myetherwallet/mewconnect-web-client": "^2.1.11",
"@portis/web3": "^2.0.0-beta.59",
"@toruslabs/torus-embed": "^1.8.6",
"@walletconnect/web3-provider": "^1.3.1",
- "@ensdomains/address-encoder": "^0.2.6",
- "@ensdomains/mock": "^2.0.34",
- "@ensdomains/react-ens-address": "^0.0.27",
- "@ensdomains/ui": "https://github.com/imperviousinc/ui.git",
"apollo-cache-inmemory": "^1.2.9",
"apollo-client": "^2.4.5",
"apollo-link": "^1.2.2",
@@ -23,6 +23,7 @@
"apollo-link-state": "^0.4.1",
"authereum": "^0.1.0",
"big-integer": "^1.6.44",
+ "bns": "^0.14.0",
"chart.js": "^2.9.3",
"core-js": "^3.1.4",
"cross-fetch": "^2.2.3",
@@ -57,8 +58,8 @@
"react-transition-group-plus": "^0.5.3",
"slugify": "^1.4.6",
"stackdriver-errors-js": "^0.8.0",
- "web3modal": "^1.9.1",
- "web3": "^1.3.0"
+ "web3": "^1.3.0",
+ "web3modal": "^1.9.1"
},
"scripts": {
"start": "react-scripts start",
diff --git a/public/locales/en.json b/public/locales/en.json
index 2f722dbda..948da73a5 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -64,6 +64,7 @@
"set": "Set",
"sync": "Sync",
"textrecord": "Text Record",
+ "dnsrecord": "DNS Record",
"transfer": "Transfer",
"warning": "Warning",
"year": "year",
diff --git a/src/api/manager/resolvers.js b/src/api/manager/resolvers.js
index 7e88765f4..fb909fbb8 100644
--- a/src/api/manager/resolvers.js
+++ b/src/api/manager/resolvers.js
@@ -12,11 +12,15 @@ import {
labelhash,
utils
} from '@ensdomains/ui'
+
+import bns from 'bns'
import { formatsByName } from '@ensdomains/address-encoder'
import isEqual from 'lodash/isEqual'
import modeNames from '../modes'
import { sendHelper, sendHelperArray } from '../resolverUtils'
import { emptyAddress, DNSREGISTRAR_ADDRESS } from '../../utils/utils'
+import { strRecord } from '../../utils/dns'
+
import TEXT_RECORD_KEYS from 'constants/textRecords'
import COIN_LIST_KEYS from 'constants/coinList'
import {
@@ -367,6 +371,7 @@ const resolvers = {
)
DEPRECATED_RESOLVERS = [...DEPRECATED_RESOLVERS, ...localResolvers]
}
+
/* Deprecated resolvers are using the new registry and can be continued to be used*/
function calculateIsDeprecatedResolver(address) {
@@ -482,6 +487,33 @@ const resolvers = {
)
return Promise.all(addresses)
},
+ getDNSRecords: async (_, { name, types }) => {
+ const ens = getENS()
+ const dnsRecords = types.map(key =>
+ ens.getDNSRecordsZoneFormat(name, name, key).then(records => {
+ let value = ''
+ if (records.length === 0) {
+ return { key, value: value }
+ }
+
+ const record = records[0]
+ const rr = bns.wire.Record.fromString(record)
+
+ if (rr.type === bns.wire.types.TXT && rr.data.txt.length === 1) {
+ value = rr.data.txt[0]
+ } else {
+ value = record
+ .trim()
+ .split(/[\s]+/)
+ .slice(4)
+ .join(' ')
+ }
+
+ return { key, value: value }
+ })
+ )
+ return Promise.all(dnsRecords)
+ },
getTextRecords: async (_, { name, keys }) => {
const ens = getENS()
const textRecords = keys.map(key =>
@@ -604,6 +636,33 @@ const resolvers = {
addMultiRecords: async (_, { name, records }, { cache }) => {
const ens = getENS()
+ // Handling DNS Records
+ try {
+ if (records.dnsRecords.length > 0) {
+ if (records.textRecords.length > 0 || records.coins.length > 0) {
+ console.warn(
+ 'dns records cannot be modified with other types of records'
+ )
+ return
+ }
+
+ const defaultTTL = '43200'
+ let owner = name + '.'
+ const strRecords = []
+
+ for (const record of records.dnsRecords) {
+ const rr = strRecord(owner, defaultTTL, record.key, record.value)
+ strRecords.push(rr)
+ }
+
+ const tx = await ens.setDNSRecordsFromZone(name, strRecords)
+ return sendHelper(tx)
+ }
+ } catch (e) {
+ console.log('unable to perform dns transaction', e)
+ return
+ }
+
function setupTransactions({ name, records, resolverInstance }) {
try {
const resolver = resolverInstance.interface.functions
diff --git a/src/components/SingleName/ResolverAndRecords/AddRecord.js b/src/components/SingleName/ResolverAndRecords/AddRecord.js
index bdb12aac5..5361c64e8 100644
--- a/src/components/SingleName/ResolverAndRecords/AddRecord.js
+++ b/src/components/SingleName/ResolverAndRecords/AddRecord.js
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'
import { validateRecord } from '../../../utils/records'
import { useEditable } from '../../hooks'
import { getOldContentWarning } from './warnings'
+import DNS_RECORD_KEYS from 'constants/dnsRecords'
import TEXT_RECORD_KEYS from 'constants/textRecords'
import COIN_LIST from 'constants/coinList'
import { getEnsAddress } from '../../../api/ens'
@@ -131,6 +132,12 @@ const textRecordOptions = TEXT_RECORD_KEYS.slice()
label: key,
value: key
}))
+const dnsRecordOptions = DNS_RECORD_KEYS.slice()
+ .sort()
+ .map(key => ({
+ label: key,
+ value: key
+ }))
const coinOptions = COIN_LIST.slice()
.sort()
.map(key => ({
@@ -168,6 +175,36 @@ function TextRecordInput({
)
}
+function DNSRecordInput({
+ selectedRecord,
+ updateValue,
+ newValue,
+ selectedKey,
+ setSelectedKey,
+ isValid,
+ isInvalid
+}) {
+ return (
+ <>
+
+
+ >
+ )
+}
+
function AddressRecordInput({
selectedRecord,
updateValue,
@@ -377,6 +414,16 @@ function Editable({
isValid={isValid}
isInvalid={isInvalid}
/>
+ ) : selectedRecord && selectedRecord.value === 'dnsRecords' ? (
+
) : null}
{selectedRecord &&
diff --git a/src/components/SingleName/ResolverAndRecords/DNSRecord/DNSRecord.js b/src/components/SingleName/ResolverAndRecords/DNSRecord/DNSRecord.js
new file mode 100644
index 000000000..9039b3509
--- /dev/null
+++ b/src/components/SingleName/ResolverAndRecords/DNSRecord/DNSRecord.js
@@ -0,0 +1,18 @@
+import React from 'react'
+import KeyValueRecord from '../KeyValueRecord'
+
+const getPlaceholder = key => {
+ return `Enter ${key}`
+}
+
+export default function DNSRecords(props) {
+ return (
+
+ )
+}
diff --git a/src/components/SingleName/ResolverAndRecords/DNSRecord/index.js b/src/components/SingleName/ResolverAndRecords/DNSRecord/index.js
new file mode 100644
index 000000000..db1002920
--- /dev/null
+++ b/src/components/SingleName/ResolverAndRecords/DNSRecord/index.js
@@ -0,0 +1,2 @@
+import DNSRecord from './DNSRecord'
+export default DNSRecord
diff --git a/src/components/SingleName/ResolverAndRecords/Records.js b/src/components/SingleName/ResolverAndRecords/Records.js
index b0708f2fd..59b869a4b 100644
--- a/src/components/SingleName/ResolverAndRecords/Records.js
+++ b/src/components/SingleName/ResolverAndRecords/Records.js
@@ -6,9 +6,11 @@ import differenceWith from 'lodash/differenceWith'
import { useQuery } from 'react-apollo'
import { useTranslation } from 'react-i18next'
import { getNamehash } from '@ensdomains/ui'
+import { validateDNSInput } from '../../../utils/records'
import { useEditable } from '../../hooks'
import { ADD_MULTI_RECORDS } from '../../../graphql/mutations'
+import DNS_RECORD_KEYS from 'constants/dnsRecords'
import COIN_LIST from 'constants/coinList'
import PendingTx from '../../PendingTx'
import { emptyAddress } from '../../../utils/utils'
@@ -17,12 +19,14 @@ import { formatsByCoinType } from '@ensdomains/address-encoder'
import {
GET_ADDRESSES,
GET_TEXT_RECORDS,
+ GET_DNS_RECORDS,
GET_RESOLVER_FROM_SUBGRAPH
} from 'graphql/queries'
import AddRecord from './AddRecord'
import ContentHash from './ContentHash'
import TextRecord from './TextRecord'
+import DNSRecord from './DNSRecord'
import Coins from './Coins'
import DefaultSaveCancel from '../SaveCancel'
import RecordsCheck from './RecordsCheck'
@@ -67,6 +71,10 @@ const RECORDS = [
{
label: 'Text',
value: 'textRecords'
+ },
+ {
+ label: 'DNS',
+ value: 'dnsRecords'
}
]
@@ -79,6 +87,8 @@ const TEXT_PLACEHOLDER_RECORDS = [
'notice'
]
+const DNS_PLACEHOLDER_RECORDS = ['A', 'CNAME', 'TXT']
+
const COIN_PLACEHOLDER_RECORDS = ['ETH', ...COIN_LIST.slice(0, 3)]
function isEmpty(record) {
@@ -120,6 +130,7 @@ function getChangedRecords(initialRecords, updatedRecords) {
if (initialRecords.loading)
return {
textRecords: [],
+ dnsRecords: [],
coins: []
}
@@ -128,6 +139,11 @@ function getChangedRecords(initialRecords, updatedRecords) {
initialRecords.textRecords,
isEqual
)
+ const dnsRecords = differenceWith(
+ updatedRecords.dnsRecords,
+ initialRecords.dnsRecords,
+ isEqual
+ )
const coins = differenceWith(
updatedRecords.coins,
initialRecords.coins,
@@ -140,6 +156,7 @@ function getChangedRecords(initialRecords, updatedRecords) {
return {
textRecords,
+ dnsRecords,
coins,
...(content !== undefined && { content })
}
@@ -148,6 +165,7 @@ function getChangedRecords(initialRecords, updatedRecords) {
function checkRecordsHaveChanged(changedRecords) {
return (
changedRecords.textRecords.length > 0 ||
+ changedRecords.dnsRecords.length > 0 ||
changedRecords.coins.length > 0 ||
changedRecords.content
)
@@ -158,12 +176,15 @@ function checkRecordsAreValid(changedRecords) {
changedRecords.textRecords.filter(record => record.isValid === false)
.length > 0
)
-
+ const dnsRecordsValid = !(
+ changedRecords.dnsRecords.filter(record => record.isValid === false)
+ .length > 0
+ )
const coinsValid = !(
changedRecords.coins.filter(record => record.isValid === false).length > 0
)
- return textRecordsValid && coinsValid
+ return textRecordsValid && dnsRecordsValid && coinsValid
}
function isContentHashEmpty(hash) {
@@ -194,7 +215,8 @@ export default function Records({
const [updatedRecords, setUpdatedRecords] = useState({
content: undefined,
coins: [],
- textRecords: []
+ textRecords: [],
+ dnsRecords: []
})
const { actions, state } = useEditable()
const { pending, confirmed, editing, txHash } = state
@@ -240,6 +262,17 @@ export default function Records({
}
)
+ const { loading: dnsRecordsLoading, data: dataDnsRecords } = useQuery(
+ GET_DNS_RECORDS,
+ {
+ variables: {
+ name: domain.name,
+ types: DNS_RECORD_KEYS
+ },
+ skip: !dataResolver
+ }
+ )
+
function processRecords(records, placeholder) {
const nonDuplicatePlaceholderRecords = placeholder.filter(
record => !records.find(r => record === r.key)
@@ -261,6 +294,10 @@ export default function Records({
TEXT_PLACEHOLDER_RECORDS
)
: processRecords([], TEXT_PLACEHOLDER_RECORDS),
+ dnsRecords:
+ dataDnsRecords && dataDnsRecords.getDNSRecords
+ ? processRecords(dataDnsRecords.getDNSRecords, DNS_PLACEHOLDER_RECORDS)
+ : processRecords([], DNS_PLACEHOLDER_RECORDS),
coins:
dataAddresses && dataAddresses.getAddresses
? processRecords(dataAddresses.getAddresses, COIN_PLACEHOLDER_RECORDS)
@@ -270,17 +307,28 @@ export default function Records({
}
useEffect(() => {
- if (textRecordsLoading === false && addressesLoading === false) {
+ if (
+ textRecordsLoading === false &&
+ dnsRecordsLoading === false &&
+ addressesLoading === false
+ ) {
setUpdatedRecords(initialRecords)
}
- }, [textRecordsLoading, addressesLoading, dataAddresses, dataTextRecords])
+ }, [
+ textRecordsLoading,
+ dnsRecordsLoading,
+ addressesLoading,
+ dataAddresses,
+ dataTextRecords,
+ dataDnsRecords
+ ])
const emptyRecords = RECORDS.filter(record => {
// Always display all options for consistency now that both Addess and text almost always have empty record
return true
})
- const hasRecords = hasAnyRecord(domain)
+ const hasRecords = hasAnyRecord(domain) || true
const changedRecords = getChangedRecords(initialRecords, updatedRecords)
const contentCreatedFirstTime =
@@ -298,7 +346,20 @@ export default function Records({
}
const haveRecordsChanged = checkRecordsHaveChanged(changedRecords)
- const areRecordsValid = checkRecordsAreValid(changedRecords)
+ let areRecordsValid = checkRecordsAreValid(changedRecords)
+
+ const basicRecordsChanged =
+ changedRecords.textRecords.length > 0 ||
+ changedRecords.coins > 0 ||
+ updatedRecords.content !== initialRecords.content
+
+ const dnsRecordsChanged = changedRecords.dnsRecords.length > 0
+
+ // we don't support changing DNS records with other
+ // types of records for now
+ if (dnsRecordsChanged && basicRecordsChanged) {
+ areRecordsValid = false
+ }
return (
+
+ {
+ return validateDNSInput(type, value)
+ }}
+ dnsRecords={dataDnsRecords && dataDnsRecords.getDNSRecords}
+ loading={dnsRecordsLoading}
+ title={t('c.dnsrecord')}
+ updatedRecords={updatedRecords}
+ placeholderRecords={DNS_PLACEHOLDER_RECORDS}
+ setUpdatedRecords={setUpdatedRecords}
+ changedRecords={changedRecords}
+ />
{pending && !confirmed && txHash && (
)}
+ {changedRecords.dnsRecords.length > 0 && (
+
+ DNS Records
+
+ {changedRecords.dnsRecords.map(record =>
+ record.value === '' ? (
+
+ ) : (
+
+ )
+ )}
+
+
+ )}
)
}
diff --git a/src/constants/dnsRecords.json b/src/constants/dnsRecords.json
new file mode 100644
index 000000000..1ecefa060
--- /dev/null
+++ b/src/constants/dnsRecords.json
@@ -0,0 +1 @@
+["A", "CNAME", "TXT"]
diff --git a/src/graphql/queries.js b/src/graphql/queries.js
index d4c0e2917..13c4e537c 100644
--- a/src/graphql/queries.js
+++ b/src/graphql/queries.js
@@ -69,6 +69,12 @@ export const GET_TEXT_RECORDS = gql`
}
`
+export const GET_DNS_RECORDS = gql`
+ query getDNSRecords($name: String, $types: [String]) {
+ getDNSRecords(name: $name, types: $types) @client
+ }
+`
+
export const GET_SINGLE_NAME = gql`
query singleName($name: String) {
singleName(name: $name) @client {
diff --git a/src/utils/dns.js b/src/utils/dns.js
new file mode 100644
index 000000000..310b76b6e
--- /dev/null
+++ b/src/utils/dns.js
@@ -0,0 +1,21 @@
+// zone file TXT value format
+import bns from 'bns'
+
+export function normalizeTXT(txt) {
+ const t = txt.trim()
+ if (t === '') return '"' + txt + '"'
+
+ if (t[0] !== '"' || t[t.length - 1] !== '"') {
+ const escape = txt.replace(/"/g, '\\"')
+ return '"' + escape + '"'
+ }
+
+ return txt
+}
+
+export function strRecord(name, ttl, type, value) {
+ if (type === 'TXT' && value !== '') value = normalizeTXT(value)
+ if (type === 'CNAME' && value !== '') value = bns.util.fqdn(value)
+
+ return name + ' ' + ttl + ' IN ' + type + ' ' + value
+}
diff --git a/src/utils/records.js b/src/utils/records.js
index 342759bd5..e091f2262 100644
--- a/src/utils/records.js
+++ b/src/utils/records.js
@@ -1,6 +1,20 @@
import { encodeContenthash, isValidContenthash } from '@ensdomains/ui'
import { addressUtils } from 'utils/utils'
+import { normalizeTXT, strRecord } from './dns'
import { formatsByName } from '@ensdomains/address-encoder'
+import bns from 'bns'
+
+export function validateDNSInput(type, value) {
+ if (value === '') return true
+
+ const record = strRecord('example.eth.', '0', type, value)
+ try {
+ bns.wire.Record.fromString(record)
+ return true
+ } catch (e) {
+ return false
+ }
+}
export function validateRecord({ type, value, contentType, selectedKey }) {
if (!type) return false
@@ -23,6 +37,8 @@ export function validateRecord({ type, value, contentType, selectedKey }) {
}
case 'textRecords':
return true
+ case 'dnsRecords':
+ return validateDNSInput(selectedKey, value)
case 'coins':
if (value === '') return false
if (selectedKey === 'ETH') {
diff --git a/yarn.lock b/yarn.lock
index ccd48ae26..ca0f1e1d7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1465,9 +1465,9 @@
lodash "^4.17.11"
web3 "^1.3.0"
-"@ensdomains/ui@https://github.com/hnsfund/ui.git":
+"@ensdomains/ui@https://github.com/buffrr/ui.git#dns-contract":
version "0.0.1"
- resolved "https://github.com/hnsfund/ui.git#4e0ab78c8dab0d38777a14027e41247c6d4bd80e"
+ resolved "https://github.com/buffrr/ui.git#30469953adf14b35e56da9b5693022558b46f63f"
dependencies:
"@0xproject/utils" "^2.0.2"
"@babel/plugin-proposal-class-properties" "^7.8.3"
@@ -1480,7 +1480,9 @@
"@ethvault/iframe-provider" "0.1.9"
base58check "^2.0.0"
bech32 "^1.1.3"
+ bns "^0.14.0"
bs58 "^4.0.1"
+ bufio "^1.0.7"
cross-fetch "^3.0.2"
dns-packet "^5.2.1"
eth-ens-namehash "^2.0.8"
@@ -4451,11 +4453,24 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
+bcrypto@~5.4.0:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/bcrypto/-/bcrypto-5.4.0.tgz#4046f0c44a4b301eff84de593b4f86fce8d91db2"
+ integrity sha512-KDX2CR29o6ZoqpQndcCxFZAtYA1jDMnXU3jmCfzP44g++Cu7AHHtZN/JbrN/MXAg9SLvtQ8XISG+eVD9zH1+Jg==
+ dependencies:
+ bufio "~1.0.7"
+ loady "~0.0.5"
+
bech32@^1.1.3:
version "1.1.4"
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
+bfile@~0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/bfile/-/bfile-0.2.2.tgz#b0c205cee1ff22a9525304ec51f09195a7afa077"
+ integrity sha512-X205SsJ7zFAnjeJ/pBLqDqF10x/4Su3pBy8UdVKw4hdGJk7t5pLoRi+uG4rPaDAClGbrEfT/06PGUbYiMYKzTg==
+
bfj@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2"
@@ -4466,6 +4481,13 @@ bfj@^7.0.2:
hoopy "^0.1.4"
tryer "^1.0.1"
+bheep@~0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/bheep/-/bheep-0.1.5.tgz#ed6a3da7857c8ebe71d71de9571ddd8f42340889"
+ integrity sha512-0KR5Zi8hgJBKL35+aYzndCTtgSGakOMxrYw2uszd5UmXTIfx3+drPGoETlVbQ6arTdAzSoQYA1j35vbaWpQXBg==
+ dependencies:
+ bsert "~0.0.10"
+
big-integer@1.6.36:
version "1.6.36"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36"
@@ -4517,6 +4539,14 @@ bindings@^1.2.1, bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
+binet@~0.3.6:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/binet/-/binet-0.3.6.tgz#82d9462fa601759956a1f1f1f0f10a5760445f85"
+ integrity sha512-6pm+Gc3uNiiJZEv0k8JDWqQlo9ki/o9UNAkLmr0EGm7hI5MboOJVIOlO1nw3YuDkLHWN78OPsaC4JhRkn2jMLw==
+ dependencies:
+ bs32 "~0.1.5"
+ bsert "~0.0.10"
+
bip39@^2.5.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c"
@@ -4604,6 +4634,23 @@ bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.3:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
+bns@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/bns/-/bns-0.14.0.tgz#538d0d91ec8272c32c774b82827699f2db168173"
+ integrity sha512-lqxDpj9gX7OtihwAzMhlMk0w38ObZu+aRSF9fzG/wUfF6RfocFSFDGHA+KVbLNXudiTStzhWVGc8cJmcL4IHYw==
+ dependencies:
+ bcrypto "~5.4.0"
+ bfile "~0.2.2"
+ bheep "~0.1.5"
+ binet "~0.3.6"
+ bs32 "~0.1.6"
+ bsert "~0.0.10"
+ btcp "~0.1.5"
+ budp "~0.1.6"
+ bufio "~1.0.7"
+ optionalDependencies:
+ unbound "~0.4.3"
+
body-parser@1.19.0, body-parser@^1.16.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
@@ -4798,6 +4845,13 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4
escalade "^3.1.1"
node-releases "^1.1.66"
+bs32@~0.1.5, bs32@~0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/bs32/-/bs32-0.1.6.tgz#2710cb70da3f55447138181fa645e2c54b1ef6d0"
+ integrity sha512-usjDesQqZ8ihHXOnOEQuAdymBHnJEfSd+aELFSg1jN/V3iAf12HrylHlRJwIt6DTMmXpBDQ+YBg3Q3DIYdhRgQ==
+ dependencies:
+ bsert "~0.0.10"
+
bs58@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e"
@@ -4828,11 +4882,26 @@ bser@2.1.1:
dependencies:
node-int64 "^0.4.0"
+bsert@~0.0.10:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/bsert/-/bsert-0.0.10.tgz#231ac82873a1418c6ade301ab5cd9ae385895597"
+ integrity sha512-NHNwlac+WPy4t2LoNh8pXk8uaIGH3NSaIUbTTRXGpE2WEbq0te/tDykYHkFK57YKLPjv/aGHmbqvnGeVWDz57Q==
+
+btcp@~0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/btcp/-/btcp-0.1.5.tgz#f76262415a0f6eaa592cdbb91c8b18386530ac28"
+ integrity sha512-tkrtMDxeJorn5p0KxaLXELneT8AbfZMpOFeoKYZ5qCCMMSluNuwut7pGccLC5YOJqmuk0DR774vNVQLC9sNq/A==
+
btoa@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73"
integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==
+budp@~0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/budp/-/budp-0.1.6.tgz#bbe166cc4842cf8d96754ee29afb1af56f6757c8"
+ integrity sha512-o+a8NPq3DhV91j4nInjht2md6mbU1XL+7ciPltP66rw5uD3KP1m5r8lA94LZVaPKcFdJ0l2HVVzRNxnY26Pefg==
+
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
@@ -4916,6 +4985,11 @@ bufferutil@^4.0.1:
dependencies:
node-gyp-build "^4.2.0"
+bufio@^1.0.7, bufio@~1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.0.7.tgz#b7f63a1369a0829ed64cc14edf0573b3e382a33e"
+ integrity sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==
+
builtin-modules@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
@@ -11869,6 +11943,11 @@ loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
emojis-list "^3.0.0"
json5 "^1.0.1"
+loady@~0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/loady/-/loady-0.0.5.tgz#b17adb52d2fb7e743f107b0928ba0b591da5d881"
+ integrity sha512-uxKD2HIj042/HBx77NBcmEPsD+hxCgAtjEWlYNScuUjIsh/62Uyu39GOR68TBR68v+jqDL9zfftCWoUo4y03sQ==
+
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -17920,6 +17999,13 @@ ultron@~1.1.0:
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
+unbound@~0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/unbound/-/unbound-0.4.3.tgz#ca4e9a3c8b678df431ec576385acc8bff9aa439a"
+ integrity sha512-2ISqZLXtzp1l9f1V8Yr6S+zuhXxEwE1CjKHjXULFDHJcfhc9Gm3mn19hdPp4rlNGEdCivKYGKjYe3WRGnafYdA==
+ dependencies:
+ loady "~0.0.5"
+
unbzip2-stream@^1.0.9:
version "1.4.3"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"