List HCX in your Exchange

HCX Send/Receive tutorial

To list HCX to your exchange you need to build two HCNet services as mentioned below and all the code snippets are given in the appendix section.Most importantly you have to add hashcash-sdk.jar with your project and you can download it from the below link. This jar is required to build HCX related code in your project.

https://github.com/HashCash-Consultants/java-hashcash-sdk/releases

For Maven Project

Also you can add this java-hashcash-sdk dependencies on your project. Use jitpack.io 's Maven repository:

  • < repositories >
  •   < repository >
  •      < id > jitpack.io </ id >
  •      < url > https://jitpack.io </url >
  •   < /repository >
  • < /repositories >
  • < dependencies >
  •   < dependency >
  •      < groupId > com.github.HashCash-Consultants </groupId >
  •      < artifactId > java-hashcash-sdk </artifactId >
  •      < version >v0.37.2 </version >
  •   < /dependency> >
  • < /dependencies >

The list of versions to install can be found in the Releases section. More information can be found in jitpack.io docs.

1.HCNet Services

a.getBalance:- For balance check. (Please Review Appendix (a)).

b.sendHCX:- For HCX send. (Please Review Appendix (b))

2.Pool Account Management

Before jumping into implementation we shall know what is a pool account and why it is needed?

Pool account is an account which holds all HCX balances of your customers. When somebody wants to transfer HCX from his address to another, the pool account is going to send on behalf of that customer. When sending HCX to somebody you should ask about MemoId which we have seen in our sendHCX service API. Similarly when your pool account receives HCX from others you have to give your Memoid. Because every customer has the same pool account we can differentiate the customers using MemoId. Now how do we create a poll account and all let's discuss below.

You need to create a HCX Pool Account for your exchange. You can do this by using the HCX accountviewer link as given below.

https://www.hashcashconsultants.com/developers-sign-in

In that portal you need to generate HCX key by hitting the Generate button, after that you will get HCX Private Key which starts with S….. and HCX Public Key which starts with G… Then you can sign in that portal by your private key. Till now your address has not been activated. To activate this please go through the paragraph below.

Only you would hold the private key of this Pool Account. You can fund this Pool Account by either buying HCX from another exchange or requesting us to send HCX to your Pool Account. You can buy HCX by registering an account on PayBito exchange hosted at https://trade.paybito.com. If you have bought HCX at PayBito or another exchange, you will need to transfer the HCX from that exchange's account to your Pool Account address. You can create any number of accounts by using HCX accountviewer and transfer funds between them using sendHCX service (you only need one Pool Account for integrating HCX to your exchange).

Note:- Please do remember to activate the HCX address 20 HCX is required. After that you have to deposit more HCX to send/receive as per your requirement.

3.HCX Notifier

HCXNotifier notifies you when a payment is being received by your exchange pool HCX address. Mainly its job is to listen to all deposit transactions. After receiving funds by your pool account you need to identify for which customer it has received. So you can easily identify it by MemoId which needs to be sent during sendHCX API call. So in this case MemoId represents to customerid or any reference to identify your customer. After identifying Memo id you need to update customer balance. Regarding this you may have a customer table and hopefully payment_history table. In this demo we will record all receiving transactions into a table called customer_HCX_tables and this table contains address,amount,memo,transactionhash columns and when row is inserted into this table one trigger will fire to update customer balance and payment_history table. (Please review appendix C)

Appendix

HCNet Services

You can use the below code to build up HCNet services. To get hashcash-sdk.jar, use the link below and add this jar to your project.

(a) getBalance(Below code snippet shows how to check balance of a HCX address)

  • static public HCXResponse getBalance(String pubkey) {
  • HCXResponse hcxResponse = new HCXResponse();
  • try {
  • Server server = new Server(" https://aurora.hashcashconsultants.com "); // Here
  • Server URL Aurora of HCX
  • AccountResponse accountResponse = server.accounts().account(pubkey);
  • for (AccountResponse.Balance balance : accountResponse.getBalances()) {
  • if (balance.getAssetType().equalsIgnoreCase("native")) {
  • hcxResponse.setBalance(balance.getBalance());
  • hcxResponse.setMessage("Balance Found");
  • hcxResponse.setStatuscode("1");
  • }
  • }
  • } catch (Exception e) {
  • System.out.println("Exception in getBalance:");
  • hcxResponse.setMessage("Error");
  • hcxResponse.setStatuscode("0");
  • e.printStackTrace();
  • }
  • return hcxResponse;
  • }
You can take a reference of below JSON to build up a getBalance api(REST API) .

yourserver:port/getBalance

  • Request Param:-
  • {
  • "pubkey":"GAAYNMBGSXBYYTDVM4TYDWN26E2N5BZ4BWBM4BCSNRC3KFDANPC6DCQR"
  • }
  • Response:-
  • {
  • "balance": "31.9999900", //balance may change in your case
  • "message": "Balance Found",
  • "statuscode": "1"
  • }
(b) sendHCX (Below code snippet shows how to send HCX from one address to other)
  • static void fundTransfer(String fromprivkey, String pubkey, String amount) {
  • Network network = new Network(“HCX MainNet”);
  • Server server = new Server(" https://aurora.hashcashconsultants.com ");
  • KeyPair source = KeyPair.fromSecretSeed(fromprivkey);
  • KeyPair destination = KeyPair.fromAccountId(pubkey);
  • try {
  • AccountResponse sourceAccount =
  • server.accounts().account(source.getAccountId());
  • Transaction transaction = new TransactionBuilder(sourceAccount,
  • network).addOperation(
  • new PaymentOperation.Builder(destination.getAccountId(), new AssetTypeNative(),
  • amount).build())
  • .addMemo(Memo.text("Fund Transfer"))
  • .setTimeout(5000).setBaseFee(Transaction.MIN_BASE_FEE).build();
  • transaction.sign(source);
  • SubmitTransactionResponse tranresponse =
  • server.submitTransaction(transaction);
  • System.out.println(tranresponse.getHash());
  • if (tranresponse.isSuccess()) {
  • System.out.println("Fund transfer successful.." + tranresponse.getHash());
  • } else {
  • System.out.println(tranresponse.getExtras().getResultCodes().getTransactionResul
  • tCode());
  • System.out.println(tranresponse.getExtras().getResultCodes().getOperationsResult
  • Codes().get(0));
  • }
  • } catch (IOException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • } catch (AccountRequiresMemoException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • }

Note:- Above code does the send transaction and if the receiving HCX address is not being activated then you might get an error if your sending amount is less than 20. To activate the address send at least 20 HCX to the receiving address. After that send transaction can happen as usual. You may ignore the memo when your pool account is going to receive the payment for the first time. After that when send/receive will originate from that pool account then you have to specify a memo(as customer reference).

You can take a reference from below JSON request and response, how to create sendHCX api.

You can take a reference from below JSON request and response, how to create sendHCX api.

yourserver:port/sendHcx

  • Request Param:-
  • {
  • "hcxprivkey":"SD……….Y", ---->This is the sender privkey, usually exchange put their poll address
  • "hcxpubkey":"G………...S", ------>This is the receiving address
  • "Amount":"20" -------->This is the sending HCX amount.
  • }
  • And response you may use below reference.
  • {
  • "message": "HCX Sent Successfully",
  • "statuscode": "1",
  • "hash": "8f721c9c63b94c676cbb38077b724ff4fed45c77a109600328c679e086f11ad9"
  • }
C. HCX Notifier:--

This project is having three .java classes as below and all are the code snippets only.

DaoImpl.Java:-

It is basically DB layer and inserts data into table.( let's say customer_HCX_details table which we have discussed earlier)

  • @Component
  • public class DaoImpl implements IDao {
  • @Autowired
  • JdbcTemplate template;
  • @Autowired
  • Environment env;
  • @Override
  • public boolean insertToken(String address, String amount, String memo,String
  • hash, int currency_id) {
  • String query = "insert into " + env.getProperty("hcxtable") + "
  • (PUBLIC_KEY,AMOUNT,MEMO,TXNHASH,CURRENCY_ID) values(?,?,?,?,?)"
  • int r = template.update(query, address, amount, memo, hash, currency_id);
  • if (r > 0) {
  • return true;
  • }
  • return false;
  • }
  • }
ServiceImpl .java

This class stores the address cursor into a file. Because if your app server has some problem and unfortunately in that period your pool address received some HCXs. So we need to start notification from the last cursor only.

  • @Service
  • public class ServiceImpl {
  • @Autowired
  • Environment env;
  • @Autowired
  • RestTemplate template;
  • @PostConstruct
  • public void getToken() {
  • try {
  • Path path = Paths.get(env.getProperty("filepath"));
  • //String token = Files.readAllLines(path).get(0);
  • List <String > s=Files.readAllLines(path);
  • if (s.size()==0) {
  • String url = env.getProperty("aurora") + "/accounts/" +
  • env.getProperty("hcxpoolaccount")
  • + "/payments?order=desc";
  • System.out.println(url);
  • String result = template.getForObject(url, String.class);
  • System.out.println(" ");
  • String finalJSON = result.toString();
  • JSONObject jsonObject = new JSONObject(finalJSON);
  • JSONObject jsonObject1 = jsonObject.getJSONObject("_links");
  • JSONObject jsonObject2 = jsonObject1.getJSONObject("prev");
  • String next = jsonObject2.getString("href");
  • System.out.println(next);
  • StringTokenizer stringTokenizer = new StringTokenizer(next, "= \u0026");
  • String[] tokens = new String[6];
  • while (stringTokenizer.hasMoreTokens()) {
  • for (int i = 0; i < tokens.length; i++) {
  • tokens[i] = stringTokenizer.nextToken();
  • }
  • }
  • String tokenid = tokens[1];
  • System.out.println("Your Operation Id = " + tokenid);
  • Files.write(Paths.get(env.getProperty("filepath")), tokenid.getBytes())
  • } else {
  • System.out.println("Token already exists.");
  • }
  • } catch (IOException e) {
  • // TODO Auto-generated catch block
  • e.printStackTrace();
  • }
  • }
  • }
HcxnotificationApplication .java

This class is the main class which notifies when to receive a payment and identify the customer by MemoId and insert the record into hcx_received_table ( any name you can give) table and update the pagingtoken.txt file by latest cursor.

  • @SpringBootApplication
  • public class HcxnotificationApplication {
  • @Autowired
  • DaoImpl daoImpl;
  • @Autowired
  • Environment env;
  • String cursor = null;
  • public static void main(String[] args) {
  • SpringApplication.run(HcxnotificationApplication.class, args);
  • }
  • @PostConstruct
  • void started() {
  • TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
  • }
  • @Bean
  • public RestTemplate getRestTemplate(){
  • return new RestTemplate();
  • @Bean
  • public void myNotification() {
  • try {
  • Path path = Paths.get(env.getProperty("filepath"));
  • cursor = Files.readAllLines(path).get(0);
  • KeyPair pair = KeyPair.fromAccountId(env.getProperty("hcxpoolaccount"));
  • Server server = new Server(env.getProperty("aurora"));
  • server.payments().cursor(cursor).forAccount(pair.getAccountId()).stream(new
  • EventListener() {
  • @Override
  • public void onFailure(Optional error, Optional
  • responseCode) {
  • // TODO Auto-generated method stub
  • }
  • @Override
  • public void onEvent(OperationResponse payment) {
  • if (payment instanceof PaymentOperationResponse) {
  • try {
  • String c = null;
  • System.out.println("Paging Token.." + payment.getPagingToken());
  • Files.write(Paths.get(env.getProperty("filepath")),
  • payment.getPagingToken().getBytes());
  • Path path = Paths.get(env.getProperty("filepath")); cursor =
  • Files.readAllLines(path).get(0);
  • String senderkeypair = ((PaymentOperationResponse) payment).getFrom()
  • String sender = senderkeypair;
  • if (sender.equals(env.getProperty("hcxpoolaccount"))) {
  • System.out.println("Now Poolaccount is sending");
  • }
  • else {
  • String from = ((PaymentOperationResponse) payment).getFrom();
  • String to = ((PaymentOperationResponse) payment).getTo();
  • System.out.println("Sender.." + from);
  • String receiver = to;
  • System.out.println("Receiver.." + receiver);
  • System.out.println(payment.getCreatedAt());
  • String amount = ((PaymentOperationResponse) payment).getAmount();
  • String hash = payment.getTransactionHash(); System.out.println("Amount:" +
  • amount + "hash " + hash);
  • String hashurl = env.getProperty("aurora") + "/transactions/" + hash;
  • RestTemplate restTemplate = new RestTemplate();
  • String result = restTemplate.getForObject(hashurl, String.class);
  • JSONObject jsonObject = new JSONObject(result.toString());
  • String memo = jsonObject.getString("memo");
  • System.out.println("Memo.." + memo);
  • boolean flag = daoImpl.insertToken(env.getProperty("hcxpoolaccount"), amount,
  • memo, hash, Integer.parseInt(env.getProperty("currencyid")));
  • if (flag == true) { System.out.println("Recored Inserted");
  • } else { System.out.println("Error");
  • }
  • }
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • }
  • }
  • });
  • } catch (Exception e) {
  • e.printStackTrace();
  • }
  • }

Note: In our above HCX Notifier code , we can say your exchange pool account receives HCX then identifies sender address,receiver address,transactional hash,timestamp,deposit amount,memo id. After that it will insert the respective details into a table and you can create a trigger or if you have some better option to update the customer balance or your payment history table if any.