Javascript
Using Javascript/node.js to sign a transaction
The documentation is designed for Liker Land and LikeCoin v2. For information on 3ook.com and LikeCoin v3, please visit docs.3ook.com.
Encode and Sign Raw Message
The parameters should consist with your account information. The accountNumber
and sequence
could be found by querying LCD /cosmos/auth/v1beta1/accounts/{fromAddress}
endpoint.
const secp256k1 = require('secp256k1');
const createHash = require('create-hash');
const Long = require('long');
const { MsgSend } = require("./build/codec/cosmos/bank/v1beta1/tx");
const { TxBody, AuthInfo, SignDoc, TxRaw } = require("./build/codec/cosmos/tx/v1beta1/tx");
const { PubKey } = require("./build/codec/cosmos/crypto/secp256k1/keys");
// define parameters
const chainId = "likechain-local-testnet";
const privateKey = "69b4e47d3aa61ad6184493529cd0feb0d2dfb55ea31aa9799af42607de3cd1a9";
const publicKey = "A4Fj1Y4k77Qaxuy496CHYB2rpfWXkM3LCnlyrU8eKbH7";
const accountNumber = 2;
const fromAddress = "cosmos1lsagfzrm4gz28he4wunt63sts5xzmczw8pkek3";
const toAddress = "cosmos1mnyn7x24xj6vraxeeq56dfkxa009tvhgknhm04";
const tokenAmount = 1000000;
const memo = "Enjoy your money";
const gasLimit = 100000;
const sequence = 17;
const messages = [{
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
value: {
fromAddress,
toAddress,
amount: [
{
denom: "nanolike",
amount: tokenAmount.toString(),
},
],
}
}];
const wrappedMessages = messages.map(msg => {
return {
typeUrl: msg.typeUrl,
value: MsgSend.encode(msg.value).finish(),
}
})
const body = {
typeUrl: "/cosmos.tx.v1beta1.TxBody",
value: {
memo,
messages: wrappedMessages,
timeoutHeight: Long.UZERO,
extensionOptions: [],
nonCriticalExtensionOptions: [],
},
}
const bodyBytes = TxBody.encode(body.value).finish();
const pubkeyBytes = PubKey.encode({ key: publicKey }).finish();
const authInfo = {
signerInfos: [
{
sequence: Long.fromNumber(sequence),
publicKey: {
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
value: pubkeyBytes,
},
modeInfo: {
single: {
mode: 1,
},
},
},
],
fee: {
gasLimit: Long.fromNumber(gasLimit),
payer: "",
granter: "",
amount: [
{
denom: "nanolike",
amount: "0",
},
],
},
}
const authInfoBytes = AuthInfo.encode(authInfo).finish();
const signDoc = {
bodyBytes,
authInfoBytes,
chainId,
accountNumber: Long.fromNumber(accountNumber),
}
const signBytes = SignDoc.encode(signDoc).finish();
const privkeyBytes = Buffer.from(privateKey, 'hex')
const sign = (msg, privateKey) => {
const msgSha256 = createHash('sha256');
msgSha256.update(msg);
const msgHash = msgSha256.digest();
const { signature: signatureArr } = secp256k1.ecdsaSign(msgHash, privateKey);
const signature = Buffer.from(signatureArr)
return signature;
}
const signatureBytes = sign(signBytes, privkeyBytes);
const tx = {
bodyBytes,
authInfoBytes,
signatures: [signatureBytes],
}
const txBytes = TxRaw.encode(tx).finish();
console.log("signature_bytes:", signatureBytes.toString('base64'));
console.log("sign_bytes:", signBytes.toString('base64'));
console.log("tx_bytes:", txBytes.toString('base64'));
// signature_bytes: zIfF132OINwGz0psHn+nxeYVQdHZXiqO/94qaXrowcRFEL2jA0qFarz22VBXYXQudOV6y0BL84/m475awNkiFA==
// sign_bytes: CqgBCpMBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnMKLWNvc21vczFsc2FnZnpybTRnejI4aGU0d3VudDYzc3RzNXh6bWN6dzhwa2VrMxItY29zbW9zMW1ueW43eDI0eGo2dnJheGVlcTU2ZGZreGEwMDl0dmhna25obTA0GhMKCG5hbm9saWtlEgcxMDAwMDAwEhBFbmpveSB5b3VyIG1vbmV5EmcKUApGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQOBY9WOJO+0GsbsuPegh2Adq6X1l5DNywp5cq1PHimx+xIECgIIARgREhMKDQoIbmFub2xpa2USATAQoI0GGhdsaWtlY2hhaW4tbG9jYWwtdGVzdG5ldCAC
// tx_bytes: CqgBCpMBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnMKLWNvc21vczFsc2FnZnpybTRnejI4aGU0d3VudDYzc3RzNXh6bWN6dzhwa2VrMxItY29zbW9zMW1ueW43eDI0eGo2dnJheGVlcTU2ZGZreGEwMDl0dmhna25obTA0GhMKCG5hbm9saWtlEgcxMDAwMDAwEhBFbmpveSB5b3VyIG1vbmV5EmcKUApGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQOBY9WOJO+0GsbsuPegh2Adq6X1l5DNywp5cq1PHimx+xIECgIIARgREhMKDQoIbmFub2xpa2USATAQoI0GGkDMh8XXfY4g3AbPSmwef6fF5hVB0dleKo7/3ippeujBxEUQvaMDSoVqvPbZUFdhdC505XrLQEvzj+bjvlrA2SIU
Commit a Transaction
Put the tx_bytes
from above step in the JSON request body as below, and post the LCD/cosmos/tx/v1beta1/txs
endpoint.
{
"tx_bytes": "Your tx bytes here",
"mode": "BROADCAST_MODE_SYNC"
}
For details of the POST /txs
and other chain RPC API, please refer to the LikeCoin chain RPC API section.
Verify Transaction Signature
const secp256k1 = require('secp256k1');
const createHash = require('create-hash');
const publicKey = Buffer.from("A4Fj1Y4k77Qaxuy496CHYB2rpfWXkM3LCnlyrU8eKbH7", "base64");
const signature = Buffer.from("zIfF132OINwGz0psHn+nxeYVQdHZXiqO/94qaXrowcRFEL2jA0qFarz22VBXYXQudOV6y0BL84/m475awNkiFA==", "base64");
const signBytes = Buffer.from("CqgBCpMBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEnMKLWNvc21vczFsc2FnZnpybTRnejI4aGU0d3VudDYzc3RzNXh6bWN6dzhwa2VrMxItY29zbW9zMW1ueW43eDI0eGo2dnJheGVlcTU2ZGZreGEwMDl0dmhna25obTA0GhMKCG5hbm9saWtlEgcxMDAwMDAwEhBFbmpveSB5b3VyIG1vbmV5EmcKUApGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQOBY9WOJO+0GsbsuPegh2Adq6X1l5DNywp5cq1PHimx+xIECgIIARgREhMKDQoIbmFub2xpa2USATAQoI0GGhdsaWtlY2hhaW4tbG9jYWwtdGVzdG5ldCAC", "base64");
const msgSha256 = createHash('sha256');
msgSha256.update(signBytes);
const msgHash = msgSha256.digest();
console.log(secp256k1.ecdsaVerify(signature, msgHash, publicKey));
// true
Last updated