registry-sdk/src/account.ts

125 lines
2.9 KiB
TypeScript
Raw Normal View History

import assert from 'assert';
import BIP32Factory from 'bip32';
import * as ecc from 'tiny-secp256k1';
import * as bip39 from 'bip39';
import canonicalStringify from 'canonical-json';
import secp256k1 from 'secp256k1';
2022-04-14 04:34:52 +00:00
import { sha256 } from 'js-sha256';
import { toHex } from '@cosmjs/encoding';
2022-04-12 10:54:26 +00:00
import { encodeSecp256k1Pubkey } from '@cosmjs/amino';
import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing';
const AMINO_PREFIX = 'EB5AE98721';
const HDPATH = "m/44'/60'/0'/0";
const ACCOUNT_PREFIX = 'laconic';
const bip32 = BIP32Factory(ecc);
/**
* Registry account.
*/
export class Account {
_privateKey: Buffer;
_publicKey!: Uint8Array;
_encodedPubkey!: string;
_registryPublicKey!: string;
_wallet!: DirectSecp256k1Wallet;
_address!: string;
2022-04-05 14:11:06 +00:00
/**
* Generate bip39 mnemonic.
*/
static generateMnemonic () {
return bip39.generateMnemonic();
}
/**
* Generate private key from mnemonic.
*/
static async generateFromMnemonic (mnemonic: string) {
assert(mnemonic);
const seed = await bip39.mnemonicToSeed(mnemonic);
const wallet = bip32.fromSeed(seed);
const account = wallet.derivePath(HDPATH);
const { privateKey } = account;
assert(privateKey);
return new Account(privateKey);
}
/**
* New Account.
*/
constructor (privateKey: Buffer) {
assert(privateKey);
this._privateKey = privateKey;
}
get privateKey () {
return this._privateKey;
}
get encodedPubkey () {
2022-04-12 10:54:26 +00:00
return this._encodedPubkey;
}
get registryPublicKey () {
return this._registryPublicKey;
}
get address () {
return this._address;
}
get wallet () {
return this._wallet;
}
async init () {
this._wallet = await DirectSecp256k1Wallet.fromKey(
this._privateKey,
ACCOUNT_PREFIX
);
const [account] = await this._wallet.getAccounts();
this._address = account.address;
// Generate public key.
this._publicKey = secp256k1.publicKeyCreate(this._privateKey);
this._encodedPubkey = encodeSecp256k1Pubkey(this._publicKey).value;
// Generate registry formatted public key.
const publicKeyInHex = AMINO_PREFIX + toHex(account.pubkey);
this._registryPublicKey = Buffer.from(publicKeyInHex, 'hex').toString('base64');
}
/**
* Get private key.
*/
getPrivateKey () {
return this._privateKey.toString('hex');
}
/**
* Get record signature.
*/
async signRecord (record: any) {
assert(record);
const recordAsJson = canonicalStringify(record);
// Double sha256.
const recordBytesToSign = Buffer.from(sha256(Buffer.from(sha256(Buffer.from(recordAsJson)), 'hex')), 'hex');
// Sign message
assert(recordBytesToSign);
const messageToSignSha256 = sha256(recordBytesToSign);
const messageToSignSha256InBytes = Buffer.from(messageToSignSha256, 'hex');
const sigObj = secp256k1.ecdsaSign(messageToSignSha256InBytes, this.privateKey);
return Buffer.from(sigObj.signature);
}
}