Implementing a Custom Key

If none of the Key solutions provided by Terra SDK or the community are able to meet your requirements, you might consider writing your own Key implementation.

Here are just a couple that help guide your design pathways:

Is the private key accessible by developer?
Can the signing agent sign arbitrary data payloads AND use ECDSA on Secp256k1?
Can you determine the public key in advance, and is it static?

Usually, reasons for requiring a custom Key fall into one of 3 patterns:

  • External signing

    Scenario: The transaction signing is to be performed outside the Python program running Terra SDK, such as signing via hardware wallet (Ledger, Trezor), etc.

  • Alternative signing algorithm

    Scenario: Terra account you need to sign transactions for requires a signature algorithm other than ECDSA on Secp256k1, such as Threshold Multisig or Ed25519.

  • Customize private key derivation

    Scenario: User wants to provide a custom interface for generating a private key, eg. alternative mnemonic schemas, directed key.

The source for MnemonicKey is provided as an example:

from terra_sdk.key.raw import RawKey
from bip32utils import BIP32_HARDEN, BIP32Key
from mnemonic import Mnemonic

class MnemonicKey(RawKey):
    def __init__(
        self,
        mnemonic: str = None,
        account: int = 0,
        index: int = 0,
        coin_type: int = 330,
    ):
        if mnemonic is None:
            mnemonic = Mnemonic("english").generate(256)
        seed = Mnemonic("english").to_seed(mnemonic)
        root = BIP32Key.fromEntropy(seed)
        # derive from hdpath
        child = (
            root.ChildKey(44 + BIP32_HARDEN)
            .ChildKey(coin_type + BIP32_HARDEN)
            .ChildKey(account + BIP32_HARDEN)
            .ChildKey(0)
            .ChildKey(index)
        )

        super().__init__(child.PrivateKey())
        self.mnemonic = mnemonic
        self.account = account
        self.index = index