diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index 4f53e011..c8359726 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [UPCOMING] +### Added + +- Add `resolveEnsName` functions + ## v0.0.1 ### Changed diff --git a/sdk/package.json b/sdk/package.json index ed4a58a6..957ac5d3 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,7 +1,7 @@ { "name": "@aragon/osx-commons-sdk", "author": "Aragon Association", - "version": "0.0.1-alpha.6", + "version": "0.0.1-alpha.7", "license": "MIT", "main": "dist/index.js", "module": "dist/osx-commons-sdk.esm.js", @@ -52,6 +52,7 @@ "typescript": "5.2.2" }, "dependencies": { + "@aragon/osx-commons-configs": "^0.2.0", "@aragon/osx-ethers": "^1.3.0-rc0.4", "@aragon/osx-ethers-v1.0.0": "npm:@aragon/osx-ethers@1.2.1", "@aragon/sdk-ipfs": "^1.1.0", diff --git a/sdk/src/ens/index.ts b/sdk/src/ens/index.ts new file mode 100644 index 00000000..04bca77e --- /dev/null +++ b/sdk/src/ens/index.ts @@ -0,0 +1 @@ +export * from './utils'; diff --git a/sdk/src/ens/utils.ts b/sdk/src/ens/utils.ts new file mode 100644 index 00000000..9362b3f4 --- /dev/null +++ b/sdk/src/ens/utils.ts @@ -0,0 +1,37 @@ +import {InvalidEnsError, UnsupportedNetworkError} from '../errors'; +import {isEnsName} from '../validation'; +import {getNetworkByAlias} from '@aragon/osx-commons-configs'; +import {Networkish} from '@ethersproject/networks'; +import {JsonRpcProvider, Provider} from '@ethersproject/providers'; + +/** + * Resolves an ENS name to an address given a provider + * + * @export + * @param {string} ensName + * @param {Provider | Networkish} providerOrNetwork + * @return {(Promise)} + */ +export function resolveEnsName( + ensName: string, + providerOrNetwork: Provider | Networkish +): Promise { + // check if the ensName is valid + if (!isEnsName(ensName)) { + throw new InvalidEnsError(ensName); + } + let provider: Provider; + // check if the providerOrNetwork is a provider or a network + // if it's a provider, use it + if (providerOrNetwork instanceof Provider) { + provider = providerOrNetwork; + // any other case, assume it's a network and create a provider + } else { + const aragonNetwork = getNetworkByAlias(providerOrNetwork.toString()); + if (!aragonNetwork) { + throw new UnsupportedNetworkError(providerOrNetwork.toString()); + } + provider = new JsonRpcProvider(aragonNetwork.url, providerOrNetwork); + } + return provider.resolveName(ensName); +} diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 8d2145dd..7666be8c 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -23,3 +23,5 @@ export * from './math'; export * from './permission'; export * from './proposal'; export * from './time'; + +export * from './ens'; diff --git a/sdk/test/unit/ens.test.ts b/sdk/test/unit/ens.test.ts new file mode 100644 index 00000000..15dfeae9 --- /dev/null +++ b/sdk/test/unit/ens.test.ts @@ -0,0 +1,65 @@ +import {InvalidEnsError, resolveEnsName} from '../../src'; +import {ADDRESS_ONE, TEST_ENS_NAME, TEST_HTTP_URI} from '../constants'; +import {JsonRpcProvider} from '@ethersproject/providers'; + +describe('ens', () => { + describe('resolveEnsName', () => { + it('should receive a JsonRpcProvider and return the correct value', async () => { + const tests = [ + { + input: TEST_ENS_NAME, + network: 'mainnet', + output: ADDRESS_ONE, + }, + { + input: TEST_HTTP_URI, + network: 'mainnet', + output: '', + error: new InvalidEnsError(TEST_HTTP_URI), + }, + ]; + for (const test of tests) { + // mocked provider + const provider = new JsonRpcProvider(); + if (test.error) { + await expect( + async () => await resolveEnsName(test.input, provider) + ).rejects.toThrow(test.error); + continue; + } + jest.spyOn(provider, 'resolveName').mockResolvedValue(test.output); + const resolvedAddress = await resolveEnsName(test.input, provider); + expect(resolvedAddress).toEqual(test.output); + } + }); + it('should receive a Networkish and return the correct value', async () => { + const tests = [ + { + input: TEST_ENS_NAME, + network: 'mainnet', + output: ADDRESS_ONE, + }, + { + input: TEST_HTTP_URI, + network: 'mainnet', + output: '', + error: new InvalidEnsError(TEST_HTTP_URI), + }, + ]; + for (const test of tests) { + // mocked provider + if (test.error) { + await expect( + async () => await resolveEnsName(test.input, test.network) + ).rejects.toThrow(test.error); + continue; + } + jest + .spyOn(JsonRpcProvider.prototype, 'resolveName') + .mockResolvedValue(test.output); + const resolvedAddress = await resolveEnsName(test.input, test.network); + expect(resolvedAddress).toEqual(test.output); + } + }); + }); +}); diff --git a/sdk/yarn.lock b/sdk/yarn.lock index 57199b18..c9d0426a 100644 --- a/sdk/yarn.lock +++ b/sdk/yarn.lock @@ -15,6 +15,13 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aragon/osx-commons-configs@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@aragon/osx-commons-configs/-/osx-commons-configs-0.2.0.tgz#32f83596f4a2e9e48aef61cf560c1c5b4d32a049" + integrity sha512-wCFtgmuGCzs8L5mCxVCYQ6uEu69IrofS7q2w7E1Fjk7/nWuSmRUpgmif3ki9BQq1qpOvDu2P+u3UNLnIz8J82g== + dependencies: + tslib "^2.6.2" + "@aragon/osx-ethers-v1.0.0@npm:@aragon/osx-ethers@1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@aragon/osx-ethers/-/osx-ethers-1.2.1.tgz#a442048137153ed5a3ca4eff3f3927b45a5134b5" @@ -7060,7 +7067,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1: +tslib@^2.0.3, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==