“Where's My Crypto Coin?” Featuring Samsung Blockchain Keystore SDK

Shuvo Saha

Distributed ledger-based technologies are becoming more popular and easy to use. Anyone can now build a new cryptocurrency or token in the Blockchain world. This rise in popularity and value makes crypto assets a big target for hackers. If you want to keep your valuable crypto assets safe, using a hardware cold wallet such as Trezor or Ledger Nano S has become a necessity. Unfortunately, that adds up to one more item in your pocket that you always have to carry around.

Thankfully, gone are the days of carrying clunky, old wallets. Recent Galaxy phones, such as the S10e, S10, S10+, Note10, and Fold, can now securely store your cryptocurrency wallet using the Samsung Blockchain Keystore (SBK). Along with storing your cryptocurrency wallet, the SBK SDK allows you to get your Blockchain address and sign cryptocurrency transactions.

In this article, we explore one of the key features offered by the Keystore SDK--how to get your Blockchain address from the SBK SDK and three ways to share it:

  • Display as QR code
  • Copy to clipboard
  • Share through Android’s share intent

Setting up the Project and Handling SBK Data

To set up your Android project with the SBK SDK, follow these instructions.

To use functionalities offered by the SDK, first fetch an instance of the service.

private ScwService mScwService = ScwService.getInstance();

After you have fetched the ScwService instance, you can check whether your device is Keystore-supported.

if (mScwService == null) {
    Log.e("KeystoreApp", "Keystore is not supported on this device.");
}

If the device is Keystore-supported, you can fetch the address list with getAddressList():

mScwService.getAddressList(addressListCallback, hdPathList);

The first parameter to getAddressList() is a ScwGetAddressListCallback, which is executed after getting a response from Keystore. ScwGetAddressListCallback() has two functions:

  • onSuccess(): This function is called when the address list has been fetched successfully from Keystore.
  • onFailure(): This function is called if any errors occur while fetching the address list from Keystore.
ScwService.ScwGetAddressListCallback addressListCallback = new
ScwService.ScwGetAddressListCallback() {
    @Override
    public void onSuccess(List addressList) {
        //You can share your address from the address list here
    }

    @Override
    public void onFailure(int failureCode) {
        //Based on the failure code you can show appropriate alerts here
    }
};

The second parameter is an ArrayList of Hierarchical Deterministic (HD) Path(s) whose addresses you want to fetch. If you want to learn more about HD paths, please refer to BIP-44. For example, if you want to find the public address of your first five accounts, pass the following list as a parameter:

ArrayList hdPathList = new ArrayList<>();
hdPathList.add("m/44'/60'/0'/0/0");
hdPathList.add("m/44'/60'/0'/0/1");
hdPathList.add("m/44'/60'/0'/0/2");
hdPathList.add("m/44'/60'/0'/0/3");
hdPathList.add("m/44'/60'/0'/0/4");

A Sample App with the SBK SDK

Now that we are familiar with getAddressList(), let’s dive into our sample application. Features of our Public Address with SBK app are:

  • Fetch your public address from the Keystore
  • Switch between multiple public addresses
  • Display QR code of the selected account
  • Copy selected address into the clipboard
  • Send the selected address with supported applications with Android’s share intent

Initially, only the address of the first account is loaded. When you press the Add button, the HD path of a new account is added to hdPathList, and public addresses are fetched.

public void addAccount(View view) {
    //Account Index is incremented by 1 to get the new account
    accountIndex++;
    //HDPath of new account is added to hdPathList
    hdPathList.add("m/44'/60'/0'/0/" + accountIndex);
    showToast("HDPath Added to list");
    //Public Address of new account is fetched
    getPublicAddress();
}

Public addresses are fetched using the getPublicAddress() function depicted below.

If the address list is fetched successfully, onSuccess() is called, and:

  • The spinner’s previous data is cleared.
  • The newly fetched list is added to the spinner.
  • The UI is updated.

If an error occurs, it is logged and available from logcat. Common errors such as ERROR_INVALID_SCW_APP_ID can be fixed very easily by enabling Developer Mode from the Keystore application. You can find instructions on how to enable Developer Mode here.

private void getPublicAddress() {
    ScwService.ScwGetAddressListCallback addressListCallback = new ScwService.ScwGetAddressListCallback() {
        @Override
        public void onSuccess(final List publicAddressList) {
            //After Address List has been fetched Spinner is updated with new list
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //Clear existing list
                    spinnerAdapter.clear();
                    //New list is added
                    spinnerAdapter.addAll(publicAddressList);
                    spinnerAdapter.notifyDataSetChanged();
                    if (publicAddressList.size() == 1) {
                        showToast(publicAddressList.size() + " address fetched.");
                    } else {
                        showToast(publicAddressList.size() + " addresses fetched.");
                    }
                }
            });
        }

        @Override
        public void onFailure(int errorCode) {
            switch (errorCode) {
                case ScwErrorCode.ERROR_INVALID_SCW_APP_ID:
                    Log.e(LOG_TAG,"Developer option not enabled.");
                    break;
                case ScwErrorCode.ERROR_CHECK_APP_VERSION_FAILED:
                    Log.e(LOG_TAG,"Check internet connection.");
                    break;
                case ScwErrorCode.ERROR_OP_FAIL:
                    Log.e(LOG_TAG,"Operation Failed");
                    break;
                default:
                    Log.e(LOG_TAG,"Error with Error Code: "+errorCode);
                    break;
            }
        }
    };
    if (mScwService == null) {
        Log.e(LOG_TAG, "Keystore is not supported in this device.");
    } else {
        //If Keystore is supported on device address list is requested
        mScwService.getAddressList(addressListCallback, hdPathList);
    }
}

After loading all addresses into the spinner, we can now select any address from it. Once an address is selected, its QR Code is generated and displayed.

publicAddressSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
        //Get Selected Address from spinner
        selectedAddress = adapterView.getItemAtPosition(position).toString();
        selectedAddressTextView.setText(selectedAddress);
        qrCodeImageView.setImageBitmap(generateQRCode(selectedAddress));
    }
  }

In this application, we used “ZXing” to generate the QR bitmap of the selected public address.

private Bitmap generateQRCode(String text) {
    MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
    Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.RGB_565);
    try {
        //Text encoded to QR BitMatrix
        BitMatrix bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, 1000, 1000);
        BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
        //QR Bitmatrix encoded to Bitmap
        bitmap = barcodeEncoder.createBitmap(bitMatrix);
    } catch (WriterException e) {
        e.printStackTrace();
    } finally {
        return bitmap;
    }
}

When you press the copy button, the address is copied to the clipboard.

public void copyAddress(View view) {
    ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clipData = ClipData.newPlainText("Public Address", selectedAddress);
    clipboardManager.setPrimaryClip(clipData);
    Toast.makeText(this, "Address Copied", Toast.LENGTH_SHORT).show();
}

We can also share the selected public address using the Android ACTION_SEND intent.

public void shareAddress(View view) {
    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, selectedAddress);
    sendIntent.setType("text/plain");
    startActivity(sendIntent);
}

Conclusion

Now that you know more about the Samsung Blockchain Keystore SDK, you can use it to enrich your Blockchain application.

Additional Resources: