Skip to content

Front-End

Overview

Your front-end serves as the interface for user interaction with the CoKeeps Hot Wallet, facilitating administrative and wallet actions. The CoKeeps Hot Wallet acts as the central component in the process flow, verifying user information and authentication with your back-end server before executing further actions.

To maintain security and prevent unauthorised access or data tampering, requests are channelled through the CoKeeps JavaScript SDK. This SDK orchestrates specific operations, such as message signing and encryption, leveraging a cryptographic key generated on the user's device during login with their raw credentials. Through this protocol, the signature ensures data integrity by detecting any tampering throughout the life-cycle of the data within the CoKeeps Hot Wallet system, while encryption shields content from view between the user and the CoKeeps Hot Wallet system. This approach is more secure than HMAC or token-based methods, as it prevents spoofing and verifies that messages originate from the intended user.

As all communication relies on cryptographic keys, and the authentication private key remains on the user's device, sensitive data such as raw credentials is never stored in the CoKeeps Hot Wallet system nor does it leave the user's device - only the authentication public key is utilised.

All communications with the CoKeeps Hot Wallet occur over TLS (Transport Layer Security) using HTTPS.

IMPORTANT

The security measures outlined above are contingent upon the integrity of your front-end platform and the security of the user's device. In the presence of malware such as key-loggers, raw credentials may be compromised, making them susceptible to spoofing attacks. Implementing Multi-Factor Authentication (MFA) on your front-end adds an extra layer of security to mitigate such risks.

Preparations

During the integration phase, you will receive the CoKeeps JavaScript SDK. Follow these steps to integrate it into your web application:

html
<script src="/cksdk-browser.js"></script>

Initialisation on Application Load

javascript
var CKSDK = null;

window.addEventListener('load', async () => {
  CKSDK = window.CKSDK;

  // setup
  const params = {
	hostSignPublicKey: "<hot_wallet_public_key>",
	hostId: "cokeeps-hotwallet",
	hostEndpoint: "<hot_wallet_https_endpoint>"
  };

  CKSDK.auth.setup(params);

  const secret = "<your_system_generated_unique_user_secret_session>";

  // Load session if it exists. Refer to the Log In section.
  if (await CKSDK.auth.load(params.hostSignPublicKey, secret)) {
	if (await CKSDK.auth.connected()) {
	  // Connection successful
	} else {
	  // Connection failure with CoKeeps Hot Wallet:
	  // - Account is blocked by your back-end verify endpoint
	  // - Invalid hot wallet public key
	  // - Invalid secret
	}
  }

  await run();
});

function run() {
	// Your application processes
}

Replace <hot_wallet_public_key>, <hot_wallet_id>, and <hot_wallet_https_endpoint> with the provided values during integration.

The <your_system_generated_unique_user_secret_session> represents a unique user device secret generated by your system for each user session. It is crucial for encryption salt to the SDK for persistence mode. Failing to provide the same secret value within the same user session will invalidate Hot Wallet authentication cryptography keys and result in connection failure.

To Log in

javascript
async function log_in() {
	const username = "<identifiable_such_as_email>";
	var password = "<user_input_credential_or_webauth_private_key_string>";
	
    // An error will be thrown if any issues arise
	await CKSDK.auth.login({ username, password });
	password = null; // Prevent future accidental use or leakage
	
	// Securely store session for persistence
	const secret = "<your_system_generated_unique_user_secret_session>";
	CKSDK.auth.store(secret);

	// Additional login routines
}

The raw password value passed to the SDK is not transmitted or stored. It is used to generate the hot wallet authentication cryptography key.

Logging Out

javascript
async function log_out() {
    // An error will be thrown if any issues arise
	await CKSDK.auth.logout();

	// Additional logout routines
}

NodeJS Version

All methods available in the Browser SDK are also accessible in the NodeJS SDK, but the strategy for managing sessions differs.

You only need to use the NodeJS version if your front-end application does not support JavaScript, such as in mobile applications. In such cases, the NodeJS version acts as a proxy for your user's requests and functions exactly like the Browser SDK version.

Here's an example of how to use this version:

javascript
const sha256 = require('crypto-js/sha256');
const { CKSDK, CKWRAP } = require("<path_to>/cksdk-node.min.js");

// Setup parameters
const setupParams = {
    hostSignPublicKey: "<hot_wallet_public_key>",
    hostId: "cokeeps-hotwallet",
    hostEndpoint: "<hot_wallet_https_endpoint>"
};

// Let's assume this is your database
// 1. You should clear the uid session when the user logs out or when they reset their password
// 2. Session should have expiry if inactive for a period of time
const simpleSessionDatabase = {};

// A secret that should be isolated from other system
const serverSecret = "<your_system_secret_separated_from_database>";

// Example of a request function by a user
async function request(uid, sealed = false) {
    // This must be within a request, not a global variable object
    const CKUSER = CKWRAP.feed(CKSDK);

    const secret = "<your_system_generated_unique_user_secret_session>";
    const sessionSecret = sha256(serverSecret + secret).toString();

    // Setup as usual - the returned bridge public key is used on your client
    const bridgePublicKey = await CKUSER.auth.setup(setupParams);

    // Check if there is already a session stored for this user
    if (simpleSessionDatabase[uid]) {
        await CKUSER.auth.self_load(simpleSessionDatabase[uid], setupParams.hostSignPublicKey, sessionSecret);
    } else if (sealed) {
        // No session - perform a log in
        await CKUSER.auth.login({ sealed });

        // Store the user session
        simpleSessionDatabase[uid] = CKUSER.auth.self_store(sessionSecret);
    } else {
        throw new Error("Invalid procedure.");
    }

    // Use the SDK as usual - Call deposit address
    let depositAddress = await CKUSER.action.generate_deposit({
        chain_id: "bitcoin"
    });

    console.log("Deposit address", depositAddress);
}

// Fake request, refer below on how to obtain this `sealed` value.
const sealed = "<hex_digest_from_your_bridge_client>";

request("<UID>", sealed).catch(console.log);

Here's an inline bridge public key generation, only use this to retrieve the hex value:

javascript
const setupParams = { // Setup parameters like the above };
CKSDK.auth.setup(setupParams).then(CKSDK.auth.get_bridge_pubkey().then(console.log));

We have the following supported language code example for bridge implementation to obtain sealed:

  • Dart (works with Flutter)