# Exchange Integration Guide(Java)

# Installation package

  • Download Bytom Java SDK package. https://github.com/Bytom/bytom-java-sdk
  • Open Bytom-sdk-java-{version No}.zip
  • import Bytom-sdk-{version No}.jar and its related Package into Project

# Generate client

public static Client generateClient() throws BytomException {
    String coreURL = Configuration.getValue("bytom.api.url");
    String accessToken = Configuration.getValue("client.access.token");
    if (coreURL == null || coreURL.isEmpty()) {
        coreURL = "http://127.0.0.1:9888/";
    }
    return new Client(coreURL, accessToken);
}

Client client = Client.generateClient();

# Generate Address

Bytom blockchain use key - account - address model, it requires 3 steps to generate address

# Generate key

 @Test
public void testClientKeyCreate() throws Exception {
    String alias = "bob";
    String password = "123456";

    Key.Builder builder = new  Key.Builder().setAlias(alias).setPassword(password);
    Key key = Key.create(client, builder);
    System.out.println(key.toJson());
}

Return

{
    "alias":"bob",
 "xpub":"10823b3b655d76c9122315bda4aded669b3087831c7e99379338d8d8d84296658cd866211a488dc234ec1ae6bbb11e6ad0e317311610e07cb2d0d098bd5f0c95",
    "file":"/Users/doraemon/bytom/testnet/keystore/UTC--2021-07-21T06-58-38.437857000Z--18a0283e-9928-4492-9d65-0dc6ab72da70" //密钥文件地址
}

# Generate account

@Test
public void testAccountCreate() throws Exception {
    String alias = "bob";
    Integer quorum = 1; 
    List<String> root_xpubs = new ArrayList<>();
    root_xpubs.add("10823b3b655d76c9122315bda4aded669b3087831c7e99379338d8d8d84296658cd866211a488dc234ec1ae6bbb11e6ad0e317311610e07cb2d0d098bd5f0c95");

    Account.Builder builder = new Account.Builder().setAlias(alias).setQuorum(quorum).setRootXpub(root_xpubs);
    account = Account.create(client, builder);
    System.out.println(account.toJson());
}

Return:

{
    "id":"9d26066f-e1ae-4e7a-88ce-2e871962db9c",
    "alias":"bob",
    "key_index":1,
    "quorum":1,
    "xpubs":[
 "10823b3b655d76c9122315bda4aded669b3087831c7e99379338d8d8d84296658cd866211a488dc234ec1ae6bbb11e6ad0e317311610e07cb2d0d098bd5f0c95"
    ]
}

# Generate account address

@Test
public void testReceiverCreate1() throws Exception {
    String alias = "bob";
    String id = "9d26066f-e1ae-4e7a-88ce-2e871962db9c";

    Account.ReceiverBuilder receiverBuilder = new Account.ReceiverBuilder().setAccountAlias(alias).setAccountId(id);
    Receiver receiver = receiverBuilder.create(client);
    System.out.println(receiver.toJson());
}

return:

{
    "address":"bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7",
    "control_program":"0014e1caf6a1f998ab4da7c41ef7fdefcf18802de064"
}

# Verify the address

@Test
public void testAddressValidate() throws Exception {
    String alias = "bob";
    String id = "9d26066f-e1ae-4e7a-88ce-2e871962db9c";

    Account.AddressBuilder addressBuilder = new Account.AddressBuilder().setAccountId(id).setAccountAlias(alias);

    String address = "bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7";
    Account.Address accountAddress = addressBuilder.validate(client, address);
    System.out.println(accountAddress.toJson());
}

Return "true" means it's a valid address

{
    "valid":true,
    "is_local":true
}

# Asset withdrawl (Transfer asset)

Transfer asset on Bytom blockchain needs Build - Sign - Submit three steps

# Build transaction

@Test
public void testSimplePayment() throws BytomException {
    Transaction.Template payment = new Transaction.Builder()
            .addAction(new Transaction.Action.SpendFromAccount()
                .setAccountAlias("bob")
                .setAssetAlias("btm")
                .setAmount(220000000)
            ).addAction(new Transaction.Action.ControlWithAddress()
                .setAddress("bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7")
                .setAssetAlias("btm")
                .setAmount(100000000)
            ).addAction(new Transaction.Action.ControlWithAddress()
                .setAddress("bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7")
                .setAssetAlias("btm")
                .setAmount(100000000)
            ).build(client);
    System.out.println(payment.toJson());
}

Return:

{
    "raw_transaction":"070100010161015fcf9c0b3b1ccb8287fc89440a83f9bb2f965527f7e688e57589f0c23d30b8d9e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c8afa0250101160014ec4e90f8a63b2177b027250f0df76a85f70ffb5d0001000301003effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80eabbb72401160014ec4e90f8a63b2177b027250f0df76a85f70ffb5d000001003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c2d72f0116001407ddd06348cdd52c3f15f94a8a8be8c52eeebb8b000001003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c2d72f0116001496b42f069ed67d19663cc46c575f191ec022eee20000",
    "signing_instructions":[
        {
            "position":0,
            "witness_components":[
                {
                    "type":"raw_tx_signature",
                    "quorum":1,
                    "keys":[
                        {
                            "xpub":"10823b3b655d76c9122315bda4aded669b3087831c7e99379338d8d8d84296658cd866211a488dc234ec1ae6bbb11e6ad0e317311610e07cb2d0d098bd5f0c95",
                            "derivation_path":[
                                "2c000000",
                                "99000000",
                                "01000000",
                                "00000000",
                                "01000000"
                            ]
                        }
                    ]
                },
                {
                    "type":"data",
                    "value":"0bca7cecfa25cfa751867083f9dcdbd32a7915018ec94675633d312c18f499a9",
                    "quorum":0
                }
            ]
        }
    ],
    "local":false,
    "allow_additional_actions":false
}

# Sign transaction

@Test
public void testSignPayment() throws BytomException {
    Transaction.Template signedPayment = new Transaction.SignerBuilder().sign(client,payment, "123456");
    System.out.println(signedPayment.toJson());
}

Return

{
    "raw_transaction":"070100010161015fcf9c0b3b1ccb8287fc89440a83f9bb2f965527f7e688e57589f0c23d30b8d9e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c8afa0250101160014ec4e90f8a63b2177b027250f0df76a85f70ffb5d0063024071c211a8f9890e088169fd2b2b9a716df906d146d4aad03abb6b56e1fbbcc9342eb99632a5f576ee9985e0048cc358633e15cf85c21fe4a97254df4a9fc3b004200bca7cecfa25cfa751867083f9dcdbd32a7915018ec94675633d312c18f499a90301003effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80eabbb72401160014ec4e90f8a63b2177b027250f0df76a85f70ffb5d000001003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c2d72f0116001407ddd06348cdd52c3f15f94a8a8be8c52eeebb8b000001003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c2d72f0116001496b42f069ed67d19663cc46c575f191ec022eee20000",
    "signing_instructions":[
        {
            "position":0,
            "witness_components":[
                {
                    "type":"raw_tx_signature",
                    "quorum":1,
                    "keys":[
                        {
                            "xpub":"10823b3b655d76c9122315bda4aded669b3087831c7e99379338d8d8d84296658cd866211a488dc234ec1ae6bbb11e6ad0e317311610e07cb2d0d098bd5f0c95",
                            "derivation_path":[
                                "2c000000",
                                "99000000",
                                "01000000",
                                "00000000",
                                "01000000"
                            ]
                        }
                    ],
                    "signatures":[
                        "71c211a8f9890e088169fd2b2b9a716df906d146d4aad03abb6b56e1fbbcc9342eb99632a5f576ee9985e0048cc358633e15cf85c21fe4a97254df4a9fc3b004"
                    ]
                },
                {
                    "type":"data",
                    "value":"0bca7cecfa25cfa751867083f9dcdbd32a7915018ec94675633d312c18f499a9",
                    "quorum":0
                }
            ]
        }
    ],
    "local":false,
    "allow_additional_actions":false
}

# Submit transaction

@Test
public void testSubmitPayment() throws BytomException {
    Transaction.SubmitResponse resp = Transaction.submit(client, signedPayment);
    System.out.println(resp.toJson());
}

Return

{
    "tx_id":"a9d6cfb172a186040579ffd9a16cd1092e57468579faa71225d0ac76098524d1"
}

# Transaction query

@Test
public void testGetTransaction() throws Exception {
    String txID = "a9d6cfb172a186040579ffd9a16cd1092e57468579faa71225d0ac76098524d1";
    Transaction.QueryBuilder query = new Transaction.QueryBuilder();
    query.setTxId(txID);
    Transaction transaction = query.get(client);
    System.out.println(transaction.toJson());
}

Return

If there is "block_time" then it means the transaction has been put into a Block successfully.

{
    "tx_id":"a9d6cfb172a186040579ffd9a16cd1092e57468579faa71225d0ac76098524d1",
    "block_time":"1626852672000",
    "block_hash":"16a8262434b956e3d60f48c67c11449e453cb48eb98892dbd44f84c46dca2dff",
    "block_index":"1",
    "block_transactions_count":"2",
    "block_height":17209,
    "inputs":[
        {
            "account_alias":"bob",
            "account_id":"9d26066f-e1ae-4e7a-88ce-2e871962db9c",
            "address":"bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7",
            "amount":10000000000,
            "asset_alias":"BTM",
            "asset_definition":{
                "decimals":8,
                "description":"Bytom Official Issue",
                "name":"BTM",
                "symbol":"BTM"
            },
            "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "spent_output_id":"3d84ae5c0092a0188c4e4b573442d94abe5dab0a50291c8d13ad682ef1860832",
            "type":"spend",
            "control_program":"0014ec4e90f8a63b2177b027250f0df76a85f70ffb5d"
        }
    ],
    "outputs":[
        {
            "id":"eaa906f3cb88f1de0167b92f9bb8c6a00b54c3c016a4e90c9de71945e21e352f",
            "type":"control",
            "position":0,
            "control_program":"0014ec4e90f8a63b2177b027250f0df76a85f70ffb5d",
            "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "asset_alias":"BTM",
            "asset_definition":{
                "decimals":8,
                "description":"Bytom Official Issue",
                "name":"BTM",
                "symbol":"BTM"
            },
            "amount":9780000000,
            "account_alias":"bob",
            "account_id":"9d26066f-e1ae-4e7a-88ce-2e871962db9c",
            "address":"bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7"
        },
        {
            "id":"3dc12eeca931d8507a0c8b7a0ab62f8711ee3277a98f4e71727df70cdb17d3a2",
            "type":"control",
            "position":1,
            "control_program":"001407ddd06348cdd52c3f15f94a8a8be8c52eeebb8b",
            "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "asset_alias":"BTM",
            "asset_definition":{
                "decimals":8,
                "description":"Bytom Official Issue",
                "name":"BTM",
                "symbol":"BTM"
            },
            "amount":100000000,
            "account_alias":"bob",
            "account_id":"9d26066f-e1ae-4e7a-88ce-2e871962db9c",
            "address":"bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7"
        },
        {
            "id":"4078fe7930a696a1a2704969b33c6187f074c7307065bc1b7d102c1dc7db9f23",
            "type":"control",
            "position":2,
            "control_program":"001496b42f069ed67d19663cc46c575f191ec022eee2",
            "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "asset_alias":"BTM",
            "asset_definition":{
                "decimals":8,
                "description":"Bytom Official Issue",
                "name":"BTM",
                "symbol":"BTM"
            },
            "amount":100000000,
            "address":"bn1qu890dg0enz45mf7yrmmlmm70rzqzmcryuvu9p7"
        }
    ]
}

If we want make sure the Transaction cannot be reversed, we need to compare the block height info with the height in "chain-status" interface.


{
  "status": "success",
  "data": {
    "current_height": 141421,
    "current_hash": "5080d6d91e58b50e4f3542ae95983b849f4eb7cfaa1b196a1d8077217d47c9d5",
    "finalized_height": 141300,
    "finalized_hash": "0072b4497621fff3a9a1821a6365b6f65d2552c2f1749560a900746df37d7a1e",
    "justified_height": 141400,
    "justified_hash": "eb682b1ba23ad6db3b3206f87ab1b725b89951ee597695ed23cfd3a8c3a50ec1"
  }
}

justified_height Equal to 6 blocks of Bitcoin confirmation,finalized_height unless more than 2 / 3 nodes commit evil, it is never possible to rollback

Last Updated: 9/2/2021, 11:51:49 AM