Implementing API for getEnsTextRecords

This commit is contained in:
Jamie Hewitt 2022-08-18 16:04:49 +03:00
parent 09f80b4e28
commit 830a5565b9
6 changed files with 212 additions and 19 deletions

105
package-lock.json generated
View File

@ -11,8 +11,10 @@
"dependencies": {
"@ensdomains/ensjs": "^2.1.0",
"@oceanprotocol/lib": "^1.1.8",
"@urql/exchange-refocus": "^0.2.5",
"cors": "^2.8.5",
"next": "^12.2.5",
"urql": "^2.2.3",
"web3": "^1.7.5"
},
"devDependencies": {
@ -1317,6 +1319,14 @@
"@ethersproject/strings": "^5.6.1"
}
},
"node_modules/@graphql-typed-document-node/core": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
@ -2117,6 +2127,30 @@
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
"dev": true
},
"node_modules/@urql/core": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@urql/core/-/core-2.6.1.tgz",
"integrity": "sha512-gYrEHy3tViJhwIhauK6MIf2Qp09QTsgNHZRd0n71rS+hF6gdwjspf1oKljl4m25+272cJF7fPjBUGmjaiEr7Kg==",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"wonka": "^4.0.14"
},
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@urql/exchange-refocus": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@urql/exchange-refocus/-/exchange-refocus-0.2.5.tgz",
"integrity": "sha512-JlrEXlG37mK/WgyxqVrHkLZtBMVC7x3GtgGJHiiXK41AQdU2hVy3IAQ208ENMIrkFw9SHQf8d8h7Wb2EY/1zdw==",
"dependencies": {
"@urql/core": ">=2.3.6",
"wonka": "^4.0.14"
},
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@ -4805,6 +4839,15 @@
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"node_modules/graphql": {
"version": "16.6.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
"integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
"peer": true,
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -8846,6 +8889,19 @@
"node": ">= 4"
}
},
"node_modules/urql": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/urql/-/urql-2.2.3.tgz",
"integrity": "sha512-XMkSYJKW9s4ZlbSuxcUz3fTBIykOn0sGileRXQeyZpaRBXJPVz5saSY05k7jdefNxShZtTI+/nr7PYUWQertfg==",
"dependencies": {
"@urql/core": "^2.6.1",
"wonka": "^4.0.14"
},
"peerDependencies": {
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
"react": ">= 16.8.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
@ -9422,6 +9478,11 @@
"node": ">= 0.10.0"
}
},
"node_modules/wonka": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz",
"integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg=="
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@ -10487,6 +10548,12 @@
"@ethersproject/strings": "^5.6.1"
}
},
"@graphql-typed-document-node/core": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
"requires": {}
},
"@humanwhocodes/config-array": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
@ -11037,6 +11104,24 @@
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
"dev": true
},
"@urql/core": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@urql/core/-/core-2.6.1.tgz",
"integrity": "sha512-gYrEHy3tViJhwIhauK6MIf2Qp09QTsgNHZRd0n71rS+hF6gdwjspf1oKljl4m25+272cJF7fPjBUGmjaiEr7Kg==",
"requires": {
"@graphql-typed-document-node/core": "^3.1.1",
"wonka": "^4.0.14"
}
},
"@urql/exchange-refocus": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@urql/exchange-refocus/-/exchange-refocus-0.2.5.tgz",
"integrity": "sha512-JlrEXlG37mK/WgyxqVrHkLZtBMVC7x3GtgGJHiiXK41AQdU2hVy3IAQ208ENMIrkFw9SHQf8d8h7Wb2EY/1zdw==",
"requires": {
"@urql/core": ">=2.3.6",
"wonka": "^4.0.14"
}
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@ -13137,6 +13222,12 @@
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
"dev": true
},
"graphql": {
"version": "16.6.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
"integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
"peer": true
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -16066,6 +16157,15 @@
"resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
"integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A=="
},
"urql": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/urql/-/urql-2.2.3.tgz",
"integrity": "sha512-XMkSYJKW9s4ZlbSuxcUz3fTBIykOn0sGileRXQeyZpaRBXJPVz5saSY05k7jdefNxShZtTI+/nr7PYUWQertfg==",
"requires": {
"@urql/core": "^2.6.1",
"wonka": "^4.0.14"
}
},
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
@ -16543,6 +16643,11 @@
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
"integrity": "sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw=="
},
"wonka": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz",
"integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg=="
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",

View File

@ -22,8 +22,10 @@
"dependencies": {
"@ensdomains/ensjs": "^2.1.0",
"@oceanprotocol/lib": "^1.1.8",
"@urql/exchange-refocus": "^0.2.5",
"cors": "^2.8.5",
"next": "^12.2.5",
"urql": "^2.2.3",
"web3": "^1.7.5"
},
"devDependencies": {

0
pages/api/_types.ts Normal file
View File

View File

@ -1,5 +1,16 @@
import { ConfigHelper, Config } from '@oceanprotocol/lib'
import { ConfigHelper, Config, LoggerInstance } from '@oceanprotocol/lib'
import Web3 from 'web3'
import ENS, { getEnsAddress as getEnsAddressVendor } from '@ensdomains/ensjs'
import {
createClient,
dedupExchange,
TypedDocumentNode,
OperationContext,
fetchExchange
} from 'urql'
import { refocusExchange } from '@urql/exchange-refocus'
let ens: any
function getOceanConfig(network: string | number): Config {
const config = new ConfigHelper().getConfig(
@ -17,7 +28,44 @@ function getOceanConfig(network: string | number): Config {
return config as Config
}
export async function getDummyWeb3(chainId: number): Promise<Web3> {
async function getDummyWeb3(chainId: number): Promise<Web3> {
const config = getOceanConfig(chainId)
return new Web3(config.nodeUri)
}
async function createUrqlClient() {
const config = getOceanConfig(1)
const client = createClient({
url: `${config.subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`,
exchanges: [dedupExchange, refocusExchange(), fetchExchange]
})
return client
}
export async function getEns(): Promise<any> {
const _ens =
ens ||
new ENS({
provider: (await getDummyWeb3(1)).currentProvider,
ensAddress: getEnsAddressVendor(1)
})
ens = _ens
return _ens
}
export async function fetchData(
query: TypedDocumentNode,
variables: any,
context: OperationContext
): Promise<any> {
try {
const client = await createUrqlClient()
const response = await client.query(query, variables, context).toPromise()
return response
} catch (error) {
LoggerInstance.error('Error fetchData: ', error.message)
}
return null
}

View File

@ -1,20 +1,5 @@
import { NextApiRequest, NextApiResponse } from 'next'
import ENS, { getEnsAddress as getEnsAddressVendor } from '@ensdomains/ensjs'
import { getDummyWeb3 } from './_utils'
let ens: any
async function getEns(): Promise<any> {
const _ens =
ens ||
new ENS({
provider: (await getDummyWeb3(1)).currentProvider,
ensAddress: getEnsAddressVendor(1)
})
ens = _ens
return _ens
}
import { getEns } from './_utils'
export default async function getEnsName(
request: NextApiRequest,
@ -33,6 +18,6 @@ export default async function getEnsName(
response.setHeader('Cache-Control', 's-maxage=86400')
response.status(200).send(name)
} catch (error) {
response.send(`${error}`)
response.status(500).send(`${error}`)
}
}

53
pages/api/text.ts Normal file
View File

@ -0,0 +1,53 @@
import { NextApiRequest, NextApiResponse } from 'next'
import { gql, OperationResult } from 'urql'
import { fetchData } from './_utils'
const ProfileTextRecordsQuery = gql<{
domains: [{ resolver: { texts: string[] } }]
}>`
query ProfileTextRecords($name: String!) {
domains(where: { name: $name }) {
resolver {
texts
}
}
}
`
export default async function getEnsTextRecords(
request: NextApiRequest,
response: NextApiResponse
): Promise<{ key: string; value: string }[]> {
try {
const ensName = String(request.query.name)
// 1. Check which text records are set for the domain with ENS subgraph,
// to prevent unnecessary contract calls.
const result: OperationResult<{
domains: [{ resolver: { texts: string[] } }]
}> = await fetchData(
ProfileTextRecordsQuery,
{ name: ensName },
{
url: `https://api.thegraph.com/subgraphs/name/ensdomains/ens`,
requestPolicy: 'cache-and-network'
}
)
if (!result?.data?.domains[0]?.resolver) return
// 2. Retrieve the text records.
const { texts } = result.data.domains[0].resolver
const records = []
let ens: any
for (let index = 0; index < texts?.length; index++) {
const key = texts[index]
const value = await ens.name(ensName).getText(key)
records.push({ key, value })
}
response.setHeader('Cache-Control', 's-maxage=86400')
response.status(200).send(records)
} catch (error) {
response.status(500).send(`${error}`)
}
}