Try Demo
Step 0: Prerequisites
Step 1: Clone Starter Code
To clone the starter code, simply copy the following code to clone in your preferred directory:
Copy mkdir universal-resolver-starter
cd universal-resolver-starter
git init
git remote add -f origin https://github.com/Airstack-xyz/demos.git
git config core.sparseCheckout true
git sparse-checkout init
git sparse-checkout set universal-resolver-starter
git pull origin main
rm -rf .git
mv xmtp/universal-resolver-starter/* .
mv xmtp/universal-resolver-starter/.* .
rm -rf xmtp
You can find all the starter code in GItHub .
Step 2: Install Dependencies
Install the dependencies using your preferred package manager with one of the following commands:
Once the installation is complete, a new node_modules
will be generated
You should also see that Airstack React SDK has been added to your package.json
as one of your dependency:
Copy {
"dependencies" : {
"@airstack/airstack-react" : "^0.3.3"
// other dependencies
}
// other config
}
Step 3: Set Environment Variables
Copy and rename .env.example
to .env.local
Copy cp .env.example .env.local
And, paste your API key to your environment variable .env.local
file.
Copy VITE_AIRSTACK_API_KEY = YOUR_API_KEY
Step 4: Run App Locally
To run the app locally, simply run one of the following command:
Then, you can go to http://localhost:5173 :
Here you have the UI all given to you out-of-the-box as part of the starter code.
However, the resolving has not been included as no Airstack query is found in the code. You can see in src/graphql/resolve.js
with it's empty query:
Copy const UNIVERSAL_RESOLVER = `` ;
export default UNIVERSAL_RESOLVER ;
In order to fill in this, the next steps will be dedicated to constructing your queries for the universal resolver.
Step 5: Create a Query Using AI
Airstack provides an AI solution for you to build a GraphQL query efficiently. You can access Airstack AI on the API Studio .
For example, let's try the following prompt to resolve vitalik.lens
:
Copy For the vitalik.lens, show me the 0x address, web3 socials, ENS domain, and XMTP
After clicking enter, the Airstack AI will output a GraphQL query as follows:
Query Responses
Copy query MyQuery {
Wallet(input: { identity : "vitalik.lens" , blockchain : ethereum}) {
addresses
socials {
dappName
profileName
}
domains {
name
}
xmtp {
isXMTPEnabled
}
}
}
Copy {
"data" : {
"Wallet" : {
"addresses" : [
"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
] ,
"socials" : [
{
"dappName" : "farcaster" ,
"profileName" : "vbuterin"
} ,
{
"dappName" : "lens" ,
"profileName" : "vitalik.lens"
}
] ,
"domains" : [
{
"name" : "quantumexchange.eth"
} ,
{
"name" : "7860000.eth"
} ,
{
"name" : "brianshaw.eth"
} ,
{
"name" : "vbuterin.stateofus.eth"
} ,
{
"name" : "quantumsmartcontracts.eth"
} ,
{
"name" : "openegp.eth"
} ,
{
"name" : "vitalik.cannafam.eth"
} ,
{
"name" : "quantumdapps.eth"
} ,
{
"name" : "vitalik.soy.eth"
} ,
{
"name" : "satoshinart.eth"
}
]
}
}
}
You can go to the API Studio to test out the query yourself:
Step 6: Modify Your Query
Now that you have your basic query, you can build more complex queries on top of it to resolve any web3 identities to another.
For this, you can simply stay in the API Studio to make the modifications.
To build a query that can universally resolve any web3 identities, it needs to satisfy 2 conditions:
Condition #1: Accept any web3 identity as input
Airstack provides an Identity API out-of-the-box that you can use to filter queries using web3 identities instead of an Ethereum address.
Thus, with Airstack Identity API , you can instead replace the query input with other web3 identities such as ENS:
Query Response
Copy query MyQuery {
Wallet(input: { identity : "vitalik.eth" , blockchain : ethereum}) {
addresses
socials {
dappName
profileName
}
domains {
name
}
xmtp {
isXMTPEnabled
}
}
}
Copy {
"data" : {
"Wallet" : {
"addresses" : [
"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
] ,
"socials" : [
{
"dappName" : "farcaster" ,
"profileName" : "vbuterin"
} ,
{
"dappName" : "lens" ,
"profileName" : "vitalik.lens"
}
] ,
"domains" : [
{
"name" : "quantumexchange.eth"
} ,
{
"name" : "7860000.eth"
} ,
{
"name" : "brianshaw.eth"
} ,
{
"name" : "vbuterin.stateofus.eth"
} ,
{
"name" : "quantumsmartcontracts.eth"
} ,
{
"name" : "openegp.eth"
} ,
{
"name" : "vitalik.cannafam.eth"
} ,
{
"name" : "quantumdapps.eth"
} ,
{
"name" : "vitalik.soy.eth"
} ,
{
"name" : "satoshinart.eth"
}
] ,
"xmtp" : [
{
"isXMTPEnabled" : true
}
]
}
}
}
Condition#2: Return all web3 identity as responses
The responses has already included everything that you need to resolve web3 identities. However, it is missing a primary ENS domain to highlight domains that is primary or not.
To add primary ENS domain, you will need this one field:
Adding the additional field, the last query with the changes highlighted will be as follows:
Query Response
Copy query MyQuery {
Wallet(
input: { identity : "vitalik.lens" , blockchain : ethereum}
) {
addresses
socials {
dappName
profileName
}
domains {
name
}
primaryDomain {
name
}
xmtp {
isXMTPEnabled
}
}
}
Copy {
"data" : {
"Wallet" : {
"addresses" : [
"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
] ,
"socials" : [
{
"dappName" : "farcaster" ,
"profileName" : "vbuterin"
} ,
{
"dappName" : "lens" ,
"profileName" : "vitalik.lens"
}
] ,
"domains" : [
{
"name" : "quantumexchange.eth"
} ,
{
"name" : "7860000.eth"
} ,
{
"name" : "brianshaw.eth"
} ,
{
"name" : "vbuterin.stateofus.eth"
} ,
{
"name" : "quantumsmartcontracts.eth"
} ,
{
"name" : "openegp.eth"
} ,
{
"name" : "vitalik.cannafam.eth"
} ,
{
"name" : "quantumdapps.eth"
} ,
{
"name" : "vitalik.soy.eth"
} ,
{
"name" : "satoshinart.eth"
}
] ,
"xmtp" : [
{
"isXMTPEnabled" : true
}
]
}
}
}
Step 7: Add Variables to Your Query
In production, you will likely need to have the input value change constantly. This is where you can add variables to your query to accept input values from your application.
Simply replace the input with variables, represented by $
followed by the variable names:
Query Variable Response
Copy query MyQuery ($address: Identity ! ) {
Wallet(input: { identity : $address, blockchain : ethereum}) {
addresses
socials {
dappName
profileName
}
domains {
name
}
primaryDomain {
name
}
xmtp {
isXMTPEnabled
}
}
}
Copy {
"address" : "vitalik.lens"
}
Copy {
"data" : {
"Wallet" : {
"addresses" : [
"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
] ,
"socials" : [
{
"dappName" : "farcaster" ,
"profileName" : "vbuterin"
} ,
{
"dappName" : "lens" ,
"profileName" : "vitalik.lens"
}
] ,
"domains" : [
{
"name" : "quantumexchange.eth"
} ,
{
"name" : "7860000.eth"
} ,
{
"name" : "brianshaw.eth"
} ,
{
"name" : "vbuterin.stateofus.eth"
} ,
{
"name" : "quantumsmartcontracts.eth"
} ,
{
"name" : "openegp.eth"
} ,
{
"name" : "vitalik.cannafam.eth"
} ,
{
"name" : "quantumdapps.eth"
} ,
{
"name" : "vitalik.soy.eth"
} ,
{
"name" : "satoshinart.eth"
}
] ,
"primaryDomain" : {
"name" : "satoshinart.eth"
} ,
"xmtp" : [
{
"isXMTPEnabled" : true
}
]
}
}
}
Step 8: Call The Airstack Query
Now that you have the query constructed, all you need is just paste it directly into the codebase.
Simply go to src/graphql/resolve.js
again and paste the query to UNIVERSAL_RESOLVER
variable:
Copy const UNIVERSAL_RESOLVER = `
query MyQuery($address: Identity!) {
Wallet(input: {identity: $address, blockchain: ethereum}) {
addresses
socials {
dappName
profileName
}
domains {
name
}
primaryDomain {
name
}
xmtp {
isXMTPEnabled
}
}
}
` ;
export default UNIVERSAL_RESOLVER ;
To call this query, use the useQuery
hook from the Airstack React SDK to src/App.jsx
:
Copy import { useQuery } from "@airstack/airstack-react" ;
import UNIVERSAL_RESOLVER from "./graphql/resolve" ;
import UniversalResolver from "./components/UniversalResolver" ;
function App () {
const { data , loading } = useQuery (
UNIVERSAL_RESOLVER ,
{ address : "vitalik.lens" } ,
{ cache : false }
);
return (
< UniversalResolver
data = {data}
loading = {loading}
/>
);
}
export default App;
With this simple code, you essentially just integrated Airstack query that you constructed for universally resolving web3 identities.
Since the code now hardcode vitalik.lens
as the query input, the app will universally resolve vitalik.lens
and have the UI look like this:
Step 9: Toggle API Query to Button Click
At its current state, you have successfully loaded Airstack and its data responses to the UI.
However, the query call is not toggled to the button click and is not dependent on the user input.
This is because you only use useQuery
which automatically calls the API for every render. To do a manual call, swap useQuery
with useLazyQuery
in src/App.jsx
as follows:
Copy import { useLazyQuery } from "@airstack/airstack-react" ;
import UNIVERSAL_RESOLVER from "./graphql/resolve" ;
import UniversalResolver from "./components/UniversalResolver" ;
function App () {
const [ resolveIdentity , { data , loading }] = useLazyQuery (
UNIVERSAL_RESOLVER ,
{} ,
{ cache : false }
);
return (
< UniversalResolver
data = {data}
loading = {loading}
onButtonClick = {resolveIdentity}
/>
);
}
export default App;
The end result is as follows:
Congratulations! đYouâve just learned how to use Airstack to build a universal resolver and integrate Airstack API into your React application.
Developer Support
If you have any questions or need help regarding universal resolver, please join our Airstack's Telegram group.
More Resources