@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemCurrencyDeletion attachment = (Attachment.MonetarySystemCurrencyDeletion) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); CurrencyType.validate(currency, transaction); if (!currency.canBeDeletedBy(transaction.getSenderId())) { throw new NxtException.NotCurrentlyValidException( "Currency " + Long.toUnsignedString(currency.getId()) + " cannot be deleted by account " + Long.toUnsignedString(transaction.getSenderId())); } }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemCurrencyMinting attachment = (Attachment.MonetarySystemCurrencyMinting) transaction.getAttachment(); CurrencyMint.mintCurrency(senderAccount, attachment); }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemCurrencyIssuance attachment = (Attachment.MonetarySystemCurrencyIssuance) transaction.getAttachment(); if (attachment.getMaxSupply() > Constants.MAX_CURRENCY_TOTAL_SUPPLY || attachment.getMaxSupply() <= 0 || attachment.getInitialSupply() < 0 || attachment.getInitialSupply() > attachment.getMaxSupply() || attachment.getReserveSupply() < 0 || attachment.getReserveSupply() > attachment.getMaxSupply() || attachment.getIssuanceHeight() < 0 || attachment.getMinReservePerUnitNQT() < 0 || attachment.getDecimals() < 0 || attachment.getDecimals() > 8 || attachment.getRuleset() != 0) { throw new NxtException.NotValidException( "Invalid currency issuance: " + attachment.getJSONObject()); } int t = 1; for (int i = 0; i < 32; i++) { if ((t & attachment.getType()) != 0 && CurrencyType.get(t) == null) { throw new NxtException.NotValidException( "Invalid currency type: " + attachment.getType()); } t <<= 1; } CurrencyType.validate(attachment.getType(), transaction); CurrencyType.validateCurrencyNaming(transaction.getSenderId(), attachment); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemPublishExchangeOffer attachment = (Attachment.MonetarySystemPublishExchangeOffer) transaction.getAttachment(); CurrencyExchangeOffer.publishOffer(transaction, attachment); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemReserveClaim attachment = (Attachment.MonetarySystemReserveClaim) transaction.getAttachment(); Currency.claimReserve(senderAccount, attachment.getCurrencyId(), attachment.getUnits()); }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemCurrencyMinting attachment = (Attachment.MonetarySystemCurrencyMinting) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); CurrencyType.validate(currency, transaction); if (attachment.getUnits() <= 0) { throw new NxtException.NotValidException( "Invalid number of units: " + attachment.getUnits()); } if (attachment.getUnits() > (currency.getMaxSupply() - currency.getReserveSupply()) / Constants.MAX_MINTING_RATIO) { throw new NxtException.NotValidException( String.format( "Cannot mint more than 1/%d of the total units supply in a single request", Constants.MAX_MINTING_RATIO)); } if (!currency.isActive()) { throw new NxtException.NotCurrentlyValidException( "Currency not currently active " + attachment.getJSONObject()); } long counter = CurrencyMint.getCounter(attachment.getCurrencyId(), transaction.getSenderId()); if (attachment.getCounter() <= counter) { throw new NxtException.NotCurrentlyValidException( String.format( "Counter %d has to be bigger than %d", attachment.getCounter(), counter)); } if (!CurrencyMinting.meetsTarget(transaction.getSenderId(), currency, attachment)) { throw new NxtException.NotCurrentlyValidException( String.format("Hash doesn't meet target %s", attachment.getJSONObject())); } }
@Override void undoAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemExchangeBuy attachment = (Attachment.MonetarySystemExchangeBuy) transaction.getAttachment(); senderAccount.addToUnconfirmedBalanceNQT( Math.multiplyExact(attachment.getUnits(), attachment.getRateNQT())); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemReserveIncrease attachment = (Attachment.MonetarySystemReserveIncrease) transaction.getAttachment(); Currency.increaseReserve( senderAccount, attachment.getCurrencyId(), attachment.getAmountPerUnitNQT()); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemCurrencyDeletion attachment = (Attachment.MonetarySystemCurrencyDeletion) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); currency.delete(getLedgerEvent(), transaction.getId(), senderAccount); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemCurrencyTransfer attachment = (Attachment.MonetarySystemCurrencyTransfer) transaction.getAttachment(); Currency.transferCurrency( senderAccount, recipientAccount, attachment.getCurrencyId(), attachment.getUnits()); CurrencyTransfer.addTransfer(transaction, attachment); }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemCurrencyIssuance attachment = (Attachment.MonetarySystemCurrencyIssuance) transaction.getAttachment(); Currency.addCurrency(transaction, senderAccount, attachment); senderAccount.addToCurrencyAndUnconfirmedCurrencyUnits( transaction.getId(), attachment.getInitialSupply()); }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemReserveClaim attachment = (Attachment.MonetarySystemReserveClaim) transaction.getAttachment(); if (attachment.getUnits() <= 0) { throw new NxtException.NotValidException( "Reserve claim number of units must be positive: " + attachment.getUnits()); } CurrencyType.validate(Currency.getCurrency(attachment.getCurrencyId()), transaction); }
@Override void undoAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemReserveIncrease attachment = (Attachment.MonetarySystemReserveIncrease) transaction.getAttachment(); long reserveSupply; Currency currency = Currency.getCurrency(attachment.getCurrencyId()); if (currency != null) { reserveSupply = currency.getReserveSupply(); } else { // currency must have been deleted, get reserve supply from the original issuance // transaction Transaction currencyIssuance = Nxt.getBlockchain().getTransaction(attachment.getCurrencyId()); Attachment.MonetarySystemCurrencyIssuance currencyIssuanceAttachment = (Attachment.MonetarySystemCurrencyIssuance) currencyIssuance.getAttachment(); reserveSupply = currencyIssuanceAttachment.getReserveSupply(); } senderAccount.addToUnconfirmedBalanceNQT( Math.multiplyExact(reserveSupply, attachment.getAmountPerUnitNQT())); }
@Override void undoAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemExchangeSell attachment = (Attachment.MonetarySystemExchangeSell) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); if (currency != null) { senderAccount.addToUnconfirmedCurrencyUnits( attachment.getCurrencyId(), attachment.getUnits()); } }
@Override boolean isUnconfirmedDuplicate( Transaction transaction, Map<TransactionType, Map<String, Integer>> duplicates) { Attachment.MonetarySystemCurrencyMinting attachment = (Attachment.MonetarySystemCurrencyMinting) transaction.getAttachment(); return TransactionType.isDuplicate( CURRENCY_MINTING, attachment.getCurrencyId() + ":" + transaction.getSenderId(), duplicates, true); }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemReserveIncrease attachment = (Attachment.MonetarySystemReserveIncrease) transaction.getAttachment(); if (attachment.getAmountPerUnitNQT() <= 0) { throw new NxtException.NotValidException( "Reserve increase NXT amount must be positive: " + attachment.getAmountPerUnitNQT()); } CurrencyType.validate(Currency.getCurrency(attachment.getCurrencyId()), transaction); }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemCurrencyTransfer attachment = (Attachment.MonetarySystemCurrencyTransfer) transaction.getAttachment(); if (attachment.getUnits() > senderAccount.getUnconfirmedCurrencyUnits(attachment.getCurrencyId())) { return false; } senderAccount.addToUnconfirmedCurrencyUnits( attachment.getCurrencyId(), -attachment.getUnits()); return true; }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemExchangeBuy attachment = (Attachment.MonetarySystemExchangeBuy) transaction.getAttachment(); if (senderAccount.getUnconfirmedBalanceNQT() >= Math.multiplyExact(attachment.getUnits(), attachment.getRateNQT())) { senderAccount.addToUnconfirmedBalanceNQT( -Math.multiplyExact(attachment.getUnits(), attachment.getRateNQT())); return true; } return false; }
@Override void undoAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemPublishExchangeOffer attachment = (Attachment.MonetarySystemPublishExchangeOffer) transaction.getAttachment(); senderAccount.addToUnconfirmedBalanceNQT( Math.multiplyExact(attachment.getInitialBuySupply(), attachment.getBuyRateNQT())); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); if (currency != null) { senderAccount.addToUnconfirmedCurrencyUnits( attachment.getCurrencyId(), attachment.getInitialSellSupply()); } }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemExchangeSell attachment = (Attachment.MonetarySystemExchangeSell) transaction.getAttachment(); if (senderAccount.getUnconfirmedCurrencyUnits(attachment.getCurrencyId()) >= attachment.getUnits()) { senderAccount.addToUnconfirmedCurrencyUnits( attachment.getCurrencyId(), -attachment.getUnits()); return true; } return false; }
@Override void applyAttachment( Transaction transaction, Account senderAccount, Account recipientAccount) { Attachment.MonetarySystemExchangeSell attachment = (Attachment.MonetarySystemExchangeSell) transaction.getAttachment(); ExchangeRequest.addExchangeRequest(transaction, attachment); CurrencyExchangeOffer.exchangeCurrencyForNXT( transaction, senderAccount, attachment.getCurrencyId(), attachment.getRateNQT(), attachment.getUnits()); }
@Override void undoAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemCurrencyTransfer attachment = (Attachment.MonetarySystemCurrencyTransfer) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); if (currency != null) { senderAccount.addToUnconfirmedCurrencyUnits( getLedgerEvent(), transaction.getId(), attachment.getCurrencyId(), attachment.getUnits()); } }
@Override final void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemExchange attachment = (Attachment.MonetarySystemExchange) transaction.getAttachment(); if (attachment.getRateNQT() <= 0 || attachment.getUnits() == 0) { throw new NxtException.NotValidException("Invalid exchange: " + attachment.getJSONObject()); } Currency currency = Currency.getCurrency(attachment.getCurrencyId()); CurrencyType.validate(currency, transaction); if (!currency.isActive()) { throw new NxtException.NotCurrentlyValidException( "Currency not active: " + attachment.getJSONObject()); } }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemReserveIncrease attachment = (Attachment.MonetarySystemReserveIncrease) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); if (senderAccount.getUnconfirmedBalanceNQT() >= Math.multiplyExact( currency.getReserveSupply(), attachment.getAmountPerUnitNQT())) { senderAccount.addToUnconfirmedBalanceNQT( -Math.multiplyExact(currency.getReserveSupply(), attachment.getAmountPerUnitNQT())); return true; } return false; }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemReserveClaim attachment = (Attachment.MonetarySystemReserveClaim) transaction.getAttachment(); if (senderAccount.getUnconfirmedCurrencyUnits(attachment.getCurrencyId()) >= attachment.getUnits()) { senderAccount.addToUnconfirmedCurrencyUnits( getLedgerEvent(), transaction.getId(), attachment.getCurrencyId(), -attachment.getUnits()); return true; } return false; }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemPublishExchangeOffer attachment = (Attachment.MonetarySystemPublishExchangeOffer) transaction.getAttachment(); if (attachment.getBuyRateNQT() <= 0 || attachment.getSellRateNQT() <= 0 || attachment.getBuyRateNQT() > attachment.getSellRateNQT()) { throw new NxtException.NotValidException( String.format( "Invalid exchange offer, buy rate %d and sell rate %d has to be larger than 0, buy rate cannot be larger than sell rate", attachment.getBuyRateNQT(), attachment.getSellRateNQT())); } if (attachment.getTotalBuyLimit() < 0 || attachment.getTotalSellLimit() < 0 || attachment.getInitialBuySupply() < 0 || attachment.getInitialSellSupply() < 0 || attachment.getExpirationHeight() < 0) { throw new NxtException.NotValidException( "Invalid exchange offer, units and height cannot be negative: " + attachment.getJSONObject()); } if (attachment.getTotalBuyLimit() < attachment.getInitialBuySupply() || attachment.getTotalSellLimit() < attachment.getInitialSellSupply()) { throw new NxtException.NotValidException( "Initial supplies must not exceed total limits"); } if (Nxt.getBlockchain().getHeight() > Constants.SHUFFLING_BLOCK) { if (attachment.getTotalBuyLimit() == 0 && attachment.getTotalSellLimit() == 0) { throw new NxtException.NotCurrentlyValidException( "Total buy and sell limits cannot be both 0"); } if (attachment.getInitialBuySupply() == 0 && attachment.getInitialSellSupply() == 0) { throw new NxtException.NotCurrentlyValidException( "Initial buy and sell supply cannot be both 0"); } } if (attachment.getExpirationHeight() <= attachment.getFinishValidationHeight(transaction)) { throw new NxtException.NotCurrentlyValidException( "Expiration height must be after transaction execution height"); } Currency currency = Currency.getCurrency(attachment.getCurrencyId()); CurrencyType.validate(currency, transaction); if (!currency.isActive()) { throw new NxtException.NotCurrentlyValidException( "Currency not currently active: " + attachment.getJSONObject()); } }
@Override boolean isDuplicate( Transaction transaction, Map<TransactionType, Map<String, Integer>> duplicates) { Attachment.MonetarySystemCurrencyIssuance attachment = (Attachment.MonetarySystemCurrencyIssuance) transaction.getAttachment(); String nameLower = attachment.getName().toLowerCase(); String codeLower = attachment.getCode().toLowerCase(); boolean isDuplicate = TransactionType.isDuplicate(CURRENCY_ISSUANCE, nameLower, duplicates, true); if (!nameLower.equals(codeLower)) { isDuplicate = isDuplicate || TransactionType.isDuplicate(CURRENCY_ISSUANCE, codeLower, duplicates, true); } return isDuplicate; }
@Override boolean applyAttachmentUnconfirmed(Transaction transaction, Account senderAccount) { Attachment.MonetarySystemPublishExchangeOffer attachment = (Attachment.MonetarySystemPublishExchangeOffer) transaction.getAttachment(); if (senderAccount.getUnconfirmedBalanceNQT() >= Math.multiplyExact( attachment.getInitialBuySupply(), attachment.getBuyRateNQT()) && senderAccount.getUnconfirmedCurrencyUnits(attachment.getCurrencyId()) >= attachment.getInitialSellSupply()) { senderAccount.addToUnconfirmedBalanceNQT( -Math.multiplyExact(attachment.getInitialBuySupply(), attachment.getBuyRateNQT())); senderAccount.addToUnconfirmedCurrencyUnits( attachment.getCurrencyId(), -attachment.getInitialSellSupply()); return true; } return false; }
@Override boolean isDuplicate( Transaction transaction, Map<TransactionType, Map<String, Boolean>> duplicates) { Attachment.MonetarySystemAttachment attachment = (Attachment.MonetarySystemAttachment) transaction.getAttachment(); Currency currency = Currency.getCurrency(attachment.getCurrencyId()); String nameLower = currency.getName().toLowerCase(); String codeLower = currency.getCode().toLowerCase(); boolean isDuplicate = TransactionType.isDuplicate(CURRENCY_ISSUANCE, nameLower, duplicates, false); if (!nameLower.equals(codeLower)) { isDuplicate = isDuplicate || TransactionType.isDuplicate(CURRENCY_ISSUANCE, codeLower, duplicates, false); } return isDuplicate; }
@Override void validateAttachment(Transaction transaction) throws NxtException.ValidationException { Attachment.MonetarySystemCurrencyTransfer attachment = (Attachment.MonetarySystemCurrencyTransfer) transaction.getAttachment(); if (attachment.getUnits() <= 0) { throw new NxtException.NotValidException( "Invalid currency transfer: " + attachment.getJSONObject()); } if (transaction.getRecipientId() == Genesis.CREATOR_ID) { throw new NxtException.NotValidException( "Currency transfer to genesis account not allowed"); } Currency currency = Currency.getCurrency(attachment.getCurrencyId()); CurrencyType.validate(currency, transaction); if (!currency.isActive()) { throw new NxtException.NotCurrentlyValidException( "Currency not currently active: " + attachment.getJSONObject()); } }