Problem generating the wallet with RawKey ()

Are we able to create wallet from privatekey exported with TerraStation?
The following code throws an error complaining about the private key:
Error: Expected private key to be an Uint8Array with length 32

import { LCDClient, MnemonicKey, RawKey } from ‘@terra-money/terra.js’

const terra = new LCDClient({
URL: ‘https://lcd.terra.dev’,
chainId: ‘columbus-4’
})

const wallet = terra.wallet(
new RawKey(
Buffer.from(‘xxxxprivatekeyxxxx’)
)
)

Buffer.from uses UTF-8 encodings by default, while private keys usually use hex or base64.

Try:

Buffer.from("yourPrivateKey", "hex")
// or
Buffer.from("yourPrivateKey", "base64")

It seems that terra.js doesn’t support private key exported from Terra Station where a password is required

Alright, I figured it out

import * as CryptoJS from "crypto-js";
import { LCDClient, MnemonicKey, RawKey } from "@terra-money/terra.js";

const terra = new LCDClient({
  chainID: "columbus-5",
  URL: "https://lcd.terra.dev",
});

First, I generate a mnemonic phrase and create a wallet from it using terra.js. I take a note of what the wallet address:

const wallet1 = terra.wallet(
  new MnemonicKey({
    mnemonic:
      "satisfy adjust timber high purchase tuition stool faith fine install that you unaware feed domain license impose boss human eager hat rent enjoy dawn",
  })
);
console.log(wallet1.key.accAddress);

Output:

terra1dcegyrekltswvyy0xy69ydgxn9x8x32zdtapd8

Now I put the same mnemonic phrase into Terra Station, export wallet, decrypt the exported private key, and create a wallet using the decrypted key with terra.js. If everything works it should give me the same wallet address as above.

/**
 * https://github.com/terra-money/station/blob/main/src/utils/terra-keystore.ts#L31
 */
function decrypt(transitmessage: string, pass: string) {
  const salt = CryptoJS.enc.Hex.parse(transitmessage.substr(0, 32));
  const iv = CryptoJS.enc.Hex.parse(transitmessage.substr(32, 32));
  const encrypted = transitmessage.substring(64);

  const keySize = 256;
  const iterations = 100;
  const key = CryptoJS.PBKDF2(pass, salt, {
    keySize: keySize / 32,
    iterations: iterations,
  });

  return CryptoJS.AES.decrypt(encrypted, key, {
    iv: iv,
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC,
  }).toString(CryptoJS.enc.Utf8);
}
type ExportedWallet = {
  name: string;
  address: string;
  encrypted_key: string;
};

const exportedWallet: ExportedWallet = JSON.parse(
  Buffer.from(
    "eyJuYW1lIjoibG9jYWx0ZXJyYTEiLCJhZGRyZXNzIjoidGVycmExZGNlZ3lyZWtsdHN3dnl5MHh5Njl5ZGd4bjl4OHgzMnpkdGFwZDgiLCJlbmNyeXB0ZWRfa2V5IjoiYThjMDg1ZTIyZjYwZmU5ZDljYzU5NGZkMWM5NjEwMjlmZDJhOGY2Y2NkYjA0MjQ5NWY3MmE2MDI1YjA3MmYyZjlJWXgybHhPcTU5Q3lJNDBEa1dXMEtkRzNLZjlnM3NrM3M5eFkwZStVRnZ0Z3VMYnAzd2QyYTFuUWVyS1hOcndveFlMQ29EUU1lTlk5NktHdSszNXh6alA3NUE3TnBTYVhRWUFqK1JNY0lBPSJ9",
    "base64"
  ).toString("utf8")
);
const decryptedKey = decrypt(exportedWallet.encrypted_key, "localterra");
const wallet2 = terra.wallet(new RawKey(Buffer.from(decryptedKey, "hex")));
console.log(wallet2.key.accAddress);

Output:

terra1dcegyrekltswvyy0xy69ydgxn9x8x32zdtapd8
1 Like

awesome.
thanks so much for the code. it worked great!