diff --git a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java index d3c8c87..fd7d338 100644 --- a/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java +++ b/src/main/java/org/arkecosystem/crypto/transactions/Deserializer.java @@ -108,6 +108,8 @@ private AbstractTransaction guessTransactionFromTransactionData( return new ValidatorResignation(transactionData.toHashMap()); } else if (TransactionTypeIdentifier.isUsernameRegistration(payload)) { return new UsernameRegistration(transactionData.toHashMap()); + } else if (TransactionTypeIdentifier.isUsernameResignation(payload)) { + return new UsernameResignation(transactionData.toHashMap()); } return new EvmCall(); diff --git a/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java new file mode 100644 index 0000000..f99f453 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilder.java @@ -0,0 +1,24 @@ +package org.arkecosystem.crypto.transactions.builder; + +import org.arkecosystem.crypto.enums.ContractAddresses; +import org.arkecosystem.crypto.transactions.types.AbstractTransaction; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; + +public class UsernameResignationBuilder + extends AbstractTransactionBuilder { + + public UsernameResignationBuilder() { + super(); + this.transaction.recipientAddress = ContractAddresses.USERNAMES.address(); + } + + @Override + protected AbstractTransaction getTransactionInstance() { + return new UsernameResignation(); + } + + @Override + protected UsernameResignationBuilder instance() { + return this; + } +} diff --git a/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java new file mode 100644 index 0000000..7b41c64 --- /dev/null +++ b/src/main/java/org/arkecosystem/crypto/transactions/types/UsernameResignation.java @@ -0,0 +1,27 @@ +package org.arkecosystem.crypto.transactions.types; + +import java.util.Map; +import org.arkecosystem.crypto.enums.AbiFunction; +import org.arkecosystem.crypto.enums.ContractAbiType; +import org.arkecosystem.crypto.utils.AbiEncoder; + +public class UsernameResignation extends AbstractTransaction { + + public UsernameResignation() { + super(); + } + + public UsernameResignation(Map data) { + super(data); + } + + @Override + public String getPayload() { + try { + return new AbiEncoder(ContractAbiType.USERNAMES) + .encodeFunctionCall(AbiFunction.USERNAME_RESIGNATION.toString()); + } catch (Exception e) { + throw new RuntimeException("Error encoding username resignation call", e); + } + } +} diff --git a/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java new file mode 100644 index 0000000..f249f46 --- /dev/null +++ b/src/test/java/org/arkecosystem/crypto/transactions/builder/UsernameResignationBuilderTest.java @@ -0,0 +1,69 @@ +package org.arkecosystem.crypto.transactions.builder; + +import static org.junit.jupiter.api.Assertions.*; + +import org.arkecosystem.crypto.AbstractTest; +import org.arkecosystem.crypto.encoding.Hex; +import org.arkecosystem.crypto.enums.ContractAddresses; +import org.arkecosystem.crypto.transactions.Deserializer; +import org.arkecosystem.crypto.transactions.types.AbstractTransaction; +import org.arkecosystem.crypto.transactions.types.UsernameResignation; +import org.junit.jupiter.api.Test; + +public class UsernameResignationBuilderTest extends AbstractTest { + + private static final String RESIGN_SELECTOR = "0xebed6dab"; + + @Test + public void it_should_default_to_the_usernames_well_known_contract() { + UsernameResignationBuilder builder = new UsernameResignationBuilder(); + + assertEquals(ContractAddresses.USERNAMES.address(), builder.transaction.recipientAddress); + } + + @Test + public void it_should_encode_resign_username_selector() { + UsernameResignationBuilder builder = + new UsernameResignationBuilder() + .gasPrice(5_000_000_000L) + .gasLimit(100_000) + .nonce(1L); + + builder.transaction.refreshPayloadData(); + + assertEquals(RESIGN_SELECTOR, builder.transaction.data); + } + + @Test + public void it_should_sign_and_verify_a_username_resignation_transaction() { + UsernameResignationBuilder builder = + new UsernameResignationBuilder() + .gasPrice(5_000_000_000L) + .gasLimit(100_000) + .nonce(1L) + .sign(this.passphrase); + + assertNotNull(builder.transaction.signature); + assertNotNull(builder.transaction.id); + assertTrue(builder.verify()); + } + + @Test + public void it_should_round_trip_through_serialization() { + UsernameResignationBuilder builder = + new UsernameResignationBuilder() + .gasPrice(5_000_000_000L) + .gasLimit(100_000) + .nonce(7L) + .sign(this.passphrase); + + String serialized = Hex.encode(builder.transaction.serialize()); + AbstractTransaction restored = Deserializer.newDeserializer(serialized).deserialize(); + + assertInstanceOf(UsernameResignation.class, restored); + assertEquals(builder.transaction.id, restored.id); + assertEquals( + builder.transaction.recipientAddress.toLowerCase(), + restored.recipientAddress.toLowerCase()); + } +}