Friday 12 April 2019

Block Chain: Create a wallet and transfer coins from one wallet to other in Java

This is continuation to my previous post. Before reading this tutorial, I would recommend you to go through my previous post 'Create simple Block chain using java'.

In this tutorial, you are going to learn,
         a. How to create a wallet
         b. How to transfer money to other wallet using block chain
        
To give a persona, Bob, Alice and John are three users, want to use buka block chain to transfer 'buka' coins.

a. Bob wants to send 100 buka coins to Alice
b. John wants to send 50 buka coins to Alice

How to create a wallet?
To transfer/receive the coins, you should have a wallet. Each wallet has unique address to receive the coins from other users.

Let's create our Wallet first.

public class Wallet {
         private PrivateKey privateKey;
         private PublicKey publicKey;
         ....
         ....
}

‘publicKey’ represents the wallet address, if User X wants to send N coins to User Y, then X send coins to Y wallet public key. For our 'buka' coin, public key of the wallet acts as address. User can share this public key to other users to receive the payment.

‘privateKey’ is used to sign the transactions(Do not share wallet private key).

How to transfer money to other wallet using block chain?
Procedure looks like below.
A.   Users Bob, Alice, and John create their own wallets from ‘Buka’ block chain.
Wallet bobWallet = bukaChainGenerator.newWallet();
Wallet aliceWallet = bukaChainGenerator.newWallet();
Wallet johnWallet = bukaChainGenerator.newWallet();

B.   If user Bob wants to send 100 ‘buka’ coins to Alice, then bob creates a transaction, that contains bobs address (Bob public key), Alice address (Alice public key), amount to transfer, time stamp.


Bob signs the transaction and submit this transaction to ‘Buka’ block chain.

public boolean sendMoney(PublicKey destinationAddress, double amount) throws Exception {

 Transaction transaction = TransactionGenerator.createTransaction(this.publicKey, destinationAddress, amount);

 byte[] signature = SignatureUtil.getSignature(transaction, this.privateKey, Constants.ALGORITHM_TO_SIGN);
 transaction.setDigitalSignature(signature);

 blockChainGenerator.submitTransaction(transaction, Constants.ALGORITHM_TO_SIGN);

 return true;
}


c. ‘Buka’ block chain verifies the signature of the transaction and checks whether Bob really has the amount in his wallet to transfer or not (right now this validation is not implemented). If validation succeeds, then it creates a new block with this transactional data.

public void createNewBlock(Transaction transactionalData) {
 Block<Transaction> block = new Block<>();
 block.setTransactionalData(transactionalData);
 block.setPreviousBlockHashCode(lastBlock.getHashCode());
 lastBlock.setNextBlock(block);
 lastBlock = block;

 HashUtil.setHashCode(block);
}

Find the below working application.


Constants.java
package com.sample.app.constants;

public class Constants {

 public static final String ALGORITHM_TO_GENERATE_KEY_PAIR = "RSA";
 public static final String ALGORITHM_TO_SIGN = "SHA256withRSA";
}


Block.java
package com.sample.app.model;

import com.google.gson.annotations.Expose;

public class Block<T> {

 @Expose
 private String hashCode;
 @Expose
 private String previousBlockHashCode;
 @Expose
 private T transactionalData;
 @Expose
 private long timeStamp;

 @Expose
 private Block<T> nextBlock;

 public String getHashCode() {
  return hashCode;
 }

 public void setHashCode(String hashCode) {
  this.hashCode = hashCode;
 }

 public String getPreviousBlockHashCode() {
  return previousBlockHashCode;
 }

 public void setPreviousBlockHashCode(String previousBlockHashCode) {
  this.previousBlockHashCode = previousBlockHashCode;
 }

 public T getTransactionalData() {
  return transactionalData;
 }

 public void setTransactionalData(T transactionalData) {
  this.transactionalData = transactionalData;
 }

 public long getTimeStamp() {
  return timeStamp;
 }

 public void setTimeStamp(long timeStamp) {
  this.timeStamp = timeStamp;
 }

 public Block<T> getNextBlock() {
  return nextBlock;
 }

 public void setNextBlock(Block<T> nextBlock) {
  this.nextBlock = nextBlock;
 }

}


Transaction.java
package com.sample.app.model;

import java.security.PublicKey;
import java.util.Date;

import com.google.gson.annotations.Expose;
import com.sample.app.util.StringUtil;

public class Transaction {

 @Expose
 private String id;
 private PublicKey sourceAddress;
 private PublicKey destinationAddress;

 @Expose
 private double amountTransferred;
 private byte[] digitalSignature;
 @Expose
 private String signature; // It is string representation of digitalSignature

 @Expose
 private long transactionCreatedTime;

 @Expose
 private String sourceWalletAddress; // String representation of sourceAddress
 @Expose
 private String destinationWalletAddress; // String representation of destinationAddress

 public Transaction() {
  Date date = new Date();
  this.transactionCreatedTime = date.getTime();
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public PublicKey getSourceAddress() {
  return sourceAddress;
 }

 public void setSourceAddress(PublicKey sourceAddress) {
  this.sourceAddress = sourceAddress;
  this.sourceWalletAddress = StringUtil.toHexString(this.sourceAddress.getEncoded());
 }

 public PublicKey getDestinationAddress() {
  return destinationAddress;
 }

 public void setDestinationAddress(PublicKey destinationAddress) {
  this.destinationAddress = destinationAddress;
  this.destinationWalletAddress = StringUtil.toHexString(this.destinationAddress.getEncoded());
 }

 public double getAmountTransferred() {
  return amountTransferred;
 }

 public void setAmountTransferred(double amountTransferred) {
  this.amountTransferred = amountTransferred;
 }

 public byte[] getDigitalSignature() {
  return digitalSignature;
 }

 public void setDigitalSignature(byte[] digitalSignature) {
  this.digitalSignature = digitalSignature;
  this.signature = StringUtil.toHexString(digitalSignature);
 }

 public long getTransactionCreatedTime() {
  return transactionCreatedTime;
 }

 public void setTransactionCreatedTime(long transactionCreatedTime) {
  this.transactionCreatedTime = transactionCreatedTime;
 }

 public String getSourceWalletAddress() {
  return this.sourceWalletAddress;
 }

 public String getDestinationWalletAddress() {
  return this.destinationWalletAddress;
 }

 public String getSignature() {
  return this.signature;
 }

 public byte[] getDataToBeSigned() {
  StringBuilder builder = new StringBuilder();

  builder.append(StringUtil.toHexString(this.sourceAddress.getEncoded()));
  builder.append(StringUtil.toHexString(this.destinationAddress.getEncoded()));
  builder.append(this.amountTransferred);
  builder.append(this.transactionCreatedTime);
  builder.append(this.id);

  return builder.toString().getBytes();
 }

 public String toString() {
  return new String(getDataToBeSigned());
 }
}


Wallet.java
package com.sample.app.model;

import java.security.PrivateKey;
import java.security.PublicKey;

import com.sample.app.constants.Constants;
import com.sample.app.generators.BlockChainGenerator;
import com.sample.app.generators.TransactionGenerator;
import com.sample.app.util.SignatureUtil;

/**
 * Wallet represents a virtual wallet where user can store crypto coins.
 * 
 * publicKey represents the wallet address, if User X wants to send N coins to
 * User Y, then X send coins to Y wallet address.
 * 
 * privateKey is used to sign the transactions. Do not share wallet private key.
 * 
 *
 */
public class Wallet {
 private PrivateKey privateKey;
 private PublicKey publicKey;
 private BlockChainGenerator blockChainGenerator;

 public PrivateKey getPrivateKey() {
  return privateKey;
 }

 public void setPrivateKey(PrivateKey privateKey) {
  this.privateKey = privateKey;
 }

 public PublicKey getPublicKey() {
  return publicKey;
 }

 public void setPublicKey(PublicKey publicKey) {
  this.publicKey = publicKey;
 }

 public BlockChainGenerator getBlockChainGenerator() {
  return blockChainGenerator;
 }

 public void setBlockChainGenerator(BlockChainGenerator blockChainGenerator) {
  this.blockChainGenerator = blockChainGenerator;
 }

 public boolean sendMoney(PublicKey destinationAddress, double amount) throws Exception {

  Transaction transaction = TransactionGenerator.createTransaction(this.publicKey, destinationAddress, amount);

  byte[] signature = SignatureUtil.getSignature(transaction, this.privateKey, Constants.ALGORITHM_TO_SIGN);
  transaction.setDigitalSignature(signature);

  blockChainGenerator.submitTransaction(transaction, Constants.ALGORITHM_TO_SIGN);

  return true;
 }

}


HashUtil.java
package com.sample.app.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

import com.sample.app.model.Block;

public class HashUtil {
 public static final char[] HEXDIGITS = "0123456789ABCDEF".toCharArray();

 private static MessageDigest getMessageDigest() {
  MessageDigest messageDigest = null;
  try {
   messageDigest = MessageDigest.getInstance("SHA-256");
   return messageDigest;
  } catch (NoSuchAlgorithmException e) {
   throw new RuntimeException(e);
  }

 }

 public static <T> void setHashCode(Block<T> block) {

  MessageDigest messageDigest = getMessageDigest();

  String hashCode = block.getPreviousBlockHashCode();

  Date date = new Date();
  block.setTimeStamp(date.getTime());
  long time = date.getTime();

  String transactionalData = block.getTransactionalData().toString();

  String finalData = hashCode + transactionalData + time;

  messageDigest.update(finalData.getBytes());

  byte[] digest = messageDigest.digest();

  block.setHashCode(StringUtil.toHexString(digest));

 }

 public static String getHash(String data) {
  MessageDigest messageDigest = getMessageDigest();
  messageDigest.update(data.getBytes());
  byte[] digest = messageDigest.digest();
  return StringUtil.toHexString(digest);
 }
}


JSONUtil.java
package com.sample.app.util;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JSONUtil {
 private static Gson gson = new Gson();
 private static Gson exclusedGson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
 private static Gson prettyGson = new GsonBuilder().setPrettyPrinting().create();

 public static String getJson(Object obj) {
  return gson.toJson(obj);
 }

 public static String getOnlyExposedJson(Object obj) {
  return exclusedGson.toJson(obj);
 }

 public static String getPrettyJson(Object obj) {
  return prettyGson.toJson(obj);
 }

 public static <T> T getObject(String json, Class<T> clazz) {
  return gson.fromJson(json, clazz);
 }

}


PublicKeyUtil.java
package com.sample.app.util;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;

public class PublicKeyUtil {
 public static KeyPair getKeyPair(String algorithm) throws NoSuchAlgorithmException {
  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
  return keyPairGenerator.generateKeyPair();
 }
}


SignatureUtil.java
package com.sample.app.util;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;

import com.sample.app.model.Transaction;

public class SignatureUtil {

 public static byte[] getSignature(Transaction transaction, PrivateKey senderPrivateKey, String algorithmToSign)
   throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
  /* Get instance of Signature object */
  Signature signature = Signature.getInstance(algorithmToSign);

  /* Initialize Signature object */
  signature.initSign(senderPrivateKey);

  /* Feed Data */
  signature.update(transaction.getDataToBeSigned());

  /* Generate signature */
  byte[] finalSig = signature.sign();

  return finalSig;
 }

 public static boolean verifySignature(Transaction transaction, PublicKey publicKey, String algorithm)
   throws Exception {
  Signature verifySignature = Signature.getInstance(algorithm);
  verifySignature.initVerify(publicKey);

  verifySignature.update(transaction.getDataToBeSigned());
  /* Verify signature */
  return verifySignature.verify(transaction.getDigitalSignature());

 }
}


StringUtil.java
package com.sample.app.util;

public class StringUtil {

 public static String toHexString(byte[] bytes) {
  StringBuilder sb = new StringBuilder(bytes.length * 3);
  for (int b : bytes) {
   b &= 0xff;
   sb.append(HashUtil.HEXDIGITS[b >> 4]);
   sb.append(HashUtil.HEXDIGITS[b & 15]);
   // sb.append(' ');
  }
  return sb.toString();
 }

 
}


BlockChainGenerator.java
package com.sample.app.generators;

import java.security.NoSuchAlgorithmException;

import com.sample.app.constants.Constants;
import com.sample.app.model.Block;
import com.sample.app.model.Transaction;
import com.sample.app.model.Wallet;
import com.sample.app.util.HashUtil;
import com.sample.app.util.JSONUtil;
import com.sample.app.util.SignatureUtil;

public class BlockChainGenerator {

 private Block<Transaction> rootBlock = null;
 private Block<Transaction> lastBlock = null;

 public void startNewBlockChain() {
  rootBlock = new Block<Transaction>();

  rootBlock.setPreviousBlockHashCode("");

  // HashUtil.update(rootBlock);

  lastBlock = rootBlock;

 }

 public void createNewBlock(Transaction transactionalData) {
  Block<Transaction> block = new Block<>();
  block.setTransactionalData(transactionalData);
  block.setPreviousBlockHashCode(lastBlock.getHashCode());
  lastBlock.setNextBlock(block);
  lastBlock = block;

  HashUtil.setHashCode(block);
 }

 public void printBlockChain() {
  System.out.println(JSONUtil.getOnlyExposedJson(rootBlock));
 }

 public boolean isChainvalid() {
  if (rootBlock == null)
   return true;

  Block<Transaction> nextBlock = rootBlock.getNextBlock();

  if (nextBlock == null)
   return true;

  Block<Transaction> currentBlock = nextBlock;
  nextBlock = currentBlock.getNextBlock();

  while (nextBlock != null) {
   if (!nextBlock.getPreviousBlockHashCode().equals(currentBlock.getHashCode())) {
    return false;
   }

   currentBlock = nextBlock;
   nextBlock = nextBlock.getNextBlock();
  }

  return true;

 }


 public boolean submitTransaction(Transaction transaction, String algorithmToSign) throws Exception {
  boolean isvalid = SignatureUtil.verifySignature(transaction, transaction.getSourceAddress(), algorithmToSign);

  if (!isvalid) {
   return false;
  }

  this.createNewBlock(transaction);
  return true;

 }

 public Wallet newWallet() throws NoSuchAlgorithmException {
  Wallet wallet = WalletGenerator.newWallet(Constants.ALGORITHM_TO_GENERATE_KEY_PAIR);
  wallet.setBlockChainGenerator(this);
  return wallet;
 }
}


TransactionGenerator.java
package com.sample.app.generators;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SignatureException;

import com.sample.app.model.Transaction;
import com.sample.app.model.Wallet;
import com.sample.app.util.HashUtil;
import com.sample.app.util.SignatureUtil;
import com.sample.app.util.StringUtil;

public class TransactionGenerator {

 public static Transaction createTransaction(PublicKey sourceAddress, PublicKey destinationAddress,
   double amountToTransfer) {
  Transaction transaction = new Transaction();

  transaction.setSourceAddress(sourceAddress);
  transaction.setDestinationAddress(destinationAddress);
  transaction.setAmountTransferred(amountToTransfer);

  String sourceAddrStr = StringUtil.toHexString(sourceAddress.getEncoded());
  String destAddrStr = StringUtil.toHexString(destinationAddress.getEncoded());

  String hashStr = sourceAddrStr + destAddrStr + transaction.getTransactionCreatedTime() + amountToTransfer;

  String id = HashUtil.getHash(hashStr);

  transaction.setId(id);

  return transaction;

 }

 public static Transaction createTransaction(Wallet senderWallet, PublicKey destinationAddress,
   double amountToTransfer, String algorithmToSign)
   throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
  Transaction transaction = createTransaction(senderWallet.getPublicKey(), destinationAddress, amountToTransfer);
  byte[] signature = SignatureUtil.getSignature(transaction, senderWallet.getPrivateKey(), algorithmToSign);
  transaction.setDigitalSignature(signature);
  return transaction;

 }

 public static Transaction canTransferBukaCoins(Wallet senderWallet, PublicKey destinationAddress,
   double coinsToTransfer, String algorithmToSign) throws Exception {
  Transaction transaction = createTransaction(senderWallet, destinationAddress, coinsToTransfer, algorithmToSign);

  boolean isvalid = SignatureUtil.verifySignature(transaction, senderWallet.getPublicKey(), algorithmToSign);

  if (isvalid) {
   return transaction;
  }

  return null;

 }
}


WalletGenerator.java
package com.sample.app.generators;

import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;

import com.sample.app.model.Wallet;
import com.sample.app.util.PublicKeyUtil;

public class WalletGenerator {

 public static Wallet newWallet(String algorithm) throws NoSuchAlgorithmException {
  Wallet wallet = new Wallet();

  KeyPair keyPair = PublicKeyUtil.getKeyPair(algorithm);
  

  wallet.setPrivateKey(keyPair.getPrivate());
  wallet.setPublicKey(keyPair.getPublic());

  return wallet;

 }

}


App.java
package com.sample.app;

import com.sample.app.generators.BlockChainGenerator;
import com.sample.app.model.Wallet;

public class App {
 public static void main(String args[]) throws Exception {

  // Start new block chain
  BlockChainGenerator bukaChainGenerator = new BlockChainGenerator();
  bukaChainGenerator.startNewBlockChain();

  // Create wallets
  Wallet bobWallet = bukaChainGenerator.newWallet();
  Wallet aliceWallet = bukaChainGenerator.newWallet();
  Wallet johnWallet = bukaChainGenerator.newWallet();

  // Bob sent 100 buka coins alice
  bobWallet.sendMoney(aliceWallet.getPublicKey(), 100);

  // John sent 50 buka coins to alice
  johnWallet.sendMoney(aliceWallet.getPublicKey(), 50);

  // Alice sent 20.76 buka coins to Bob
  aliceWallet.sendMoney(bobWallet.getPublicKey(), 20.76);

  // Print block chain, if it is valid
  if (bukaChainGenerator.isChainvalid()) {
   bukaChainGenerator.printBlockChain();
  }

 }
}


Run App.java, you can see below kind of output in console.
{
 "previousBlockHashCode": "",
 "timeStamp": 0,
 "nextBlock": {
  "hashCode": "D6EF76B13B91A6CCEC1A88B5AF69D9C5F9CA9B742E7031D28375BAE744D8C3F9",
  "transactionalData": {
   "id": "A250200EAFE9D115FD1706C6BF44CD45A7F7AB2BC45CAA16453664FD01532EBE",
   "amountTransferred": 100.0,
   "signature": "60488582D6929FE0C2E5EAC16598C40ABFF43B5F115F612A37C2E5CBFC0F8260238DEDB1D8B6000E254336EAC2F34FA36A72701F3EE77EEBAC4FCBBB96E5330D768C32BC51A7C6AFCD1F3B242DE02A5B0A2F7CA286EA4545D9E31F214ACBC35E0D0CEDDAB9C888B8E32D5D78E5C25A09C52745A234129AE1F75E08C9AFE9DEEA782C11A0E257701D8F956B63C60F5E0EDE8012CF28BC97B7DB8E880472C84774C931929712E9A48405D759D210CA13D87CF5F53294F2FCA841814FD347C3068355BD7929426EC8C4B79732D0ADBD1131930D099704A96AB03F0C9C2ACA82FA825EF69C751C719F2E3A05760C5990E4FD2FE6AC67EA9EECE2E60575C1D69F3A03",
   "transactionCreatedTime": 1555058167442,
   "sourceWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A02820101009F8216980AE9DFE731A8C99656F8A3907B5B55B39FC4E3003B6A1C74A381DB5FE585010EAECCA51E90807E79B7A0F90A3D119F9B3D4ACBB27D7D638A84B9FFC2EAB1A17038F905F6A6963F1250E104FA4EBDE9DD65090306E671BC76A2D1DF00BE6ABCD8FF92EC6BBCE603577FDF66BC7A578367A84DBF65C9A2F8FFD0185BDDD8831A6981E53F4100863655E6383662B371899645C6D539BA83DE3F408E6DC8B5AABDD6B8C5D8D702E6A832DC64B327D974433C911B1B1D5F147628E8399819F53B740BE43EB90EE12661786A2196BA3BB2055888558C7EFF31E504DDEA997D2D64F43E2E7C8B48E5D2647AE418EA48CC6A9461DD10BC3730A22AA069CC0BB70203010001",
   "destinationWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A028201010088DD5533E812C8627F78A7DCACFA5CD9F8AA4C79645EBF40DA3363E3EABD1C0452826B5276A1CBBCC687A6B95D0DE145B6A4A22465A229FD694F45A28C122042E48F3AF13524FF63D01B6DECC4D4629A459017DD43FB757D1796DF23B062A4E1D749074F0FA21C518693DBEAAAE84B5DEBA72103F38DA33B58D1C8353BAB9F29CD41F237945BFDE2E49E9AACAA3FD01BA310344A42706FAC47AA12DA61F68A3E9663E65C0F91D51817A1A0E67F9BFBF5CC9DA19ADFE5816689958B3DB6346A4A64B57C9EC0D3B3B6BC2606E55B35AC7CAE9D3C2AE588767CBF3EC3DAEC004BDB7DF82FA6C0DAB0F6D38DF393AC9D1CAE09D1D5A4C4A66B8BF48D9079EA0DF9490203010001"
  },
  "timeStamp": 1555058167450,
  "nextBlock": {
   "hashCode": "9725431A8C0D0B3442BC9B77A5A25F63D6DCB9C19931DCB8FFBCB38F0340034B",
   "previousBlockHashCode": "D6EF76B13B91A6CCEC1A88B5AF69D9C5F9CA9B742E7031D28375BAE744D8C3F9",
   "transactionalData": {
    "id": "433729572422DF6C8ECE982A2AC41C9480F83FA2231088310208F0FFD611BCE7",
    "amountTransferred": 50.0,
    "signature": "281A6B380297967A24E23B57447ED7928992C50D8129E2915F860127C41BD101BCB68A60F6D2D47DBBAC5E8C89CCF41D6F979B92406921544D21269601F4A3F60EA71485E89797E7527348EBC2AD570547EE0AA79A61361A1283A9D3FE1381D7B03E73B251D7F9F5731E3950F7C2C905180A61AF15EE0628BB832FA97FEA80400062DE0428FA3DFB0698EC7E0956A80C1523D2EA114E459CC6A8E488302418DE6878A67C2BBABA8EB8DBC41257ECC2242C3D72649B835930164E6A939C57B83BF50431B27E1F26176AFC1AE262AA8E6FDCD99D6F68939F8895D71135090CDFC9E675403801BEFBEAAC1F1BFE3D0FED470C7DDEB2C575AFAF5687F28CDCF9E5D8",
    "transactionCreatedTime": 1555058167450,
    "sourceWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A0282010100AD6E07E87133DB7ED20B5B14AD7DA145B50710CF5E0A58BE159B766D17015C288378A4D5BD00A999DA819357433F6457CC9B277014065639D9C3CDFE6BC4A4EB2426879C2C765FDDD1FFFC5FC4BB900E97B355F3E4D539D2BFB3936D9A8F48B9469DC2AA5E63F780992ADEE5719CD1F0D8B18E95EF085E8F53FF6AD79837FD148A306BA09A219A690E6A761788DF0EFE3546CE3DE57AA5172AC728374B338333033A7D8F1EA648F40BE9F50BC2DCF97B340C4A39D6A2F7B22220F0608ABC0A8AE79E12463259595FA9697223EE9F38B5AF8969EF15117EA4E02DEC0EDBCEFC6EA3EE57984E4903C00297B7A9C035720CD7620362C1E9728A1051338BDA087AAB0203010001",
    "destinationWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A028201010088DD5533E812C8627F78A7DCACFA5CD9F8AA4C79645EBF40DA3363E3EABD1C0452826B5276A1CBBCC687A6B95D0DE145B6A4A22465A229FD694F45A28C122042E48F3AF13524FF63D01B6DECC4D4629A459017DD43FB757D1796DF23B062A4E1D749074F0FA21C518693DBEAAAE84B5DEBA72103F38DA33B58D1C8353BAB9F29CD41F237945BFDE2E49E9AACAA3FD01BA310344A42706FAC47AA12DA61F68A3E9663E65C0F91D51817A1A0E67F9BFBF5CC9DA19ADFE5816689958B3DB6346A4A64B57C9EC0D3B3B6BC2606E55B35AC7CAE9D3C2AE588767CBF3EC3DAEC004BDB7DF82FA6C0DAB0F6D38DF393AC9D1CAE09D1D5A4C4A66B8BF48D9079EA0DF9490203010001"
   },
   "timeStamp": 1555058167454,
   "nextBlock": {
    "hashCode": "80C800216856D149CE0CFF8B139239875438E7C33CED86EC73C87B1FECAE2EA0",
    "previousBlockHashCode": "9725431A8C0D0B3442BC9B77A5A25F63D6DCB9C19931DCB8FFBCB38F0340034B",
    "transactionalData": {
     "id": "F3B9B65EBF6B815DCBC148471FCB7C178D7ADEE652516F4E357D2F8F05B65541",
     "amountTransferred": 20.76,
     "signature": "028826E5CBB9B352CA1B64B400B71713AAFE7A50DB8800D1DED5C02CA22402857D56EA80AA46A22071A0537A21F36AA4BCFC6BDFAE3F87B9D22129BC3336C993BE810A15F63A5798D39DDD96AB500809D689CDE5D7254BA613163960FA1AC75E683775417068F52E60F4931A37176CF536C58AC76B5A2CE137FC47D6E3C0A749B6FCB19FC0A684EC7103A1A0C9477C6F1AAB65080C5DA6FE15122842C88AC2A2C082FF1BE5C5628340031489604EF6C6C58B7C3EC10169D629E3A4D96CFA69FCD7042FB75AACA6E29DEB5636727CE8D3BF7936D01CCA0E6FEC2E742B5D94774A6B4E42CF6BC3624DDD6B1BA322171D2AE252C9DF23EE82F6293E22ABF950C427",
     "transactionCreatedTime": 1555058167454,
     "sourceWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A028201010088DD5533E812C8627F78A7DCACFA5CD9F8AA4C79645EBF40DA3363E3EABD1C0452826B5276A1CBBCC687A6B95D0DE145B6A4A22465A229FD694F45A28C122042E48F3AF13524FF63D01B6DECC4D4629A459017DD43FB757D1796DF23B062A4E1D749074F0FA21C518693DBEAAAE84B5DEBA72103F38DA33B58D1C8353BAB9F29CD41F237945BFDE2E49E9AACAA3FD01BA310344A42706FAC47AA12DA61F68A3E9663E65C0F91D51817A1A0E67F9BFBF5CC9DA19ADFE5816689958B3DB6346A4A64B57C9EC0D3B3B6BC2606E55B35AC7CAE9D3C2AE588767CBF3EC3DAEC004BDB7DF82FA6C0DAB0F6D38DF393AC9D1CAE09D1D5A4C4A66B8BF48D9079EA0DF9490203010001",
     "destinationWalletAddress": "30820122300D06092A864886F70D01010105000382010F003082010A02820101009F8216980AE9DFE731A8C99656F8A3907B5B55B39FC4E3003B6A1C74A381DB5FE585010EAECCA51E90807E79B7A0F90A3D119F9B3D4ACBB27D7D638A84B9FFC2EAB1A17038F905F6A6963F1250E104FA4EBDE9DD65090306E671BC76A2D1DF00BE6ABCD8FF92EC6BBCE603577FDF66BC7A578367A84DBF65C9A2F8FFD0185BDDD8831A6981E53F4100863655E6383662B371899645C6D539BA83DE3F408E6DC8B5AABDD6B8C5D8D702E6A832DC64B327D974433C911B1B1D5F147628E8399819F53B740BE43EB90EE12661786A2196BA3BB2055888558C7EFF31E504DDEA997D2D64F43E2E7C8B48E5D2647AE418EA48CC6A9461DD10BC3730A22AA069CC0BB70203010001"
    },
    "timeStamp": 1555058167457
   }
  }
 }
}

You can get the source code from following github location.


You may like







No comments:

Post a Comment