From c2b46e4b0a93ac521a72f74b87efbc526776d8db Mon Sep 17 00:00:00 2001 From: "Nelson R. Perez" Date: Tue, 29 Nov 2016 12:23:18 -0500 Subject: [PATCH] Adding support to invoice generation --- .../com/luminiasoft/bitshares/Invoice.java | 64 ++++++++++++++++ .../java/com/luminiasoft/bitshares/Main.java | 6 +- .../java/com/luminiasoft/bitshares/Test.java | 19 +++++ .../java/com/luminiasoft/bitshares/Util.java | 75 ++++++++++++++++++- 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/luminiasoft/bitshares/Invoice.java diff --git a/src/main/java/com/luminiasoft/bitshares/Invoice.java b/src/main/java/com/luminiasoft/bitshares/Invoice.java new file mode 100644 index 0000000..c391a1a --- /dev/null +++ b/src/main/java/com/luminiasoft/bitshares/Invoice.java @@ -0,0 +1,64 @@ +package com.luminiasoft.bitshares; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.luminiasoft.bitshares.interfaces.JsonSerializable; +import org.bitcoinj.core.Base58; + +/** + * Class used to handle invoice generation, compression and QR-Code data derivation, + * as detailed in this link. + * @author Nelson R. PĂ©rez + */ +public class Invoice implements JsonSerializable { + public static class LineItem { + private String label; + private int quantity; + private String price; + + public LineItem(String label, int quantity, String price){ + this.label = label; + this.quantity = quantity; + this.price = price; + } + } + private String to; + private String to_label; + private String memo; + private String currency; + private LineItem[] line_items; + private String note; + private String callback; + + public Invoice(String to, String to_label, String memo, String currency, LineItem[] items, String note, String callback){ + this.to = to; + this.to_label = to_label; + this.memo = memo; + this.currency = currency; + this.line_items = items; + this.note = note; + this.callback = callback; + } + + @Override + public String toJsonString() { + Gson gson = new Gson(); + return gson.toJson(this); + } + + @Override + public JsonElement toJsonObject() { + return null; + } + + public static String toQrCode(Invoice invoice){ + String json = invoice.toJsonString(); + return Base58.encode(Util.compress(json.getBytes())); + } + + public static Invoice fromQrCode(String encoded){ + String json = new String(Util.decompress(Base58.decode(encoded))); + Gson gson = new Gson(); + return gson.fromJson(json, Invoice.class); + } +} diff --git a/src/main/java/com/luminiasoft/bitshares/Main.java b/src/main/java/com/luminiasoft/bitshares/Main.java index 42d31e7..0652be7 100644 --- a/src/main/java/com/luminiasoft/bitshares/Main.java +++ b/src/main/java/com/luminiasoft/bitshares/Main.java @@ -72,10 +72,14 @@ public class Main { // test.testBip39Opertion(); - test.testAccountNamebyAddress(); +// test.testAccountNamebyAddress(); // test.testAccountNameById(); // test.testRelativeAccountHistory(); + + test.testingInvoiceGeneration(); + +// test.testCompression(); } } diff --git a/src/main/java/com/luminiasoft/bitshares/Test.java b/src/main/java/com/luminiasoft/bitshares/Test.java index 588a103..d54a83e 100644 --- a/src/main/java/com/luminiasoft/bitshares/Test.java +++ b/src/main/java/com/luminiasoft/bitshares/Test.java @@ -705,4 +705,23 @@ public class Test { System.out.println("NoSuchAlgorithmException. Msg: " + e.getMessage()); } } + + public void testingInvoiceGeneration(){ + Invoice.LineItem[] lineItem = new Invoice.LineItem[] { new Invoice.LineItem("Apples", 2, "20 CSD")}; + Invoice invoice = new Invoice("bilthon-83", "Bilthon's store", "Invoice #12", "BTS", lineItem, "Thank you", ""); + String qrCodeData = Invoice.toQrCode(invoice); + System.out.println("qrCodeData"); + System.out.println(qrCodeData); + Invoice recovered = Invoice.fromQrCode(qrCodeData); + System.out.println("recovered invoice: "+recovered.toJsonString()); + } + + public void testCompression(){ + String test = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + System.out.println("to compress"); + System.out.println(Util.bytesToHex(test.getBytes())); + byte[] compressed = Util.compress(test.getBytes()); + System.out.println("compressed"); + System.out.println(Util.bytesToHex(compressed)); + } } diff --git a/src/main/java/com/luminiasoft/bitshares/Util.java b/src/main/java/com/luminiasoft/bitshares/Util.java index 635cb16..c423673 100644 --- a/src/main/java/com/luminiasoft/bitshares/Util.java +++ b/src/main/java/com/luminiasoft/bitshares/Util.java @@ -1,7 +1,17 @@ package com.luminiasoft.bitshares; +import org.tukaani.xz.LZMA2Options; +import org.tukaani.xz.LZMAInputStream; +import org.tukaani.xz.LZMAOutputStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + /** - * Created by nelson on 11/8/16. + * Class used to encapsulate common utility methods */ public class Util { final private static char[] hexArray = "0123456789abcdef".toCharArray(); @@ -25,4 +35,67 @@ public class Util { } return new String(hexChars); } + + /** + * Utility function that compresses data using the LZMA algorithm. + * @param inputBytes Input bytes of the data to be compressed. + * @return Compressed data + * @author Henry Varona + */ + public static byte[] compress(byte[] inputBytes) { + LZMAOutputStream out = null; + try { + ByteArrayInputStream input = new ByteArrayInputStream(inputBytes); + ByteArrayOutputStream output = new ByteArrayOutputStream(2048); + LZMA2Options options = new LZMA2Options(); + out = new LZMAOutputStream(output, options,-1); + byte[] buf = new byte[inputBytes.length]; + int size; + while ((size = input.read(buf)) != -1) { + out.write(buf, 0, size); + } + out.finish(); + return output.toByteArray(); + } catch (IOException ex) { + Logger.getLogger(FileBin.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + out.close(); + } catch (IOException ex) { + Logger.getLogger(FileBin.class.getName()).log(Level.SEVERE, null, ex); + } + } + return null; + } + + /** + * Utility function that decompresses data that has been compressed using the LZMA algorithm + * by the {@link Util#compress(byte[])} method. + * @param inputBytes Compressed data + * @return Uncompressed data + * @author Henry Varona + */ + public static byte[] decompress(byte[] inputBytes) { + LZMAInputStream in = null; + try { + ByteArrayInputStream input = new ByteArrayInputStream(inputBytes); + ByteArrayOutputStream output = new ByteArrayOutputStream(2048); + in = new LZMAInputStream(input); + int size; + while ((size = in.read()) != -1) { + output.write(size); + } + in.close(); + return output.toByteArray(); + } catch (IOException ex) { + Logger.getLogger(FileBin.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + in.close(); + } catch (IOException ex) { + Logger.getLogger(FileBin.class.getName()).log(Level.SEVERE, null, ex); + } + } + return null; + } }