From 0fc17d76aea4114a5cb77052bcc55bb23a6ec549 Mon Sep 17 00:00:00 2001 From: catbref Date: Mon, 2 Jul 2018 18:09:36 +0100 Subject: [PATCH] Added SellNameTransactions + tests --- .../transaction/SellNameTransactionData.java | 42 +++++ src/qora/naming/Name.java | 19 +++ src/qora/transaction/SellNameTransaction.java | 151 ++++++++++++++++++ src/qora/transaction/Transaction.java | 5 +- .../HSQLDBSellNameTransactionRepository.java | 50 ++++++ .../HSQLDBTransactionRepository.java | 13 +- src/test/LoadTests.java | 5 +- src/test/SerializationTests.java | 5 + src/test/TransactionTests.java | 49 +++++- .../SellNameTransactionTransformer.java | 111 +++++++++++++ .../transaction/TransactionTransformer.java | 20 ++- 11 files changed, 461 insertions(+), 9 deletions(-) create mode 100644 src/data/transaction/SellNameTransactionData.java create mode 100644 src/qora/transaction/SellNameTransaction.java create mode 100644 src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java create mode 100644 src/transform/transaction/SellNameTransactionTransformer.java diff --git a/src/data/transaction/SellNameTransactionData.java b/src/data/transaction/SellNameTransactionData.java new file mode 100644 index 00000000..f934def9 --- /dev/null +++ b/src/data/transaction/SellNameTransactionData.java @@ -0,0 +1,42 @@ +package data.transaction; + +import java.math.BigDecimal; + +import qora.transaction.Transaction.TransactionType; + +public class SellNameTransactionData extends TransactionData { + + // Properties + private byte[] ownerPublicKey; + private String name; + private BigDecimal amount; + + // Constructors + + public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { + super(TransactionType.SELL_NAME, fee, ownerPublicKey, timestamp, reference, signature); + + this.ownerPublicKey = ownerPublicKey; + this.name = name; + this.amount = amount; + } + + public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference) { + this(ownerPublicKey, name, amount, fee, timestamp, reference, null); + } + + // Getters / setters + + public byte[] getOwnerPublicKey() { + return this.ownerPublicKey; + } + + public String getName() { + return this.name; + } + + public BigDecimal getAmount() { + return this.amount; + } + +} diff --git a/src/qora/naming/Name.java b/src/qora/naming/Name.java index 7cc837fe..45ee75ec 100644 --- a/src/qora/naming/Name.java +++ b/src/qora/naming/Name.java @@ -2,6 +2,7 @@ package qora.naming; import data.naming.NameData; import data.transaction.RegisterNameTransactionData; +import data.transaction.SellNameTransactionData; import data.transaction.TransactionData; import data.transaction.UpdateNameTransactionData; import repository.DataException; @@ -99,4 +100,22 @@ public class Name { this.repository.getNameRepository().save(this.nameData); } + public void sell(SellNameTransactionData sellNameTransactionData) throws DataException { + // Mark as for-sale and set price + this.nameData.setIsForSale(true); + this.nameData.setSalePrice(sellNameTransactionData.getAmount()); + + // Save sale info into repository + this.repository.getNameRepository().save(this.nameData); + } + + public void unsell(SellNameTransactionData sellNameTransactionData) throws DataException { + // Mark not for-sale and unset price + this.nameData.setIsForSale(false); + this.nameData.setSalePrice(null); + + // Save no-sale info into repository + this.repository.getNameRepository().save(this.nameData); + } + } diff --git a/src/qora/transaction/SellNameTransaction.java b/src/qora/transaction/SellNameTransaction.java new file mode 100644 index 00000000..2498f9bd --- /dev/null +++ b/src/qora/transaction/SellNameTransaction.java @@ -0,0 +1,151 @@ +package qora.transaction; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import data.naming.NameData; +import data.transaction.SellNameTransactionData; +import data.transaction.TransactionData; +import qora.account.Account; +import qora.account.PublicKeyAccount; +import qora.assets.Asset; +import qora.block.BlockChain; +import qora.naming.Name; +import repository.DataException; +import repository.Repository; + +public class SellNameTransaction extends Transaction { + + // Properties + private SellNameTransactionData sellNameTransactionData; + + // Constructors + + public SellNameTransaction(Repository repository, TransactionData transactionData) { + super(repository, transactionData); + + this.sellNameTransactionData = (SellNameTransactionData) this.transactionData; + } + + // More information + + @Override + public List getRecipientAccounts() { + return new ArrayList(); + } + + @Override + public boolean isInvolved(Account account) throws DataException { + String address = account.getAddress(); + + if (address.equals(this.getOwner().getAddress())) + return true; + + return false; + } + + @Override + public BigDecimal getAmount(Account account) throws DataException { + String address = account.getAddress(); + BigDecimal amount = BigDecimal.ZERO.setScale(8); + + if (address.equals(this.getOwner().getAddress())) + amount = amount.subtract(this.transactionData.getFee()); + + return amount; + } + + // Navigation + + public Account getOwner() throws DataException { + return new PublicKeyAccount(this.repository, this.sellNameTransactionData.getOwnerPublicKey()); + } + + // Processing + + @Override + public ValidationResult isValid() throws DataException { + // Check name size bounds + if (sellNameTransactionData.getName().length() < 1 || sellNameTransactionData.getName().length() > Name.MAX_NAME_SIZE) + return ValidationResult.INVALID_NAME_LENGTH; + + // Check name is lowercase + if (!sellNameTransactionData.getName().equals(sellNameTransactionData.getName().toLowerCase())) + return ValidationResult.NAME_NOT_LOWER_CASE; + + NameData nameData = this.repository.getNameRepository().fromName(sellNameTransactionData.getName()); + + // Check name exists + if (nameData == null) + return ValidationResult.NAME_DOES_NOT_EXIST; + + // Check name isn't currently for sale + if (nameData.getIsForSale()) + return ValidationResult.NAME_ALREADY_FOR_SALE; + + // Check transaction's public key matches name's current owner + Account owner = new PublicKeyAccount(this.repository, sellNameTransactionData.getOwnerPublicKey()); + if (!owner.getAddress().equals(nameData.getOwner())) + return ValidationResult.INVALID_NAME_OWNER; + + // Check amount is positive + if (sellNameTransactionData.getAmount().compareTo(BigDecimal.ZERO) <= 0) + return ValidationResult.NEGATIVE_AMOUNT; + + // Check amount within bounds + if (sellNameTransactionData.getAmount().compareTo(BlockChain.MAX_BALANCE) > 0) + return ValidationResult.INVALID_AMOUNT; + + // Check fee is positive + if (sellNameTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) + return ValidationResult.NEGATIVE_FEE; + + // Check reference is correct + if (!Arrays.equals(owner.getLastReference(), sellNameTransactionData.getReference())) + return ValidationResult.INVALID_REFERENCE; + + // Check issuer has enough funds + if (owner.getConfirmedBalance(Asset.QORA).compareTo(sellNameTransactionData.getFee()) == -1) + return ValidationResult.NO_BALANCE; + + return ValidationResult.OK; + + } + + @Override + public void process() throws DataException { + // Update Name + Name name = new Name(this.repository, sellNameTransactionData.getName()); + name.sell(sellNameTransactionData); + + // Save this transaction, now with updated "name reference" to previous transaction that updated name + this.repository.getTransactionRepository().save(sellNameTransactionData); + + // Update owner's balance + Account owner = new PublicKeyAccount(this.repository, sellNameTransactionData.getOwnerPublicKey()); + owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).subtract(sellNameTransactionData.getFee())); + + // Update owner's reference + owner.setLastReference(sellNameTransactionData.getSignature()); + } + + @Override + public void orphan() throws DataException { + // Revert name + Name name = new Name(this.repository, sellNameTransactionData.getName()); + name.unsell(sellNameTransactionData); + + // Delete this transaction itself + this.repository.getTransactionRepository().delete(sellNameTransactionData); + + // Update owner's balance + Account owner = new PublicKeyAccount(this.repository, sellNameTransactionData.getOwnerPublicKey()); + owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(sellNameTransactionData.getFee())); + + // Update owner's reference + owner.setLastReference(sellNameTransactionData.getReference()); + } + +} diff --git a/src/qora/transaction/Transaction.java b/src/qora/transaction/Transaction.java index daedae62..9fe0b541 100644 --- a/src/qora/transaction/Transaction.java +++ b/src/qora/transaction/Transaction.java @@ -111,6 +111,9 @@ public abstract class Transaction { case UPDATE_NAME: return new UpdateNameTransaction(repository, transactionData); + case SELL_NAME: + return new SellNameTransaction(repository, transactionData); + case CREATE_POLL: return new CreatePollTransaction(repository, transactionData); @@ -136,7 +139,7 @@ public abstract class Transaction { return new MessageTransaction(repository, transactionData); default: - return null; + throw new IllegalStateException("Unsupported transaction type [" + transactionData.getType().value + "] during fetch from repository"); } } diff --git a/src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java new file mode 100644 index 00000000..7669f0da --- /dev/null +++ b/src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java @@ -0,0 +1,50 @@ +package repository.hsqldb.transaction; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import data.transaction.SellNameTransactionData; +import data.transaction.TransactionData; +import repository.DataException; +import repository.hsqldb.HSQLDBRepository; +import repository.hsqldb.HSQLDBSaver; + +public class HSQLDBSellNameTransactionRepository extends HSQLDBTransactionRepository { + + public HSQLDBSellNameTransactionRepository(HSQLDBRepository repository) { + this.repository = repository; + } + + TransactionData fromBase(byte[] signature, byte[] reference, byte[] ownerPublicKey, long timestamp, BigDecimal fee) throws DataException { + try { + ResultSet rs = this.repository.checkedExecute("SELECT name, amount FROM SellNameTransactions WHERE signature = ?", signature); + if (rs == null) + return null; + + String name = rs.getString(1); + BigDecimal amount = rs.getBigDecimal(2); + + return new SellNameTransactionData(ownerPublicKey, name, amount, fee, timestamp, reference, signature); + } catch (SQLException e) { + throw new DataException("Unable to fetch sell name transaction from repository", e); + } + } + + @Override + public void save(TransactionData transactionData) throws DataException { + SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData; + + HSQLDBSaver saveHelper = new HSQLDBSaver("SellNameTransactions"); + + saveHelper.bind("signature", sellNameTransactionData.getSignature()).bind("owner", sellNameTransactionData.getOwnerPublicKey()) + .bind("name", sellNameTransactionData.getName()).bind("amount", sellNameTransactionData.getAmount()); + + try { + saveHelper.execute(this.repository); + } catch (SQLException e) { + throw new DataException("Unable to save sell name transaction into repository", e); + } + } + +} diff --git a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java index ff1c59d6..92dcca7b 100644 --- a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java +++ b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java @@ -23,6 +23,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { private HSQLDBPaymentTransactionRepository paymentTransactionRepository; private HSQLDBRegisterNameTransactionRepository registerNameTransactionRepository; private HSQLDBUpdateNameTransactionRepository updateNameTransactionRepository; + private HSQLDBSellNameTransactionRepository sellNameTransactionRepository; private HSQLDBCreatePollTransactionRepository createPollTransactionRepository; private HSQLDBVoteOnPollTransactionRepository voteOnPollTransactionRepository; private HSQLDBIssueAssetTransactionRepository issueAssetTransactionRepository; @@ -38,6 +39,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { this.paymentTransactionRepository = new HSQLDBPaymentTransactionRepository(repository); this.registerNameTransactionRepository = new HSQLDBRegisterNameTransactionRepository(repository); this.updateNameTransactionRepository = new HSQLDBUpdateNameTransactionRepository(repository); + this.sellNameTransactionRepository = new HSQLDBSellNameTransactionRepository(repository); this.createPollTransactionRepository = new HSQLDBCreatePollTransactionRepository(repository); this.voteOnPollTransactionRepository = new HSQLDBVoteOnPollTransactionRepository(repository); this.issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository); @@ -102,6 +104,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository { case UPDATE_NAME: return this.updateNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); + case SELL_NAME: + return this.sellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); + case CREATE_POLL: return this.createPollTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); @@ -127,7 +132,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { return this.messageTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); default: - return null; + throw new DataException("Unsupported transaction type [" + type.value + "] during fetch from HSQLDB repository"); } } @@ -238,6 +243,10 @@ public class HSQLDBTransactionRepository implements TransactionRepository { this.updateNameTransactionRepository.save(transactionData); break; + case SELL_NAME: + this.sellNameTransactionRepository.save(transactionData); + break; + case CREATE_POLL: this.createPollTransactionRepository.save(transactionData); break; @@ -271,7 +280,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { break; default: - throw new DataException("Unsupported transaction type during save into repository"); + throw new DataException("Unsupported transaction type [" + transactionData.getType().value + "] during save into HSQLDB repository"); } } diff --git a/src/test/LoadTests.java b/src/test/LoadTests.java index 1b40ac75..aa617985 100644 --- a/src/test/LoadTests.java +++ b/src/test/LoadTests.java @@ -59,11 +59,14 @@ public class LoadTests extends Common { if (transactionData == null) break; + if (transactionData.getType() != TransactionType.PAYMENT) + break; + PaymentTransactionData paymentTransactionData = (PaymentTransactionData) transactionData; System.out.println(PublicKeyAccount.getAddress(paymentTransactionData.getSenderPublicKey()) + " sent " + paymentTransactionData.getAmount() + " QORA to " + paymentTransactionData.getRecipient()); - signature = paymentTransactionData.getReference(); + signature = transactionData.getReference(); } } } diff --git a/src/test/SerializationTests.java b/src/test/SerializationTests.java index d27857ff..0fd4080c 100644 --- a/src/test/SerializationTests.java +++ b/src/test/SerializationTests.java @@ -99,6 +99,11 @@ public class SerializationTests extends Common { testSpecificBlockTransactions(673, TransactionType.UPDATE_NAME); } + @Test + public void testSellNameSerialization() throws TransformationException, DataException { + testSpecificBlockTransactions(673, TransactionType.SELL_NAME); + } + @Test public void testCreatePollSerialization() throws TransformationException, DataException { // Block 10537 has only create poll transactions diff --git a/src/test/TransactionTests.java b/src/test/TransactionTests.java index a20bbb02..b22679ac 100644 --- a/src/test/TransactionTests.java +++ b/src/test/TransactionTests.java @@ -19,6 +19,7 @@ import data.naming.NameData; import data.transaction.CreatePollTransactionData; import data.transaction.PaymentTransactionData; import data.transaction.RegisterNameTransactionData; +import data.transaction.SellNameTransactionData; import data.transaction.UpdateNameTransactionData; import data.transaction.VoteOnPollTransactionData; import data.voting.PollData; @@ -33,6 +34,7 @@ import qora.block.BlockChain; import qora.transaction.CreatePollTransaction; import qora.transaction.PaymentTransaction; import qora.transaction.RegisterNameTransaction; +import qora.transaction.SellNameTransaction; import qora.transaction.Transaction; import qora.transaction.Transaction.ValidationResult; import qora.transaction.UpdateNameTransaction; @@ -208,7 +210,7 @@ public class TransactionTests { } @Test - public void testUpdateNamesTransaction() throws DataException { + public void testUpdateNameTransaction() throws DataException { // Register name using another test testRegisterNameTransaction(); @@ -256,6 +258,51 @@ public class TransactionTests { assertEquals(originalNameData.getData(), actualNameData.getData()); } + @Test + public void testSellNameTransaction() throws DataException { + // Register name using another test + testRegisterNameTransaction(); + + String name = "test name"; + + // Sale price + BigDecimal amount = BigDecimal.valueOf(1234L).setScale(8); + + BigDecimal fee = BigDecimal.ONE; + long timestamp = parentBlockData.getTimestamp() + 2_000; + SellNameTransactionData sellNameTransactionData = new SellNameTransactionData(sender.getPublicKey(), name, amount, fee, timestamp, reference); + + Transaction sellNameTransaction = new SellNameTransaction(repository, sellNameTransactionData); + sellNameTransaction.calcSignature(sender); + assertTrue(sellNameTransaction.isSignatureValid()); + assertEquals(ValidationResult.OK, sellNameTransaction.isValid()); + + // Forge new block with transaction + Block block = new Block(repository, parentBlockData, generator, null, null); + block.addTransaction(sellNameTransactionData); + block.sign(); + + assertTrue("Block signatures invalid", block.isSignatureValid()); + assertEquals("Block is invalid", Block.ValidationResult.OK, block.isValid()); + + block.process(); + repository.saveChanges(); + + // Check name was updated + NameData actualNameData = this.repository.getNameRepository().fromName(name); + assertTrue(actualNameData.getIsForSale()); + assertEquals(amount, actualNameData.getSalePrice()); + + // Now orphan block + block.orphan(); + repository.saveChanges(); + + // Check name has been reverted correctly + actualNameData = this.repository.getNameRepository().fromName(name); + assertFalse(actualNameData.getIsForSale()); + assertNull(actualNameData.getSalePrice()); + } + @Test public void testCreatePollTransaction() throws DataException { // This test requires GenesisBlock's timestamp is set to something after BlockChain.VOTING_RELEASE_TIMESTAMP diff --git a/src/transform/transaction/SellNameTransactionTransformer.java b/src/transform/transaction/SellNameTransactionTransformer.java new file mode 100644 index 00000000..2b070beb --- /dev/null +++ b/src/transform/transaction/SellNameTransactionTransformer.java @@ -0,0 +1,111 @@ +package transform.transaction; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.ByteBuffer; + +import org.json.simple.JSONObject; + +import com.google.common.hash.HashCode; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; + +import data.transaction.SellNameTransactionData; +import data.transaction.TransactionData; +import qora.account.PublicKeyAccount; +import qora.naming.Name; +import transform.TransformationException; +import utils.Serialization; + +public class SellNameTransactionTransformer extends TransactionTransformer { + + // Property lengths + private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH; + private static final int NAME_SIZE_LENGTH = INT_LENGTH; + private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH; + + private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + AMOUNT_LENGTH; + + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { + if (byteBuffer.remaining() < TYPELESS_DATALESS_LENGTH) + throw new TransformationException("Byte data too short for SellNameTransaction"); + + long timestamp = byteBuffer.getLong(); + + byte[] reference = new byte[REFERENCE_LENGTH]; + byteBuffer.get(reference); + + byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer); + + String name = Serialization.deserializeSizedString(byteBuffer, Name.MAX_NAME_SIZE); + + // Still need to make sure there are enough bytes left for remaining fields + if (byteBuffer.remaining() < AMOUNT_LENGTH + FEE_LENGTH + SIGNATURE_LENGTH) + throw new TransformationException("Byte data too short for SellNameTransaction"); + + BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer); + + BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); + + byte[] signature = new byte[SIGNATURE_LENGTH]; + byteBuffer.get(signature); + + return new SellNameTransactionData(ownerPublicKey, name, amount, fee, timestamp, reference, signature); + } + + public static int getDataLength(TransactionData transactionData) throws TransformationException { + SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData; + + int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + sellNameTransactionData.getName().length(); + + return dataLength; + } + + public static byte[] toBytes(TransactionData transactionData) throws TransformationException { + try { + SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + bytes.write(Ints.toByteArray(sellNameTransactionData.getType().value)); + bytes.write(Longs.toByteArray(sellNameTransactionData.getTimestamp())); + bytes.write(sellNameTransactionData.getReference()); + + bytes.write(sellNameTransactionData.getOwnerPublicKey()); + Serialization.serializeSizedString(bytes, sellNameTransactionData.getName()); + Serialization.serializeBigDecimal(bytes, sellNameTransactionData.getAmount()); + + Serialization.serializeBigDecimal(bytes, sellNameTransactionData.getFee()); + + if (sellNameTransactionData.getSignature() != null) + bytes.write(sellNameTransactionData.getSignature()); + + return bytes.toByteArray(); + } catch (IOException | ClassCastException e) { + throw new TransformationException(e); + } + } + + @SuppressWarnings("unchecked") + public static JSONObject toJSON(TransactionData transactionData) throws TransformationException { + JSONObject json = TransactionTransformer.getBaseJSON(transactionData); + + try { + SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData; + + byte[] ownerPublicKey = sellNameTransactionData.getOwnerPublicKey(); + + json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey)); + json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString()); + + json.put("name", sellNameTransactionData.getName()); + json.put("amount", sellNameTransactionData.getAmount().toPlainString()); + } catch (ClassCastException e) { + throw new TransformationException(e); + } + + return json; + } + +} diff --git a/src/transform/transaction/TransactionTransformer.java b/src/transform/transaction/TransactionTransformer.java index d21cbcb1..bcd643a5 100644 --- a/src/transform/transaction/TransactionTransformer.java +++ b/src/transform/transaction/TransactionTransformer.java @@ -43,6 +43,9 @@ public class TransactionTransformer extends Transformer { case UPDATE_NAME: return UpdateNameTransactionTransformer.fromByteBuffer(byteBuffer); + case SELL_NAME: + return SellNameTransactionTransformer.fromByteBuffer(byteBuffer); + case CREATE_POLL: return CreatePollTransactionTransformer.fromByteBuffer(byteBuffer); @@ -68,7 +71,7 @@ public class TransactionTransformer extends Transformer { return MessageTransactionTransformer.fromByteBuffer(byteBuffer); default: - throw new TransformationException("Unsupported transaction type"); + throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion from bytes"); } } @@ -86,6 +89,9 @@ public class TransactionTransformer extends Transformer { case UPDATE_NAME: return UpdateNameTransactionTransformer.getDataLength(transactionData); + case SELL_NAME: + return SellNameTransactionTransformer.getDataLength(transactionData); + case CREATE_POLL: return CreatePollTransactionTransformer.getDataLength(transactionData); @@ -111,7 +117,7 @@ public class TransactionTransformer extends Transformer { return MessageTransactionTransformer.getDataLength(transactionData); default: - throw new TransformationException("Unsupported transaction type"); + throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] when requesting byte length"); } } @@ -129,6 +135,9 @@ public class TransactionTransformer extends Transformer { case UPDATE_NAME: return UpdateNameTransactionTransformer.toBytes(transactionData); + case SELL_NAME: + return SellNameTransactionTransformer.toBytes(transactionData); + case CREATE_POLL: return CreatePollTransactionTransformer.toBytes(transactionData); @@ -154,7 +163,7 @@ public class TransactionTransformer extends Transformer { return MessageTransactionTransformer.toBytes(transactionData); default: - throw new TransformationException("Unsupported transaction type"); + throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] during conversion to bytes"); } } @@ -172,6 +181,9 @@ public class TransactionTransformer extends Transformer { case UPDATE_NAME: return UpdateNameTransactionTransformer.toJSON(transactionData); + case SELL_NAME: + return SellNameTransactionTransformer.toJSON(transactionData); + case CREATE_POLL: return CreatePollTransactionTransformer.toJSON(transactionData); @@ -197,7 +209,7 @@ public class TransactionTransformer extends Transformer { return MessageTransactionTransformer.toJSON(transactionData); default: - throw new TransformationException("Unsupported transaction type"); + throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] during conversion to JSON"); } }