Resolution-Java is a library for interacting with blockchain domain names. It can be used to retrieve payment addresses and IPFS hashes for decentralized websites.
Resolution-Java is primarily built and maintained by Unstoppable Domains.
Resolution supports different decentralized domains. Please, refer to the Top Level Domains List
- Installing Resolution
- Using Resolution
- Development
- Contributions
- Free advertising for integrated apps
The most recent release of this library is available on JitPack.
Java 8+ version is required to use this library.
// obtain a key by following this document https://docs.unstoppabledomains.com/domain-distribution-and-management/quickstart/retrieve-an-api-key/#api-key
DomainResolution resolution = new Resolution("<api_key>");
// or
DomainResolution resolution = Resolution
.builder()
.udUnsClient("<api_key>")
.build();
NOTE: The apiKey is only used resolve domains from UNS. Behind the scene, it still uses the default ZNS (Zilliqa) RPC url. For additional control, please specify your ZNS configuration.
DomainResolution resolution = Resolution
.builder()
.udUnsClient("<api_key>")
.znsProviderUrl("https://api.zilliqa.com")
.build();
You may want to specify a custom provider:
- if you want to use a dedicated blockchain node
- if you want to monitor app usage
- if you already have a provider in your app to re-use it for domain resolution
Default provider can be changed by using the builder class ResolutionBuilder
.
// obtain a key from https://www.infura.io
String ethProviderURL = "https://mainnet.infura.io/v3/<infura_api_key>";
String polygonProviderURL = "https://polygon-mainnet.infura.io/v3/<infura_api_key>";
DomainResolution resolution = Resolution.builder()
.unsProviderUrl(UNSLocation.Layer1, ethProviderURL)
.unsProviderUrl(UNSLocation.Layer2, polygonProviderURL)
.znsProviderUrl("https://api.zilliqa.com")
.build();
DomainResolution resolution = Resolution
.builder()
.udUnsClient("<api_key>") // or your custom Ethereum provider
.provider(
new IProvider() {
@Override
public JsonObject request(String url, JsonObject body) throws IOException {
// TODO Make post request to url with given body
// and return JsonObject from the response
return null;
}
@Override
public IProvider setHeader(String key, String value) {
return this;
}
}
)
.build();
// Adding a custom header to the DefaultProvider
DefaultProvider myProvider = DefaultProvider
.cleanBuild()
.setHeader("custom-header", "custom-value")
.setHeader("new-header", "new-value");
DomainResolution resolution = Resolution
.builder()
.udUnsClient("<api_key>") // or your custom Ethereum provider
.provider(myProvider)
.build();
// All network calls will be made with headers "custom-header" and "new-header" instead of default ones
Resolving a domain and getting a currency address.
getAddress(String domain, String ticker)
This API is used to retrieve wallet address for single address record. (See Cryptocurrency payment section for the record format)
With brad.crypto
has crypto.ETH.address
on-chain:
String addr = resolution.getAddress("brad.crypto", "eth");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
getMultiChainAddress(String domain, String ticker, String network)
This API is used to retrieve wallet address for multi-chain address records. (See multi-chain currency)
With brad.crypto
has crypto.USDT.version.ERC20.address
and crypto.USDT.version.OMNI.address
on-chain:
// Get address of token present in multiple chains
String usdtErc20Addr = resolution.getMultiChainAddress("brad.crypto", "USDT", "ERC20");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", usdtErc20Addr);
String usdtOmniAddr = resolution.getMultiChainAddress("brad.crypto", "USDT", "OMNI");
assertEquals("1Ap8kmF4ZoPjt6ZYAfCaTKsbncky3F8eTV", usdtOmniAddr);
getAddress(String domain, String network, String token)
This (Beta) API can be used to retrieve wallet address for single chain and multi-chain address records.
With brad.crypto
has crypto.ETH.address
, crypto.USDT.version.ERC20.address
and crypto.USDT.version.OMNI.address
on-chain:
String addr = resolution.getAddress("brad.crypto", "eth", "eth");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
// Get address of token present in multiple chains
String usdtErc20Addr = resolution.getAddress("brad.crypto", "ETH", "USDT");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", usdtErc20Addr);
String usdtOmniAddr = resolution.getAddress("brad.crypto", "OMNI", "USDT");
assertEquals("1Ap8kmF4ZoPjt6ZYAfCaTKsbncky3F8eTV", usdtOmniAddr);
Note that the API will infer
ERC20
standard asETH
network.
The API can also be used by crypto exchanges to infer wallet addresses. In centralized exchanges, users have same wallet addresses on different networks with same wallet family. (See Blockchain Family, Network, Token Level Addresses section for the record format)
With brad.crypto
only has token.EVM.address
record on-chain.
The API resolves to same wallet address for tokens live on EVM compatible networks.
String ethAddr = resolution.getAddress("brad.crypto", "eth", "eth");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
String usdtETHAddr = resolution.getAddress("brad.crypto", "eth", "usdt");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
String usdtOnAvaxAddr = resolution.getAddress("brad.crypto", "avax", "usdt");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
With brad.crypto
only has token.EVM.ETH.address
record on chain. The API resolves to the same wallet address for tokens
specifically on Ethereum network.
String ethAddr = resolution.getAddress("brad.crypto", "eth", "eth");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
String usdtETHAddr = resolution.getAddress("brad.crypto", "eth", "usdt");
assertEquals("0x8aaD44321A86b170879d7A244c1e8d360c99DdA8", addr);
String usdtOnAvaxAddr = resolution.getAddress("brad.crypto", "avax", "usdt");
assertEquals(null, addr); // it won't resolve for AVAX
The API is compatible with other address formats. If a domain has multiple address formats set, it will follow the algorithm described as follow:
if a domain has following records set:
token.EVM.address
crypto.USDC.version.ERC20.address
token.EVM.ETH.USDC.address
crypto.USDC.address
token.EVM.ETH.address
getAddress(domain, 'ETH', 'USDC')
will lookup records in the following order:
1. token.EVM.ETH.USDC.address
2. crypto.USDC.address
3. crypto.USDC.version.ERC20.address
4. token.EVM.ETH.address
5. token.EVM.address
Each decentralized domain is owned by someone on the blockchain and held within their wallet. The following command will return the domain owner's Ethereum address.
String owner = resolution.getOwner("brad.crypto");
assertEquals("0x8aad44321a86b170879d7a244c1e8d360c99dda8", owner);
You can also get the result in a batch format for UNS:
List<String> domains = Arrays.asList("brad.crypto", "homecakes.crypto");
Map<String, String> owners = mainnetResolution.getBatchOwners(domains);
assertEquals("0x8aad44321a86b170879d7a244c1e8d360c99dda8", owners.get("brad.crypto"));
assertEquals("0xe7474d07fd2fa286e7e0aa23cd107f8379085037", owners.get("homecakes.crypto"));
Decentralized websites host their content on decentralized file storage systems such as IPFS.
To get the IPFS hash associated with a domain (and therefore its content), you can use the getIpfsHash
method.
String ipfs = resolution.getIpfsHash("brad.crypto");
assertEquals("Qme54oEzRkgooJbCDr78vzKAWcv6DDEZqRhhDyDtzgrZP6", ipfs);
Retrieve any record of domain. Applications sometimes set custom records for a domain to use within their application. To read these records, use the getRecord
method.
String record = resolution.getRecord("ryan.crypto", "custom.record.value");
assertEquals("Example custom record value", record);
If the domain you requested is not registered or doesn't have the record you are looking for, this library will throw a NamingServiceException
error with one of these codes. We recommend creating customized errors in your app based on the return value of the error.
public enum NSExceptionCode {
UnsupportedDomain,
UnregisteredDomain,
UnknownCurrency,
RecordNotFound,
BlockchainIsDown,
UnknownError,
IncorrectContractAddress,
IncorrectMethodName,
UnspecifiedResolver,
UnsupportedCurrency,
NotImplemented,
InconsistentDomainArray,
InvalidDomain,
ReverseResolutionNotSpecified;
}
Please see the Resolution-Java Error Codes page for details of the specific error codes.
Resolution library relies on environment variables to load TestNet RPC Urls. This way, our keys don't expose directly to the code. These environment variables are:
- L1_TEST_NET_RPC_URL
- L2_TEST_NET_RPC_URL
Note: if you don't wish to install Gradle you can use it with wrapper:
./gradlew
instead ofgradle
.
- To run a build with associated tests, use
gradle build
. - To run a build without running the tests, use
gradle build -x test
.
Internal network config
can be updated by running the gradle pullNetworkConfig
task and committing the updated file.
Contributions to this library are more than welcome. The easiest way to contribute is through GitHub issues and pull requests.
Once your app has a working Unstoppable Domains integration, register it here. Registered apps appear on the Unstoppable Domains homepage and Applications page — putting your app in front of tens of thousands of potential customers per day.
Also, every week we select a newly-integrated app to feature in the Unstoppable Update newsletter. This newsletter is delivered to straight into the inbox of ~100,000 crypto fanatics — all of whom could be new customers to grow your business.
Join our discord community and ask questions.
We're always looking for ways to improve how developers use and integrate our products into their applications. We'd love to hear about your experience to help us improve by taking our survey.