Skip to content

Commit

Permalink
Merge pull request #262 from unstoppabledomains/sam/api-1177-base-sup…
Browse files Browse the repository at this point in the history
…port

feat: support Base resolution
  • Loading branch information
sammyluo authored Oct 22, 2024
2 parents 3c10dce + d495e81 commit db48ae3
Show file tree
Hide file tree
Showing 24 changed files with 1,509 additions and 582 deletions.
8 changes: 4 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
L1_TEST_NET_RPC_URL=https://goerli.infura.io/v3/<your_key>
L1_TEST_NET_RPC_WSS_URL=wss://goerli.infura.io/ws/v3/<your_key>
L2_TEST_NET_RPC_URL=https://polygon-mumbai.infura.io/v3/<your_key>
L2_TEST_NET_RPC_WSS_URL=wss://polygon-mumbai.g.alchemy.com/v2/<your_key>
L1_TEST_NET_RPC_URL=https://sepolia.infura.io/v3/<your_key>
L1_TEST_NET_RPC_WSS_URL=wss://sepolia.infura.io/ws/v3/<your_key>
L2_TEST_NET_RPC_URL=https://polygon-amoy.infura.io/v3/<your_key>
L2_TEST_NET_RPC_WSS_URL=wss://polygon-amoy.g.alchemy.com/v2/<your_key>
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 9.3.0

- Support Base blockchain UNS domains resolution

## 9.2.2

- Changed devDependencies to dependencies
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"files": [
"build"
],
"author": "JohnnyJumper <https://github.com/JohnnyJumper>, Bogdan Gusiev <https://github.com/bogdan>, Braden Pezeshki <https://github.com/perfect-cents, Vladyslav Batyrenko <https://github.com/mvlabat>, Matthew Gould <https://github.com/theporpoise>",
"author": "Unstoppable Domains",
"repository": {
"type": "git",
"url": "https://github.com/unstoppabledomains/resolution.git"
Expand All @@ -60,7 +60,6 @@
},
"homepage": "https://github.com/unstoppabledomains/resolution.git#readme",
"devDependencies": {
"@ethersproject/providers": "^5.4.5",
"@types/bn.js": "^4.11.6",
"@types/crypto-js": "^4.1.1",
"@types/elliptic": "^6.4.13",
Expand All @@ -76,6 +75,7 @@
"eslint": "^7.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jest": "^24.1.0",
"ethers": "^6.13.4",
"husky": "^6.0.0",
"jest": "^27.0.4",
"lint-staged": "11.0.0",
Expand Down Expand Up @@ -104,7 +104,6 @@
"cross-fetch": "4.0.0",
"crypto-js": "^4.1.1",
"elliptic": "^6.5.4",
"ethereum-ens-network-map": "^1.0.2",
"js-sha256": "^0.9.0",
"js-sha3": "^0.8.0"
},
Expand Down
22 changes: 2 additions & 20 deletions src/Ens.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as contentHash from 'content-hash';
import bip44Constants from 'bip44-constants';
import {formatsByCoinType} from '@ensdomains/address-encoder';
import EnsNetworkMap from 'ethereum-ens-network-map';
import {default as ensInterface} from './contracts/ens/ens';
import {default as resolverInterface} from './contracts/ens/resolver';
import {default as nameWrapperInterface} from './contracts/ens/nameWrapper';
Expand All @@ -15,7 +14,6 @@ import {
Locations,
NamingServiceName,
Provider,
TokenUriMetadata,
BlockchainType,
DnsRecordType,
DnsRecord,
Expand Down Expand Up @@ -60,7 +58,8 @@ export default class Ens extends NamingService {
this.proxyServiceApiKey = finalSource['proxyServiceApiKey'];

const registryAddress =
finalSource['registryAddress'] || EnsNetworkMap[this.network];
finalSource['registryAddress'] ||
ensConfig.networks[this.network].contracts.ENSRegistry.address;
this.registryContract = new EthereumContract(
ensInterface,
registryAddress,
Expand Down Expand Up @@ -289,7 +288,6 @@ export default class Ens extends NamingService {
let domainName = '';
const nameWrapperMetadataResponse = await Networking.fetch(
`https://metadata.ens.domains/${this.networkName}/${this.nameWrapperContract.address}/${hash}`,
{},
);
if (nameWrapperMetadataResponse.status === 200) {
const jsonResponse = await nameWrapperMetadataResponse.json();
Expand All @@ -299,7 +297,6 @@ export default class Ens extends NamingService {

const baseRegistrarMetadataResponse = await Networking.fetch(
`https://metadata.ens.domains/${this.networkName}/${this.baseRegistrarContract.address}/${hash}`,
{},
);

if (baseRegistrarMetadataResponse.status === 200) {
Expand Down Expand Up @@ -614,19 +611,4 @@ export default class Ens extends NamingService {
this.namehash(domain),
]);
}

private async getMetadataFromTokenURI(
tokenUri: string,
): Promise<TokenUriMetadata> {
const resp = await Networking.fetch(tokenUri, {});
if (resp.ok) {
return resp.json();
}

throw new ResolutionError(ResolutionErrorCode.ServiceProviderError, {
providerMessage: await resp.text(),
method: 'UDAPI',
methodName: 'tokenURIMetadata',
});
}
}
68 changes: 57 additions & 11 deletions src/Resolution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
Web3Version1Provider,
ReverseResolutionOptions,
UnsLocation,
BlockchainType,
} from './types/publicTypes';
import ResolutionError, {ResolutionErrorCode} from './errors/resolutionError';
import DnsUtils from './utils/DnsUtils';
Expand Down Expand Up @@ -71,6 +72,7 @@ export default class Resolution {

constructor(config: {sourceConfig?: SourceConfig; apiKey?: string} = {}) {
const uns = this.getUnsConfig(config);
const unsBase = this.getUnsBaseConfig(config);
const zns = this.getZnsConfig(config);
const ens = this.getEnsConfig(config);

Expand All @@ -86,6 +88,10 @@ export default class Resolution {
usedServices: [uns],
native: uns instanceof Uns ? uns : new Uns(),
},
[NamingServiceName.UNS_BASE]: {
usedServices: [unsBase],
native: unsBase instanceof Uns ? unsBase : new Uns(),
},
[NamingServiceName.ZNS]: {
usedServices: equalUdApiProviders ? [uns] : [uns, zns],
native: zns instanceof Zns ? zns : new Zns(),
Expand Down Expand Up @@ -657,7 +663,7 @@ export default class Resolution {
async email(domain: string): Promise<string> {
domain = prepareAndValidateDomain(domain);
let key = 'whois.email.value';
const serviceName = findNamingServiceName(domain);
const serviceName = await findNamingServiceName(domain);
if (serviceName === 'ENS') {
key = 'email';
}
Expand Down Expand Up @@ -1057,7 +1063,7 @@ export default class Resolution {
private async getMetadataFromTokenURI(
tokenUri: string,
): Promise<TokenUriMetadata> {
const resp = await Networking.fetch(tokenUri, {});
const resp = await Networking.fetch(tokenUri);
if (resp.ok) {
return resp.json();
}
Expand Down Expand Up @@ -1097,7 +1103,7 @@ export default class Resolution {
domain: string,
func: (service: NamingService) => T,
): Promise<UnwrapPromise<T>> {
const serviceName = findNamingServiceName(domain);
const serviceName = await findNamingServiceName(domain);
if (!serviceName) {
throw new ResolutionError(ResolutionErrorCode.UnsupportedDomain, {
domain,
Expand Down Expand Up @@ -1136,7 +1142,7 @@ export default class Resolution {
func: (service: NamingService) => Promise<boolean>,
options: {throwIfUnsupportedDomain: boolean; expectedValue: boolean},
): Promise<boolean> {
const serviceName = findNamingServiceName(domain);
const serviceName = await findNamingServiceName(domain);
if (!serviceName) {
if (!options.throwIfUnsupportedDomain) {
return !options.expectedValue;
Expand Down Expand Up @@ -1173,10 +1179,18 @@ export default class Resolution {
private async reverseGetTokenId(
address: string,
location?: UnsLocation,
): Promise<string> {
const service = this.serviceMap['UNS'].native;
const tokenId = await service.reverseOf(address, location);
return tokenId as string;
): Promise<string | null> {
let tokenId: string | null = null;

const unsService = this.serviceMap['UNS'].native;
tokenId = await unsService.reverseOf(address, location);

if (!tokenId) {
const baseUnsService = this.serviceMap['UNS_BASE'].native;
tokenId = await baseUnsService.reverseOf(address, location);
}

return tokenId;
}

private getUnsConfig(config: ResolutionConfig): Uns | UdApi {
Expand All @@ -1187,11 +1201,38 @@ export default class Resolution {
url: `${DEFAULT_UNS_PROXY_SERVICE_URL}/chains/eth/rpc`,
network: 'mainnet',
proxyServiceApiKey: config.apiKey,
blockchain: BlockchainType.ETH,
},
Layer2: {
url: `${DEFAULT_UNS_PROXY_SERVICE_URL}/chains/matic/rpc`,
network: 'polygon-mainnet',
proxyServiceApiKey: config.apiKey,
blockchain: BlockchainType.POL,
},
},
});
}

return isApi(config.sourceConfig?.uns)
? new UdApi(config.sourceConfig?.uns)
: new Uns(config.sourceConfig?.uns);
}

private getUnsBaseConfig(config: ResolutionConfig): Uns | UdApi {
if (config.apiKey) {
return new Uns({
locations: {
Layer1: {
url: `${DEFAULT_UNS_PROXY_SERVICE_URL}/chains/eth/rpc`,
network: 'mainnet',
proxyServiceApiKey: config.apiKey,
blockchain: BlockchainType.ETH,
},
Layer2: {
url: `${DEFAULT_UNS_PROXY_SERVICE_URL}/chains/base/rpc`,
network: 'base-mainnet',
proxyServiceApiKey: config.apiKey,
blockchain: BlockchainType.BASE,
},
},
});
Expand All @@ -1202,13 +1243,13 @@ export default class Resolution {
: new Uns(config.sourceConfig?.uns);
}

getZnsConfig(config: ResolutionConfig): Zns | UdApi {
private getZnsConfig(config: ResolutionConfig): Zns | UdApi {
return isApi(config.sourceConfig?.zns)
? new UdApi(config.sourceConfig?.zns)
: new Zns(config.sourceConfig?.zns);
}

getEnsConfig(config: ResolutionConfig): Ens | UdApi {
private getEnsConfig(config: ResolutionConfig): Ens | UdApi {
if (config.apiKey) {
return new Ens({
url: `${DEFAULT_UNS_PROXY_SERVICE_URL}/chains/eth/rpc`,
Expand All @@ -1231,5 +1272,10 @@ type ServicesEntry = {
};

function isApi(obj: any): obj is Api {
return obj && obj.api;
return (
typeof obj === 'object' &&
obj !== null &&
'api' in obj &&
typeof obj.api === 'boolean'
);
}
8 changes: 4 additions & 4 deletions src/UdApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export default class UdApi extends NamingService {

constructor(api?: Api) {
super();
this.url = api?.url || 'https://unstoppabledomains.com/api/v1';
this.url = api?.url || 'https://unstoppabledomains.com/api/v1'; // TODO: this is about to be deprecated
const DefaultUserAgent =
'cross-fetch/3.1.4 (+https://github.com/lquixada/cross-fetch)';
'cross-fetch/4.0.0 (+https://github.com/lquixada/cross-fetch)';
const CustomUserAgent = `${DefaultUserAgent} Resolution`;
this.headers = {'X-user-agent': CustomUserAgent};
}
Expand Down Expand Up @@ -77,7 +77,7 @@ export default class UdApi extends NamingService {
}

async twitter(domain: string): Promise<string> {
const serviceName = findNamingServiceName(domain);
const serviceName = await findNamingServiceName(domain);
if (serviceName !== NamingServiceName.UNS) {
throw new ResolutionError(ResolutionErrorCode.UnsupportedMethod, {
domain,
Expand Down Expand Up @@ -150,7 +150,7 @@ export default class UdApi extends NamingService {

private async getMetadata(tokenId: string): Promise<ResolutionResponse> {
const tokenUri = `${this.url}/${tokenId}`;
const resp = await Networking.fetch(tokenUri, {}).catch((err) => {
const resp = await Networking.fetch(tokenUri).catch((err) => {
throw new ResolutionError(ResolutionErrorCode.MetadataEndpointError, {
tokenUri: tokenUri || 'undefined',
errorMessage: err.message,
Expand Down
6 changes: 3 additions & 3 deletions src/Uns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ export default class Uns extends NamingService {
this.unsl1 = new UnsInternal(
UnsLocation.Layer1,
source.locations.Layer1,
BlockchainType.ETH,
source.locations.Layer1.blockchain ?? BlockchainType.ETH,
);
this.unsl2 = new UnsInternal(
UnsLocation.Layer2,
source.locations.Layer2,
BlockchainType.MATIC,
source.locations.Layer2.blockchain ?? BlockchainType.POL,
);
}

Expand Down Expand Up @@ -447,7 +447,7 @@ export default class Uns extends NamingService {

private async getMetadata(tokenId: string): Promise<DomainMetadata> {
const tokenUri = await this.getTokenUri(tokenId);
const resp = await Networking.fetch(tokenUri, {}).catch((err) => {
const resp = await Networking.fetch(tokenUri).catch((err) => {
throw new ResolutionError(ResolutionErrorCode.MetadataEndpointError, {
tokenUri: tokenUri || 'undefined',
errorMessage: err.message,
Expand Down
Loading

0 comments on commit db48ae3

Please sign in to comment.