mcps-sdk-js
Version:
MCPS JavaScript SDK
314 lines • 11.7 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tx = void 0;
const is = require("is_js");
const types = require("../types");
const errors_1 = require("../errors");
const utils_1 = require("../utils");
/**
* Tx module allows you to sign or broadcast transactions
*
* @category Modules
* @since v0.17
*/
class Tx {
/** @hidden */
constructor(client) {
this.client = client;
}
/**
* Build Tx
* @param msgs Msgs to be sent
* @param baseTx
* @returns unsignedTx
* @since v0.17
*/
buildTx(msgs, baseTx) {
let msgList = msgs.map(msg => {
return this.createMsg(msg);
});
const unsignedTx = this.client.auth.newStdTx(msgList, baseTx);
return unsignedTx;
}
/**
* generate StdTx from protoTxModel
* @param {[type]} protoTxModel:any instance of cosmos.tx.v1beta1.Tx
* @return {[type]} unsignedTx
*/
newStdTxFromProtoTxModel(protoTxModel) {
return types.ProtoTx.newStdTxFromProtoTxModel(protoTxModel);
}
/**
* Build, sign and broadcast the msgs
* @param msgs Msgs to be sent
* @param baseTx
* @returns
* @since v0.17
*/
buildAndSend(msgs, baseTx) {
return __awaiter(this, void 0, void 0, function* () {
// Build Unsigned Tx
const unsignedTx = this.buildTx(msgs, baseTx);
// Not supported in ibc-alpha
// const fee = await this.client.utils.toMinCoins(unsignedTx.value.fee.amount);
// unsignedTx.value.fee.amount = fee;
// Sign Tx
const signedTx = yield this.sign(unsignedTx, baseTx);
// Broadcast Tx
return this.broadcast(signedTx, baseTx.mode);
});
}
/**
* Broadcast a tx
* @param signedTx The tx object with signatures
* @param mode Broadcast mode
* @returns
* @since v0.17
*/
broadcast(signedTx, mode) {
const txBytes = signedTx.getData();
switch (mode) {
case types.BroadcastMode.Commit:
return this.broadcastTxCommit(txBytes);
case types.BroadcastMode.Sync:
return this.broadcastTxSync(txBytes).then(response => {
return this.newTxResult(response);
});
default:
return this.broadcastTxAsync(txBytes).then(response => {
return this.newTxResult(response);
});
}
}
/**
* Single sign a transaction
*
* @param stdTx StdTx with no signatures
* @param baseTx baseTx.from && baseTx.password is requred
* @returns The signed tx
* @since v0.17
*/
sign(stdTx, baseTx) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (is.empty(baseTx.from)) {
throw new errors_1.SdkError(`baseTx.from of the key can not be empty`);
}
if (is.empty(baseTx.password)) {
throw new errors_1.SdkError(`baseTx.password of the key can not be empty`);
}
if (!this.client.config.keyDAO.decrypt) {
throw new errors_1.SdkError(`Decrypt method of KeyDAO not implemented`);
}
const keyObj = this.client.config.keyDAO.read(baseTx.from);
if (!keyObj) {
throw new errors_1.SdkError(`Key with name '${baseTx.from}' not found`);
}
let accountNumber = (_a = baseTx.account_number) !== null && _a !== void 0 ? _a : '0';
let sequence = baseTx.sequence || '0';
if (!baseTx.account_number || !baseTx.sequence) {
const account = yield this.client.bank.queryAccount(keyObj.address);
if (account.account_number) {
accountNumber = account.account_number;
}
if (account.sequence) {
sequence = account.sequence;
}
}
// Query account info from block chain
const privKey = this.client.config.keyDAO.decrypt(keyObj.privKey, baseTx.password);
if (!stdTx.hasPubKey()) {
const pubKey = utils_1.Crypto.getPublicKeyFromPrivateKey(privKey, baseTx.pubkeyType);
stdTx.setPubKey(pubKey, sequence || undefined);
}
const signature = utils_1.Crypto.generateSignature(stdTx.getSignDoc(accountNumber || undefined, this.client.config.chainId).serializeBinary(), privKey, baseTx.pubkeyType);
stdTx.addSignature(signature);
return stdTx;
});
}
/**
* Single sign a transaction with signDoc
*
* @param signDoc from protobuf
* @param name Name of the key to sign the tx
* @param password Password of the key
* @param type pubkey Type
* @returns signature
* @since v0.17
*/
sign_signDoc(signDoc, name, password, type = types.PubkeyType.secp256k1) {
if (is.empty(name)) {
throw new errors_1.SdkError(`Name of the key can not be empty`);
}
if (is.empty(password)) {
throw new errors_1.SdkError(`Password of the key can not be empty`);
}
if (!this.client.config.keyDAO.decrypt) {
throw new errors_1.SdkError(`Decrypt method of KeyDAO not implemented`);
}
const keyObj = this.client.config.keyDAO.read(name);
if (!keyObj) {
throw new errors_1.SdkError(`Key with name '${name}' not found`);
}
const privKey = this.client.config.keyDAO.decrypt(keyObj.privKey, password);
const signature = utils_1.Crypto.generateSignature(signDoc, privKey, type);
return signature;
}
/**
* Broadcast tx async
* @param txBytes The tx bytes with signatures
* @returns
*/
broadcastTxAsync(txBytes) {
return this.broadcastTx(txBytes, types.RpcMethods.BroadcastTxAsync);
}
/**
* Broadcast tx sync
* @param txBytes The tx bytes with signatures
* @returns The result object of broadcasting
*/
broadcastTxSync(txBytes) {
return this.broadcastTx(txBytes, types.RpcMethods.BroadcastTxSync);
}
/**
* Broadcast tx and wait for it to be included in a block.
* @param txBytes The tx bytes with signatures
* @returns The result object of broadcasting
*/
broadcastTxCommit(txBytes) {
return this.client.rpcClient
.request(types.RpcMethods.BroadcastTxCommit, {
tx: utils_1.Utils.bytesToBase64(txBytes),
})
.then(response => {
// Check tx error
if (response.check_tx && response.check_tx.code > 0) {
console.error(response.check_tx);
throw new errors_1.SdkError(response.check_tx.log, response.check_tx.code);
}
// Deliver tx error
if (response.deliver_tx && response.deliver_tx.code > 0) {
console.error(response.deliver_tx);
throw new errors_1.SdkError(response.deliver_tx.log, response.deliver_tx.code);
}
if (response.deliver_tx && response.deliver_tx.tags) {
response.deliver_tx.tags = utils_1.Utils.decodeTags(response.deliver_tx.tags);
}
return this.newTxResult(response);
});
}
/**
* Broadcast tx sync or async
* @private
* @param signedTx The tx object with signatures
* @returns The result object of broadcasting
*/
broadcastTx(txBytes, method) {
// Only accepts 'broadcast_tx_sync' and 'broadcast_tx_async'
if (is.not.inArray(method, [
types.RpcMethods.BroadcastTxSync,
types.RpcMethods.BroadcastTxAsync,
])) {
throw new errors_1.SdkError(`Unsupported broadcast method: ${method}`);
}
return this.client.rpcClient
.request(method, {
tx: utils_1.Utils.bytesToBase64(txBytes),
})
.then(response => {
if (response.code && response.code > 0) {
throw new errors_1.SdkError(response.log, response.code);
}
return response;
});
}
// private marshal(stdTx: types.Tx<types.StdTx>): types.Tx<types.StdTx> {
// const copyStdTx: types.Tx<types.StdTx> = stdTx;
// Object.assign(copyStdTx, stdTx);
// stdTx.value.msg.forEach((msg, idx) => {
// if (msg.marshal) {
// copyStdTx.value.msg[idx] = msg.marshal();
// }
// });
// return copyStdTx;
// }
newTxResult(txRespond) {
const txResult = { hash: txRespond.hash };
if (txRespond.height) {
txResult.height = txRespond.height;
}
;
if (txRespond.deliver_tx) {
try {
txResult.log = JSON.parse(txRespond.deliver_tx.log);
}
catch (e) {
txResult.log = txRespond.deliver_tx.log;
}
txResult.info = txRespond.deliver_tx.info;
txResult.gas_wanted = txRespond.deliver_tx.gas_wanted;
txResult.gas_used = txRespond.deliver_tx.gas_used;
txResult.events = txRespond.deliver_tx.events;
}
return txResult;
}
/**
* create message
* @param {[type]} txMsg:{type:string, value:any} message
* @return {[type]} message instance of types.Msg
*/
createMsg(txMsg) {
let msg = {};
switch (txMsg.type) {
//bank
case types.TxType.MsgSend: {
msg = new types.MsgSend(txMsg.value);
break;
}
case types.TxType.MsgMultiSend: {
msg = new types.MsgMultiSend(txMsg.value);
break;
}
//contract
case types.TxType.MsgStoreCode: {
msg = new types.MsgStoreCode(txMsg.value);
break;
}
case types.TxType.MsgInstantiateContract: {
msg = new types.MsgInstantiateContract(txMsg.value);
break;
}
case types.TxType.MsgExecuteContract: {
msg = new types.MsgExecuteContract(txMsg.value);
break;
}
case types.TxType.MsgMigrateContract: {
msg = new types.MsgMigrateContract(txMsg.value);
break;
}
case types.TxType.MsgUpdateAdmin: {
msg = new types.MsgUpdateAdmin(txMsg.value);
break;
}
case types.TxType.MsgClearAdmin: {
msg = new types.MsgClearAdmin(txMsg.value);
break;
}
default: {
throw new Error("not exist tx type");
}
}
return msg;
}
}
exports.Tx = Tx;
//# sourceMappingURL=tx.js.map
;