package jstellarapi.keys; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.math.BigInteger; import java.security.SecureRandom; import javax.xml.bind.DatatypeConverter; import jstellarapi.connection.StellarAddressPublicInformation; import jstellarapi.connection.StellarDaemonRPCConnection; import jstellarapi.core.DenominatedIssuedCurrency; import jstellarapi.core.StellarAddress; import jstellarapi.core.StellarPaymentTransaction; import jstellarapi.core.StellarSeedAddress; import jstellarapi.serialization.StellarBinaryObject; import jstellarapi.serialization.StellarBinarySerializer; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; public class StellarWallet implements Serializable { private static final long serialVersionUID = -4849034810727882329L; transient File walletFile; StellarSeedAddress seed; int nextTransactionSequenceNumber; byte[] pendingTransaction; protected StellarWallet(StellarSeedAddress seed, int nextTransactionSequenceNumber, File walletFile) throws IOException{ this.seed = seed; this.nextTransactionSequenceNumber = nextTransactionSequenceNumber; this.walletFile=walletFile; } static public StellarWallet createWallet(StellarSeedAddress seed, File walletFile) throws Exception { StellarDaemonRPCConnection conn = new StellarDaemonRPCConnection(); StellarAddressPublicInformation publicInfo = conn.getPublicInformation(seed.getPublicStellarAddress()); StellarWallet wallet = new StellarWallet(seed, (int) publicInfo.nextTransactionSequence, walletFile); wallet.saveWallet(walletFile); return wallet; } public StellarSeedAddress getSeed(){ return seed; } public StellarWallet(File walletFile) throws Exception { this.walletFile=walletFile; if(walletFile.canWrite()==false){ throw new RuntimeException("We will need to write to the wallet file"); } StellarDaemonRPCConnection conn = new StellarDaemonRPCConnection(); if(walletFile.canRead()){ JSONObject root=(JSONObject) new JSONParser().parse(new FileReader(walletFile)); seed=new StellarSeedAddress((String) root.get("master_seed")); StellarAddressPublicInformation publicInfo = conn.getPublicInformation(seed.getPublicStellarAddress()); nextTransactionSequenceNumber=(int) publicInfo.nextTransactionSequence; if(root.containsKey("pendingTransaction")){ String hexTX=(String) root.get("pendingTransaction"); pendingTransaction=DatatypeConverter.parseHexBinary(hexTX); } } } public StellarWallet() { seed=new StellarSeedAddress(new SecureRandom().generateSeed(16)); nextTransactionSequenceNumber=0; pendingTransaction=null; } /** * This is the all-in-one API, it constructs the TX, signs it, stores it, and submits it to the network * * @param STRAmount * @param payee * @throws Exception */ public void sendSTR(BigInteger STRAmount, StellarAddress payee) throws Exception{ DenominatedIssuedCurrency amount = new DenominatedIssuedCurrency(STRAmount); StellarPaymentTransaction tx = new StellarPaymentTransaction(seed.getPublicStellarAddress(), payee, amount, this.nextTransactionSequenceNumber); //TODO Compute the required fee from the server_info tx.fee=new DenominatedIssuedCurrency(new BigInteger("10")); StellarBinaryObject rbo = tx.getBinaryObject(); rbo = new StellarSigner(seed.getPrivateKey()).sign(rbo); StellarDaemonRPCConnection conn = new StellarDaemonRPCConnection(); byte[] signedTXBytes = new StellarBinarySerializer().writeBinaryObject(rbo).array(); pendingTransaction = signedTXBytes; nextTransactionSequenceNumber++; saveWallet(walletFile); conn.submitTransaction(signedTXBytes); pendingTransaction = null; saveWallet(walletFile); } @SuppressWarnings("unchecked") public void saveWallet(File saveToFile) throws IOException { JSONObject root=new JSONObject(); root.put("address", seed.getPublicStellarAddress().toString()); root.put("seed", seed.toString()); root.put("nextTransactionSequenceNumber", nextTransactionSequenceNumber); if(pendingTransaction!=null){ root.put("pendingTransaction", DatatypeConverter.printHexBinary(pendingTransaction)); } File tempWalletFile = new File(saveToFile.getAbsolutePath()+".tmp"); Writer writer=new FileWriter(tempWalletFile); root.writeJSONString(writer); writer.close(); saveToFile.delete(); tempWalletFile.renameTo(saveToFile); } }