UNPKG

@sei-js/cosmjs

Version:

TypeScript library for CosmJS interactions on the Sei blockchain

119 lines (118 loc) 4.69 kB
import { ripemd160 } from '@cosmjs/crypto'; import { fromBech32 } from '@cosmjs/encoding'; import { secp256k1 } from '@noble/curves/secp256k1'; import { ec as EllipticCurve } from 'elliptic'; import { toBech32 } from './bech32'; import { sha256 } from './hash'; /** * Derives and returns the address from a given private key. * @param privateKeyHex A hex (0x) string of the private key of an account. * @returns The corresponding address for the given private key. * @category Utils */ export const deriveAddressesFromPrivateKey = (privateKeyHex) => { const privateKey = Uint8Array.from(Buffer.from(privateKeyHex.padStart(64, '0'), 'hex')); const publicKey = secp256k1.getPublicKey(privateKey, true); return compressedPubKeyToAddress(publicKey); }; /** * Creates a hex encoded ECC KeyPair given a public key. * @param pubKey A byte array representing a public key. * @returns A hex encoded ECC KeyPair. * @category Utils */ export const pubKeyToKeyPair = (pubKey) => { const secp256k1 = new EllipticCurve('secp256k1'); return secp256k1.keyFromPublic(Buffer.from(pubKey).toString('hex'), 'hex'); }; /** * Converts the given public key to a bytestring * @param pubKey The public key to convert. * @param uncompressed Whether the public key has already been compressed. * @returns A byte array representing the converted public key. * @category Utils */ export const pubKeyToBytes = (pubKey, uncompressed) => { if (uncompressed && pubKey.length === 65) { return pubKey; } if (!uncompressed && pubKey.length === 33) { return pubKey; } const keyPair = pubKeyToKeyPair(pubKey); if (uncompressed) { return new Uint8Array(Buffer.from(keyPair.getPublic().encode('hex', false), 'hex')); } else { return new Uint8Array(Buffer.from(keyPair.getPublic().encodeCompressed('hex'), 'hex')); } }; /** * Gets the corresponding address from a byte array representing a compressed public key. * @param publicKey A byte array representing a compressed public key. * @returns The corresponding address to the given compressed public key. * @category Utils */ export const compressedPubKeyToAddress = (publicKey) => { return toBech32(getAddressHashFromPubKey(publicKey)); }; /** * Gets the corresponding sha256 hashed address to a given compressed public key. * @param compressedPublicKey A byte array representing a compressed public key. * @returns A sha256 hashed address that corresponds to the given public key. * @category Utils */ export const getAddressHashFromPubKey = (compressedPublicKey) => { return ripemd160(sha256(compressedPublicKey)); }; /** * Verifies a digest signed with a private key using the corresponding public key. * @param digest A byte array representing the digest we wish to verify. * @param signature A byte array representing the digital signature. * @param pubKey A byte array representing the public key of the signer. * @returns True if the digest is verified to have been signed using the private key complementing the given public key. * @category Utils */ export const verifyDigest32 = (digest, signature, pubKey) => { if (digest.length !== 32) { throw new Error(`Invalid length of digest to verify: ${digest.length}`); } if (signature.length !== 64) { throw new Error(`Invalid length of signature: ${signature.length}`); } const secp256k1 = new EllipticCurve('secp256k1'); const r = signature.slice(0, 32); const s = signature.slice(32); return secp256k1.verify(digest, { r: Buffer.from(r).toString('hex'), s: Buffer.from(s).toString('hex') }, pubKeyToKeyPair(pubKey)); }; /** * Returns a boolean representing if the given string is a valid Sei address. * @param address The string we wish to verify. * @returns True if a string is a valid Sei address * @category Utils */ export const isValidSeiCosmosAddress = (address) => { try { const { prefix } = fromBech32(address); return prefix && prefix === 'sei'; } catch (e) { return false; } }; /** * Shortens a sei address to display it in the format sei...xxxxx where xxxxx is the last five characters of the address. * Used to display sei address in an easily identifiable way. * @param address The address to truncate * @returns A shortened version of the address in the format sei...xxxxx. Returns the input address if it is not a valid sei address. * @category Utils */ export const truncateSeiAddress = (address) => { if (!isValidSeiCosmosAddress(address)) { return address; } return `${address.slice(0, 3)}....${address.slice(address.length - 5)}`; };