UNPKG

js-cosmos-wallet

Version:
171 lines (165 loc) 6.66 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.jsCosmosWallet = {}))); }(this, (function (exports) { 'use strict'; // Import here Polyfills if needed. Recommended core-js (npm i -D core-js) // import "core-js/fn/array.find" // ... var bip39 = require("bip39"); var bip32 = require("bip32"); var bech32 = require("bech32"); var secp256k1 = require("secp256k1"); var sha256 = require("crypto-js/sha256"); var ripemd160 = require("crypto-js/ripemd160"); var CryptoJS = require("crypto-js"); var hdPathAtom = "m/44'/118'/0'/0/0"; // key controlling ATOM allocation var standardRandomBytesFunc = function (x) { return CryptoJS.lib.WordArray.random(x).toString(); }; function generateWalletFromSeed(mnemonic) { var masterKey = deriveMasterKey(mnemonic); var _a = deriveKeypair(masterKey), privateKey = _a.privateKey, publicKey = _a.publicKey; var cosmosAddress = createCosmosAddress(publicKey); return { privateKey: privateKey.toString("hex"), publicKey: publicKey.toString("hex"), cosmosAddress: cosmosAddress }; } function generateSeed(randomBytesFunc) { if (randomBytesFunc === void 0) { randomBytesFunc = standardRandomBytesFunc; } var randomBytes = Buffer.from(randomBytesFunc(32), "hex"); if (randomBytes.length !== 32) throw Error("Entropy has incorrect length"); var mnemonic = bip39.entropyToMnemonic(randomBytes.toString("hex")); return mnemonic; } function generateWallet(randomBytesFunc) { if (randomBytesFunc === void 0) { randomBytesFunc = standardRandomBytesFunc; } var mnemonic = generateSeed(randomBytesFunc); return generateWalletFromSeed(mnemonic); } // NOTE: this only works with a compressed public key (33 bytes) function createCosmosAddress(publicKey) { var message = CryptoJS.enc.Hex.parse(publicKey.toString("hex")); var hash = ripemd160(sha256(message)).toString(); var address = Buffer.from(hash, "hex"); var cosmosAddress = bech32ify(address, "cosmos"); return cosmosAddress; } function deriveMasterKey(mnemonic) { // throws if mnemonic is invalid bip39.validateMnemonic(mnemonic); var seed = bip39.mnemonicToSeed(mnemonic); var masterKey = bip32.fromSeed(seed); return masterKey; } function deriveKeypair(masterKey) { var cosmosHD = masterKey.derivePath(hdPathAtom); var privateKey = cosmosHD.privateKey; var publicKey = secp256k1.publicKeyCreate(privateKey, true); return { privateKey: privateKey, publicKey: publicKey }; } function bech32ify(address, prefix) { var words = bech32.toWords(address); return bech32.encode(prefix, words); } // Transactions often have amino decoded objects in them {type, value}. // We need to strip this clutter as we need to sign only the values. function prepareSignBytes(jsonTx) { if (Array.isArray(jsonTx)) { return jsonTx.map(prepareSignBytes); } // string or number if (typeof jsonTx !== "object") { return jsonTx; } var sorted = {}; Object.keys(jsonTx) .sort() .forEach(function (key) { if (jsonTx[key] === undefined || jsonTx[key] === null) return; sorted[key] = prepareSignBytes(jsonTx[key]); }); return sorted; } /* The SDK expects a certain message format to serialize and then sign. type StdSignMsg struct { ChainID string `json:"chain_id"` AccountNumber uint64 `json:"account_number"` Sequence uint64 `json:"sequence"` Fee auth.StdFee `json:"fee"` Msgs []sdk.Msg `json:"msgs"` Memo string `json:"memo"` } */ function createSignMessage(jsonTx, _a) { var sequence = _a.sequence, account_number = _a.account_number, chain_id = _a.chain_id; // sign bytes need amount to be an array var fee = { amount: jsonTx.fee.amount || [], gas: jsonTx.fee.gas }; return JSON.stringify(prepareSignBytes({ fee: fee, memo: jsonTx.memo, msgs: jsonTx.msg, sequence: sequence, account_number: account_number, chain_id: chain_id })); } // produces the signature for a message (returns Buffer) function signWithPrivateKey(signMessage, privateKey) { var signHash = Buffer.from(sha256(signMessage).toString(), "hex"); var signature = secp256k1.sign(signHash, Buffer.from(privateKey, "hex")).signature; return signature; } function createSignature(signature, publicKey) { return { signature: signature.toString("base64"), pub_key: { type: "tendermint/PubKeySecp256k1", value: publicKey.toString("base64") } }; } // main function to sign a jsonTx using the local keystore wallet // returns the complete signature object to add to the tx function sign(jsonTx, wallet, requestMetaData) { var signMessage = createSignMessage(jsonTx, requestMetaData); var signatureBuffer = signWithPrivateKey(signMessage, wallet.privateKey); var pubKeyBuffer = Buffer.from(wallet.publicKey, "hex"); return createSignature(signatureBuffer, pubKeyBuffer); } // adds the signature object to the tx function createSignedTx(tx, signature) { return Object.assign({}, tx, { signatures: [signature] }); } // the broadcast body consists of the signed tx and a return type function createBroadcastBody(signedTx) { return JSON.stringify({ tx: signedTx, return: "block" }); } exports.generateWalletFromSeed = generateWalletFromSeed; exports.generateSeed = generateSeed; exports.generateWallet = generateWallet; exports.createCosmosAddress = createCosmosAddress; exports.prepareSignBytes = prepareSignBytes; exports.createSignMessage = createSignMessage; exports.signWithPrivateKey = signWithPrivateKey; exports.createSignature = createSignature; exports.sign = sign; exports.createSignedTx = createSignedTx; exports.createBroadcastBody = createBroadcastBody; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=js-cosmos-wallet.umd.js.map