forked from Qortal/qortal
Merge branch 'asset-fixes' into launch
This commit is contained in:
commit
956ad7bfa8
@ -1,5 +1,6 @@
|
|||||||
package org.qortal.asset;
|
package org.qortal.asset;
|
||||||
|
|
||||||
|
import org.qortal.crypto.Crypto;
|
||||||
import org.qortal.data.asset.AssetData;
|
import org.qortal.data.asset.AssetData;
|
||||||
import org.qortal.data.transaction.IssueAssetTransactionData;
|
import org.qortal.data.transaction.IssueAssetTransactionData;
|
||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
@ -22,7 +23,7 @@ public class Asset {
|
|||||||
|
|
||||||
// Other useful constants
|
// Other useful constants
|
||||||
|
|
||||||
public static final int MAX_NAME_SIZE = 400;
|
public static final int MAX_NAME_SIZE = 40;
|
||||||
public static final int MAX_DESCRIPTION_SIZE = 4000;
|
public static final int MAX_DESCRIPTION_SIZE = 4000;
|
||||||
public static final int MAX_DATA_SIZE = 400000;
|
public static final int MAX_DATA_SIZE = 400000;
|
||||||
|
|
||||||
@ -42,11 +43,13 @@ public class Asset {
|
|||||||
public Asset(Repository repository, IssueAssetTransactionData issueAssetTransactionData) {
|
public Asset(Repository repository, IssueAssetTransactionData issueAssetTransactionData) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
|
|
||||||
|
String ownerAddress = Crypto.toAddress(issueAssetTransactionData.getCreatorPublicKey());
|
||||||
|
|
||||||
// NOTE: transaction's reference is used to look up newly assigned assetID on creation!
|
// NOTE: transaction's reference is used to look up newly assigned assetID on creation!
|
||||||
this.assetData = new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(),
|
this.assetData = new AssetData(ownerAddress, issueAssetTransactionData.getAssetName(),
|
||||||
issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(),
|
issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(),
|
||||||
issueAssetTransactionData.getIsDivisible(), issueAssetTransactionData.getData(),
|
issueAssetTransactionData.isDivisible(), issueAssetTransactionData.getData(),
|
||||||
issueAssetTransactionData.getIsUnspendable(),
|
issueAssetTransactionData.isUnspendable(),
|
||||||
issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature());
|
issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,10 +121,11 @@ public class Asset {
|
|||||||
throw new IllegalStateException("Missing referenced transaction when orphaning UPDATE_ASSET");
|
throw new IllegalStateException("Missing referenced transaction when orphaning UPDATE_ASSET");
|
||||||
|
|
||||||
switch (previousTransactionData.getType()) {
|
switch (previousTransactionData.getType()) {
|
||||||
case ISSUE_ASSET:
|
case ISSUE_ASSET: {
|
||||||
IssueAssetTransactionData previousIssueAssetTransactionData = (IssueAssetTransactionData) previousTransactionData;
|
IssueAssetTransactionData previousIssueAssetTransactionData = (IssueAssetTransactionData) previousTransactionData;
|
||||||
|
|
||||||
this.assetData.setOwner(previousIssueAssetTransactionData.getOwner());
|
String ownerAddress = Crypto.toAddress(previousIssueAssetTransactionData.getCreatorPublicKey());
|
||||||
|
this.assetData.setOwner(ownerAddress);
|
||||||
|
|
||||||
if (needDescription) {
|
if (needDescription) {
|
||||||
this.assetData.setDescription(previousIssueAssetTransactionData.getDescription());
|
this.assetData.setDescription(previousIssueAssetTransactionData.getDescription());
|
||||||
@ -133,8 +137,9 @@ public class Asset {
|
|||||||
needData = false;
|
needData = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case UPDATE_ASSET:
|
case UPDATE_ASSET: {
|
||||||
UpdateAssetTransactionData previousUpdateAssetTransactionData = (UpdateAssetTransactionData) previousTransactionData;
|
UpdateAssetTransactionData previousUpdateAssetTransactionData = (UpdateAssetTransactionData) previousTransactionData;
|
||||||
|
|
||||||
this.assetData.setOwner(previousUpdateAssetTransactionData.getNewOwner());
|
this.assetData.setOwner(previousUpdateAssetTransactionData.getNewOwner());
|
||||||
@ -152,7 +157,9 @@ public class Asset {
|
|||||||
// Get signature for previous transaction in chain, just in case we need it
|
// Get signature for previous transaction in chain, just in case we need it
|
||||||
if (needDescription || needData)
|
if (needDescription || needData)
|
||||||
previousTransactionSignature = previousUpdateAssetTransactionData.getOrphanReference();
|
previousTransactionSignature = previousUpdateAssetTransactionData.getOrphanReference();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Invalid referenced transaction when orphaning UPDATE_ASSET");
|
throw new IllegalStateException("Invalid referenced transaction when orphaning UPDATE_ASSET");
|
||||||
|
@ -335,7 +335,7 @@ public class Order {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Calculate amount granularity, based on price and both assets' divisibility, so that return-amount traded is a valid value (integer or to 8 d.p.)
|
// Calculate amount granularity, based on price and both assets' divisibility, so that return-amount traded is a valid value (integer or to 8 d.p.)
|
||||||
long granularity = calculateAmountGranularity(matchingAssetData.getIsDivisible(), returnAssetData.getIsDivisible(), theirOrderData.getPrice());
|
long granularity = calculateAmountGranularity(matchingAssetData.isDivisible(), returnAssetData.isDivisible(), theirOrderData.getPrice());
|
||||||
LOGGER.trace(() -> String.format("granularity (amount granularity): %s %s", prettyAmount(granularity), matchingAssetData.getName()));
|
LOGGER.trace(() -> String.format("granularity (amount granularity): %s %s", prettyAmount(granularity), matchingAssetData.getName()));
|
||||||
|
|
||||||
// Reduce matched amount (if need be) to fit granularity
|
// Reduce matched amount (if need be) to fit granularity
|
||||||
@ -395,7 +395,7 @@ public class Order {
|
|||||||
* @throws DataException if divisibility check fails
|
* @throws DataException if divisibility check fails
|
||||||
*/
|
*/
|
||||||
private void checkDivisibility(AssetData assetData, long amount, OrderData orderData) throws DataException {
|
private void checkDivisibility(AssetData assetData, long amount, OrderData orderData) throws DataException {
|
||||||
if (assetData.getIsDivisible() || amount % Amounts.MULTIPLIER == 0)
|
if (assetData.isDivisible() || amount % Amounts.MULTIPLIER == 0)
|
||||||
// Asset is divisible or amount has no fractional part
|
// Asset is divisible or amount has no fractional part
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public class AssetData {
|
|||||||
return this.quantity;
|
return this.quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsDivisible() {
|
public boolean isDivisible() {
|
||||||
return this.isDivisible;
|
return this.isDivisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ public class AssetData {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsUnspendable() {
|
public boolean isUnspendable() {
|
||||||
return this.isUnspendable;
|
return this.isUnspendable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,6 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
@Schema(description = "asset issuer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
|
@Schema(description = "asset issuer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
|
||||||
private byte[] issuerPublicKey;
|
private byte[] issuerPublicKey;
|
||||||
|
|
||||||
@Schema(description = "asset owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v")
|
|
||||||
private String owner;
|
|
||||||
|
|
||||||
@Schema(description = "asset name", example = "GOLD")
|
@Schema(description = "asset name", example = "GOLD")
|
||||||
private String assetName;
|
private String assetName;
|
||||||
|
|
||||||
@ -72,12 +69,11 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
|
|
||||||
/** From repository */
|
/** From repository */
|
||||||
public IssueAssetTransactionData(BaseTransactionData baseTransactionData,
|
public IssueAssetTransactionData(BaseTransactionData baseTransactionData,
|
||||||
Long assetId, String owner, String assetName, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable) {
|
Long assetId, String assetName, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable) {
|
||||||
super(TransactionType.ISSUE_ASSET, baseTransactionData);
|
super(TransactionType.ISSUE_ASSET, baseTransactionData);
|
||||||
|
|
||||||
this.assetId = assetId;
|
this.assetId = assetId;
|
||||||
this.issuerPublicKey = baseTransactionData.creatorPublicKey;
|
this.issuerPublicKey = baseTransactionData.creatorPublicKey;
|
||||||
this.owner = owner;
|
|
||||||
this.assetName = assetName;
|
this.assetName = assetName;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.quantity = quantity;
|
this.quantity = quantity;
|
||||||
@ -87,9 +83,9 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** From network/API */
|
/** From network/API */
|
||||||
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description,
|
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String assetName, String description,
|
||||||
long quantity, boolean isDivisible, String data, boolean isUnspendable) {
|
long quantity, boolean isDivisible, String data, boolean isUnspendable) {
|
||||||
this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data, isUnspendable);
|
this(baseTransactionData, null, assetName, description, quantity, isDivisible, data, isUnspendable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters/Setters
|
// Getters/Setters
|
||||||
@ -106,14 +102,6 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
return this.issuerPublicKey;
|
return this.issuerPublicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOwner() {
|
|
||||||
return this.owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(String owner) {
|
|
||||||
this.owner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAssetName() {
|
public String getAssetName() {
|
||||||
return this.assetName;
|
return this.assetName;
|
||||||
}
|
}
|
||||||
@ -126,7 +114,7 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
return this.quantity;
|
return this.quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsDivisible() {
|
public boolean isDivisible() {
|
||||||
return this.isDivisible;
|
return this.isDivisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +122,7 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsUnspendable() {
|
public boolean isUnspendable() {
|
||||||
return this.isUnspendable;
|
return this.isUnspendable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ public class Payment {
|
|||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
||||||
|
|
||||||
// Do not allow non-owner asset holders to use asset
|
// Do not allow non-owner asset holders to use asset
|
||||||
if (assetData.getIsUnspendable() && !assetData.getOwner().equals(sender.getAddress()))
|
if (assetData.isUnspendable() && !assetData.getOwner().equals(sender.getAddress()))
|
||||||
return ValidationResult.ASSET_NOT_SPENDABLE;
|
return ValidationResult.ASSET_NOT_SPENDABLE;
|
||||||
|
|
||||||
// If we're sending to an AT then assetId must match AT's assetId
|
// If we're sending to an AT then assetId must match AT's assetId
|
||||||
@ -94,7 +94,7 @@ public class Payment {
|
|||||||
return ValidationResult.ASSET_DOES_NOT_MATCH_AT;
|
return ValidationResult.ASSET_DOES_NOT_MATCH_AT;
|
||||||
|
|
||||||
// Check asset amount is integer if asset is not divisible
|
// Check asset amount is integer if asset is not divisible
|
||||||
if (!assetData.getIsDivisible() && paymentData.getAmount() % Amounts.MULTIPLIER != 0)
|
if (!assetData.isDivisible() && paymentData.getAmount() % Amounts.MULTIPLIER != 0)
|
||||||
return ValidationResult.INVALID_AMOUNT;
|
return ValidationResult.INVALID_AMOUNT;
|
||||||
|
|
||||||
// Set or add amount into amounts-by-asset map
|
// Set or add amount into amounts-by-asset map
|
||||||
|
@ -159,8 +159,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
|
|
||||||
saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner())
|
saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner())
|
||||||
.bind("asset_name", assetData.getName()).bind("description", assetData.getDescription())
|
.bind("asset_name", assetData.getName()).bind("description", assetData.getDescription())
|
||||||
.bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.getIsDivisible())
|
.bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.isDivisible())
|
||||||
.bind("data", assetData.getData()).bind("is_unspendable", assetData.getIsUnspendable())
|
.bind("data", assetData.getData()).bind("is_unspendable", assetData.isUnspendable())
|
||||||
.bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference());
|
.bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -384,8 +384,7 @@ public class HSQLDBDatabaseUpdates {
|
|||||||
stmt.execute("CREATE INDEX AssetTradeSellOrderIndex on AssetTrades (target_order_id, traded_when)");
|
stmt.execute("CREATE INDEX AssetTradeSellOrderIndex on AssetTrades (target_order_id, traded_when)");
|
||||||
|
|
||||||
// Issue Asset Transactions
|
// Issue Asset Transactions
|
||||||
stmt.execute("CREATE TABLE IssueAssetTransactions (signature Signature, issuer QortalPublicKey NOT NULL, owner QortalAddress NOT NULL, "
|
stmt.execute("CREATE TABLE IssueAssetTransactions (signature Signature, issuer QortalPublicKey NOT NULL, asset_name AssetName NOT NULL, "
|
||||||
+ "asset_name AssetName NOT NULL, "
|
|
||||||
+ "description GenericDescription NOT NULL, quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, asset_id AssetID, "
|
+ "description GenericDescription NOT NULL, quantity BIGINT NOT NULL, is_divisible BOOLEAN NOT NULL, asset_id AssetID, "
|
||||||
+ "is_unspendable BOOLEAN NOT NULL, data AssetData NOT NULL DEFAULT '', " + TRANSACTION_KEYS + ")");
|
+ "is_unspendable BOOLEAN NOT NULL, data AssetData NOT NULL DEFAULT '', " + TRANSACTION_KEYS + ")");
|
||||||
|
|
||||||
|
@ -17,26 +17,25 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException {
|
TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException {
|
||||||
String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, is_unspendable, asset_id FROM IssueAssetTransactions WHERE signature = ?";
|
String sql = "SELECT asset_name, description, quantity, is_divisible, data, is_unspendable, asset_id FROM IssueAssetTransactions WHERE signature = ?";
|
||||||
|
|
||||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) {
|
||||||
if (resultSet == null)
|
if (resultSet == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
String owner = resultSet.getString(1);
|
String assetName = resultSet.getString(1);
|
||||||
String assetName = resultSet.getString(2);
|
String description = resultSet.getString(2);
|
||||||
String description = resultSet.getString(3);
|
long quantity = resultSet.getLong(3);
|
||||||
long quantity = resultSet.getLong(4);
|
boolean isDivisible = resultSet.getBoolean(4);
|
||||||
boolean isDivisible = resultSet.getBoolean(5);
|
String data = resultSet.getString(5);
|
||||||
String data = resultSet.getString(6);
|
boolean isUnspendable = resultSet.getBoolean(6);
|
||||||
boolean isUnspendable = resultSet.getBoolean(7);
|
|
||||||
|
|
||||||
// Special null-checking for asset ID
|
// Special null-checking for asset ID
|
||||||
Long assetId = resultSet.getLong(8);
|
Long assetId = resultSet.getLong(7);
|
||||||
if (assetId == 0 && resultSet.wasNull())
|
if (assetId == 0 && resultSet.wasNull())
|
||||||
assetId = null;
|
assetId = null;
|
||||||
|
|
||||||
return new IssueAssetTransactionData(baseTransactionData, assetId, owner, assetName, description, quantity, isDivisible,
|
return new IssueAssetTransactionData(baseTransactionData, assetId, assetName, description, quantity, isDivisible,
|
||||||
data, isUnspendable);
|
data, isUnspendable);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to fetch issue asset transaction from repository", e);
|
throw new DataException("Unable to fetch issue asset transaction from repository", e);
|
||||||
@ -50,10 +49,10 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
|
|||||||
HSQLDBSaver saveHelper = new HSQLDBSaver("IssueAssetTransactions");
|
HSQLDBSaver saveHelper = new HSQLDBSaver("IssueAssetTransactions");
|
||||||
|
|
||||||
saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey())
|
saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey())
|
||||||
.bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName())
|
.bind("asset_name", issueAssetTransactionData.getAssetName())
|
||||||
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
|
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
|
||||||
.bind("is_divisible", issueAssetTransactionData.getIsDivisible()).bind("data", issueAssetTransactionData.getData())
|
.bind("is_divisible", issueAssetTransactionData.isDivisible()).bind("data", issueAssetTransactionData.getData())
|
||||||
.bind("is_unspendable", issueAssetTransactionData.getIsUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId());
|
.bind("is_unspendable", issueAssetTransactionData.isUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saveHelper.execute(this.repository);
|
saveHelper.execute(this.repository);
|
||||||
|
@ -114,7 +114,7 @@ public class AtTransaction extends Transaction {
|
|||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
||||||
|
|
||||||
// Check asset amount is integer if asset is not divisible
|
// Check asset amount is integer if asset is not divisible
|
||||||
if (!assetData.getIsDivisible() && amount % Amounts.MULTIPLIER != 0)
|
if (!assetData.isDivisible() && amount % Amounts.MULTIPLIER != 0)
|
||||||
return ValidationResult.INVALID_AMOUNT;
|
return ValidationResult.INVALID_AMOUNT;
|
||||||
|
|
||||||
Account sender = getATAccount();
|
Account sender = getATAccount();
|
||||||
|
@ -76,7 +76,7 @@ public class CreateAssetOrderTransaction extends Transaction {
|
|||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
||||||
|
|
||||||
// Unspendable assets are not tradable
|
// Unspendable assets are not tradable
|
||||||
if (haveAssetData.getIsUnspendable() || wantAssetData.getIsUnspendable())
|
if (haveAssetData.isUnspendable() || wantAssetData.isUnspendable())
|
||||||
return ValidationResult.ASSET_NOT_SPENDABLE;
|
return ValidationResult.ASSET_NOT_SPENDABLE;
|
||||||
|
|
||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
@ -109,11 +109,11 @@ public class CreateAssetOrderTransaction extends Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check amount is integer if amount's asset is not divisible
|
// Check amount is integer if amount's asset is not divisible
|
||||||
if (!haveAssetData.getIsDivisible() && committedCost.mod(Amounts.MULTIPLIER_BI).signum() != 0)
|
if (!haveAssetData.isDivisible() && committedCost.mod(Amounts.MULTIPLIER_BI).signum() != 0)
|
||||||
return ValidationResult.INVALID_AMOUNT;
|
return ValidationResult.INVALID_AMOUNT;
|
||||||
|
|
||||||
// Check total return from fulfilled order would be integer if return's asset is not divisible
|
// Check total return from fulfilled order would be integer if return's asset is not divisible
|
||||||
if (!wantAssetData.getIsDivisible() && maxOtherAmount.mod(Amounts.MULTIPLIER_BI).signum() != 0)
|
if (!wantAssetData.isDivisible() && maxOtherAmount.mod(Amounts.MULTIPLIER_BI).signum() != 0)
|
||||||
return ValidationResult.INVALID_RETURN;
|
return ValidationResult.INVALID_RETURN;
|
||||||
|
|
||||||
// Check order creator has enough asset balance AFTER removing fee, in case asset is QORT
|
// Check order creator has enough asset balance AFTER removing fee, in case asset is QORT
|
||||||
|
@ -113,11 +113,11 @@ public class DeployAtTransaction extends Transaction {
|
|||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
||||||
|
|
||||||
// Unspendable assets are not valid
|
// Unspendable assets are not valid
|
||||||
if (assetData.getIsUnspendable())
|
if (assetData.isUnspendable())
|
||||||
return ValidationResult.ASSET_NOT_SPENDABLE;
|
return ValidationResult.ASSET_NOT_SPENDABLE;
|
||||||
|
|
||||||
// Check asset amount is integer if asset is not divisible
|
// Check asset amount is integer if asset is not divisible
|
||||||
if (!assetData.getIsDivisible() && this.deployATTransactionData.getAmount() % Amounts.MULTIPLIER != 0)
|
if (!assetData.isDivisible() && this.deployATTransactionData.getAmount() % Amounts.MULTIPLIER != 0)
|
||||||
return ValidationResult.INVALID_AMOUNT;
|
return ValidationResult.INVALID_AMOUNT;
|
||||||
|
|
||||||
Account creator = this.getCreator();
|
Account creator = this.getCreator();
|
||||||
|
@ -5,7 +5,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.qortal.account.Account;
|
import org.qortal.account.Account;
|
||||||
import org.qortal.asset.Asset;
|
import org.qortal.asset.Asset;
|
||||||
import org.qortal.crypto.Crypto;
|
|
||||||
import org.qortal.data.transaction.IssueAssetTransactionData;
|
import org.qortal.data.transaction.IssueAssetTransactionData;
|
||||||
import org.qortal.data.transaction.TransactionData;
|
import org.qortal.data.transaction.TransactionData;
|
||||||
import org.qortal.repository.DataException;
|
import org.qortal.repository.DataException;
|
||||||
@ -19,7 +18,6 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
private IssueAssetTransactionData issueAssetTransactionData;
|
private IssueAssetTransactionData issueAssetTransactionData;
|
||||||
private Account ownerAccount = null;
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -33,7 +31,7 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getRecipientAddresses() throws DataException {
|
public List<String> getRecipientAddresses() throws DataException {
|
||||||
return Collections.singletonList(this.issueAssetTransactionData.getOwner());
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
@ -42,21 +40,10 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
return this.getCreator();
|
return this.getCreator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Account getOwner() {
|
|
||||||
if (this.ownerAccount == null)
|
|
||||||
this.ownerAccount = new Account(this.repository, this.issueAssetTransactionData.getOwner());
|
|
||||||
|
|
||||||
return this.ownerAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Processing
|
// Processing
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValidationResult isValid() throws DataException {
|
public ValidationResult isValid() throws DataException {
|
||||||
// Check owner address is valid
|
|
||||||
if (!Crypto.isValidAddress(this.issueAssetTransactionData.getOwner()))
|
|
||||||
return ValidationResult.INVALID_ADDRESS;
|
|
||||||
|
|
||||||
// Check name size bounds
|
// Check name size bounds
|
||||||
int assetNameLength = Utf8.encodedLength(this.issueAssetTransactionData.getAssetName());
|
int assetNameLength = Utf8.encodedLength(this.issueAssetTransactionData.getAssetName());
|
||||||
if (assetNameLength < 1 || assetNameLength > Asset.MAX_NAME_SIZE)
|
if (assetNameLength < 1 || assetNameLength > Asset.MAX_NAME_SIZE)
|
||||||
@ -78,7 +65,7 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_QUANTITY;
|
return ValidationResult.INVALID_QUANTITY;
|
||||||
|
|
||||||
// Check quantity versus indivisibility
|
// Check quantity versus indivisibility
|
||||||
if (!this.issueAssetTransactionData.getIsDivisible() && this.issueAssetTransactionData.getQuantity() % Amounts.MULTIPLIER != 0)
|
if (!this.issueAssetTransactionData.isDivisible() && this.issueAssetTransactionData.getQuantity() % Amounts.MULTIPLIER != 0)
|
||||||
return ValidationResult.INVALID_QUANTITY;
|
return ValidationResult.INVALID_QUANTITY;
|
||||||
|
|
||||||
Account issuer = getIssuer();
|
Account issuer = getIssuer();
|
||||||
@ -105,9 +92,9 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
Asset asset = new Asset(this.repository, this.issueAssetTransactionData);
|
Asset asset = new Asset(this.repository, this.issueAssetTransactionData);
|
||||||
asset.issue();
|
asset.issue();
|
||||||
|
|
||||||
// Add asset to owner
|
// Add asset to issuer
|
||||||
Account owner = getOwner();
|
Account issuer = this.getIssuer();
|
||||||
owner.setConfirmedBalance(asset.getAssetData().getAssetId(), this.issueAssetTransactionData.getQuantity());
|
issuer.setConfirmedBalance(asset.getAssetData().getAssetId(), this.issueAssetTransactionData.getQuantity());
|
||||||
|
|
||||||
// Note newly assigned asset ID in our transaction record
|
// Note newly assigned asset ID in our transaction record
|
||||||
this.issueAssetTransactionData.setAssetId(asset.getAssetData().getAssetId());
|
this.issueAssetTransactionData.setAssetId(asset.getAssetData().getAssetId());
|
||||||
@ -118,9 +105,9 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void orphan() throws DataException {
|
public void orphan() throws DataException {
|
||||||
// Remove asset from owner
|
// Remove asset from issuer
|
||||||
Account owner = getOwner();
|
Account issuer = this.getIssuer();
|
||||||
owner.deleteBalance(this.issueAssetTransactionData.getAssetId());
|
issuer.deleteBalance(this.issueAssetTransactionData.getAssetId());
|
||||||
|
|
||||||
// Deissue asset
|
// Deissue asset
|
||||||
Asset asset = new Asset(this.repository, this.issueAssetTransactionData.getAssetId());
|
Asset asset = new Asset(this.repository, this.issueAssetTransactionData.getAssetId());
|
||||||
|
@ -18,7 +18,6 @@ import com.google.common.primitives.Longs;
|
|||||||
public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
||||||
|
|
||||||
// Property lengths
|
// Property lengths
|
||||||
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
|
|
||||||
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
|
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
|
||||||
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
|
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
|
||||||
private static final int QUANTITY_LENGTH = AMOUNT_LENGTH;
|
private static final int QUANTITY_LENGTH = AMOUNT_LENGTH;
|
||||||
@ -26,7 +25,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
|
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
|
||||||
private static final int IS_UNSPENDABLE_LENGTH = BOOLEAN_LENGTH;
|
private static final int IS_UNSPENDABLE_LENGTH = BOOLEAN_LENGTH;
|
||||||
|
|
||||||
private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH
|
private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH
|
||||||
+ IS_DIVISIBLE_LENGTH + DATA_SIZE_LENGTH + IS_UNSPENDABLE_LENGTH;
|
+ IS_DIVISIBLE_LENGTH + DATA_SIZE_LENGTH + IS_UNSPENDABLE_LENGTH;
|
||||||
|
|
||||||
protected static final TransactionLayout layout;
|
protected static final TransactionLayout layout;
|
||||||
@ -38,7 +37,6 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
layout.add("transaction's groupID", TransformationType.INT);
|
layout.add("transaction's groupID", TransformationType.INT);
|
||||||
layout.add("reference", TransformationType.SIGNATURE);
|
layout.add("reference", TransformationType.SIGNATURE);
|
||||||
layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY);
|
layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY);
|
||||||
layout.add("asset owner", TransformationType.ADDRESS);
|
|
||||||
layout.add("asset name length", TransformationType.INT);
|
layout.add("asset name length", TransformationType.INT);
|
||||||
layout.add("asset name", TransformationType.STRING);
|
layout.add("asset name", TransformationType.STRING);
|
||||||
layout.add("asset description length", TransformationType.INT);
|
layout.add("asset description length", TransformationType.INT);
|
||||||
@ -62,8 +60,6 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
byte[] issuerPublicKey = Serialization.deserializePublicKey(byteBuffer);
|
byte[] issuerPublicKey = Serialization.deserializePublicKey(byteBuffer);
|
||||||
|
|
||||||
String owner = Serialization.deserializeAddress(byteBuffer);
|
|
||||||
|
|
||||||
String assetName = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_NAME_SIZE);
|
String assetName = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_NAME_SIZE);
|
||||||
|
|
||||||
String description = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DESCRIPTION_SIZE);
|
String description = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DESCRIPTION_SIZE);
|
||||||
@ -83,7 +79,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature);
|
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature);
|
||||||
|
|
||||||
return new IssueAssetTransactionData(baseTransactionData, owner, assetName, description, quantity, isDivisible, data, isUnspendable);
|
return new IssueAssetTransactionData(baseTransactionData, assetName, description, quantity, isDivisible, data, isUnspendable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
@ -103,18 +99,16 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
transformCommonBytes(transactionData, bytes);
|
transformCommonBytes(transactionData, bytes);
|
||||||
|
|
||||||
Serialization.serializeAddress(bytes, issueAssetTransactionData.getOwner());
|
|
||||||
|
|
||||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getAssetName());
|
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getAssetName());
|
||||||
|
|
||||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getDescription());
|
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getDescription());
|
||||||
|
|
||||||
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
|
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
|
||||||
bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0));
|
bytes.write((byte) (issueAssetTransactionData.isDivisible() ? 1 : 0));
|
||||||
|
|
||||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
||||||
|
|
||||||
bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0));
|
bytes.write((byte) (issueAssetTransactionData.isUnspendable() ? 1 : 0));
|
||||||
|
|
||||||
bytes.write(Longs.toByteArray(issueAssetTransactionData.getFee()));
|
bytes.write(Longs.toByteArray(issueAssetTransactionData.getFee()));
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class AssetUtils {
|
|||||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
|
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
|
||||||
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), assetName, "desc", quantity, isDivisible, "{}", false);
|
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, assetName, "desc", quantity, isDivisible, "{}", false);
|
||||||
|
|
||||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ public class IssueAssetTestTransaction extends TestTransaction {
|
|||||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
String owner = account.getAddress();
|
|
||||||
String assetName = "test-asset-" + random.nextInt(1_000_000);
|
String assetName = "test-asset-" + random.nextInt(1_000_000);
|
||||||
String description = "random test asset";
|
String description = "random test asset";
|
||||||
final long quantity = 1_000_000L;
|
final long quantity = 1_000_000L;
|
||||||
@ -22,7 +21,7 @@ public class IssueAssetTestTransaction extends TestTransaction {
|
|||||||
String data = AssetUtils.randomData();
|
String data = AssetUtils.randomData();
|
||||||
final boolean isUnspendable = false;
|
final boolean isUnspendable = false;
|
||||||
|
|
||||||
return new IssueAssetTransactionData(generateBase(account), owner, assetName, description, quantity, isDivisible, data, isUnspendable);
|
return new IssueAssetTransactionData(generateBase(account), assetName, description, quantity, isDivisible, data, isUnspendable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ public class GroupApprovalTests extends Common {
|
|||||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null);
|
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null);
|
||||||
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), "test asset", "test asset desc", 1000L, true, "{}", false);
|
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, "test asset", "test asset desc", 1000L, true, "{}", false);
|
||||||
|
|
||||||
return Transaction.fromData(repository, transactionData);
|
return Transaction.fromData(repository, transactionData);
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
"version": 4,
|
"version": 4,
|
||||||
"timestamp": 0,
|
"timestamp": 0,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
"version": 4,
|
"version": 4,
|
||||||
"timestamp": 0,
|
"timestamp": 0,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
||||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
"version": 4,
|
"version": 4,
|
||||||
"timestamp": 0,
|
"timestamp": 0,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
||||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
||||||
@ -64,9 +64,9 @@
|
|||||||
|
|
||||||
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||||
|
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
|
|
||||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
"version": 4,
|
"version": 4,
|
||||||
"timestamp": 0,
|
"timestamp": 0,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
||||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
||||||
@ -64,9 +64,9 @@
|
|||||||
|
|
||||||
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||||
|
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||||
|
|
||||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 },
|
||||||
|
@ -50,9 +50,9 @@
|
|||||||
"version": 4,
|
"version": 4,
|
||||||
"timestamp": 0,
|
"timestamp": 0,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QdSnUy6sUiEnaN87dWmE92g1uQjrvPgrWG", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
{ "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true },
|
||||||
|
|
||||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" },
|
||||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" },
|
||||||
@ -61,9 +61,9 @@
|
|||||||
|
|
||||||
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||||
|
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
||||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
{ "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 },
|
||||||
|
|
||||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": "100" },
|
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": "100" },
|
||||||
|
Loading…
Reference in New Issue
Block a user