Merge branch 'hvarona-master' into develop
This commit is contained in:
commit
f8990e7643
4 changed files with 253 additions and 1 deletions
5
LICENSE
5
LICENSE
|
@ -1,6 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 BitShares Munich IVS
|
||||
Copyright (c) 2017 AGORISE, LTD.
|
||||
An International Business Company, Cyprus Reg# ΗΕ375959
|
||||
|
||||
Contains works from BitShares Munich IVS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package cy.agorise.graphenej.operations;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import cy.agorise.graphenej.AssetAmount;
|
||||
import cy.agorise.graphenej.BaseOperation;
|
||||
import cy.agorise.graphenej.OperationType;
|
||||
import cy.agorise.graphenej.UserAccount;
|
||||
|
||||
/**
|
||||
* Created by henry on 19/5/2018.
|
||||
*/
|
||||
|
||||
public class AccountUpgradeOperation extends BaseOperation {
|
||||
|
||||
private static final String KEY_ACCOUNT = "account_to_upgrade";
|
||||
private static final String KEY_UPGRADE = "upgrade_to_lifetime_member";
|
||||
|
||||
private AssetAmount fee;
|
||||
private UserAccount accountToUpgrade;
|
||||
private boolean upgradeToLifeTimeMember;
|
||||
|
||||
public AccountUpgradeOperation(UserAccount accountToUpgrade, boolean upgradeToLifeTimeMember) {
|
||||
super(OperationType.ACCOUNT_UPGRADE_OPERATION);
|
||||
this.accountToUpgrade = accountToUpgrade;
|
||||
this.upgradeToLifeTimeMember = upgradeToLifeTimeMember;
|
||||
}
|
||||
|
||||
public AccountUpgradeOperation(UserAccount accountToUpgrade, boolean upgradeToLifeTimeMember, AssetAmount fee) {
|
||||
super(OperationType.ACCOUNT_UPGRADE_OPERATION);
|
||||
this.accountToUpgrade = accountToUpgrade;
|
||||
this.upgradeToLifeTimeMember = upgradeToLifeTimeMember;
|
||||
this.fee = fee;
|
||||
}
|
||||
|
||||
public AssetAmount getFee() {
|
||||
return fee;
|
||||
}
|
||||
|
||||
public UserAccount getAccountToUpgrade() {
|
||||
return accountToUpgrade;
|
||||
}
|
||||
|
||||
public void setAccountToUpgrade(UserAccount accountToUpgrade) {
|
||||
this.accountToUpgrade = accountToUpgrade;
|
||||
}
|
||||
|
||||
public boolean isUpgradeToLifeTimeMember() {
|
||||
return upgradeToLifeTimeMember;
|
||||
}
|
||||
|
||||
public void setUpgradeToLifeTimeMember(boolean upgradeToLifeTimeMember) {
|
||||
this.upgradeToLifeTimeMember = upgradeToLifeTimeMember;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFee(AssetAmount assetAmount) {
|
||||
this.fee = assetAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
byte[] feeBytes = fee.toBytes();
|
||||
byte[] accountBytes = accountToUpgrade.toBytes();
|
||||
byte[] upgradeToLifeTimeMemberBytes = this.upgradeToLifeTimeMember ? new byte[]{ 0x1 } : new byte[]{ 0x0 };
|
||||
byte[] extensions = this.extensions.toBytes();
|
||||
return Bytes.concat(feeBytes, accountBytes, upgradeToLifeTimeMemberBytes, extensions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJsonString() {
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder.registerTypeAdapter(AccountUpgradeOperation.class, new AccountUpgradeSerializer());
|
||||
return gsonBuilder.create().toJson(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement toJsonObject() {
|
||||
JsonArray array = new JsonArray();
|
||||
array.add(this.getId());
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
if(fee != null)
|
||||
jsonObject.add(KEY_FEE, fee.toJsonObject());
|
||||
jsonObject.addProperty(KEY_ACCOUNT, accountToUpgrade.getObjectId());
|
||||
jsonObject.addProperty(KEY_UPGRADE, this.upgradeToLifeTimeMember ? "true" : "false");
|
||||
jsonObject.add(KEY_EXTENSIONS, new JsonArray());
|
||||
array.add(jsonObject);
|
||||
return array;
|
||||
}
|
||||
|
||||
public static class AccountUpgradeSerializer implements JsonSerializer<AccountUpgradeOperation> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(AccountUpgradeOperation accountUpgrade, Type type, JsonSerializationContext jsonSerializationContext) {
|
||||
return accountUpgrade.toJsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AccountUpgradeDeserializer implements JsonDeserializer<AccountUpgradeOperation> {
|
||||
|
||||
@Override
|
||||
public AccountUpgradeOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
if(json.isJsonArray()){
|
||||
// This block is used just to check if we are in the first step of the deserialization
|
||||
// when we are dealing with an array.
|
||||
JsonArray serializedAccountUpgrade = json.getAsJsonArray();
|
||||
if(serializedAccountUpgrade.get(0).getAsInt() != OperationType.ACCOUNT_UPGRADE_OPERATION.ordinal()){
|
||||
// If the operation type does not correspond to a transfer operation, we return null
|
||||
return null;
|
||||
}else{
|
||||
// Calling itself recursively, this is only done once, so there will be no problems.
|
||||
return context.deserialize(serializedAccountUpgrade.get(1), AccountUpgradeOperation.class);
|
||||
}
|
||||
}else{
|
||||
JsonObject jsonObject = json.getAsJsonObject();
|
||||
|
||||
// Deserializing AssetAmount objects
|
||||
AssetAmount fee = context.deserialize(jsonObject.get(KEY_FEE), AssetAmount.class);
|
||||
|
||||
// Deserializing UserAccount objects
|
||||
UserAccount accountToUpgrade = new UserAccount(jsonObject.get(KEY_ACCOUNT).getAsString());
|
||||
|
||||
boolean upgradeToLifeTime = jsonObject.get(KEY_UPGRADE).getAsBoolean();
|
||||
AccountUpgradeOperation upgrade = new AccountUpgradeOperation(accountToUpgrade, upgradeToLifeTime, fee);
|
||||
|
||||
return upgrade;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package cy.agorise.graphenej.operations;
|
||||
|
||||
import cy.agorise.graphenej.AssetAmount;
|
||||
import cy.agorise.graphenej.UserAccount;
|
||||
import cy.agorise.graphenej.errors.MalformedOperationException;
|
||||
|
||||
/**
|
||||
* Created by henry on 19/5/2018.
|
||||
*/
|
||||
|
||||
public class AccountUpgradeOperationBuilder extends BaseOperationBuilder {
|
||||
|
||||
private UserAccount accountToUpgrade;
|
||||
private AssetAmount fee;
|
||||
private boolean isUpgrade = true;
|
||||
|
||||
public AccountUpgradeOperationBuilder setAccountToUpgrade(UserAccount accountToUpgrade) {
|
||||
this.accountToUpgrade = accountToUpgrade;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountUpgradeOperationBuilder setFee(AssetAmount fee) {
|
||||
this.fee = fee;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountUpgradeOperationBuilder setIsUpgrade(Boolean isUpgrade) {
|
||||
this.isUpgrade = isUpgrade;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountUpgradeOperation build(){
|
||||
AccountUpgradeOperation accountUpgrade;
|
||||
if(accountToUpgrade == null ){
|
||||
throw new MalformedOperationException("Missing account to upgrade information");
|
||||
}
|
||||
|
||||
if(fee != null){
|
||||
accountUpgrade = new AccountUpgradeOperation(accountToUpgrade, isUpgrade, fee);
|
||||
}else{
|
||||
accountUpgrade = new AccountUpgradeOperation(accountToUpgrade, isUpgrade);
|
||||
}
|
||||
return accountUpgrade;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package cy.agorise.graphenej.operations;
|
||||
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cy.agorise.graphenej.Asset;
|
||||
import cy.agorise.graphenej.AssetAmount;
|
||||
import cy.agorise.graphenej.BaseOperation;
|
||||
import cy.agorise.graphenej.BlockData;
|
||||
import cy.agorise.graphenej.BrainKey;
|
||||
import cy.agorise.graphenej.Chains;
|
||||
import cy.agorise.graphenej.Transaction;
|
||||
import cy.agorise.graphenej.UserAccount;
|
||||
import cy.agorise.graphenej.Util;
|
||||
|
||||
public class AccountUpgradeOperationTest {
|
||||
private static final String BILTHON_16_BRAIN_KEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI";
|
||||
|
||||
private final Asset CORE = new Asset("1.3.0");
|
||||
|
||||
// This was obtained by calling the 'serialized_transaction' command of the cli_wallet utility and stripping it away
|
||||
// from its signature.
|
||||
//
|
||||
// Ex:
|
||||
// >>> serialize_transaction {"expiration":"2017-04-18T21:42:47","signatures":["207dd63cb89d05266ed4af0935270f269839154d5f04229041997e6c98f10bba21752d6638eb7539c69fb22874fb1e39aad00a5eed6dd5e81e14845e79b60a0590"],"operations":[[8,{"fee":{"amount":69470219,"asset_id":"1.3.0"},"account_to_upgrade":"1.2.143569","upgrade_to_lifetime_member":"true","extensions":[]}]],"extensions":[],"ref_block_num":3703,"ref_block_prefix":2015738269}
|
||||
private final String SERIALIZED_TX = "770e9db925785788f65801080b0824040000000000d1e108010000";
|
||||
|
||||
@Test
|
||||
public void testOperationSerialization(){
|
||||
AccountUpgradeOperationBuilder builder = new AccountUpgradeOperationBuilder()
|
||||
.setAccountToUpgrade(new UserAccount("1.2.143569"))
|
||||
.setFee(new AssetAmount(UnsignedLong.valueOf(69470219), CORE))
|
||||
.setIsUpgrade(true);
|
||||
|
||||
AccountUpgradeOperation upgradeOperation = builder.build();
|
||||
|
||||
ArrayList<BaseOperation> operations = new ArrayList<>();
|
||||
operations.add(upgradeOperation);
|
||||
ECKey privateKey = new BrainKey(BILTHON_16_BRAIN_KEY, 0).getPrivateKey();
|
||||
BlockData blockData = new BlockData(3703, 2015738269, 1492551764);
|
||||
|
||||
Transaction tx = new Transaction(privateKey, blockData, operations);
|
||||
|
||||
// Serialized transaction
|
||||
byte[] serialized = tx.toBytes();
|
||||
|
||||
// The expected serialized transaction is a concatenation of the chain id + the serialized tx
|
||||
byte[] expectedTx = Bytes.concat(Util.hexToBytes(Chains.BITSHARES.CHAIN_ID),Util.hexToBytes(SERIALIZED_TX));
|
||||
|
||||
Assert.assertArrayEquals(expectedTx, serialized);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue