diff --git a/config.json b/config.json index 7845c37..24c65aa 100644 --- a/config.json +++ b/config.json @@ -25,6 +25,14 @@ "type": "withdraw_delegation_reward", "prefix": "irishub/distr/MsgWithdrawDelegationReward" }, + "deposit": { + "type": "deposit", + "prefix": "irishub/gov/MsgDeposit" + }, + "vote": { + "type": "vote", + "prefix": "irishub/gov/MsgVote" + }, "stdTx": { "type": "", "prefix": "irishub/bank/StdTx" @@ -53,7 +61,7 @@ "keystore": { "kdf": "pbkdf2", "cipherAlg": "aes-128-ctr", - "c": 262144 + "c": 10000 } }, "cosmos": { @@ -86,9 +94,17 @@ "type": "withdraw_validator_commission", "prefix": "cosmos-sdk/MsgWithdrawValidatorCommission" }, + "deposit": { + "type": "deposit", + "prefix": "cosmos-sdk/MsgDeposit" + }, + "vote": { + "type": "vote", + "prefix": "cosmos-sdk/MsgVote" + }, "stdTx": { "type": "stdTx", - "prefix": "auth/StdTx" + "prefix": "cosmos-sdk/StdTx" } }, "bech32": { @@ -119,4 +135,4 @@ "ethermint": "ethermint", "cosmos": "cosmos" } -} \ No newline at end of file +} diff --git a/index.js b/index.js index 5133f07..3318a60 100644 --- a/index.js +++ b/index.js @@ -29,5 +29,4 @@ function setNetwork(network){ } return config } - module.exports = {getCrypto,getBuilder,config,Codec}; \ No newline at end of file diff --git a/package.json b/package.json index 61d5810..562c775 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "irisnet-crypto", - "version": "1.3.3", + "version": "1.3.4", "description": "irisnet-crypto", "main": "index.js", "scripts": { @@ -27,7 +27,7 @@ "bech32": "^1.1.3", "bignumber.js": "^5.0.0", "bip39": "^2.5.0", - "bn": "git+https://github.com/shineabel/bn.git", + "bn": "git+https://github.com/irisnet/bn.js.git#v4.12.0", "create-hmac": "^1.1.7", "ethereumjs-tx": "^1.3.0", "ethereumjs-util": "^5.1.2", diff --git a/src/chains/base.js b/src/chains/base.js index 9699386..56d29c6 100644 --- a/src/chains/base.js +++ b/src/chains/base.js @@ -87,6 +87,8 @@ amino.RegisterConcrete(R_Cosmos.cosmos.MsgWithdrawDelegatorReward, Config.cosmos amino.RegisterConcrete(R_Cosmos.cosmos.MsgWithdrawValidatorCommission, Config.cosmos.tx.withdrawValidatorCommission.prefix); amino.RegisterConcrete(R_Cosmos.cosmos.MsgUndelegate, Config.cosmos.tx.undelegate.prefix); amino.RegisterConcrete(R_Cosmos.cosmos.MsgBeginRedelegate, Config.cosmos.tx.beginRedelegate.prefix); +amino.RegisterConcrete(R_Cosmos.cosmos.MsgDeposit, Config.cosmos.tx.deposit.prefix); +amino.RegisterConcrete(R_Cosmos.cosmos.MsgVote, Config.cosmos.tx.vote.prefix); amino.RegisterConcrete(R_Cosmos.cosmos.StdTx, Config.cosmos.tx.stdTx.prefix); amino.RegisterConcrete(null, Config.iris.amino.pubKey); @@ -97,5 +99,7 @@ amino.RegisterConcrete(R_Iris.irisnet.tx.MsgBeginRedelegate, Config.iris.tx.rede amino.RegisterConcrete(R_Iris.irisnet.tx.MsgBeginUnbonding, Config.iris.tx.undelegate.prefix); amino.RegisterConcrete(R_Iris.irisnet.tx.MsgWithdrawDelegatorRewardsAll, Config.iris.tx.withdrawDelegationRewardsAll.prefix); amino.RegisterConcrete(R_Iris.irisnet.tx.MsgWithdrawDelegatorReward, Config.iris.tx.withdrawDelegationReward.prefix); +amino.RegisterConcrete(R_Iris.irisnet.tx.MsgDeposit, Config.iris.tx.deposit.prefix); +amino.RegisterConcrete(R_Iris.irisnet.tx.MsgVote, Config.iris.tx.vote.prefix); amino.RegisterConcrete(R_Iris.irisnet.tx.StdTx, Config.iris.tx.stdTx.prefix); -module.exports = amino; \ No newline at end of file +module.exports = amino; diff --git a/src/chains/cosmos/builder.js b/src/chains/cosmos/builder.js index 8f836cc..b5f7479 100644 --- a/src/chains/cosmos/builder.js +++ b/src/chains/cosmos/builder.js @@ -4,6 +4,7 @@ const Old = require('old'); const Bank = require('./bank'); const Stake = require('./stake'); const Distribution = require('./distribution'); +const Gov = require('./gov'); const CosmosKeypair = require('./keypair'); const Codec = require("../../util/codec"); const Config = require('../../../config'); @@ -50,6 +51,14 @@ class CosmosBuilder extends Builder { msg = Distribution.CreateMsgWithdrawValidatorCommission(req); break; } + case Config.cosmos.tx.deposit.type: { + msg = Gov.createMsgDeposit(req); + break; + } + case Config.cosmos.tx.vote.type: { + msg = Gov.createMsgVote(req); + break; + } default: { throw new Error("not exist tx type"); } diff --git a/src/chains/cosmos/gov.js b/src/chains/cosmos/gov.js new file mode 100644 index 0000000..557492f --- /dev/null +++ b/src/chains/cosmos/gov.js @@ -0,0 +1,141 @@ +const Config = require('../../../config'); +const Root = require('./tx/tx'); +const BECH32 = require('bech32'); +const Utils = require('../../util/utils'); +const Amino = require("../base"); + +const voteOptionMapping = { + 0x00: 'Empty', + 0x01: 'Yes', + 0x02: 'Abstain', + 0x03: 'No', + 0x04: 'NoWithVeto' +}; + +const MsgDeposit = Root.cosmos.MsgDeposit; +MsgDeposit.prototype.type = Config.cosmos.tx.deposit.prefix; +MsgDeposit.prototype.GetSignBytes = function () { + let depositor = BECH32.encode(Config.cosmos.bech32.accAddr, this.depositor); + let signMsg = { + proposal_id: `${this.proposalID}`, + depositor: depositor, + amount: this.amount + }; + let sortMsg = Utils.sortObjectKeys(signMsg); + return Amino.MarshalJSON(this.type, sortMsg) +}; + +MsgDeposit.prototype.ValidateBasic = function () { + if (Utils.isEmpty(this.amount)) { + throw new Error("amount is empty"); + } + if (Utils.isEmpty(this.proposalID)) { + throw new Error("proposal_id is empty"); + } + if (Utils.isEmpty(this.depositor)) { + throw new Error("depositor is empty"); + } +}; + +MsgDeposit.prototype.GetMsg = function () { + let depositor = BECH32.fromWords(this.depositor); + return { + proposalID: this.proposalID, + depositor: depositor, + amount: this.amount + } +}; + +MsgDeposit.prototype.GetDisplayContent = function () { + let depositor = BECH32.encode(Config.cosmos.bech32.accAddr, this.depositor); + return { + i18n_tx_type: "i18n_deposit", + i18n_proposal_id:this.proposalID, + i18n_depositor: depositor, + i18n_amount: this.amount + } +}; +MsgDeposit.prototype.toJSON = function () { + let depositor = BECH32.encode(Config.cosmos.bech32.accAddr, this.depositor); + return { + proposal_id: this.proposalID, + depositor: depositor, + amount: this.amount + } +}; + +const MsgVote = Root.cosmos.MsgVote; +MsgVote.prototype.type = Config.cosmos.tx.vote.prefix; +MsgVote.prototype.GetSignBytes = function () { + let voter = BECH32.encode(Config.cosmos.bech32.accAddr, this.voter); + let signMsg = { + proposal_id: `${this.proposalID}`, + voter: voter, + option: voteOptionMapping[this.option] + }; + let sortMsg = Utils.sortObjectKeys(signMsg); + return Amino.MarshalJSON(this.type, sortMsg) +}; +MsgVote.prototype.ValidateBasic = function () { + if (Utils.isEmpty(this.option)) { + throw new Error("option is empty"); + } + if (Utils.isEmpty(this.proposalID)) { + throw new Error("proposal_id is empty"); + } + if (Utils.isEmpty(this.voter)) { + throw new Error("voter is empty"); + } +}; +MsgVote.prototype.GetMsg = function () { + let voter = BECH32.fromWords(this.voter); + return { + proposalID: this.proposalID, + voter: voter, + option: this.option + } +}; +MsgVote.prototype.GetDisplayContent = function () { + let voter = BECH32.encode(Config.cosmos.bech32.accAddr, this.voter); + return { + i18n_tx_type: "i18n_vote", + i18n_proposal_id: this.proposalID, + i18n_voter: voter, + option: voteOptionMapping[this.option] + } +}; +MsgVote.prototype.toJSON = function () { + let voter = BECH32.encode(Config.cosmos.bech32.accAddr, this.voter); + return { + proposal_id: this.proposalID, + voter: voter, + option: voteOptionMapping[this.option] + } +}; + +module.exports = class Gov { + static createMsgDeposit(req){ + let coins = []; + if (!Utils.isEmpty(req.msg.amount)) { + req.msg.amount.forEach(function(item) { + coins.push({ + denom: item.denom, + amount: Utils.toString(item.amount), + }); + }); + } + return new MsgDeposit({ + proposalID: `${req.msg.proposal_id}`, + depositor: BECH32.decode(req.from).words, + amount: coins + }) + } + + static createMsgVote(req){ + return new MsgVote({ + proposalID: `${req.msg.proposal_id}`, + voter: BECH32.decode(req.from).words, + option: req.msg.option + }) + } +}; diff --git a/src/chains/cosmos/proto/tx.proto b/src/chains/cosmos/proto/tx.proto index 4dd1291..2ea37ce 100644 --- a/src/chains/cosmos/proto/tx.proto +++ b/src/chains/cosmos/proto/tx.proto @@ -45,6 +45,18 @@ message MsgWithdrawValidatorCommission { required bytes ValidatorAddress = 1; } +message MsgDeposit { + required int64 proposalID = 1; + required bytes depositor = 2; + repeated Coin amount = 3; +} + +message MsgVote { + required int64 proposalID = 1; + required bytes voter = 2; + required uint64 option = 3; +} + message StdFee { repeated Coin amount = 1; required int64 gas = 2; diff --git a/src/chains/cosmos/tx/tx.js b/src/chains/cosmos/tx/tx.js index c6084f0..033a5be 100644 --- a/src/chains/cosmos/tx/tx.js +++ b/src/chains/cosmos/tx/tx.js @@ -1951,6 +1951,552 @@ $root.cosmos = (function() { return MsgWithdrawValidatorCommission; })(); + cosmos.MsgDeposit = (function() { + + /** + * Properties of a MsgDeposit. + * @memberof cosmos + * @interface IMsgDeposit + * @property {number|Long} proposalID MsgDeposit proposalID + * @property {Uint8Array} depositor MsgDeposit depositor + * @property {Array.|null} [amount] MsgDeposit amount + */ + + /** + * Constructs a new MsgDeposit. + * @memberof cosmos + * @classdesc Represents a MsgDeposit. + * @implements IMsgDeposit + * @constructor + * @param {cosmos.IMsgDeposit=} [properties] Properties to set + */ + function MsgDeposit(properties) { + this.amount = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MsgDeposit proposalID. + * @member {number|Long} proposalID + * @memberof cosmos.MsgDeposit + * @instance + */ + MsgDeposit.prototype.proposalID = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * MsgDeposit depositor. + * @member {Uint8Array} depositor + * @memberof cosmos.MsgDeposit + * @instance + */ + MsgDeposit.prototype.depositor = $util.newBuffer([]); + + /** + * MsgDeposit amount. + * @member {Array.} amount + * @memberof cosmos.MsgDeposit + * @instance + */ + MsgDeposit.prototype.amount = $util.emptyArray; + + /** + * Creates a new MsgDeposit instance using the specified properties. + * @function create + * @memberof cosmos.MsgDeposit + * @static + * @param {cosmos.IMsgDeposit=} [properties] Properties to set + * @returns {cosmos.MsgDeposit} MsgDeposit instance + */ + MsgDeposit.create = function create(properties) { + return new MsgDeposit(properties); + }; + + /** + * Encodes the specified MsgDeposit message. Does not implicitly {@link cosmos.MsgDeposit.verify|verify} messages. + * @function encode + * @memberof cosmos.MsgDeposit + * @static + * @param {cosmos.IMsgDeposit} message MsgDeposit message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgDeposit.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + writer.uint32(/* id 1, wireType 0 =*/8).int64(message.proposalID); + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.depositor); + if (message.amount != null && message.amount.length) + for (var i = 0; i < message.amount.length; ++i) + $root.cosmos.Coin.encode(message.amount[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified MsgDeposit message, length delimited. Does not implicitly {@link cosmos.MsgDeposit.verify|verify} messages. + * @function encodeDelimited + * @memberof cosmos.MsgDeposit + * @static + * @param {cosmos.IMsgDeposit} message MsgDeposit message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgDeposit.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MsgDeposit message from the specified reader or buffer. + * @function decode + * @memberof cosmos.MsgDeposit + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {cosmos.MsgDeposit} MsgDeposit + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgDeposit.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.cosmos.MsgDeposit(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.proposalID = reader.int64(); + break; + case 2: + message.depositor = reader.bytes(); + break; + case 3: + if (!(message.amount && message.amount.length)) + message.amount = []; + message.amount.push($root.cosmos.Coin.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + if (!message.hasOwnProperty("proposalID")) + throw $util.ProtocolError("missing required 'proposalID'", { instance: message }); + if (!message.hasOwnProperty("depositor")) + throw $util.ProtocolError("missing required 'depositor'", { instance: message }); + return message; + }; + + /** + * Decodes a MsgDeposit message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof cosmos.MsgDeposit + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {cosmos.MsgDeposit} MsgDeposit + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgDeposit.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MsgDeposit message. + * @function verify + * @memberof cosmos.MsgDeposit + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MsgDeposit.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (!$util.isInteger(message.proposalID) && !(message.proposalID && $util.isInteger(message.proposalID.low) && $util.isInteger(message.proposalID.high))) + return "proposalID: integer|Long expected"; + if (!(message.depositor && typeof message.depositor.length === "number" || $util.isString(message.depositor))) + return "depositor: buffer expected"; + if (message.amount != null && message.hasOwnProperty("amount")) { + if (!Array.isArray(message.amount)) + return "amount: array expected"; + for (var i = 0; i < message.amount.length; ++i) { + var error = $root.cosmos.Coin.verify(message.amount[i]); + if (error) + return "amount." + error; + } + } + return null; + }; + + /** + * Creates a MsgDeposit message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof cosmos.MsgDeposit + * @static + * @param {Object.} object Plain object + * @returns {cosmos.MsgDeposit} MsgDeposit + */ + MsgDeposit.fromObject = function fromObject(object) { + if (object instanceof $root.cosmos.MsgDeposit) + return object; + var message = new $root.cosmos.MsgDeposit(); + if (object.proposalID != null) + if ($util.Long) + (message.proposalID = $util.Long.fromValue(object.proposalID)).unsigned = false; + else if (typeof object.proposalID === "string") + message.proposalID = parseInt(object.proposalID, 10); + else if (typeof object.proposalID === "number") + message.proposalID = object.proposalID; + else if (typeof object.proposalID === "object") + message.proposalID = new $util.LongBits(object.proposalID.low >>> 0, object.proposalID.high >>> 0).toNumber(); + if (object.depositor != null) + if (typeof object.depositor === "string") + $util.base64.decode(object.depositor, message.depositor = $util.newBuffer($util.base64.length(object.depositor)), 0); + else if (object.depositor.length) + message.depositor = object.depositor; + if (object.amount) { + if (!Array.isArray(object.amount)) + throw TypeError(".cosmos.MsgDeposit.amount: array expected"); + message.amount = []; + for (var i = 0; i < object.amount.length; ++i) { + if (typeof object.amount[i] !== "object") + throw TypeError(".cosmos.MsgDeposit.amount: object expected"); + message.amount[i] = $root.cosmos.Coin.fromObject(object.amount[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a MsgDeposit message. Also converts values to other types if specified. + * @function toObject + * @memberof cosmos.MsgDeposit + * @static + * @param {cosmos.MsgDeposit} message MsgDeposit + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MsgDeposit.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.amount = []; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.proposalID = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.proposalID = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.depositor = ""; + else { + object.depositor = []; + if (options.bytes !== Array) + object.depositor = $util.newBuffer(object.depositor); + } + } + if (message.proposalID != null && message.hasOwnProperty("proposalID")) + if (typeof message.proposalID === "number") + object.proposalID = options.longs === String ? String(message.proposalID) : message.proposalID; + else + object.proposalID = options.longs === String ? $util.Long.prototype.toString.call(message.proposalID) : options.longs === Number ? new $util.LongBits(message.proposalID.low >>> 0, message.proposalID.high >>> 0).toNumber() : message.proposalID; + if (message.depositor != null && message.hasOwnProperty("depositor")) + object.depositor = options.bytes === String ? $util.base64.encode(message.depositor, 0, message.depositor.length) : options.bytes === Array ? Array.prototype.slice.call(message.depositor) : message.depositor; + if (message.amount && message.amount.length) { + object.amount = []; + for (var j = 0; j < message.amount.length; ++j) + object.amount[j] = $root.cosmos.Coin.toObject(message.amount[j], options); + } + return object; + }; + + /** + * Converts this MsgDeposit to JSON. + * @function toJSON + * @memberof cosmos.MsgDeposit + * @instance + * @returns {Object.} JSON object + */ + MsgDeposit.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MsgDeposit; + })(); + + cosmos.MsgVote = (function() { + + /** + * Properties of a MsgVote. + * @memberof cosmos + * @interface IMsgVote + * @property {number|Long} proposalID MsgVote proposalID + * @property {Uint8Array} voter MsgVote voter + * @property {number|Long} option MsgVote option + */ + + /** + * Constructs a new MsgVote. + * @memberof cosmos + * @classdesc Represents a MsgVote. + * @implements IMsgVote + * @constructor + * @param {cosmos.IMsgVote=} [properties] Properties to set + */ + function MsgVote(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MsgVote proposalID. + * @member {number|Long} proposalID + * @memberof cosmos.MsgVote + * @instance + */ + MsgVote.prototype.proposalID = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * MsgVote voter. + * @member {Uint8Array} voter + * @memberof cosmos.MsgVote + * @instance + */ + MsgVote.prototype.voter = $util.newBuffer([]); + + /** + * MsgVote option. + * @member {number|Long} option + * @memberof cosmos.MsgVote + * @instance + */ + MsgVote.prototype.option = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Creates a new MsgVote instance using the specified properties. + * @function create + * @memberof cosmos.MsgVote + * @static + * @param {cosmos.IMsgVote=} [properties] Properties to set + * @returns {cosmos.MsgVote} MsgVote instance + */ + MsgVote.create = function create(properties) { + return new MsgVote(properties); + }; + + /** + * Encodes the specified MsgVote message. Does not implicitly {@link cosmos.MsgVote.verify|verify} messages. + * @function encode + * @memberof cosmos.MsgVote + * @static + * @param {cosmos.IMsgVote} message MsgVote message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgVote.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + writer.uint32(/* id 1, wireType 0 =*/8).int64(message.proposalID); + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.voter); + writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.option); + return writer; + }; + + /** + * Encodes the specified MsgVote message, length delimited. Does not implicitly {@link cosmos.MsgVote.verify|verify} messages. + * @function encodeDelimited + * @memberof cosmos.MsgVote + * @static + * @param {cosmos.IMsgVote} message MsgVote message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgVote.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MsgVote message from the specified reader or buffer. + * @function decode + * @memberof cosmos.MsgVote + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {cosmos.MsgVote} MsgVote + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgVote.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.cosmos.MsgVote(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.proposalID = reader.int64(); + break; + case 2: + message.voter = reader.bytes(); + break; + case 3: + message.option = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + if (!message.hasOwnProperty("proposalID")) + throw $util.ProtocolError("missing required 'proposalID'", { instance: message }); + if (!message.hasOwnProperty("voter")) + throw $util.ProtocolError("missing required 'voter'", { instance: message }); + if (!message.hasOwnProperty("option")) + throw $util.ProtocolError("missing required 'option'", { instance: message }); + return message; + }; + + /** + * Decodes a MsgVote message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof cosmos.MsgVote + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {cosmos.MsgVote} MsgVote + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgVote.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MsgVote message. + * @function verify + * @memberof cosmos.MsgVote + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MsgVote.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (!$util.isInteger(message.proposalID) && !(message.proposalID && $util.isInteger(message.proposalID.low) && $util.isInteger(message.proposalID.high))) + return "proposalID: integer|Long expected"; + if (!(message.voter && typeof message.voter.length === "number" || $util.isString(message.voter))) + return "voter: buffer expected"; + if (!$util.isInteger(message.option) && !(message.option && $util.isInteger(message.option.low) && $util.isInteger(message.option.high))) + return "option: integer|Long expected"; + return null; + }; + + /** + * Creates a MsgVote message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof cosmos.MsgVote + * @static + * @param {Object.} object Plain object + * @returns {cosmos.MsgVote} MsgVote + */ + MsgVote.fromObject = function fromObject(object) { + if (object instanceof $root.cosmos.MsgVote) + return object; + var message = new $root.cosmos.MsgVote(); + if (object.proposalID != null) + if ($util.Long) + (message.proposalID = $util.Long.fromValue(object.proposalID)).unsigned = false; + else if (typeof object.proposalID === "string") + message.proposalID = parseInt(object.proposalID, 10); + else if (typeof object.proposalID === "number") + message.proposalID = object.proposalID; + else if (typeof object.proposalID === "object") + message.proposalID = new $util.LongBits(object.proposalID.low >>> 0, object.proposalID.high >>> 0).toNumber(); + if (object.voter != null) + if (typeof object.voter === "string") + $util.base64.decode(object.voter, message.voter = $util.newBuffer($util.base64.length(object.voter)), 0); + else if (object.voter.length) + message.voter = object.voter; + if (object.option != null) + if ($util.Long) + (message.option = $util.Long.fromValue(object.option)).unsigned = true; + else if (typeof object.option === "string") + message.option = parseInt(object.option, 10); + else if (typeof object.option === "number") + message.option = object.option; + else if (typeof object.option === "object") + message.option = new $util.LongBits(object.option.low >>> 0, object.option.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a MsgVote message. Also converts values to other types if specified. + * @function toObject + * @memberof cosmos.MsgVote + * @static + * @param {cosmos.MsgVote} message MsgVote + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MsgVote.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.proposalID = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.proposalID = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.voter = ""; + else { + object.voter = []; + if (options.bytes !== Array) + object.voter = $util.newBuffer(object.voter); + } + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.option = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.option = options.longs === String ? "0" : 0; + } + if (message.proposalID != null && message.hasOwnProperty("proposalID")) + if (typeof message.proposalID === "number") + object.proposalID = options.longs === String ? String(message.proposalID) : message.proposalID; + else + object.proposalID = options.longs === String ? $util.Long.prototype.toString.call(message.proposalID) : options.longs === Number ? new $util.LongBits(message.proposalID.low >>> 0, message.proposalID.high >>> 0).toNumber() : message.proposalID; + if (message.voter != null && message.hasOwnProperty("voter")) + object.voter = options.bytes === String ? $util.base64.encode(message.voter, 0, message.voter.length) : options.bytes === Array ? Array.prototype.slice.call(message.voter) : message.voter; + if (message.option != null && message.hasOwnProperty("option")) + if (typeof message.option === "number") + object.option = options.longs === String ? String(message.option) : message.option; + else + object.option = options.longs === String ? $util.Long.prototype.toString.call(message.option) : options.longs === Number ? new $util.LongBits(message.option.low >>> 0, message.option.high >>> 0).toNumber(true) : message.option; + return object; + }; + + /** + * Converts this MsgVote to JSON. + * @function toJSON + * @memberof cosmos.MsgVote + * @instance + * @returns {Object.} JSON object + */ + MsgVote.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MsgVote; + })(); + cosmos.StdFee = (function() { /** diff --git a/src/chains/iris/bank.js b/src/chains/iris/bank.js index 77acb8c..0a31cfa 100644 --- a/src/chains/iris/bank.js +++ b/src/chains/iris/bank.js @@ -331,7 +331,7 @@ class StdTx { } module.exports = class Bank { - static CreateMsgSend(req) { + static createMsgSend(req) { let coins = []; if (!Utils.isEmpty(req.msg.coins)) { req.msg.coins.forEach(function(item) { @@ -360,4 +360,4 @@ module.exports = class Bank { static NewStdSignMsg(chainID, accnum, sequence, fee, msg, memo, msgType) { return new StdSignMsg(chainID, accnum, sequence, fee, msg, memo, msgType) } -}; \ No newline at end of file +}; diff --git a/src/chains/iris/builder.js b/src/chains/iris/builder.js index 22ea942..4631131 100644 --- a/src/chains/iris/builder.js +++ b/src/chains/iris/builder.js @@ -4,6 +4,7 @@ const Old = require('old'); const Bank = require('./bank'); const Stake = require('./stake'); const Distribution = require('./distribution'); +const Gov = require('./gov'); const IrisKeypair = require('./keypair'); const Codec = require("../../util/codec"); const Config = require('../../../config'); @@ -23,27 +24,35 @@ class IrisBuilder extends Builder { let msg; switch (req.type) { case Config.iris.tx.transfer.type: { - msg = Bank.CreateMsgSend(req); + msg = Bank.createMsgSend(req); break; } case Config.iris.tx.delegate.type: { - msg = Stake.CreateMsgDelegate(req); + msg = Stake.createMsgDelegate(req); break; } case Config.iris.tx.undelegate.type: { - msg = Stake.CreateMsgBeginUnbonding(req); + msg = Stake.createMsgBeginUnbonding(req); break; } case Config.iris.tx.redelegate.type: { - msg = Stake.CreateMsgBeginRedelegate(req); + msg = Stake.createMsgBeginRedelegate(req); break; } case Config.iris.tx.withdrawDelegationRewardsAll.type: { - msg = Distribution.CreateMsgWithdrawDelegatorRewardsAll(req); + msg = Distribution.createMsgWithdrawDelegatorRewardsAll(req); break; } case Config.iris.tx.withdrawDelegationReward.type: { - msg = Distribution.CreateMsgWithdrawDelegatorReward(req); + msg = Distribution.createMsgWithdrawDelegatorReward(req); + break; + } + case Config.iris.tx.deposit.type: { + msg = Gov.createMsgDeposit(req); + break; + } + case Config.iris.tx.vote.type: { + msg = Gov.createMsgVote(req); break; } default: { @@ -99,4 +108,4 @@ class IrisBuilder extends Builder { return stdTx } } -module.exports = Old(IrisBuilder); \ No newline at end of file +module.exports = Old(IrisBuilder); diff --git a/src/chains/iris/crypto.js b/src/chains/iris/crypto.js index 54614c2..69396e9 100644 --- a/src/chains/iris/crypto.js +++ b/src/chains/iris/crypto.js @@ -68,8 +68,8 @@ class IrisCrypto extends Crypto { return address; } - // @referance:https://github.com/binance-chain/javascript-sdk/blob/master/src/crypto/index.js - exportKeystore(privateKeyHex,password){ + // @see:https://github.com/binance-chain/javascript-sdk/blob/master/src/crypto/index.js + exportKeystore(privateKeyHex,password,opts = {}){ if (Utils.isEmpty(password) || password.length < 8){ throw new Error("password's length must be greater than 8") } @@ -78,14 +78,15 @@ class IrisCrypto extends Crypto { } const salt = Cryp.randomBytes(32); const iv = Cryp.randomBytes(16); - const cipherAlg = Config.iris.keystore.cipherAlg; - const kdf = Config.iris.keystore.kdf; + const cipherAlg = opts.cipherAlg ? opts.cipherAlg : Config.iris.keystore.cipherAlg; + const kdf = opts.kdf ? opts.kdf : Config.iris.keystore.kdf; + const c = opts.c ? opts.c : Config.iris.keystore.c; const address = this.import(privateKeyHex).address; const kdfparams = { dklen: 32, salt: salt.toString("hex"), - c: Config.iris.keystore.c, + c: c, prf: "hmac-sha256" }; const derivedKey = Cryp.pbkdf2Sync(Buffer.from(password), salt, kdfparams.c, kdfparams.dklen, "sha256"); diff --git a/src/chains/iris/distribution.js b/src/chains/iris/distribution.js index fb8c350..af0124a 100644 --- a/src/chains/iris/distribution.js +++ b/src/chains/iris/distribution.js @@ -101,11 +101,11 @@ class MsgWithdrawDelegatorReward extends Builder.Msg { module.exports = class Distribution { - static CreateMsgWithdrawDelegatorRewardsAll(req) { + static createMsgWithdrawDelegatorRewardsAll(req) { return new MsgWithdrawDelegatorRewardsAll(req.from); } - static CreateMsgWithdrawDelegatorReward(req) { + static createMsgWithdrawDelegatorReward(req) { return new MsgWithdrawDelegatorReward(req.from,req.msg.validator_addr); } -}; \ No newline at end of file +}; diff --git a/src/chains/iris/gov.js b/src/chains/iris/gov.js index c106427..1020c09 100644 --- a/src/chains/iris/gov.js +++ b/src/chains/iris/gov.js @@ -1,65 +1,139 @@ -'use strict'; - -const Builder = require("../../builder"); +const Config = require('../../../config'); +const Root = require('./tx/tx'); +const BECH32 = require('bech32'); const Utils = require('../../util/utils'); -const Amino = require('../base'); -const Bank = require('./bank'); -class SubmitProposalMsg extends Builder.Msg{ - constructor(title, description, proposalKind,proposer,deposit) { - super(); - this.Title = title; - this.Description = description; - this.ProposalKind = proposalKind; - this.Proposer = proposer; - this.InitialDeposit = deposit; - } - GetSignBytes() { - let msg = { - "Title": this.Title, - "Description": this.Description, - "ProposalKind": this.ProposalKind, - "Proposer": this.Proposer, - "InitialDeposit": this.InitialDeposit - }; - let sortMsg = Utils.sortObjectKeys(msg); - return Amino.MarshalJSON(this.Type(),sortMsg) - } - ValidateBasic() { - if (Utils.isEmpty(this.Title)){ - throw new Error("Title is empty"); - } +const voteOptionMapping = { + 0x00: 'Empty', + 0x01: 'Yes', + 0x02: 'Abstain', + 0x03: 'No', + 0x04: 'NoWithVeto' +}; - if (Utils.isEmpty(this.Description)){ - throw new Error("Description is empty"); - } +const MsgDeposit = Root.irisnet.tx.MsgDeposit; +MsgDeposit.prototype.type = Config.iris.tx.deposit.prefix; +MsgDeposit.prototype.GetSignBytes = function () { + let depositor = BECH32.encode(Config.iris.bech32.accAddr, this.depositor); + let signMsg = { + proposal_id: `${this.proposalID}`, + depositor: depositor, + amount: this.amount + }; + return Utils.sortObjectKeys(signMsg); +}; - if (Utils.isEmpty(this.ProposalKind)){ - throw new Error("delegation must great than 0"); - } +MsgDeposit.prototype.ValidateBasic = function () { + if (Utils.isEmpty(this.amount)) { + throw new Error("amount is empty"); + } + if (Utils.isEmpty(this.proposalID)) { + throw new Error("proposal_id is empty"); + } + if (Utils.isEmpty(this.depositor)) { + throw new Error("depositor is empty"); + } +}; - if (Utils.isEmpty(this.Proposer)){ - throw new Error("Proposer must great than 0"); - } +MsgDeposit.prototype.GetMsg = function () { + let depositor = BECH32.fromWords(this.depositor); + return { + proposalID: this.proposalID, + depositor: depositor, + amount: this.amount + } +}; - if (Utils.isEmpty(this.InitialDeposit)){ - throw new Error("InitialDeposit must great than 0"); - } +MsgDeposit.prototype.GetDisplayContent = function () { + let depositor = BECH32.encode(Config.iris.bech32.accAddr, this.depositor); + return { + i18n_tx_type: "i18n_deposit", + i18n_proposal_id:this.proposalID, + i18n_depositor: depositor, + i18n_amount: this.amount + } +}; +MsgDeposit.prototype.toJSON = function () { + let depositor = BECH32.encode(Config.iris.bech32.accAddr, this.depositor); + return { + proposal_id: this.proposalID, + depositor: depositor, + amount: this.amount } +}; - Type(){ - return "cosmos-sdk/MsgSubmitProposal"; +const MsgVote = Root.irisnet.tx.MsgVote; +MsgVote.prototype.type = Config.iris.tx.vote.prefix; +MsgVote.prototype.GetSignBytes = function () { + let voter = BECH32.encode(Config.iris.bech32.accAddr, this.voter); + let signMsg = { + proposal_id: `${this.proposalID}`, + voter: voter, + option: voteOptionMapping[this.option] + }; + return Utils.sortObjectKeys(signMsg); +}; +MsgVote.prototype.ValidateBasic = function () { + if (Utils.isEmpty(this.option)) { + throw new Error("option is empty"); + } + if (Utils.isEmpty(this.proposalID)) { + throw new Error("proposal_id is empty"); + } + if (Utils.isEmpty(this.voter)) { + throw new Error("voter is empty"); } -} +}; +MsgVote.prototype.GetMsg = function () { + let voter = BECH32.fromWords(this.voter); + return { + proposalID: this.proposalID, + voter: voter, + option: this.option + } +}; +MsgVote.prototype.GetDisplayContent = function () { + let voter = BECH32.encode(Config.iris.bech32.accAddr, this.voter); + return { + i18n_tx_type: "i18n_vote", + i18n_proposal_id: this.proposalID, + i18n_voter: voter, + option: voteOptionMapping[this.option] + } +}; +MsgVote.prototype.toJSON = function () { + let voter = BECH32.encode(Config.iris.bech32.accAddr, this.voter); + return { + proposal_id: this.proposalID, + voter: voter, + option: voteOptionMapping[this.option] + } +}; module.exports = class Gov { + static createMsgDeposit(req){ + let coins = []; + if (!Utils.isEmpty(req.msg.amount)) { + req.msg.amount.forEach(function(item) { + coins.push({ + denom: item.denom, + amount: Utils.toString(item.amount), + }); + }); + } + return new MsgDeposit({ + proposalID: `${req.msg.proposal_id}`, + depositor: BECH32.decode(req.from).words, + amount: coins + }) + } - // TODO - static GetSubmitProposalMsg(acc, validatorAddr, coins, fee, gas, memo){ - let stdFee = Bank.NewStdFee(fee, gas); - let msg = new SubmitProposalMsg(acc.address, validatorAddr, coins); - let signMsg = Bank.NewStdSignMsg(acc.chain_id, acc.account_number, acc.sequence, stdFee, msg,memo); - return signMsg; + static createMsgVote(req){ + return new MsgVote({ + proposalID: `${req.msg.proposal_id}`, + voter: BECH32.decode(req.from).words, + option: req.msg.option + }) } -}; \ No newline at end of file +}; diff --git a/src/chains/iris/keypair.js b/src/chains/iris/keypair.js index 164cd9e..d276486 100644 --- a/src/chains/iris/keypair.js +++ b/src/chains/iris/keypair.js @@ -96,6 +96,11 @@ class IrisKeypair { static import(secretKey){ let secretBytes = Buffer.from(secretKey,"hex"); + //compatible with previous versions of bugs + if(secretBytes.length === 31){ + let pad = Buffer.from([0]); + secretBytes = Buffer.concat([pad,secretBytes]); + } //构造公钥 let pubKey = Secp256k1.publicKeyCreate(secretBytes); pubKey = Amino.MarshalBinary(Config.iris.amino.pubKey,pubKey); diff --git a/src/chains/iris/proto/tx.proto b/src/chains/iris/proto/tx.proto index 969db2f..e0785f4 100644 --- a/src/chains/iris/proto/tx.proto +++ b/src/chains/iris/proto/tx.proto @@ -49,6 +49,18 @@ message MsgWithdrawDelegatorReward { required bytes validatorAddr = 2; } +message MsgDeposit { + required int64 proposalID = 1; + required bytes depositor = 2; + repeated Coin amount = 3; +} + +message MsgVote { + required int64 proposalID = 1; + required bytes voter = 2; + required uint64 option = 3; +} + message StdFee { repeated Coin amount = 1; required int64 gas = 2; @@ -66,4 +78,4 @@ message StdTx { required StdFee fee = 2; repeated StdSignature signatures = 3; optional string memo = 4; //空值需要处理 -} \ No newline at end of file +} diff --git a/src/chains/iris/stake.js b/src/chains/iris/stake.js index 822390f..998681c 100644 --- a/src/chains/iris/stake.js +++ b/src/chains/iris/stake.js @@ -205,7 +205,7 @@ class MsgBeginRedelegate extends Builder.Msg { } module.exports = class Stake { - static CreateMsgDelegate(req) { + static createMsgDelegate(req) { let delegation = { denom: req.msg.delegation.denom, amount: Utils.toString(req.msg.delegation.amount), @@ -214,24 +214,15 @@ module.exports = class Stake { return msg; } - static CreateMsgBeginUnbonding(req) { - let shares = Dec.String(req.msg.shares_amount); + static createMsgBeginUnbonding(req) { + let shares = Utils.toDecString(req.msg.shares_amount); let msg = new MsgBeginUnbonding(req.from, req.msg.validator_addr, shares); return msg; } - static CreateMsgBeginRedelegate(req) { - let shares = Dec.String(req.msg.shares_amount); + static createMsgBeginRedelegate(req) { + let shares = Utils.toDecString(req.msg.shares_amount); let msg = new MsgBeginRedelegate(req.from, req.msg.validator_src_addr, req.msg.validator_dst_addr, shares); return msg; }; }; - -class Dec { - static String(share) { - if (share.indexOf(".") === -1) { - share = share + ".0000000000" - } - return share - } -} \ No newline at end of file diff --git a/src/chains/iris/tx/tx.js b/src/chains/iris/tx/tx.js index a88ae64..7b844c3 100644 --- a/src/chains/iris/tx/tx.js +++ b/src/chains/iris/tx/tx.js @@ -2182,6 +2182,552 @@ $root.irisnet = (function() { return MsgWithdrawDelegatorReward; })(); + tx.MsgDeposit = (function() { + + /** + * Properties of a MsgDeposit. + * @memberof irisnet.tx + * @interface IMsgDeposit + * @property {number|Long} proposalID MsgDeposit proposalID + * @property {Uint8Array} depositor MsgDeposit depositor + * @property {Array.|null} [amount] MsgDeposit amount + */ + + /** + * Constructs a new MsgDeposit. + * @memberof irisnet.tx + * @classdesc Represents a MsgDeposit. + * @implements IMsgDeposit + * @constructor + * @param {irisnet.tx.IMsgDeposit=} [properties] Properties to set + */ + function MsgDeposit(properties) { + this.amount = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MsgDeposit proposalID. + * @member {number|Long} proposalID + * @memberof irisnet.tx.MsgDeposit + * @instance + */ + MsgDeposit.prototype.proposalID = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * MsgDeposit depositor. + * @member {Uint8Array} depositor + * @memberof irisnet.tx.MsgDeposit + * @instance + */ + MsgDeposit.prototype.depositor = $util.newBuffer([]); + + /** + * MsgDeposit amount. + * @member {Array.} amount + * @memberof irisnet.tx.MsgDeposit + * @instance + */ + MsgDeposit.prototype.amount = $util.emptyArray; + + /** + * Creates a new MsgDeposit instance using the specified properties. + * @function create + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {irisnet.tx.IMsgDeposit=} [properties] Properties to set + * @returns {irisnet.tx.MsgDeposit} MsgDeposit instance + */ + MsgDeposit.create = function create(properties) { + return new MsgDeposit(properties); + }; + + /** + * Encodes the specified MsgDeposit message. Does not implicitly {@link irisnet.tx.MsgDeposit.verify|verify} messages. + * @function encode + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {irisnet.tx.IMsgDeposit} message MsgDeposit message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgDeposit.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + writer.uint32(/* id 1, wireType 0 =*/8).int64(message.proposalID); + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.depositor); + if (message.amount != null && message.amount.length) + for (var i = 0; i < message.amount.length; ++i) + $root.irisnet.tx.Coin.encode(message.amount[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified MsgDeposit message, length delimited. Does not implicitly {@link irisnet.tx.MsgDeposit.verify|verify} messages. + * @function encodeDelimited + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {irisnet.tx.IMsgDeposit} message MsgDeposit message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgDeposit.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MsgDeposit message from the specified reader or buffer. + * @function decode + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {irisnet.tx.MsgDeposit} MsgDeposit + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgDeposit.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.irisnet.tx.MsgDeposit(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.proposalID = reader.int64(); + break; + case 2: + message.depositor = reader.bytes(); + break; + case 3: + if (!(message.amount && message.amount.length)) + message.amount = []; + message.amount.push($root.irisnet.tx.Coin.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + if (!message.hasOwnProperty("proposalID")) + throw $util.ProtocolError("missing required 'proposalID'", { instance: message }); + if (!message.hasOwnProperty("depositor")) + throw $util.ProtocolError("missing required 'depositor'", { instance: message }); + return message; + }; + + /** + * Decodes a MsgDeposit message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {irisnet.tx.MsgDeposit} MsgDeposit + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgDeposit.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MsgDeposit message. + * @function verify + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MsgDeposit.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (!$util.isInteger(message.proposalID) && !(message.proposalID && $util.isInteger(message.proposalID.low) && $util.isInteger(message.proposalID.high))) + return "proposalID: integer|Long expected"; + if (!(message.depositor && typeof message.depositor.length === "number" || $util.isString(message.depositor))) + return "depositor: buffer expected"; + if (message.amount != null && message.hasOwnProperty("amount")) { + if (!Array.isArray(message.amount)) + return "amount: array expected"; + for (var i = 0; i < message.amount.length; ++i) { + var error = $root.irisnet.tx.Coin.verify(message.amount[i]); + if (error) + return "amount." + error; + } + } + return null; + }; + + /** + * Creates a MsgDeposit message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {Object.} object Plain object + * @returns {irisnet.tx.MsgDeposit} MsgDeposit + */ + MsgDeposit.fromObject = function fromObject(object) { + if (object instanceof $root.irisnet.tx.MsgDeposit) + return object; + var message = new $root.irisnet.tx.MsgDeposit(); + if (object.proposalID != null) + if ($util.Long) + (message.proposalID = $util.Long.fromValue(object.proposalID)).unsigned = false; + else if (typeof object.proposalID === "string") + message.proposalID = parseInt(object.proposalID, 10); + else if (typeof object.proposalID === "number") + message.proposalID = object.proposalID; + else if (typeof object.proposalID === "object") + message.proposalID = new $util.LongBits(object.proposalID.low >>> 0, object.proposalID.high >>> 0).toNumber(); + if (object.depositor != null) + if (typeof object.depositor === "string") + $util.base64.decode(object.depositor, message.depositor = $util.newBuffer($util.base64.length(object.depositor)), 0); + else if (object.depositor.length) + message.depositor = object.depositor; + if (object.amount) { + if (!Array.isArray(object.amount)) + throw TypeError(".irisnet.tx.MsgDeposit.amount: array expected"); + message.amount = []; + for (var i = 0; i < object.amount.length; ++i) { + if (typeof object.amount[i] !== "object") + throw TypeError(".irisnet.tx.MsgDeposit.amount: object expected"); + message.amount[i] = $root.irisnet.tx.Coin.fromObject(object.amount[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a MsgDeposit message. Also converts values to other types if specified. + * @function toObject + * @memberof irisnet.tx.MsgDeposit + * @static + * @param {irisnet.tx.MsgDeposit} message MsgDeposit + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MsgDeposit.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.amount = []; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.proposalID = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.proposalID = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.depositor = ""; + else { + object.depositor = []; + if (options.bytes !== Array) + object.depositor = $util.newBuffer(object.depositor); + } + } + if (message.proposalID != null && message.hasOwnProperty("proposalID")) + if (typeof message.proposalID === "number") + object.proposalID = options.longs === String ? String(message.proposalID) : message.proposalID; + else + object.proposalID = options.longs === String ? $util.Long.prototype.toString.call(message.proposalID) : options.longs === Number ? new $util.LongBits(message.proposalID.low >>> 0, message.proposalID.high >>> 0).toNumber() : message.proposalID; + if (message.depositor != null && message.hasOwnProperty("depositor")) + object.depositor = options.bytes === String ? $util.base64.encode(message.depositor, 0, message.depositor.length) : options.bytes === Array ? Array.prototype.slice.call(message.depositor) : message.depositor; + if (message.amount && message.amount.length) { + object.amount = []; + for (var j = 0; j < message.amount.length; ++j) + object.amount[j] = $root.irisnet.tx.Coin.toObject(message.amount[j], options); + } + return object; + }; + + /** + * Converts this MsgDeposit to JSON. + * @function toJSON + * @memberof irisnet.tx.MsgDeposit + * @instance + * @returns {Object.} JSON object + */ + MsgDeposit.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MsgDeposit; + })(); + + tx.MsgVote = (function() { + + /** + * Properties of a MsgVote. + * @memberof irisnet.tx + * @interface IMsgVote + * @property {number|Long} proposalID MsgVote proposalID + * @property {Uint8Array} voter MsgVote voter + * @property {number|Long} option MsgVote option + */ + + /** + * Constructs a new MsgVote. + * @memberof irisnet.tx + * @classdesc Represents a MsgVote. + * @implements IMsgVote + * @constructor + * @param {irisnet.tx.IMsgVote=} [properties] Properties to set + */ + function MsgVote(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * MsgVote proposalID. + * @member {number|Long} proposalID + * @memberof irisnet.tx.MsgVote + * @instance + */ + MsgVote.prototype.proposalID = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * MsgVote voter. + * @member {Uint8Array} voter + * @memberof irisnet.tx.MsgVote + * @instance + */ + MsgVote.prototype.voter = $util.newBuffer([]); + + /** + * MsgVote option. + * @member {number|Long} option + * @memberof irisnet.tx.MsgVote + * @instance + */ + MsgVote.prototype.option = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Creates a new MsgVote instance using the specified properties. + * @function create + * @memberof irisnet.tx.MsgVote + * @static + * @param {irisnet.tx.IMsgVote=} [properties] Properties to set + * @returns {irisnet.tx.MsgVote} MsgVote instance + */ + MsgVote.create = function create(properties) { + return new MsgVote(properties); + }; + + /** + * Encodes the specified MsgVote message. Does not implicitly {@link irisnet.tx.MsgVote.verify|verify} messages. + * @function encode + * @memberof irisnet.tx.MsgVote + * @static + * @param {irisnet.tx.IMsgVote} message MsgVote message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgVote.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + writer.uint32(/* id 1, wireType 0 =*/8).int64(message.proposalID); + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.voter); + writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.option); + return writer; + }; + + /** + * Encodes the specified MsgVote message, length delimited. Does not implicitly {@link irisnet.tx.MsgVote.verify|verify} messages. + * @function encodeDelimited + * @memberof irisnet.tx.MsgVote + * @static + * @param {irisnet.tx.IMsgVote} message MsgVote message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MsgVote.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MsgVote message from the specified reader or buffer. + * @function decode + * @memberof irisnet.tx.MsgVote + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {irisnet.tx.MsgVote} MsgVote + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgVote.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.irisnet.tx.MsgVote(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.proposalID = reader.int64(); + break; + case 2: + message.voter = reader.bytes(); + break; + case 3: + message.option = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + if (!message.hasOwnProperty("proposalID")) + throw $util.ProtocolError("missing required 'proposalID'", { instance: message }); + if (!message.hasOwnProperty("voter")) + throw $util.ProtocolError("missing required 'voter'", { instance: message }); + if (!message.hasOwnProperty("option")) + throw $util.ProtocolError("missing required 'option'", { instance: message }); + return message; + }; + + /** + * Decodes a MsgVote message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof irisnet.tx.MsgVote + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {irisnet.tx.MsgVote} MsgVote + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MsgVote.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MsgVote message. + * @function verify + * @memberof irisnet.tx.MsgVote + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MsgVote.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (!$util.isInteger(message.proposalID) && !(message.proposalID && $util.isInteger(message.proposalID.low) && $util.isInteger(message.proposalID.high))) + return "proposalID: integer|Long expected"; + if (!(message.voter && typeof message.voter.length === "number" || $util.isString(message.voter))) + return "voter: buffer expected"; + if (!$util.isInteger(message.option) && !(message.option && $util.isInteger(message.option.low) && $util.isInteger(message.option.high))) + return "option: integer|Long expected"; + return null; + }; + + /** + * Creates a MsgVote message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof irisnet.tx.MsgVote + * @static + * @param {Object.} object Plain object + * @returns {irisnet.tx.MsgVote} MsgVote + */ + MsgVote.fromObject = function fromObject(object) { + if (object instanceof $root.irisnet.tx.MsgVote) + return object; + var message = new $root.irisnet.tx.MsgVote(); + if (object.proposalID != null) + if ($util.Long) + (message.proposalID = $util.Long.fromValue(object.proposalID)).unsigned = false; + else if (typeof object.proposalID === "string") + message.proposalID = parseInt(object.proposalID, 10); + else if (typeof object.proposalID === "number") + message.proposalID = object.proposalID; + else if (typeof object.proposalID === "object") + message.proposalID = new $util.LongBits(object.proposalID.low >>> 0, object.proposalID.high >>> 0).toNumber(); + if (object.voter != null) + if (typeof object.voter === "string") + $util.base64.decode(object.voter, message.voter = $util.newBuffer($util.base64.length(object.voter)), 0); + else if (object.voter.length) + message.voter = object.voter; + if (object.option != null) + if ($util.Long) + (message.option = $util.Long.fromValue(object.option)).unsigned = true; + else if (typeof object.option === "string") + message.option = parseInt(object.option, 10); + else if (typeof object.option === "number") + message.option = object.option; + else if (typeof object.option === "object") + message.option = new $util.LongBits(object.option.low >>> 0, object.option.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a MsgVote message. Also converts values to other types if specified. + * @function toObject + * @memberof irisnet.tx.MsgVote + * @static + * @param {irisnet.tx.MsgVote} message MsgVote + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MsgVote.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, false); + object.proposalID = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.proposalID = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.voter = ""; + else { + object.voter = []; + if (options.bytes !== Array) + object.voter = $util.newBuffer(object.voter); + } + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.option = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.option = options.longs === String ? "0" : 0; + } + if (message.proposalID != null && message.hasOwnProperty("proposalID")) + if (typeof message.proposalID === "number") + object.proposalID = options.longs === String ? String(message.proposalID) : message.proposalID; + else + object.proposalID = options.longs === String ? $util.Long.prototype.toString.call(message.proposalID) : options.longs === Number ? new $util.LongBits(message.proposalID.low >>> 0, message.proposalID.high >>> 0).toNumber() : message.proposalID; + if (message.voter != null && message.hasOwnProperty("voter")) + object.voter = options.bytes === String ? $util.base64.encode(message.voter, 0, message.voter.length) : options.bytes === Array ? Array.prototype.slice.call(message.voter) : message.voter; + if (message.option != null && message.hasOwnProperty("option")) + if (typeof message.option === "number") + object.option = options.longs === String ? String(message.option) : message.option; + else + object.option = options.longs === String ? $util.Long.prototype.toString.call(message.option) : options.longs === Number ? new $util.LongBits(message.option.low >>> 0, message.option.high >>> 0).toNumber(true) : message.option; + return object; + }; + + /** + * Converts this MsgVote to JSON. + * @function toJSON + * @memberof irisnet.tx.MsgVote + * @instance + * @returns {Object.} JSON object + */ + MsgVote.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return MsgVote; + })(); + tx.StdFee = (function() { /** diff --git a/src/util/utils.js b/src/util/utils.js index 543d0a7..68528a0 100644 --- a/src/util/utils.js +++ b/src/util/utils.js @@ -53,7 +53,7 @@ module.exports = class Utils { static toString(str) { if (typeof str === "number") { - str = str.toLocaleString(); + str = str.toLocaleString("en"); return str.replace(/[,]/g, ''); } else if (this.isEmpty(str)) { return "" @@ -62,6 +62,24 @@ module.exports = class Utils { } } + static toDecString(str,precision = 10){ + if(str === "" || str === null) return str; + let item = str.split("."); + if(item[1] && item[1].length > precision){ + throw Error(`too much precision, maximum ${precision}, len decimal ${item[1].length}`); + } + let suffix = ""; + if (item.length === 1){ + suffix = "." + } + let bit = item[1] ? precision - item[1].length : precision; + while (bit > 0){ + suffix = `${suffix}0`; + bit-- + } + return `${str}${suffix}` + } + static hasRepeatElement(target,splitChar){ if (!(target instanceof Array)){ if (this.isEmpty(splitChar)){ diff --git a/test/common.js b/test/common.js index d211e0b..6d7bf17 100644 --- a/test/common.js +++ b/test/common.js @@ -35,30 +35,24 @@ function randomHex(range){ return str.toUpperCase(); } -function verifyTx(url, tx, privateKey, chainName,callback) { +async function verifyTx(url, tx, privateKey, chainName,callback) { let builder = Irisnet.getBuilder(chainName,"testnet"); let stdTx = builder.buildAndSignTx(tx, privateKey); let exp = stdTx.Hash(); let payload = stdTx.GetData(); - sendByAsync("POST",url,payload).then(response => { - callback(response,exp,payload); - }).catch(e =>{ - console.log(`lcd request failed`,e) - }); + let response = await sendByAsync("POST",url,payload); + callback(response,exp,payload); } -function verifyAccount(url, account){ +async function verifyAccount(url, account){ let payload = { password: "1234567890", seed: account.phrase }; - sendByAsync("POST",url,payload).then(response => { - assert.strictEqual(response.address,account.address); - assert.strictEqual(response.pub_key,account.publicKey) - }).catch(e =>{ - console.log(`lcd request failed`,e) - }); + let response = await sendByAsync("POST",url,payload); + assert.strictEqual(response.address,account.address); + assert.strictEqual(response.pub_key,account.publicKey); } function sendBySync(method,url,payload) { @@ -72,7 +66,7 @@ function sendBySync(method,url,payload) { function getSequence(host,address) { let url = `${host}/auth/accounts/${address}`; let res = sendBySync("GET", url); - let account = res.value; + let account = res.result.value; return account.sequence } diff --git a/test/keystore.json b/test/keystore.json index 2fee29e..1a58314 100644 --- a/test/keystore.json +++ b/test/keystore.json @@ -1 +1 @@ -{"version":"1","id":"65177bc2-8240-4024-8180-dd0b2d888903","address":"faa1ljemm0yznz58qxxs8xyak7fashcfxf5lssn6jm","crypto":{"ciphertext":"793acc81ed7d3f8aead7872f81cc7297e0527ab9ee87a24f8aa7de6a6b4072e9","cipherparams":{"iv":"7ebe22befa6b278f0f348fe9e3f7c524"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"0fa96f07f73d3dfe2bff410b708de347080a326c898e2d5631af4d598e851401","c":262144,"prf":"hmac-sha256"},"mac":"15467c52ade57fd59200544612cccd2310825f8378d3f52228b52d07b56fbdba"}} \ No newline at end of file +{"version":"1","id":"cdda101b-cb44-4daf-8ed6-2a28b1289f6c","address":"faa1ljemm0yznz58qxxs8xyak7fashcfxf5lssn6jm","crypto":{"ciphertext":"03878b0196704fcfe13f56f9e12ff003c9c33b249e87b981ca0c8763ebe085f1","cipherparams":{"iv":"4848b511d0647dd572c4d1dfa9f65289"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"06f0a45bd8f512d17349723da67d1eddbfac1cc497b6cbd2ad8a2852376d76db","c":10000,"prf":"hmac-sha256"},"mac":"f6c13e10eb8496847710bcedde95b5bf9aed85a834ce05c7b7eb01db05f26568"}} \ No newline at end of file diff --git a/test/test_account.js b/test/test_account.js index 4380d31..837ee2c 100644 --- a/test/test_account.js +++ b/test/test_account.js @@ -2,6 +2,7 @@ const Irisnet = require('../index'); const chai = require('chai'); const assert = chai.assert; const common = require('./common'); +const utils = require('../src/util/utils'); describe('account', function () { @@ -38,7 +39,7 @@ describe('account', function () { it('should recover', function () { let crypto = Irisnet.getCrypto(chainName, 'testnet'); - let seed = "tube lonely pause spring gym veteran know want grid tired taxi such same mesh charge orient bracket ozone concert once good quick dry boss"; + let seed = "error nerve credit mail coyote melt property afford design wool dune sibling loan tunnel acid joke father bid home pupil giant share age warrior"; let keyPair2 = crypto.recover(seed, Irisnet.config.language.en); console.log(JSON.stringify(keyPair2)) }); @@ -93,5 +94,14 @@ describe('account', function () { assert.equal(srcAccount.privateKey, dstaccount.privateKey); assert.equal(srcAccount.publicKey, dstaccount.publicKey); }); + + it('should utils', function () { + assert.equal(utils.toDecString("0.1"),"0.1000000000"); + assert.equal(utils.toDecString("1"),"1.0000000000"); + assert.equal(utils.toDecString("1.0"),"1.0000000000"); + assert.equal(utils.toDecString("1.0000000000"),"1.0000000000"); + //assert.ifError(utils.toDecString("1.1234567890123456789012")); + assert.equal(utils.toDecString("10000000000000000000000"),"10000000000000000000000.0000000000"); + }); }); }); \ No newline at end of file diff --git a/test/test_tx_cosmos.js b/test/test_tx_cosmos.js index 9d6e67b..87068b5 100644 --- a/test/test_tx_cosmos.js +++ b/test/test_tx_cosmos.js @@ -3,17 +3,17 @@ const common = require('./common'); const chai = require('chai'); const assert = chai.assert; -const host ="http://192.168.150.31:31317"; +const host ="http://192.168.150.31:21317"; const url = host + "/txs"; //const lcdServer ="http://127.0.0.1:1317/txs"; describe('cosmos transaction', function () { let chain_id = "cosmos-dev"; - let from = "cosmos192xdyxer5hvtrrredragyup2gejv73ztzpa7j3"; + let from = "cosmos1r33tlrh7cawtzxmct7zatau6vdydp0rg5s6vyg"; let gas = 200000; - let account_number = 4; + let account_number = 0; let fees = {denom: "stake", amount: "2"}; - let privateKey = "4F13455BE209B262E8F28D610B8396F8BB0C8318154C1719EF055BDA44EA9EFF"; + let privateKey = "67F17C4F34C4353A6AABD5175FD9A7C452CF5AA18C65CC5A539145A928F93ADE"; let chainName = "cosmos"; @@ -150,6 +150,98 @@ describe('cosmos transaction', function () { common.verifyTx(url,tx,privateKey,chainName,verify); }); + it('test MsgDeposit', function () { + let seq = common.getSequence(host,from); + let tx = { + chain_id: chain_id, + from: from, + account_number: account_number, + sequence: seq, + fees: fees, + gas: gas, + memo: common.randomWord(100), + type: Irisnet.config.cosmos.tx.deposit.type, + msg: { + proposal_id : 22, + amount : [ + { + denom: "stake", + amount: 10000 + } + ] + } + }; + common.verifyTx(url,tx,privateKey,chainName,verify); + }); + + it('test MsgVote', function () { + let seq = common.getSequence(host,from); + this.timeout(10000); + let tx = { + chain_id: chain_id, + from: from, + account_number: account_number, + sequence: seq, + fees: fees, + gas: gas, + memo: common.randomWord(100), + type: Irisnet.config.cosmos.tx.vote.type, + msg: { + proposal_id : 23, + option: 0x02 + } + }; + // common.verifyTx(url,tx,privateKey,chainName,verify); + extracted(tx); + }); + + //冷钱包调用 + function extracted(tx, chain = 'cosmos') { + let builder = Irisnet.getBuilder(chain,'testnet'); + //①先用联网的钱包构造一笔交易 + let stdTx = builder.buildTx(tx); + //②把步骤①的结构序列化为字符串,装入二维码 + let signStr = JSON.stringify(stdTx.GetSignBytes()); + //③用未联网的钱包(存有账户秘钥)扫描步骤②的二维码,拿到待签名的字符串,调用signTx签名 + console.log("GetSignBytes:", signStr); + let signature = builder.sign(signStr, privateKey); + //④ + let signatureStr = JSON.stringify(signature);//二维码字符串 + stdTx.SetSignature(signatureStr); + //console.log("======待提交交易======"); + //④步骤③的结果调用GetData,得到交易字符串,回传给联网的钱包,并发送该内容给irishub-server + console.log('GetData:',JSON.stringify(stdTx.GetData())); + console.log('GetDisplayContent:',JSON.stringify(stdTx.GetDisplayContent())); + + //以下步骤为异常处理:在请求irishub-server超时的时候,服务器可能没有任何返回结果,这笔交易状态为止,所以需要客户端计算出 + //本次交易的hash,校准该笔交易的状态。调用步骤③结构的Hash,可以得到交易hash以及本次交易内容的base64编码(以后考虑使用该编码内容替换 + // GetPostData,解耦crypto和irishub交易结构的依赖) + + let postTx = stdTx.GetData(); + // postTx.mode = "commit"; + let resp = common.sendBySync("POST",url,postTx); + let result = stdTx.Hash(); + console.log("data:", result.data); + console.log("hash", result.hash); + + console.log(`hash=${result.hash}`); + assert.notExists(resp.code,`tx commit failed,${resp.raw_log}`); + //console.log("displayContent", JSON.stringify(stdTx.GetDisplayContent())); + + } + + // //simulate + // function simulate(tx) { + // let builder = Irisnet.getBuilder(chain); + // let stdTx = builder.buildAndSignTx(tx); + // stdTx.SetPubKey(pubKey); + // console.log("======stdTx======"); + // console.log(JSON.stringify(stdTx.GetData())); + // // console.log("======待提交交易======"); + // let result = stdTx.Hash(); + // console.log("hash", result.hash); + // } + //TODO Pending verification // it('test MsgWithdrawValidatorCommission', function () { // let seq = common.getSequence(host,from); @@ -172,5 +264,6 @@ describe('cosmos transaction', function () { }); function verify(act,exp,data) { + console.log('result:',act,exp,data) assert.notExists(act.code,`tx commit failed,${act.raw_log}`); } diff --git a/test/test_tx_iris.js b/test/test_tx_iris.js index 9a1c6c3..5fd4dfc 100644 --- a/test/test_tx_iris.js +++ b/test/test_tx_iris.js @@ -3,20 +3,20 @@ const chai = require('chai'); const assert = chai.assert; const common = require('./common'); -const url ="http://irisnet-lcd.dev.rainbow.one/tx/broadcast"; +const url ="http://10.1.4.124:1317/tx/broadcast?commit=true"; const chainName ="iris"; describe('iris transaction', function () { - let chain_id = "hash"; - let from = "faa1aake3umjllpd9es5d3qmry4egcne0f8a8u5rsx"; - let gas = 10000; - let account_number = 0; + let chain_id = "irishub-test"; + let from = "faa1f3vflz39qr5sjzfkqmkzkr5dy7t646wyexy92y"; + let gas = 20000; + let account_number = 2; let fees = {denom: "iris-atto", amount: 600000000000000000}; let memo = "1"; - let privateKey = "465820F3AC6B406F8D599E558ACC48A135C57A2537CB96EF544A3D66449E7D63"; - let pubKey = "fap1addwnpepqtdme789cpm8zww058ndlhzpwst3s0mxnhdhu5uyps0wjucaufha6v3ce99"; + let privateKey = "80D45E1FAB9ACF59254F23C376E3AEAF139C847CD7A3126CDFD5216568730C90"; + let pubKey = "fap1addwnpepqwqw5pshzzswemf6t00xvf0ccf2fxslaz40dp76uyad5mgujfju4zt8km3u"; let chain = Irisnet.config.chain.iris; @@ -289,16 +289,61 @@ describe('iris transaction', function () { extracted(tx); }); + + it('test MsgDeposit', function () { + let tx = { + chain_id: chain_id, + from: from, + account_number: account_number, + sequence: 11, + fees: fees, + gas: gas, + memo: memo, + type: Irisnet.config.iris.tx.deposit.type, + msg: { + proposal_id : 3, + amount : [ + { + denom: "iris-atto", + amount: 3000000000000000000000 + } + ] + } + }; + + extracted(tx); + }); + + it('test MsgVote', function () { + this.timeout(10000); + let tx = { + chain_id: chain_id, + from: from, + account_number: account_number, + sequence: 13, + fees: fees, + gas: gas, + memo: memo, + type: Irisnet.config.iris.tx.vote.type, + msg: { + proposal_id : 3, + option: 0x01 + } + }; + + extracted(tx); + }); }); //冷钱包调用 function extracted(tx, chain = 'iris') { - let builder = Irisnet.getBuilder(chain); + let builder = Irisnet.getBuilder(chain,'testnet'); //①先用联网的钱包构造一笔交易 let stdTx = builder.buildTx(tx); //②把步骤①的结构序列化为字符串,装入二维码 let signStr = JSON.stringify(stdTx.GetSignBytes()); //③用未联网的钱包(存有账户秘钥)扫描步骤②的二维码,拿到待签名的字符串,调用signTx签名 + console.log("GetSignBytes:", signStr); let signature = builder.sign(signStr, privateKey); //④ let signatureStr = JSON.stringify(signature);//二维码字符串 @@ -311,12 +356,14 @@ describe('iris transaction', function () { //本次交易的hash,校准该笔交易的状态。调用步骤③结构的Hash,可以得到交易hash以及本次交易内容的base64编码(以后考虑使用该编码内容替换 // GetPostData,解耦crypto和irishub交易结构的依赖) - let resp = common.sendBySync("POST",url,stdTx.GetData()); + let postTx = stdTx.GetData(); + postTx.mode = "commit"; + let resp = common.sendBySync("POST",url,postTx); let result = stdTx.Hash(); console.log("data:", result.data); console.log("hash", result.hash); - console.log(`hash=${result.hash}`) + console.log(`hash=${result.hash}`); assert.notExists(resp.code,`tx commit failed,${resp.raw_log}`); //console.log("displayContent", JSON.stringify(stdTx.GetDisplayContent())); @@ -337,4 +384,4 @@ describe('iris transaction', function () { function verify(act,exp,data) { assert.notExists(act.check_tx.code,`tx commit failed,${act.check_tx.log}`); -} \ No newline at end of file +}