diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ac14f931d..73c1a29c28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,13 +7,15 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
### Bug Fixes
-*
+* fixed several code issues found by sonar [#2113](https://github.com/hyperledger/web3j/pull/2113)
+* update GitHub actions versions [#2114](https://github.com/hyperledger/web3j/pull/2114)
### Features
* bump snapshot version to 4.12.3 [#2101](https://github.com/hyperledger/web3j/pull/2101)
* Add HSM kms implementation [#2105](https://github.com/hyperledger/web3j/pull/2105)
* Added support for Holesky [#2111](https://github.com/hyperledger/web3j/pull/2111)
+* Advance ENS features and metadata retrieval [#2116](https://github.com/hyperledger/web3j/pull/2116)
### BREAKING CHANGES
diff --git a/core/src/main/java/org/web3j/ens/EnsMetadataResponse.java b/core/src/main/java/org/web3j/ens/EnsMetadataResponse.java
new file mode 100644
index 0000000000..0c91390ccf
--- /dev/null
+++ b/core/src/main/java/org/web3j/ens/EnsMetadataResponse.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2024 Web3 Labs Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.web3j.ens;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class EnsMetadataResponse {
+ public boolean is_normalized;
+ public String name;
+ public String description;
+ public Attribute[] attributes;
+ public String url;
+ public long last_request_date;
+ public int version;
+ public String background_image;
+ public String image;
+ public String image_url;
+
+ public boolean isIs_normalized() {
+ return is_normalized;
+ }
+
+ public void setIs_normalized(boolean is_normalized) {
+ this.is_normalized = is_normalized;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Attribute[] getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Attribute[] attributes) {
+ this.attributes = attributes;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public long getLast_request_date() {
+ return last_request_date;
+ }
+
+ public void setLast_request_date(long last_request_date) {
+ this.last_request_date = last_request_date;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ public String getBackground_image() {
+ return background_image;
+ }
+
+ public void setBackground_image(String background_image) {
+ this.background_image = background_image;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public String getImage_url() {
+ return image_url;
+ }
+
+ public void setImage_url(String image_url) {
+ this.image_url = image_url;
+ }
+
+ public static class Attribute {
+ public String trait_type;
+ public String display_type;
+ public Object value;
+ }
+
+ @Override
+ public String toString() {
+ try {
+ return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(this);
+ } catch (JsonProcessingException e) {
+ return "Error serializing EnsMetadataResponse: " + e.getMessage();
+ }
+ }
+}
diff --git a/core/src/main/java/org/web3j/ens/EnsResolver.java b/core/src/main/java/org/web3j/ens/EnsResolver.java
index 73018379b2..15cac0dad6 100644
--- a/core/src/main/java/org/web3j/ens/EnsResolver.java
+++ b/core/src/main/java/org/web3j/ens/EnsResolver.java
@@ -25,12 +25,14 @@
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
+import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.web3j.abi.DefaultFunctionReturnDecoder;
import org.web3j.abi.datatypes.ens.OffchainLookup;
+import org.web3j.crypto.Credentials;
import org.web3j.crypto.Keys;
import org.web3j.crypto.WalletUtils;
import org.web3j.dto.EnsGatewayRequestDTO;
@@ -38,12 +40,14 @@
import org.web3j.ens.contracts.generated.ENS;
import org.web3j.ens.contracts.generated.OffchainResolverContract;
import org.web3j.ens.contracts.generated.PublicResolver;
+import org.web3j.ens.contracts.generated.ReverseRegistrar;
import org.web3j.protocol.ObjectMapperFactory;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.protocol.core.methods.response.EthSyncing;
import org.web3j.protocol.core.methods.response.NetVersion;
+import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.ClientTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.DefaultGasProvider;
@@ -150,6 +154,31 @@ protected OffchainResolverContract obtainOffchainResolver(String ensName) {
}
}
+ protected OffchainResolverContract obtainOffchainResolver(
+ String ensName, Credentials credentials) {
+ if (isValidEnsName(ensName, addressLength)) {
+ boolean isSynced;
+
+ try {
+ isSynced = isSynced();
+ } catch (Exception e) {
+ throw new EnsResolutionException("Unable to determine sync status of node", e);
+ }
+
+ if (!isSynced) {
+ throw new EnsResolutionException("Node is not currently synced");
+ }
+
+ try {
+ return lookupOffchainResolver(ensName, credentials);
+ } catch (Exception e) {
+ throw new EnsResolutionException("Unable to get resolver", e);
+ }
+ } else {
+ throw new EnsResolutionException("EnsName is invalid: " + ensName);
+ }
+ }
+
/**
* Returns the address of the resolver for the specified node.
*
@@ -336,6 +365,19 @@ protected Request buildRequest(String url, String sender, String data)
}
}
+ public TransactionReceipt setReverseName(String name, Credentials credentials)
+ throws Exception {
+ ReverseRegistrar reverseRegistrar = getReverseRegistrarContract(credentials);
+ return reverseRegistrar.setName(name).send();
+ }
+
+ public TransactionReceipt setReverseName(
+ String addr, String owner, String resolver, String name, Credentials credentials)
+ throws Exception {
+ ReverseRegistrar reverseRegistrar = getReverseRegistrarContract(credentials);
+ return reverseRegistrar.setNameForAddr(addr, owner, resolver, name).send();
+ }
+
/**
* Reverse name resolution as documented in the specification.
@@ -376,13 +418,14 @@ private OffchainResolverContract lookupOffchainResolver(String ensName) throws E
getResolverAddress(ensName), web3j, transactionManager, new DefaultGasProvider());
}
- private String getResolverAddress(String ensName) throws Exception {
- NetVersion netVersion = web3j.netVersion().send();
- String registryContract = Contracts.resolveRegistryContract(netVersion.getNetVersion());
-
- ENS ensRegistry =
- ENS.load(registryContract, web3j, transactionManager, new DefaultGasProvider());
+ private OffchainResolverContract lookupOffchainResolver(String ensName, Credentials credentials)
+ throws Exception {
+ return OffchainResolverContract.load(
+ getResolverAddress(ensName), web3j, credentials, new DefaultGasProvider());
+ }
+ public String getResolverAddress(String ensName) throws Exception {
+ ENS ensRegistry = getRegistryContract();
byte[] nameHash = NameHash.nameHashAsBytes(ensName);
String address = ensRegistry.resolver(nameHash).send();
@@ -393,6 +436,66 @@ private String getResolverAddress(String ensName) throws Exception {
return address;
}
+ public String getOwnerAddress(String ensName) throws Exception {
+ ENS ensRegistry = getRegistryContract();
+ byte[] nameHash = NameHash.nameHashAsBytes(ensName);
+ return ensRegistry.owner(nameHash).send();
+ }
+
+ private ENS getRegistryContract() throws IOException {
+ NetVersion netVersion = web3j.netVersion().send();
+ String registryContract = Contracts.resolveRegistryContract(netVersion.getNetVersion());
+
+ return ENS.load(registryContract, web3j, transactionManager, new DefaultGasProvider());
+ }
+
+ protected ReverseRegistrar getReverseRegistrarContract(Credentials credentials)
+ throws IOException {
+ NetVersion netVersion = web3j.netVersion().send();
+ String reverseRegistrarContract =
+ ReverseRegistrarContracts.resolveReverseRegistrarContract(
+ netVersion.getNetVersion());
+
+ return ReverseRegistrar.load(
+ reverseRegistrarContract, web3j, credentials, new DefaultGasProvider());
+ }
+
+ public EnsMetadataResponse getEnsMetadata(String name) throws IOException {
+ NetVersion netVersion = web3j.netVersion().send();
+ byte[] nameHash = NameHash.nameHashAsBytes(name);
+ String apiUrl =
+ NameWrapperUrl.getEnsMetadataApi(netVersion.getNetVersion())
+ + Numeric.toHexString(nameHash);
+
+ Request request = new Request.Builder().url(apiUrl).get().build();
+
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) {
+ throw new IOException(
+ "Failed to fetch ENS metadata. HTTP error code: " + response.code());
+ }
+
+ // Parse the JSON response
+ assert response.body() != null;
+ String responseBody = response.body().string();
+ return new ObjectMapper().readValue(responseBody, EnsMetadataResponse.class);
+ }
+ }
+
+ public String getEnsText(String name, String key) throws Exception {
+ OffchainResolverContract offchainResolverContract = obtainOffchainResolver(name);
+ byte[] nameHash = NameHash.nameHashAsBytes(name);
+ return offchainResolverContract.text(nameHash, key).send();
+ }
+
+ public TransactionReceipt setEnsText(
+ String name, String key, String value, Credentials credentials) throws Exception {
+ OffchainResolverContract offchainResolverContract =
+ obtainOffchainResolver(name, credentials);
+ byte[] nameHash = NameHash.nameHashAsBytes(name);
+ return offchainResolverContract.setText(nameHash, key, value).send();
+ }
+
boolean isSynced() throws Exception {
EthSyncing ethSyncing = web3j.ethSyncing().send();
if (ethSyncing.isSyncing()) {
diff --git a/core/src/main/java/org/web3j/ens/NameWrapperUrl.java b/core/src/main/java/org/web3j/ens/NameWrapperUrl.java
new file mode 100644
index 0000000000..6d41000f75
--- /dev/null
+++ b/core/src/main/java/org/web3j/ens/NameWrapperUrl.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2024 Web3 Labs Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.web3j.ens;
+
+import org.web3j.tx.ChainIdLong;
+
+public class NameWrapperUrl {
+
+ public static final String BASE_URL = "https://ens-metadata-service.appspot.com/";
+ public static final String MAINNET_URL =
+ BASE_URL + "mainnet/" + "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401/";
+ public static final String SEPOLIA_URL =
+ BASE_URL + "sepolia/" + "0x0635513f179D50A207757E05759CbD106d7dFcE8/";
+ public static final String HOLESKY_URL =
+ BASE_URL + "holesky/" + "0xab50971078225D365994dc1Edcb9b7FD72Bb4862/";
+
+ private NameWrapperUrl() {}
+
+ public static String getEnsMetadataApi(String chainId) {
+ final Long chainIdLong = Long.parseLong(chainId);
+ if (chainIdLong.equals(ChainIdLong.MAINNET)) {
+ return MAINNET_URL;
+ } else if (chainIdLong.equals(ChainIdLong.SEPOLIA)) {
+ return SEPOLIA_URL;
+ } else if (chainIdLong.equals(ChainIdLong.HOLESKY)) {
+ return HOLESKY_URL;
+ } else {
+ throw new EnsResolutionException(
+ "Unable to get ENS metadata API for network id: " + chainId);
+ }
+ }
+}
diff --git a/core/src/main/java/org/web3j/ens/ReverseRegistrarContracts.java b/core/src/main/java/org/web3j/ens/ReverseRegistrarContracts.java
new file mode 100644
index 0000000000..9d02946a2a
--- /dev/null
+++ b/core/src/main/java/org/web3j/ens/ReverseRegistrarContracts.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 Web3 Labs Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.web3j.ens;
+
+import org.web3j.tx.ChainIdLong;
+
+public class ReverseRegistrarContracts {
+
+ public static final String MAINNET = "0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb";
+ public static final String SEPOLIA = "0xA0a1AbcDAe1a2a4A2EF8e9113Ff0e02DD81DC0C6";
+ public static final String HOLESKY = "0x132AC0B116a73add4225029D1951A9A707Ef673f";
+ public static final String LINEA = "0x08D3fF6E65f680844fd2465393ff6f0d742b67D5";
+ public static final String LINEA_SEPOLIA = "0x4aAA964D8EB65508ca3DA3b0A3C060c16059E613";
+
+ private ReverseRegistrarContracts() {}
+
+ public static String resolveReverseRegistrarContract(String chainId) {
+ final Long chainIdLong = Long.parseLong(chainId);
+ if (chainIdLong.equals(ChainIdLong.MAINNET)) {
+ return MAINNET;
+ } else if (chainIdLong.equals(ChainIdLong.SEPOLIA)) {
+ return SEPOLIA;
+ } else if (chainIdLong.equals(ChainIdLong.HOLESKY)) {
+ return HOLESKY;
+ } else if (chainIdLong.equals(ChainIdLong.LINEA)) {
+ return LINEA;
+ } else if (chainIdLong.equals(ChainIdLong.LINEA_SEPOLIA)) {
+ return LINEA_SEPOLIA;
+ } else {
+ throw new EnsResolutionException(
+ "Unable to resolve ENS reverse registrar contract for network id: " + chainId);
+ }
+ }
+}
diff --git a/core/src/main/java/org/web3j/ens/contracts/generated/ReverseRegistrar.java b/core/src/main/java/org/web3j/ens/contracts/generated/ReverseRegistrar.java
new file mode 100644
index 0000000000..a882ebf876
--- /dev/null
+++ b/core/src/main/java/org/web3j/ens/contracts/generated/ReverseRegistrar.java
@@ -0,0 +1,450 @@
+package org.web3j.ens.contracts.generated;
+
+import io.reactivex.Flowable;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.web3j.abi.EventEncoder;
+import org.web3j.abi.FunctionEncoder;
+import org.web3j.abi.TypeReference;
+import org.web3j.abi.datatypes.Address;
+import org.web3j.abi.datatypes.Bool;
+import org.web3j.abi.datatypes.Event;
+import org.web3j.abi.datatypes.Function;
+import org.web3j.abi.datatypes.Type;
+import org.web3j.abi.datatypes.generated.Bytes32;
+import org.web3j.crypto.Credentials;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.DefaultBlockParameter;
+import org.web3j.protocol.core.RemoteCall;
+import org.web3j.protocol.core.RemoteFunctionCall;
+import org.web3j.protocol.core.methods.request.EthFilter;
+import org.web3j.protocol.core.methods.response.BaseEventResponse;
+import org.web3j.protocol.core.methods.response.Log;
+import org.web3j.protocol.core.methods.response.TransactionReceipt;
+import org.web3j.tx.Contract;
+import org.web3j.tx.TransactionManager;
+import org.web3j.tx.gas.ContractGasProvider;
+
+/**
+ *
Auto generated code.
+ *
Do not modify!
+ *
Please use the web3j command line tools,
+ * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
+ * codegen module to update.
+ *
+ *
Generated with web3j version 4.12.2.
+ */
+@SuppressWarnings("rawtypes")
+public class ReverseRegistrar extends Contract {
+ public static final String BINARY = "60a060405234801561000f575f80fd5b50604051610e27380380610e2783398101604081905261002e916101ab565b61003733610145565b6001600160a01b03811660808190526040516302571be360e01b81527f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260048201525f91906302571be390602401602060405180830381865afa1580156100a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100c491906101ab565b90506001600160a01b0381161561013e57604051630f41a04d60e11b81523360048201526001600160a01b03821690631e83409a906024016020604051808303815f875af1158015610118573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013c91906101cd565b505b50506101e4565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101a8575f80fd5b50565b5f602082840312156101bb575f80fd5b81516101c681610194565b9392505050565b5f602082840312156101dd575f80fd5b5051919050565b608051610c1d61020a5f395f8181610127015281816102cb01526104c40152610c1d5ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80638da5cb5b11610088578063c66485b211610063578063c66485b2146101da578063da8c229e146101ed578063e0dba60f1461021f578063f2fde38b14610232575f80fd5b80638da5cb5b146101a4578063bffbe61c146101b4578063c47f0027146101c7575f80fd5b806365669631116100c35780636566963114610161578063715018a6146101745780637a806d6b1461017e578063828eab0e14610191575f80fd5b80630f5a5466146100e95780631e83409a1461010f5780633f15457f14610122575b5f80fd5b6100fc6100f7366004610958565b610245565b6040519081526020015b60405180910390f35b6100fc61011d36600461098f565b610258565b6101497f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610106565b6100fc61016f3660046109aa565b610279565b61017c610526565b005b6100fc61018c366004610a91565b610539565b600254610149906001600160a01b031681565b5f546001600160a01b0316610149565b6100fc6101c236600461098f565b6105ae565b6100fc6101d5366004610b02565b610608565b61017c6101e836600461098f565b610624565b61020f6101fb36600461098f565b60016020525f908152604090205460ff1681565b6040519015158152602001610106565b61017c61022d366004610b49565b6106e4565b61017c61024036600461098f565b61074a565b5f610251338484610279565b9392505050565b6002545f9061027390339084906001600160a01b0316610279565b92915050565b5f836001600160a01b0381163314806102a05750335f9081526001602052604090205460ff165b80610334575060405163e985e9c560e01b81526001600160a01b0382811660048301523360248301527f0000000000000000000000000000000000000000000000000000000000000000169063e985e9c590604401602060405180830381865afa158015610310573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103349190610b75565b806103435750610343816107c3565b6103e05760405162461bcd60e51b815260206004820152605b60248201527f526576657273655265676973747261723a2043616c6c6572206973206e6f742060448201527f6120636f6e74726f6c6c6572206f7220617574686f726973656420627920616460648201527f6472657373206f7220746865206164647265737320697473656c660000000000608482015260a4015b60405180910390fd5b5f6103ea8661083a565b604080517f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2602080830191909152818301849052825180830384018152606090920192839052815191012091925081906001600160a01b038916907f6ada868dd3058cf77a48a74489fd7963688e5464b2b0fa957ace976243270e92905f90a36040516305ef2c7f60e41b81527f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e26004820152602481018390526001600160a01b03878116604483015286811660648301525f60848301527f00000000000000000000000000000000000000000000000000000000000000001690635ef2c7f09060a4015f604051808303815f87803b158015610505575f80fd5b505af1158015610517573d5f803e3d5ffd5b50929998505050505050505050565b61052e61089c565b6105375f6108f5565b565b5f80610546868686610279565b604051637737221360e01b81529091506001600160a01b038516906377372213906105779084908790600401610b90565b5f604051808303815f87803b15801561058e575f80fd5b505af11580156105a0573d5f803e3d5ffd5b509298975050505050505050565b5f7f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e26105d98361083a565b604080516020810193909352820152606001604051602081830303815290604052805190602001209050919050565b6002545f9061027390339081906001600160a01b031685610539565b61062c61089c565b6001600160a01b03811661069b5760405162461bcd60e51b815260206004820152603060248201527f526576657273655265676973747261723a205265736f6c76657220616464726560448201526f07373206d757374206e6f7420626520360841b60648201526084016103d7565b600280546001600160a01b0319166001600160a01b0383169081179091556040517feae17a84d9eb83d8c8eb317f9e7d64857bc363fa51674d996c023f4340c577cf905f90a250565b6106ec61089c565b6001600160a01b0382165f81815260016020908152604091829020805460ff191685151590811790915591519182527f4c97694570a07277810af7e5669ffd5f6a2d6b74b6e9a274b8b870fd5114cf87910160405180910390a25050565b61075261089c565b6001600160a01b0381166107b75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103d7565b6107c0816108f5565b50565b5f816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561081e575060408051601f3d908101601f1916820190925261081b91810190610bcc565b60015b61082957505f919050565b6001600160a01b0316331492915050565b5f60285b8015610891575f19016f181899199a1a9b1b9c1cb0b131b232b360811b600f84161a81536010909204915f19016f181899199a1a9b1b9c1cb0b131b232b360811b600f84161a815360108304925061083e565b505060285f20919050565b5f546001600160a01b031633146105375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103d7565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146107c0575f80fd5b5f8060408385031215610969575f80fd5b823561097481610944565b9150602083013561098481610944565b809150509250929050565b5f6020828403121561099f575f80fd5b813561025181610944565b5f805f606084860312156109bc575f80fd5b83356109c781610944565b925060208401356109d781610944565b915060408401356109e781610944565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610a15575f80fd5b813567ffffffffffffffff811115610a2f57610a2f6109f2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610a5e57610a5e6109f2565b604052818152838201602001851015610a75575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215610aa4575f80fd5b8435610aaf81610944565b93506020850135610abf81610944565b92506040850135610acf81610944565b9150606085013567ffffffffffffffff811115610aea575f80fd5b610af687828801610a06565b91505092959194509250565b5f60208284031215610b12575f80fd5b813567ffffffffffffffff811115610b28575f80fd5b610b3484828501610a06565b949350505050565b80151581146107c0575f80fd5b5f8060408385031215610b5a575f80fd5b8235610b6581610944565b9150602083013561098481610b3c565b5f60208284031215610b85575f80fd5b815161025181610b3c565b828152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b5f60208284031215610bdc575f80fd5b81516102518161094456fea2646970667358221220c370a6c9398b82bdee5c1487b08a61e11feefc977b7701fd97121b9b92b9c81164736f6c634300081a0033";
+
+ private static String librariesLinkedBinary;
+
+ public static final String FUNC_CLAIM = "claim";
+
+ public static final String FUNC_CLAIMFORADDR = "claimForAddr";
+
+ public static final String FUNC_CLAIMWITHRESOLVER = "claimWithResolver";
+
+ public static final String FUNC_CONTROLLERS = "controllers";
+
+ public static final String FUNC_DEFAULTRESOLVER = "defaultResolver";
+
+ public static final String FUNC_ENS = "ens";
+
+ public static final String FUNC_NODE = "node";
+
+ public static final String FUNC_OWNER = "owner";
+
+ public static final String FUNC_RENOUNCEOWNERSHIP = "renounceOwnership";
+
+ public static final String FUNC_SETCONTROLLER = "setController";
+
+ public static final String FUNC_SETDEFAULTRESOLVER = "setDefaultResolver";
+
+ public static final String FUNC_SETNAME = "setName";
+
+ public static final String FUNC_SETNAMEFORADDR = "setNameForAddr";
+
+ public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership";
+
+ public static final Event CONTROLLERCHANGED_EVENT = new Event("ControllerChanged",
+ Arrays.>asList(new TypeReference(true) {}, new TypeReference() {}));
+ ;
+
+ public static final Event DEFAULTRESOLVERCHANGED_EVENT = new Event("DefaultResolverChanged",
+ Arrays.>asList(new TypeReference(true) {}));
+ ;
+
+ public static final Event OWNERSHIPTRANSFERRED_EVENT = new Event("OwnershipTransferred",
+ Arrays.>asList(new TypeReference(true) {}, new TypeReference(true) {}));
+ ;
+
+ public static final Event REVERSECLAIMED_EVENT = new Event("ReverseClaimed",
+ Arrays.>asList(new TypeReference(true) {}, new TypeReference(true) {}));
+ ;
+
+ @Deprecated
+ protected ReverseRegistrar(String contractAddress, Web3j web3j, Credentials credentials,
+ BigInteger gasPrice, BigInteger gasLimit) {
+ super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
+ }
+
+ protected ReverseRegistrar(String contractAddress, Web3j web3j, Credentials credentials,
+ ContractGasProvider contractGasProvider) {
+ super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
+ }
+
+ @Deprecated
+ protected ReverseRegistrar(String contractAddress, Web3j web3j,
+ TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+ super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+ }
+
+ protected ReverseRegistrar(String contractAddress, Web3j web3j,
+ TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+ super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
+ }
+
+ public static List getControllerChangedEvents(
+ TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(CONTROLLERCHANGED_EVENT, transactionReceipt);
+ ArrayList responses = new ArrayList(valueList.size());
+ for (Contract.EventValuesWithLog eventValues : valueList) {
+ ControllerChangedEventResponse typedResponse = new ControllerChangedEventResponse();
+ typedResponse.log = eventValues.getLog();
+ typedResponse.controller = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.enabled = (Boolean) eventValues.getNonIndexedValues().get(0).getValue();
+ responses.add(typedResponse);
+ }
+ return responses;
+ }
+
+ public static ControllerChangedEventResponse getControllerChangedEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(CONTROLLERCHANGED_EVENT, log);
+ ControllerChangedEventResponse typedResponse = new ControllerChangedEventResponse();
+ typedResponse.log = log;
+ typedResponse.controller = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.enabled = (Boolean) eventValues.getNonIndexedValues().get(0).getValue();
+ return typedResponse;
+ }
+
+ public Flowable controllerChangedEventFlowable(
+ EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getControllerChangedEventFromLog(log));
+ }
+
+ public Flowable controllerChangedEventFlowable(
+ DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
+ EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
+ filter.addSingleTopic(EventEncoder.encode(CONTROLLERCHANGED_EVENT));
+ return controllerChangedEventFlowable(filter);
+ }
+
+ public static List getDefaultResolverChangedEvents(
+ TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(DEFAULTRESOLVERCHANGED_EVENT, transactionReceipt);
+ ArrayList responses = new ArrayList(valueList.size());
+ for (Contract.EventValuesWithLog eventValues : valueList) {
+ DefaultResolverChangedEventResponse typedResponse = new DefaultResolverChangedEventResponse();
+ typedResponse.log = eventValues.getLog();
+ typedResponse.resolver = (String) eventValues.getIndexedValues().get(0).getValue();
+ responses.add(typedResponse);
+ }
+ return responses;
+ }
+
+ public static DefaultResolverChangedEventResponse getDefaultResolverChangedEventFromLog(
+ Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(DEFAULTRESOLVERCHANGED_EVENT, log);
+ DefaultResolverChangedEventResponse typedResponse = new DefaultResolverChangedEventResponse();
+ typedResponse.log = log;
+ typedResponse.resolver = (String) eventValues.getIndexedValues().get(0).getValue();
+ return typedResponse;
+ }
+
+ public Flowable defaultResolverChangedEventFlowable(
+ EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getDefaultResolverChangedEventFromLog(log));
+ }
+
+ public Flowable defaultResolverChangedEventFlowable(
+ DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
+ EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
+ filter.addSingleTopic(EventEncoder.encode(DEFAULTRESOLVERCHANGED_EVENT));
+ return defaultResolverChangedEventFlowable(filter);
+ }
+
+ public static List getOwnershipTransferredEvents(
+ TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt);
+ ArrayList responses = new ArrayList(valueList.size());
+ for (Contract.EventValuesWithLog eventValues : valueList) {
+ OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse();
+ typedResponse.log = eventValues.getLog();
+ typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.newOwner = (String) eventValues.getIndexedValues().get(1).getValue();
+ responses.add(typedResponse);
+ }
+ return responses;
+ }
+
+ public static OwnershipTransferredEventResponse getOwnershipTransferredEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, log);
+ OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse();
+ typedResponse.log = log;
+ typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.newOwner = (String) eventValues.getIndexedValues().get(1).getValue();
+ return typedResponse;
+ }
+
+ public Flowable ownershipTransferredEventFlowable(
+ EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getOwnershipTransferredEventFromLog(log));
+ }
+
+ public Flowable ownershipTransferredEventFlowable(
+ DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
+ EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
+ filter.addSingleTopic(EventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT));
+ return ownershipTransferredEventFlowable(filter);
+ }
+
+ public static List getReverseClaimedEvents(
+ TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(REVERSECLAIMED_EVENT, transactionReceipt);
+ ArrayList responses = new ArrayList(valueList.size());
+ for (Contract.EventValuesWithLog eventValues : valueList) {
+ ReverseClaimedEventResponse typedResponse = new ReverseClaimedEventResponse();
+ typedResponse.log = eventValues.getLog();
+ typedResponse.addr = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.node = (byte[]) eventValues.getIndexedValues().get(1).getValue();
+ responses.add(typedResponse);
+ }
+ return responses;
+ }
+
+ public static ReverseClaimedEventResponse getReverseClaimedEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(REVERSECLAIMED_EVENT, log);
+ ReverseClaimedEventResponse typedResponse = new ReverseClaimedEventResponse();
+ typedResponse.log = log;
+ typedResponse.addr = (String) eventValues.getIndexedValues().get(0).getValue();
+ typedResponse.node = (byte[]) eventValues.getIndexedValues().get(1).getValue();
+ return typedResponse;
+ }
+
+ public Flowable reverseClaimedEventFlowable(EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getReverseClaimedEventFromLog(log));
+ }
+
+ public Flowable reverseClaimedEventFlowable(
+ DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
+ EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
+ filter.addSingleTopic(EventEncoder.encode(REVERSECLAIMED_EVENT));
+ return reverseClaimedEventFlowable(filter);
+ }
+
+ public RemoteFunctionCall claim(String owner) {
+ final Function function = new Function(
+ FUNC_CLAIM,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall claimForAddr(String addr, String owner,
+ String resolver) {
+ final Function function = new Function(
+ FUNC_CLAIMFORADDR,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, addr),
+ new org.web3j.abi.datatypes.Address(160, owner),
+ new org.web3j.abi.datatypes.Address(160, resolver)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall claimWithResolver(String owner, String resolver) {
+ final Function function = new Function(
+ FUNC_CLAIMWITHRESOLVER,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, owner),
+ new org.web3j.abi.datatypes.Address(160, resolver)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall controllers(String param0) {
+ final Function function = new Function(FUNC_CONTROLLERS,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, param0)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, Boolean.class);
+ }
+
+ public RemoteFunctionCall defaultResolver() {
+ final Function function = new Function(FUNC_DEFAULTRESOLVER,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall ens() {
+ final Function function = new Function(FUNC_ENS,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall node(String addr) {
+ final Function function = new Function(FUNC_NODE,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, addr)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, byte[].class);
+ }
+
+ public RemoteFunctionCall owner() {
+ final Function function = new Function(FUNC_OWNER,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall renounceOwnership() {
+ final Function function = new Function(
+ FUNC_RENOUNCEOWNERSHIP,
+ Arrays.asList(),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall setController(String controller,
+ Boolean enabled) {
+ final Function function = new Function(
+ FUNC_SETCONTROLLER,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, controller),
+ new org.web3j.abi.datatypes.Bool(enabled)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall setDefaultResolver(String resolver) {
+ final Function function = new Function(
+ FUNC_SETDEFAULTRESOLVER,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, resolver)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall setName(String name) {
+ final Function function = new Function(
+ FUNC_SETNAME,
+ Arrays.asList(new org.web3j.abi.datatypes.Utf8String(name)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall setNameForAddr(String addr, String owner,
+ String resolver, String name) {
+ final Function function = new Function(
+ FUNC_SETNAMEFORADDR,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, addr),
+ new org.web3j.abi.datatypes.Address(160, owner),
+ new org.web3j.abi.datatypes.Address(160, resolver),
+ new org.web3j.abi.datatypes.Utf8String(name)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall transferOwnership(String newOwner) {
+ final Function function = new Function(
+ FUNC_TRANSFEROWNERSHIP,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, newOwner)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ @Deprecated
+ public static ReverseRegistrar load(String contractAddress, Web3j web3j,
+ Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+ return new ReverseRegistrar(contractAddress, web3j, credentials, gasPrice, gasLimit);
+ }
+
+ @Deprecated
+ public static ReverseRegistrar load(String contractAddress, Web3j web3j,
+ TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+ return new ReverseRegistrar(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+ }
+
+ public static ReverseRegistrar load(String contractAddress, Web3j web3j,
+ Credentials credentials, ContractGasProvider contractGasProvider) {
+ return new ReverseRegistrar(contractAddress, web3j, credentials, contractGasProvider);
+ }
+
+ public static ReverseRegistrar load(String contractAddress, Web3j web3j,
+ TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
+ return new ReverseRegistrar(contractAddress, web3j, transactionManager, contractGasProvider);
+ }
+
+ public static RemoteCall deploy(Web3j web3j, Credentials credentials,
+ ContractGasProvider contractGasProvider, String ensAddr) {
+ String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, ensAddr)));
+ return deployRemoteCall(ReverseRegistrar.class, web3j, credentials, contractGasProvider, getDeploymentBinary(), encodedConstructor);
+ }
+
+ public static RemoteCall deploy(Web3j web3j,
+ TransactionManager transactionManager, ContractGasProvider contractGasProvider,
+ String ensAddr) {
+ String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, ensAddr)));
+ return deployRemoteCall(ReverseRegistrar.class, web3j, transactionManager, contractGasProvider, getDeploymentBinary(), encodedConstructor);
+ }
+
+ @Deprecated
+ public static RemoteCall deploy(Web3j web3j, Credentials credentials,
+ BigInteger gasPrice, BigInteger gasLimit, String ensAddr) {
+ String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, ensAddr)));
+ return deployRemoteCall(ReverseRegistrar.class, web3j, credentials, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor);
+ }
+
+ @Deprecated
+ public static RemoteCall deploy(Web3j web3j,
+ TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit,
+ String ensAddr) {
+ String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(160, ensAddr)));
+ return deployRemoteCall(ReverseRegistrar.class, web3j, transactionManager, gasPrice, gasLimit, getDeploymentBinary(), encodedConstructor);
+ }
+
+ public static void linkLibraries(List references) {
+ librariesLinkedBinary = linkBinaryWithReferences(BINARY, references);
+ }
+
+ private static String getDeploymentBinary() {
+ if (librariesLinkedBinary != null) {
+ return librariesLinkedBinary;
+ } else {
+ return BINARY;
+ }
+ }
+
+ public static class ControllerChangedEventResponse extends BaseEventResponse {
+ public String controller;
+
+ public Boolean enabled;
+ }
+
+ public static class DefaultResolverChangedEventResponse extends BaseEventResponse {
+ public String resolver;
+ }
+
+ public static class OwnershipTransferredEventResponse extends BaseEventResponse {
+ public String previousOwner;
+
+ public String newOwner;
+ }
+
+ public static class ReverseClaimedEventResponse extends BaseEventResponse {
+ public String addr;
+
+ public byte[] node;
+ }
+}
diff --git a/core/src/main/resources/solidity/ens/abi/reverseRegistrar/ReverseRegistrar.abi b/core/src/main/resources/solidity/ens/abi/reverseRegistrar/ReverseRegistrar.abi
new file mode 100644
index 0000000000..1e0c33c3f1
--- /dev/null
+++ b/core/src/main/resources/solidity/ens/abi/reverseRegistrar/ReverseRegistrar.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"contract ENS","name":"ensAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"ControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract NameResolver","name":"resolver","type":"address"}],"name":"DefaultResolverChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ReverseClaimed","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"claim","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"}],"name":"claimForAddr","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"}],"name":"claimWithResolver","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"controllers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultResolver","outputs":[{"internalType":"contract NameResolver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ens","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"node","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"resolver","type":"address"}],"name":"setDefaultResolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"string","name":"name","type":"string"}],"name":"setNameForAddr","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
diff --git a/core/src/test/java/org/web3j/ens/ContractsTest.java b/core/src/test/java/org/web3j/ens/ContractsTest.java
index ef1c40cae6..265ab8c66e 100644
--- a/core/src/test/java/org/web3j/ens/ContractsTest.java
+++ b/core/src/test/java/org/web3j/ens/ContractsTest.java
@@ -26,6 +26,8 @@
import static org.web3j.ens.Contracts.ROPSTEN;
import static org.web3j.ens.Contracts.SEPOLIA;
import static org.web3j.ens.Contracts.resolveRegistryContract;
+import static org.web3j.ens.NameWrapperUrl.getEnsMetadataApi;
+import static org.web3j.ens.ReverseRegistrarContracts.resolveReverseRegistrarContract;
@SuppressWarnings("deprecation")
class ContractsTest {
@@ -41,9 +43,42 @@ void testResolveRegistryContract() {
assertEquals(resolveRegistryContract(ChainIdLong.LINEA_SEPOLIA + ""), (LINEA_SEPOLIA));
}
+ @Test
+ void testReverseRegistrarContract() {
+ assertEquals(
+ resolveReverseRegistrarContract(ChainIdLong.MAINNET + ""),
+ (ReverseRegistrarContracts.MAINNET));
+ assertEquals(
+ resolveReverseRegistrarContract(ChainIdLong.SEPOLIA + ""),
+ (ReverseRegistrarContracts.SEPOLIA));
+ assertEquals(
+ resolveReverseRegistrarContract(ChainIdLong.HOLESKY + ""),
+ (ReverseRegistrarContracts.HOLESKY));
+ assertEquals(
+ resolveReverseRegistrarContract(ChainIdLong.LINEA + ""),
+ (ReverseRegistrarContracts.LINEA));
+ assertEquals(
+ resolveReverseRegistrarContract(ChainIdLong.LINEA_SEPOLIA + ""),
+ (ReverseRegistrarContracts.LINEA_SEPOLIA));
+ }
+
+ @Test
+ void testNameWrapperApiLinks() {
+ assertEquals(getEnsMetadataApi(ChainIdLong.MAINNET + ""), (NameWrapperUrl.MAINNET_URL));
+ assertEquals(getEnsMetadataApi(ChainIdLong.SEPOLIA + ""), (NameWrapperUrl.SEPOLIA_URL));
+ assertEquals(getEnsMetadataApi(ChainIdLong.HOLESKY + ""), (NameWrapperUrl.HOLESKY_URL));
+ }
+
@Test
void testResolveRegistryContractInvalid() {
assertThrows(
EnsResolutionException.class, () -> resolveRegistryContract(ChainIdLong.NONE + ""));
}
+
+ @Test
+ void testReverseRegistrarContractInvalid() {
+ assertThrows(
+ EnsResolutionException.class,
+ () -> resolveReverseRegistrarContract(ChainIdLong.NONE + ""));
+ }
}
diff --git a/core/src/test/java/org/web3j/ens/EnsResolverTest.java b/core/src/test/java/org/web3j/ens/EnsResolverTest.java
index 8fbe4aed13..92a5214351 100644
--- a/core/src/test/java/org/web3j/ens/EnsResolverTest.java
+++ b/core/src/test/java/org/web3j/ens/EnsResolverTest.java
@@ -20,8 +20,10 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.Call;
+import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
+import okhttp3.Response;
import okhttp3.ResponseBody;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -29,8 +31,10 @@
import org.web3j.abi.TypeEncoder;
import org.web3j.abi.datatypes.Utf8String;
+import org.web3j.crypto.Credentials;
import org.web3j.dto.EnsGatewayResponseDTO;
import org.web3j.ens.contracts.generated.OffchainResolverContract;
+import org.web3j.ens.contracts.generated.ReverseRegistrar;
import org.web3j.protocol.ObjectMapperFactory;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.Web3jService;
@@ -40,6 +44,7 @@
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthSyncing;
import org.web3j.protocol.core.methods.response.NetVersion;
+import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.ChainIdLong;
import org.web3j.utils.EnsUtils;
import org.web3j.utils.Numeric;
@@ -456,6 +461,8 @@ void resolveOffchainWhenLookUpCallsOutOfLimit() throws Exception {
class EnsResolverForTest extends EnsResolver {
private OffchainResolverContract resolverMock;
+ private ReverseRegistrar reverseRegistrarMock;
+
public EnsResolverForTest(Web3j web3j) {
super(web3j);
}
@@ -465,6 +472,17 @@ protected OffchainResolverContract obtainOffchainResolver(String ensName) {
return resolverMock;
}
+ @Override
+ protected OffchainResolverContract obtainOffchainResolver(
+ String ensName, Credentials credentials) {
+ return resolverMock;
+ }
+
+ @Override
+ protected ReverseRegistrar getReverseRegistrarContract(Credentials credentials) {
+ return reverseRegistrarMock;
+ }
+
public OffchainResolverContract getResolverMock() {
return resolverMock;
}
@@ -472,6 +490,10 @@ public OffchainResolverContract getResolverMock() {
public void setResolverMock(OffchainResolverContract resolverMock) {
this.resolverMock = resolverMock;
}
+
+ public void setReverseRegistrarMock(ReverseRegistrar reverseRegistrarMock) {
+ this.reverseRegistrarMock = reverseRegistrarMock;
+ }
}
@Test
@@ -525,6 +547,134 @@ public void testResolveWildCardWhenResolvedAddressNotValid() throws Exception {
() -> ensResolverForTest.resolve("1.offchainexample.eth"));
}
+ @Test
+ void testGetEnsTextSuccess() throws Exception {
+ String expectedText = "value";
+ String name = "example.eth";
+ String key = "key";
+
+ OffchainResolverContract resolverMock = mock(OffchainResolverContract.class);
+
+ RemoteFunctionCall remoteFunctionCallMock = mock(RemoteFunctionCall.class);
+ when(resolverMock.text(any(), eq(key))).thenReturn(remoteFunctionCallMock);
+ when(remoteFunctionCallMock.send()).thenReturn(expectedText);
+
+ EnsResolverForTest ensResolverForTest = new EnsResolverForTest(web3j);
+ ensResolverForTest.setResolverMock(resolverMock);
+
+ String result = ensResolverForTest.getEnsText(name, key);
+
+ assertNotNull(result);
+ assertEquals(expectedText, result);
+ }
+
+ @Test
+ void testSetEnsTextSuccess() throws Exception {
+ String name = "example.eth";
+ String key = "key";
+ String value = "value";
+
+ TransactionReceipt receipt = new TransactionReceipt();
+ receipt.setTransactionHash("0x123");
+
+ Credentials credentials = mock(Credentials.class);
+
+ OffchainResolverContract resolverMock = mock(OffchainResolverContract.class);
+ RemoteFunctionCall remoteFunctionCallMock =
+ mock(RemoteFunctionCall.class);
+
+ when(resolverMock.setText(any(), eq(key), eq(value))).thenReturn(remoteFunctionCallMock);
+ when(remoteFunctionCallMock.send()).thenReturn(receipt);
+
+ EnsResolverForTest ensResolverForTest = new EnsResolverForTest(web3j);
+ ensResolverForTest.setResolverMock(resolverMock);
+
+ TransactionReceipt receiptResult =
+ ensResolverForTest.setEnsText(name, key, value, credentials);
+
+ assertNotNull(receiptResult);
+ assertEquals(receipt.getTransactionHash(), receiptResult.getTransactionHash());
+ }
+
+ @Test
+ void testSetReverseName() throws Exception {
+ String name = "example.eth";
+ Credentials credentials = mock(Credentials.class);
+
+ TransactionReceipt receipt = new TransactionReceipt();
+ receipt.setTransactionHash("0x123");
+ ReverseRegistrar reverseRegistrarMock = mock(ReverseRegistrar.class);
+ RemoteFunctionCall remoteFunctionCallMock =
+ mock(RemoteFunctionCall.class);
+
+ when(remoteFunctionCallMock.send()).thenReturn(receipt);
+ when(reverseRegistrarMock.setName(name)).thenReturn(remoteFunctionCallMock);
+
+ EnsResolverForTest resolver = new EnsResolverForTest(web3j);
+ resolver.setReverseRegistrarMock(reverseRegistrarMock);
+
+ TransactionReceipt receiptResult = resolver.setReverseName(name, credentials);
+
+ assertNotNull(receiptResult);
+ assertEquals(receipt.getTransactionHash(), receiptResult.getTransactionHash());
+ }
+
+ @Test
+ void testSetNameForAddr() throws Exception {
+ String addr = "0x41563129cdbbd0c5d3e1c86cf9563926b243834d";
+ String owner = "0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8";
+ String resolver = "0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8";
+ String name = "example.eth";
+ Credentials credentials = mock(Credentials.class);
+
+ TransactionReceipt receipt = new TransactionReceipt();
+ receipt.setTransactionHash("0xabc123");
+
+ ReverseRegistrar reverseRegistrarMock = mock(ReverseRegistrar.class);
+ RemoteFunctionCall remoteFunctionCallMock =
+ mock(RemoteFunctionCall.class);
+
+ when(remoteFunctionCallMock.send()).thenReturn(receipt);
+ when(reverseRegistrarMock.setNameForAddr(addr, owner, resolver, name))
+ .thenReturn(remoteFunctionCallMock);
+
+ EnsResolverForTest resolverObj = new EnsResolverForTest(web3j);
+ resolverObj.setReverseRegistrarMock(reverseRegistrarMock);
+
+ TransactionReceipt receiptResult =
+ resolverObj.setReverseName(addr, owner, resolver, name, credentials);
+
+ assertNotNull(receiptResult);
+ assertEquals(receipt.getTransactionHash(), receiptResult.getTransactionHash());
+ }
+
+ @Test
+ void testGetEnsMetadataSuccess() throws Exception {
+ OkHttpClient httpClientMock = mock(OkHttpClient.class);
+ String name = "example.eth";
+ String apiUrl = "https://ens-api.example.com/";
+
+ NetVersion netVersion = new NetVersion();
+ netVersion.setResult(Long.toString(ChainIdLong.MAINNET));
+ when(web3jService.send(any(Request.class), eq(NetVersion.class))).thenReturn(netVersion);
+
+ EnsMetadataResponse expectedResponse = new EnsMetadataResponse();
+ expectedResponse.setName("example.eth");
+ expectedResponse.setDescription("example.eth, an ENS name.");
+ String jsonResponse = new ObjectMapper().writeValueAsString(expectedResponse);
+
+ okhttp3.Response mockResponse = buildResponse(200, apiUrl, jsonResponse);
+ Call mockCall = mock(Call.class);
+ when(mockCall.execute()).thenReturn(mockResponse);
+ when(httpClientMock.newCall(any())).thenReturn(mockCall);
+
+ EnsMetadataResponse actualResponse = ensResolver.getEnsMetadata(name);
+
+ assertNotNull(actualResponse);
+ assertEquals(expectedResponse.getName(), actualResponse.getName());
+ assertEquals(expectedResponse.getDescription(), actualResponse.getDescription());
+ }
+
private okhttp3.Response buildResponse(int code, String url, String sender, String data)
throws JsonProcessingException {
EnsGatewayResponseDTO responseDTO = new EnsGatewayResponseDTO(data);
@@ -537,4 +687,16 @@ private okhttp3.Response buildResponse(int code, String url, String sender, Stri
.message("Some error message Code: " + code)
.build();
}
+
+ private okhttp3.Response buildResponse(int code, String url, String jsonBody) {
+ okhttp3.Request request = new okhttp3.Request.Builder().url(url).build();
+
+ return new Response.Builder()
+ .request(request)
+ .protocol(Protocol.HTTP_2)
+ .code(code)
+ .message("Response Message")
+ .body(ResponseBody.create(jsonBody, MediaType.parse("application/json")))
+ .build();
+ }
}