import {
Network,
getNetworkEndpoints,
getInjNameRegistryContractForNetwork,
getInjNameReverseResolverContractForNetwork,
} from "@injectivelabs/networks";
import {
QueryInjName,
ChainGrpcWasmApi,
QueryResolverAddress,
QueryInjectiveAddress,
InjNameServiceQueryTransformer,
} from "@injectivelabs/sdk-ts/client/wasm";
import { nameToNode, normalizeName } from "@injectivelabs/sdk-ts/utils";
export class InjNameService {
private reverseResolverAddress: string;
private registryAddress: string;
private chainGrpcWasmApi: ChainGrpcWasmApi;
constructor(network: Network = Network.Mainnet) {
const endpoints = getNetworkEndpoints(network);
this.chainGrpcWasmApi = new ChainGrpcWasmApi(endpoints.grpc);
this.registryAddress = getInjNameRegistryContractForNetwork(network);
this.reverseResolverAddress =
getInjNameReverseResolverContractForNetwork(network);
}
/**
* Fetch the .inj name for a given Injective address (reverse resolution)
* @param address - The Injective address to resolve
* @returns The .inj domain name
*/
async fetchInjName(address: string): Promise<string> {
const query = new QueryInjName({ address }).toPayload();
const response = await this.chainGrpcWasmApi.fetchSmartContractState(
this.reverseResolverAddress,
query
);
const name =
InjNameServiceQueryTransformer.injectiveNameResponseToInjectiveName(
response
);
if (!name) {
throw new Error(`.inj name not found for ${address}`);
}
// Verify the reverse resolution by checking if the name resolves back to the same address
const addressFromName = await this.fetchInjAddress(name);
if (addressFromName.toLowerCase() !== address.toLowerCase()) {
throw new Error(`.inj name not found for ${address}`);
}
return name;
}
/**
* Fetch the Injective address for a given .inj domain name (forward resolution)
* @param name - The .inj domain name to resolve
* @returns The Injective address
*/
async fetchInjAddress(name: string): Promise<string> {
const normalizedName = normalizeName(name);
const node = nameToNode(normalizedName);
if (!node || node.length === 0) {
throw new Error(`The ${name} can't be normalized`);
}
const resolverAddress = await this.fetchResolverAddress(node);
if (!resolverAddress) {
throw new Error(`Resolver address not found for ${name}`);
}
const query = new QueryInjectiveAddress({ node }).toPayload();
const response = await this.chainGrpcWasmApi.fetchSmartContractState(
resolverAddress,
query
);
const address =
InjNameServiceQueryTransformer.injectiveAddressResponseToInjectiveAddress(
response
);
if (!address) {
throw new Error(`Address not found for ${name}`);
}
return address;
}
/**
* Fetch the resolver address for a given node
* @private
*/
private async fetchResolverAddress(node: number[]): Promise<string> {
const query = new QueryResolverAddress({ node }).toPayload();
const response = await this.chainGrpcWasmApi.fetchSmartContractState(
this.registryAddress,
query
);
return InjNameServiceQueryTransformer.resolverAddressResponseToResolverAddress(
response
);
}
}