public class StellarAddress extends StellarIdentifier {

//	public static final StellarAddress STELLAR_ROOT_ACCOUNT=new StellarAddress("gHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
//	public static final StellarAddress STELLAR_ADDRESS_ZERO=new StellarAddress("grrrrrrrrrrrrrrrrrrrrhoLvTp");
//	public static final StellarAddress STELLAR_ADDRESS_ONE=new StellarAddress("grrrrrrrrrrrrrrrrrrrBZbvji");
//	public static final StellarAddress STELLAR_ADDRESS_NEUTRAL=Stellar_ADDRESS_ONE;
//	public static final StellarAddress STELLAR_ADDRESS_NAN=new StellarAddress("grrrrrrrrrrrrrrrrrrn5RM1rHd");
	public static final StellarAddress STELLAR_ADDRESS_JSTELLARAPI=new StellarAddress("gB2ZjFkenMnZLGZHEckAXn7xzTpn1omFti");
	public static final StellarAddress STELLAR_ADDRESS_PMARCHES=new StellarAddress("gDh15vDi6gN4ZXvxNPoo2wZ2KNmMRBGto1");
	public static final StellarAddress STELLAR_ADDRESS_DEFAULT_INFLATION_ADDRESS=new StellarAddress("g4eRqgZfzfj3132y17iaf2fp6HQj1gofjt");

	public StellarAddress(byte[] payloadBytes) {
		super(payloadBytes, 0);
	}

	public StellarAddress(String string) {
		super(string);
	}
} public class StellarEngineException extends RuntimeException {

	/**
	 * 
	 */
	private static final long serialVersionUID = 9010916677189222829L;
	private final String engine_result, engine_result_message;
	private final long engine_result_code;

	public StellarEngineException(String engine_result, long engine_result_code, String engine_result_message) {
		super(engine_result_message);
		this.engine_result = engine_result;
		this.engine_result_code = engine_result_code;
		this.engine_result_message = engine_result_message;
	}

	public String getEngine_result() {
		return engine_result;
	}

	public long getEngine_result_code() {
		return engine_result_code;
	}

	public String getEngine_result_message() {
		return engine_result_message;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("StellarEngineException [engine_result=").append(engine_result).append(", engine_result_code=").append(engine_result_code).append(", engine_result_message=")
				.append(engine_result_message).append("]");
		return builder.toString();
	}

} public class StellarPaymentTransaction extends StellarTransaction implements JSONSerializable {
	public StellarAddress payer;
	public StellarAddress payee;
	public DenominatedIssuedCurrency amount;
	public String signedTransactionBlob;
	public long sequenceNumber;
	public long destinationTag = -1;
	public String txHash;
	public String signature;
	public String publicKeyUsedToSign;
	public DenominatedIssuedCurrency fee;
	public long flags;

	public StellarPaymentTransaction(StellarAddress payer, StellarAddress payee, DenominatedIssuedCurrency amount, int sequenceNumber) {
		this.payer = payer;
		this.payee = payee;
		this.amount = amount;
		this.sequenceNumber = sequenceNumber;
		this.fee = DenominatedIssuedCurrency.FEE;
	}

	public StellarPaymentTransaction(StellarBinaryObject serObj) {
		super(serObj);
		if (serObj.getTransactionType() != TransactionTypes.PAYMENT) {
			throw new RuntimeException("The StellarBinaryObject is not a payment transaction, but a " + serObj.getTransactionType());
		}
		payer = (StellarAddress) serObj.getField(BinaryFormatField.Account);
		payee = (StellarAddress) serObj.getField(BinaryFormatField.Destination);
		amount = (DenominatedIssuedCurrency) serObj.getField(BinaryFormatField.Amount);
		sequenceNumber = (long) serObj.getField(BinaryFormatField.Sequence);
		fee = (DenominatedIssuedCurrency) serObj.getField(BinaryFormatField.Fee);
		flags = (long) serObj.getField(BinaryFormatField.Flags);
	}

	public StellarPaymentTransaction(JSONObject jsonTx) {
		fromTxJSON(jsonTx);
	}

	public StellarBinaryObject getBinaryObject() {
		StellarBinaryObject rbo = new StellarBinaryObject();
		rbo.putField(BinaryFormatField.TransactionType, (int) TransactionTypes.PAYMENT.byteValue);
		rbo.putField(BinaryFormatField.Account, this.payer);
		rbo.putField(BinaryFormatField.Destination, this.payee);
		rbo.putField(BinaryFormatField.Amount, this.amount);
		rbo.putField(BinaryFormatField.Sequence, this.sequenceNumber);
		rbo.putField(BinaryFormatField.Fee, this.fee);
		rbo.putField(BinaryFormatField.Flags, this.flags);

		return rbo;
	}

	@SuppressWarnings("unchecked")
	public JSONObject toTxJSON() {
		JSONObject jsonTx = new JSONObject();
		jsonTx.put("Account", payer.toString());
		jsonTx.put("Destination", payee.toString());
		jsonTx.put("Amount", amount.toJSON());
		jsonTx.put("TransactionType", "Payment");
		if(destinationTag>=0&&destinationTag<=4294967295l){
			jsonTx.put("DestinationTag", String.valueOf(destinationTag));
		}
		return jsonTx;
	}

	@Override
	public void copyFrom(JSONObject jsonCommandResult) {
		signedTransactionBlob = (String) jsonCommandResult.get("tx_blob");
		JSONObject tx_json = (JSONObject) jsonCommandResult.get("tx_json");
		if (tx_json != null) {
			fromTxJSON(tx_json);
		}
	}

	protected void fromTxJSON(JSONObject tx_json) {
		payer = new StellarAddress((String) tx_json.get("Account"));
		payee = new StellarAddress((String) tx_json.get("Destination"));
		sequenceNumber = (Long) tx_json.get("Sequence");
		txHash = (String) tx_json.get("hash");
		signature = (String) tx_json.get("TxnSignature");
		publicKeyUsedToSign = (String) tx_json.get("SigningPubKey");
		flags = (Long) tx_json.get("Flags");
		Object amount = tx_json.get("Amount");
		if (amount instanceof String) {
			String amountInMicroSTR = (String) amount;
			this.amount = new DenominatedIssuedCurrency(amountInMicroSTR);
		} else if (amount instanceof JSONObject) {
			JSONObject jamt = (JSONObject) amount;
			this.amount = new DenominatedIssuedCurrency(jamt.get("value").toString(), new StellarAddress(jamt.get("issuer").toString()), jamt.get("currency").toString());
		} else {
			this.amount = new DenominatedIssuedCurrency();
		}
		Object fee = tx_json.get("Fee");
		if (fee != null) {
			this.fee = new DenominatedIssuedCurrency(new BigInteger(fee.toString()));
		}
	}

	public String getSignedTxBlob() {
		return signedTransactionBlob;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

} public class StellarSeedAddress extends StellarIdentifier {
	private static final long serialVersionUID = 1845189349528742766L;
	protected StellarPrivateKey privateKey;

	public StellarSeedAddress(byte[] payloadBytes) {
		super(payloadBytes, 33);
		if(payloadBytes.length!=32){
			throw new RuntimeException("The seed bytes should be 32 bytes in length. They can be random bytes, or the first 256bit of the SHA512 hash of the passphrase");
		}
	}

	public StellarSeedAddress(String stringID) {
		super(stringID);
	}

	public StellarPrivateKey getPrivateKey() {
		if(privateKey==null){
			EdDSAPrivateKeySpec keySpec=new EdDSAPrivateKeySpec(payloadBytes, StellarPublicKey.ed25519);
			byte[] publicKeyBytes=keySpec.getA().toByteArray();
			byte[] privateBytes=keySpec.geta();
			privateKey=new StellarPrivateKey(privateBytes, publicKeyBytes);
		}
		return privateKey;
	}

	public StellarAddress getPublicStellarAddress() {
		return getPrivateKey().getPublicKey().getAddress();
	}
} @Generated("org.jsonschema2pojo")
public class AccountTx {

    @Expose
    @Valid
    private Result result;

    /**
     * 
     * @return
     *     The result
     */
    public Result getResult() {
        return result;
    }

    /**
     * 
     * @param result
     *     The result
     */
    public void setResult(Result result) {
        this.result = result;
    }

    public AccountTx withResult(Result result) {
        this.result = result;
        return this;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(result).toHashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if ((other instanceof AccountTx) == false) {
            return false;
        }
        AccountTx rhs = ((AccountTx) other);
        return new EqualsBuilder().append(result, rhs.result).isEquals();
    }

} @Generated("org.jsonschema2pojo")
public class Balance {

	@Expose
	private String currency;
	@Expose
	private String issuer;
	@Expose
	private BigDecimal value;

	/**
	 * 
	 * @return The currency
	 */
	public String getCurrency() {
		return currency;
	}

	/**
	 * 
	 * @param currency
	 *            The currency
	 */
	public void setCurrency(String currency) {
		this.currency = currency;
	}

	public Balance withCurrency(String currency) {
		this.currency = currency;
		return this;
	}

	/**
	 * 
	 * @return The issuer
	 */
	public String getIssuer() {
		return issuer;
	}

	/**
	 * 
	 * @param issuer
	 *            The issuer
	 */
	public void setIssuer(String issuer) {
		this.issuer = issuer;
	}

	public Balance withIssuer(String issuer) {
		this.issuer = issuer;
		return this;
	}

	/**
	 * 
	 * @return The value
	 */
	public BigDecimal getValue() {
		return value;
	}

	/**
	 * 
	 * @param value
	 *            The value
	 */
	public void setValue(BigDecimal value) {
		this.value = value;
	}

	public Balance withValue(BigDecimal value) {
		this.value = value;
		return this;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(currency).append(issuer).append(value).toHashCode();
	}

	@Override
	public boolean equals(Object other) {
		if (other == this) {
			return true;
		}
		if ((other instanceof Balance) == false) {
			return false;
		}
		Balance rhs = ((Balance) other);
		return new EqualsBuilder().append(currency, rhs.currency).append(issuer, rhs.issuer).append(value, rhs.value).isEquals();
	}

} public class BalanceAdapter extends TypeAdapter<Balance> {

	@Override
	public void write(JsonWriter out, Balance balance) throws IOException {
		if(balance==null||balance.getCurrency()==null){
			out.nullValue();
		}else if("STR".equals(balance.getCurrency())||balance.getCurrency()==null||balance.getIssuer()==null){
			out.value(balance.getValue().toPlainString());
		}else{
			out.beginObject();
			out.name("currency");
			out.value(balance.getCurrency());
			out.name("issuer");
			out.value(balance.getIssuer());
			out.name("value");
			out.value(balance.getValue().toPlainString());
			out.endObject();
		}
	}

	@Override
	public Balance read(JsonReader reader) throws IOException {
		if (reader.peek() == JsonToken.NULL) {
			reader.nextNull();
			return null;
		} else if (reader.peek() == JsonToken.STRING) {
			String amt = reader.nextString();
			Balance balance = new Balance().withCurrency("STR").withValue(new BigDecimal(amt));
			return balance;
		}else if (reader.peek() == JsonToken.BEGIN_OBJECT) {
			reader.beginObject();
			Balance balance = new Balance();
			while(reader.hasNext()){
				String name = reader.nextName();
				String val = reader.nextString();
				switch(name){
				case "currency":
					balance.setCurrency(val);
					break;
				case "issuer":
					balance.setIssuer(val);
					break;
				case "value":
					balance.setValue(new BigDecimal(val));
					break;
				}
			}
			reader.endObject();
			return balance;
		}
		throw new IOException();
	}

} @Generated("org.jsonschema2pojo")
public class Amount {

    @Expose
    private String currency;
    @Expose
    private String issuer;
    @Expose
    private BigDecimal value;

    /**
     * 
     * @return
     *     The currency
     */
    public String getCurrency() {
        return currency;
    }

    /**
     * 
     * @param currency
     *     The currency
     */
    public void setCurrency(String currency) {
        this.currency = currency;
    }

    public Amount withCurrency(String currency) {
        this.currency = currency;
        return this;
    }

    /**
     * 
     * @return
     *     The issuer
     */
    public String getIssuer() {
        return issuer;
    }

    /**
     * 
     * @param issuer
     *     The issuer
     */
    public void setIssuer(String issuer) {
        this.issuer = issuer;
    }

    public Amount withIssuer(String issuer) {
        this.issuer = issuer;
        return this;
    }

    /**
     * 
     * @return
     *     The value
     */
    public BigDecimal getValue() {
        return value;
    }

    /**
     * 
     * @param value
     *     The value
     */
    public void setValue(BigDecimal value) {
        this.value = value;
    }

    public Amount withValue(BigDecimal value) {
        this.value = value;
        return this;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(currency).append(issuer).append(value).toHashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if ((other instanceof Amount) == false) {
            return false;
        }
        Amount rhs = ((Amount) other);
        return new EqualsBuilder().append(currency, rhs.currency).append(issuer, rhs.issuer).append(value, rhs.value).isEquals();
    }

} public class AmountAdapter extends TypeAdapter<Amount> {

	@Override
	public void write(JsonWriter out, Amount amount) throws IOException {
		if(amount==null||amount.getCurrency()==null){
			out.nullValue();
		}else if("STR".equals(amount.getCurrency())||amount.getCurrency()==null||amount.getIssuer()==null){
			out.value(amount.getValue().toPlainString());
		}else{
			out.beginObject();
			out.name("currency");
			out.value(amount.getCurrency());
			out.name("issuer");
			out.value(amount.getIssuer());
			out.name("value");
			out.value(amount.getValue().toPlainString());
			out.endObject();
		}
	}

	@Override
	public Amount read(JsonReader reader) throws IOException {
		if (reader.peek() == JsonToken.NULL) {
			reader.nextNull();
			return null;
		} else if (reader.peek() == JsonToken.STRING) {
			String amt = reader.nextString();
			Amount amount = new Amount().withCurrency("STR").withValue(new BigDecimal(amt));
			return amount;
		}else if (reader.peek() == JsonToken.BEGIN_OBJECT) {
			reader.beginObject();
			Amount amount = new Amount();
			while(reader.hasNext()){
				String name = reader.nextName();
				String val = reader.nextString();
				switch(name){
				case "currency":
					amount.setCurrency(val);
					break;
				case "issuer":
					amount.setIssuer(val);
					break;
				case "value":
					amount.setValue(new BigDecimal(val));
					break;
				}
			}
			reader.endObject();
			return amount;
		}
		throw new IOException();
	}

} @Generated("org.jsonschema2pojo")
public class Tx {

	@Expose
	@Valid
	private Result result;

	/**
	 * 
	 * @return The result
	 */
	public Result getResult() {
		return result;
	}

	/**
	 * 
	 * @param result
	 *            The result
	 */
	public void setResult(Result result) {
		this.result = result;
	}

	public Tx withResult(Result result) {
		this.result = result;
		return this;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(result).toHashCode();
	}

	@Override
	public boolean equals(Object other) {
		if (other == this) {
			return true;
		}
		if ((other instanceof Tx) == false) {
			return false;
		}
		Tx rhs = ((Tx) other);
		return new EqualsBuilder().append(result, rhs.result).isEquals();
	}

}
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.util.Arrays;
import javax.xml.bind.DatatypeConverter;
import jstellarapi.core.StellarAddress;
import jstellarapi.core.StellarEngineException;
import jstellarapi.core.StellarPaymentTransaction;
import jstellarapi.core.StellarSeedAddress;
import jstellarapi.ds.account.tx.AccountTx;
import jstellarapi.ds.account.tx.Balance;
import jstellarapi.ds.account.tx.BalanceAdapter;
import jstellarapi.ds.tx.Amount;
import jstellarapi.ds.tx.AmountAdapter;
import jstellarapi.ds.tx.Tx;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.google.gson.GsonBuilder;
package jstellarapi.connection;






/**
 * This class should use only http POST/GET, not the websocket. For small
 * operations, (submit a TX), this could be faster than setting up a websocket
 * connection.
 *
 * @author pmarches
 */
@SuppressWarnings("unchecked")
public class StellarDaemonRPCConnection extends StellarDaemonConnection {
	protected URI stellarDaemonURI;
	public static URI STELLAR_RPC_URI = URI.create("http://test.stellar.org:9002");

	public StellarDaemonRPCConnection(URI StellarDaemonURI){
		this.stellarDaemonURI = StellarDaemonURI;
	}

	public StellarDaemonRPCConnection(){
		this(StellarDaemonRPCConnection.STELLAR_RPC_URI);
	}

	public StellarPaymentTransaction submitTransaction(byte[] signedTransactionBytes) throws Exception {
		return submitTransaction(DatatypeConverter.printHexBinary(signedTransactionBytes));
	}

	public StellarPaymentTransaction submitTransaction(String tx_blob) throws Exception {
		JSONObject txBlob = new JSONObject();
		txBlob.put("tx_blob", tx_blob);
		JSONObject command = createJSONCommand("submit", txBlob);
		JSONObject response = executeJSONCommand(command);

		JSONObject result = (JSONObject) response.get("result");
		if ((Long) result.get("engine_result_code") != 0) {
			throw new StellarEngineException((String) result.get("engine_result"), (Long) result.get("engine_result_code"), (String) result.get("engine_result_message"));
		}
		StellarPaymentTransaction txToSign = new StellarPaymentTransaction(null, null, null, 0);
		txToSign.copyFrom(result);
		return txToSign;
	}

	protected JSONObject createJSONCommand(String commandName, JSONObject... parameterObjects) {
		JSONObject command = new JSONObject();
		command.put("method", commandName);
		JSONArray parameterArray = new JSONArray();
		command.put("params", parameterArray);
		parameterArray.addAll(Arrays.asList(parameterObjects));
		return command;
	}

	protected JSONObject executeJSONCommand(JSONObject command) throws Exception {
		String jsonString = command.toJSONString();

		HttpURLConnection connection = (HttpURLConnection) stellarDaemonURI.toURL().openConnection();
		connection.setUseCaches(false);
		connection.setRequestProperty("Content-Length", "" + jsonString.length());
		connection.setRequestMethod("POST");
		connection.setDoOutput(true);

		OutputStream os = connection.getOutputStream();
		os.write(jsonString.getBytes());
		os.close();

		try {
			// TODO The response handling is probably common between the
			// websocket and the RPC
			InputStream is = connection.getInputStream();
			BufferedReader rd = new BufferedReader(new InputStreamReader(is));
			JSONObject response = (JSONObject) new JSONParser().parse(rd);
			rd.close();
			return response;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public StellarAddressPublicInformation getPublicInformation(StellarAddress StellarAddress) throws Exception {
		JSONObject account = new JSONObject();
		account.put("account", StellarAddress.toString());
		JSONObject command = createJSONCommand("account_info", account);
		JSONObject response = executeJSONCommand(command);
		StellarAddressPublicInformation info = new StellarAddressPublicInformation();
		info.copyFrom((JSONObject) response.get("result"));
		return info;
	}

	public TrustLines getTrustLines(StellarAddress StellarAddress) throws Exception {
		JSONObject account = new JSONObject();
		account.put("account", StellarAddress.toString());
		JSONObject command = createJSONCommand("account_lines", account);
		JSONObject response = executeJSONCommand(command);
		TrustLines info = new TrustLines();
		info.copyFrom((JSONObject) response.get("result"));
		return info;
	}

	public AccountTx getAccountTx(StellarAddress StellarAddress) throws Exception {