Knowledge Base Home

HD Wallet

An abbreviation for hierarchical determinism, the Kaleido HD Wallet is a key tree that provides a deterministic derivation of Ethereum account addresses and their corresponding private signing keys from a single seed phrase. The overall HD wallet implementation is a byproduct of several Bitcoin Improvement Proposals (BIP), specifically BIP32 for the core cryptography and key generation, BIP39 for seed phrase and recovery, and BIP44 for multi-protocol account hierarchy. The seed phrase, a 12 word mnemonic, can be generated in one of two ways: either by the service via the BIP39 spec or submitted manually by the user as an “easy to remember hard to guess” expression. The seed phrase serves as the master root for the entire key tree, therefore strong entropy should be applied if manual submission is the desired course of action. HD wallets provide an elegant solution for both account management and identity masking, as the key tree can be deterministically regenerated from the master seed phrase and users can increment their account index on a per-transaction basis to anonymize identity via unique signing keys.

Provision the HD Wallet Service

You can elect for one of two approaches to provision the HD Wallet: Kaleido Console UI or Admin API. For users unfamiliar with the Kaleido REST API, the console interface is the recommended happy path. Both approaches will ultimately result in a new service instance within the specified environment.

UI:

  • Navigate to an existing environment, and click the +ADD dropdown in the top right portion of the screen.
  • Select the Add Services option. This will open a new panel exposing the currently available Kaleido Services.
  • Click the ADD button beneath Identity Masking HD Wallet.
  • Supply an arbitrary name for the wallet and click ADD. Click DONE to finish the deployment.
  • The newly created wallet will appear under the Member Services view on your environment dashboard.

NOTE: The following documentation and example REST calls assume a strong understanding of the Kaleido APIs. Please refer to the Kaleido Resource Model for object relationships, the API 101 topic for sample CRUD operations and Understanding the Kaleido API for detailed descriptions of the various endpoints and routes.

API:

The HD Wallet is provisioned against the /services API endpoint and exists as an environment-specific member resource. The orchestration is identical to nodes and application credentials, where the object is directly bound to one of the consortium’s membership IDs. To create the service, specify the consortia and environment IDs in the path and POST to the /services endpoint with a name, the service type and membership ID in the body of the call. This sample assumes that the following environment variables have been set as follows:

export APIURL="https://console.kaleido.io/api/v1"
export APIKEY="YOUR_API_KEY"
export HDR_AUTH="Authorization: Bearer $APIKEY"
export HDR_CT="Content-Type: application/json"

If you are targeting an environment outside of the US, make sure to modify your URL accordingly. The ap qualifier resolves to Sydney, while ko resolves to Seoul:

export APIURL="https://console-eu.kaleido.io/api/v1"
export APIURL="https://console-ap.kaleido.io/api/v1"
export APIURL="https://console-ko.kaleido.io/api/v1"

Use the POST method to provision the service and optionally format the output using jq:

# replace the membership_ID placeholder with one of your membership IDs
curl -X POST -H "$HDR_AUTH" -H "$HDR_CT" "$APIURL/consortia/{consortia_id}/environments/{environment_id}/services" -d '{"name":"ExampleHDwallet", "service":"hdwallet", "membership_id":"{membership_id}"}' | jq

This will return you the 10 character HD wallet service ID. For example:


{
  "name": "ExampleHDwallet",
  "service": "hdwallet",
  "membership_id": "u0amsb3epp",
  "service_guid": "1878bcdf-a5b5-45a9-b279-5f8bb38d36da",
  "service_type": "member",
  "details": {},
  "zone_id": "u0iqva64fj",
  "state": "provisioning",
  "_id": "u0cyjmmgwt",
  "_revision": "0",
  "created_at": "2019-04-10T14:42:30.362Z",
  "environment_id": "u0n9z64z07"
}

Query the Service ID and Retrieve the URL

Use the GET method and specify the HD wallet service ID in the path:

curl -X GET -H "$HDR_AUTH" -H "$HDR_CT" "$APIURL/consortia/{consortia_id}/environments/{environment_id}/services/{service_id}" | jq

This will return you the HD Wallet details, including the targetable URL for account/key retrieval and transaction signing. For example:


{
  "_id": "u0cyjmmgwt",
  "name": "ExampleHDwallet",
  "service": "hdwallet",
  "membership_id": "u0amsb3epp",
  "service_guid": "1878bcdf-a5b5-45a9-b279-5f8bb38d36da",
  "service_type": "member",
  "details": {},
  "zone_id": "u0iqva64fj",
  "state": "started",
  "_revision": "1",
  "created_at": "2019-04-10T14:42:30.362Z",
  "environment_id": "u0n9z64z07",
  "urls": {
    "http": "https://u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io"
  },
  "updated_at": "2019-04-10T14:42:40.431Z"
}

The URL of interest is "https://u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io".

As with all Kaleido REST API calls, /api/v1 must be appended to the endpoint and application credentials must be supplied inline or as a base64 encoded object in the header auth. Therefore, using the above URL as a reference, the targetable endpoint would be as follows:

https://{username}:{password}@u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io/api/v1

Generate the Mnemonic and Create a New Wallet

UI:

  • Click the dropdown menu next to your HD Wallet and click View Dashboard.
  • Create a new set of application credentials for the wallet and store them somewhere safe.  You will need for subsequent interactions with the service.
  • Click GENERATE NEW WALLET
  • Now you can increment through your account indices to retrieve unique accounts and signing keys as you need them.

API:

Similar to node connections, the HD Wallet ingress is secured via application credentials. Generate a
set of credentials against the same membership ID used to provision the wallet and construct your
fully qualified HD Wallet URL with the following syntax – https://{username}:{password}@{wallet_url}/api/v1.

Using the fully qualified HD Wallet URL, send a POST to the /wallets endpoint to generate the wallet ID and seed phrase. An example call using the HD Wallet Service URL from the previous page might resemble
the following:

curl -X POST -H "$HDR_CT" https://{username}:{password}@u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io/api/v1/wallets | jq

Alternatively, you can use one of the readily available API tools such as Postman to send your REST calls.

A successful wallet creation will return the wallet ID and 12 word mnemonic serving as the root seed for the wallet. For example:

{
  "id": "no0008g9",
  "secret": "image antique paper bonus vehicle menu budget wild tilt pitch equal lift"
}

The mnemonic should be stored safely in the same manner as you would secure a private key. This phrase is the root seed for the wallet and the only way it can be restored. The id field is the specific path to the wallet and is used on the HTTP calls to target accounts and retrieve signing keys.

Retrieve an account and its private signing key

Once the wallet has been successfully initialized, you can enumerate an account index to retrieve an Ethereum address and its corresponding private key.  This allows for the client side application to locally sign an Ethereum transaction object prior to submission.  To retrieve an account and key, follow the same baseline URL:

https://{username}:{password}@{wallet_url}/api/v1

And then append /wallets/{wallet_id}/accounts/{index} to the path. For example, using our previously created HD Wallet instance, a call to retrieve the initial account would resemble the following:

curl -X GET -H "$HDR_CT" https://{username}:{password}@u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io/api/v1/wallets/no0008g9/accounts/0 | jq

This will return an Ethereum account address and its associated secp256k1 private signing key. For example:


{
  "address": "0xA9337C15af4Fa03D0411fd4d1dFc7dA753A87D89",
  "privateKey": "e4bffefd3dd3f9fbec0f264d6326e7cc139ac34531ededf950c5dd114ea327f6"
}

Specify an account and sign a transaction

Additionally, you can use the HD Wallet service as a signing utility by specifying an account and passing an unsigned Ethereum transaction object in the body of the call. To sign a transaction, follow the same base URL and append /wallets/{wallet_id}/accounts/{account_number}/sign to the path. The body of the call is the standard Ethereum transaction object, with hex-encoded values for all fields except for chainID. If desired, nonce, gasPrice and gasLimit can be expressed as plaintext integers; this is up to the developer. The transaction body might resemble the following:

{
  nonce: 'Ox1',
  gasPrice: '0',
  gasLimit: '10000',
  to: '0xd0a6E6C54DbC68Db5db3A091B171A77407Ff7ccf',
  value: '0x00',
  data: '0x1',
  // chainId of the Kaleido environment, displayed in the environment view in the Kaleido console UI
  chainId: 1213888410
}

For example, using the wallet ID returned above, the first account in the wallet, a hex-encoded nonce of “1”, a hex-encoded data field of “1”, and a gasLimit of 10000:

curl -X POST -H "$HDR_CT" https://{username}:{password}@u0n9z64z07-u0cyjmmgwt-hdwallet.us0-aws.kaleido.io/api/v1/wallets/no0008g9/accounts/0/sign -d '{"nonce":"0x1", "gasPrice":"0", "gasLimit":"10000", "to":"0xd0a6E6C54DbC68Db5db3A091B171A77407Ff7ccf", "value":"0x00", "data":"0x1", "chainID":"1213888410"}'

This will return the transaction signed with the private key of account 0. For example:

0xf84b02808227108080011ca0a4b459168b0d9ddf74a5723e4b6ad9d5ba6d62e5b8a72edc7222694730dc6943a03afe606962f0fe16565a8029f2a7f6c6a3adcc222ae7fe0d885942c310d3b1d6

This is the hex string that an application would submit to the network via one of the Ethereum-compatible APIs. For example, using the sendSignedTransaction method via the well known Web3.js library:

web3.eth.sendSignedTransaction('0xf84b02808227108080011ca0a4b459168b0d9ddf74a5723e4b6ad9d5ba6d62e5b8a72edc7222694730dc6943a03afe606962f0fe16565a8029f2a7f6c6a3adcc222ae7fe0d885942c310d3b1d6')
.on('receipt', console.log);

Transaction Management and Account Iteration

Hex-encoding, nonce management and gasLimit values are the responsibilities of the wallet user. Once you are comfortable with your transaction modeling, you can sequentially iterate through the wallet accounts and obtain a different signing key for every transaction entering the network. This will effectively anonymize your identity for any transaction that is appended to the chain.

If complete anonymity is your desired result, then you should never use a signing key more than once. The wallet is capable of generating an infinite number of accounts and signing keys, so per-transaction incrementation is the recommended best practice.

You can programmatically interact with your wallet by calling the /wallet API against your basic auth protected wallet URL.  The /wallet endpoint exposes two sub-routes, /accounts and /sign.  The /accounts route allows you to retrieve or specify an index for signing.  The /sign route is fronted by an enumerated account index and signs a supplied Ethereum transaction object.

    • Refer to the API Reference documentation for details on provisioning the wallet against the /services endpoint.
    • Refer to the Technical Info tab for sample calls and additional clarification.  For example, to generate the wallet mnemonic via the BIP39 spec:

curl -X POST -H "$HDR_CT" https://{username}:{password}@{walletURL}/api/v1/wallets | jq"

Try out the HD Wallet in the Kaleido Samples Gallery.  The HD Wallet sample is reliant on the following configuration parameters:

  • Consortia ID
  • App Credentials username and password
  • HD Wallet RPC endpoint
  • HD Wallet ID

You can create these resources using the Kaleido console or with the administrative API.

Prev Block Explorer Next IPFS