UNPKG

@meterio/devkit

Version:

Typescript library to aid DApp development on Meter network

1,070 lines 95.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ScriptEngine = void 0; const rlp_1 = require("./rlp"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const blake = require('blakejs'); const abi_1 = require("./abi"); var ScriptEngine; (function (ScriptEngine) { ScriptEngine.SCRIPT_ENGINE_PREFIX = 'ffffffff'; ScriptEngine.SCRIPT_ENGINE_VERSION = 0; ScriptEngine.SCRIPT_DATA_PREFIX = 'deadbeef'; ScriptEngine.STAKING_VERSION = 0; ScriptEngine.AUCTION_VERSION = 0; ScriptEngine.EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000'; ScriptEngine.EMPTY_BYTE32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; let ModuleID; (function (ModuleID) { ModuleID[ModuleID["Staking"] = 1000] = "Staking"; ModuleID[ModuleID["Auction"] = 1001] = "Auction"; ModuleID[ModuleID["AccountLock"] = 1002] = "AccountLock"; })(ModuleID = ScriptEngine.ModuleID || (ScriptEngine.ModuleID = {})); let Token; (function (Token) { Token[Token["Meter"] = 0] = "Meter"; Token[Token["MeterGov"] = 1] = "MeterGov"; })(Token = ScriptEngine.Token || (ScriptEngine.Token = {})); let StakingOpCode; (function (StakingOpCode) { StakingOpCode[StakingOpCode["Bound"] = 1] = "Bound"; StakingOpCode[StakingOpCode["Unbound"] = 2] = "Unbound"; StakingOpCode[StakingOpCode["Candidate"] = 3] = "Candidate"; StakingOpCode[StakingOpCode["Uncandidate"] = 4] = "Uncandidate"; StakingOpCode[StakingOpCode["Delegate"] = 5] = "Delegate"; StakingOpCode[StakingOpCode["Undelegate"] = 6] = "Undelegate"; StakingOpCode[StakingOpCode["CandidateUpdate"] = 7] = "CandidateUpdate"; StakingOpCode[StakingOpCode["BucketUpdate"] = 8] = "BucketUpdate"; StakingOpCode[StakingOpCode["DelegateStats"] = 101] = "DelegateStats"; StakingOpCode[StakingOpCode["BailOut"] = 102] = "BailOut"; StakingOpCode[StakingOpCode["FlushAllStats"] = 103] = "FlushAllStats"; StakingOpCode[StakingOpCode["Governing"] = 10001] = "Governing"; })(StakingOpCode = ScriptEngine.StakingOpCode || (ScriptEngine.StakingOpCode = {})); ScriptEngine.NativeBucketOpenABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'bucketID', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'token', type: 'uint256' }, ], name: 'NativeBucketOpen', type: 'event', }; ScriptEngine.NativeBucketCloseABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'bucketID', type: 'bytes32' }, ], name: 'NativeBucketClose', type: 'event', }; ScriptEngine.NativeBucketDepositABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'bucketID', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'token', type: 'uint256' }, ], name: 'NativeBucketDeposit', type: 'event', }; ScriptEngine.NativeBucketMergeABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'fromBktID', type: 'bytes32' }, { indexed: false, internalType: 'bytes32', name: 'toBktID', type: 'bytes32' }, ], name: 'NativeBucketMerge', type: 'event', }; ScriptEngine.NativeBucketTransferFundABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'fromBktID', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'token', type: 'uint256' }, { indexed: false, internalType: 'bytes32', name: 'toBktID', type: 'bytes32' }, ], name: 'NativeBucketTransferFund', type: 'event', }; ScriptEngine.NativeBucketUpdateCandidateABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'bucketID', type: 'bytes32' }, { indexed: false, internalType: 'address', name: 'fromCandidate', type: 'address' }, { indexed: false, internalType: 'address', name: 'toCandidate', type: 'address' }, ], name: 'NativeBucketUpdateCandidate', type: 'event', }; ScriptEngine.NativeBucketWithdrawABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'owner', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'fromBktID', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'token', type: 'uint256' }, { indexed: false, internalType: 'address', name: 'recipient', type: 'address' }, { indexed: false, internalType: 'bytes32', name: 'toBktID', type: 'bytes32' }, ], name: 'NativeBucketWithdraw', type: 'event', }; ScriptEngine.NativeAuctionEndABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'bytes32', name: 'id', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'receivedMTR', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'releasedMTRG', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'actualPrice', type: 'uint256' }, ], name: 'NativeAuctionEnd', type: 'event', }; ScriptEngine.NativeAuctionStartABI = { anonymous: false, inputs: [ { indexed: true, internalType: 'bytes32', name: 'id', type: 'bytes32' }, { indexed: false, internalType: 'uint256', name: 'startHeight', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'endHeight', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'mtrgOnAuction', type: 'uint256' }, { indexed: false, internalType: 'uint256', name: 'reservedPrice', type: 'uint256' }, ], name: 'NativeAuctionStart', type: 'event', }; ScriptEngine.NativeBucketOpen = new abi_1.abi.Event(ScriptEngine.NativeBucketOpenABI); ScriptEngine.NativeBucketClose = new abi_1.abi.Event(ScriptEngine.NativeBucketCloseABI); ScriptEngine.NativeBucketDeposit = new abi_1.abi.Event(ScriptEngine.NativeBucketDepositABI); ScriptEngine.NativeBucketWithdraw = new abi_1.abi.Event(ScriptEngine.NativeBucketWithdrawABI); ScriptEngine.NativeBucketMerge = new abi_1.abi.Event(ScriptEngine.NativeBucketMergeABI); ScriptEngine.NativeBucketTransferFund = new abi_1.abi.Event(ScriptEngine.NativeBucketTransferFundABI); ScriptEngine.NativeBucketUpdateCandidate = new abi_1.abi.Event(ScriptEngine.NativeBucketUpdateCandidateABI); ScriptEngine.NativeAuctionEnd = new abi_1.abi.Event(ScriptEngine.NativeAuctionEndABI); ScriptEngine.NativeAuctionStart = new abi_1.abi.Event(ScriptEngine.NativeAuctionStartABI); ScriptEngine.explainStakingOpCode = (opCode) => { switch (opCode) { case StakingOpCode.Bound: return 'Bound'; case StakingOpCode.Unbound: return 'Unbound'; case StakingOpCode.Candidate: return 'Candidate'; case StakingOpCode.Uncandidate: return 'Uncandidate'; case StakingOpCode.Delegate: return 'Delegate'; case StakingOpCode.Undelegate: return 'Undelegate'; case StakingOpCode.CandidateUpdate: return 'UpdateCandidate'; case StakingOpCode.BucketUpdate: return 'UpdateBucket'; case StakingOpCode.DelegateStats: return 'DelegateStats'; case StakingOpCode.BailOut: return 'BailOut'; case StakingOpCode.FlushAllStats: return 'FlushStats'; case StakingOpCode.Governing: return 'Govern'; } }; let StakingOption; (function (StakingOption) { StakingOption[StakingOption["Empty"] = 0] = "Empty"; // staking bound StakingOption[StakingOption["OneWeekLock"] = 1] = "OneWeekLock"; StakingOption[StakingOption["TwoWeekLock"] = 2] = "TwoWeekLock"; StakingOption[StakingOption["ThreeWeekLock"] = 3] = "ThreeWeekLock"; StakingOption[StakingOption["FourWeekLock"] = 4] = "FourWeekLock"; })(StakingOption = ScriptEngine.StakingOption || (ScriptEngine.StakingOption = {})); let BucketUpdateOption; (function (BucketUpdateOption) { BucketUpdateOption[BucketUpdateOption["Add"] = 0] = "Add"; BucketUpdateOption[BucketUpdateOption["Sub"] = 1] = "Sub"; })(BucketUpdateOption = ScriptEngine.BucketUpdateOption || (ScriptEngine.BucketUpdateOption = {})); let AuctionOpCode; (function (AuctionOpCode) { AuctionOpCode[AuctionOpCode["Start"] = 1] = "Start"; AuctionOpCode[AuctionOpCode["End"] = 2] = "End"; AuctionOpCode[AuctionOpCode["Bid"] = 3] = "Bid"; })(AuctionOpCode = ScriptEngine.AuctionOpCode || (ScriptEngine.AuctionOpCode = {})); let AuctionOption; (function (AuctionOption) { AuctionOption[AuctionOption["Userbid"] = 0] = "Userbid"; AuctionOption[AuctionOption["Autobid"] = 1] = "Autobid"; })(AuctionOption = ScriptEngine.AuctionOption || (ScriptEngine.AuctionOption = {})); ScriptEngine.explainAuctionOpCode = (opCode, option) => { switch (opCode) { case AuctionOpCode.Start: return 'StartAuction'; case AuctionOpCode.End: return 'EndAuction'; case AuctionOpCode.Bid: if (option === AuctionOption.Userbid) { return 'Userbid'; } else if (option === AuctionOption.Autobid) { return 'Autobid'; } else { return 'Bid'; } } }; let AccountLockOpCode; (function (AccountLockOpCode) { // account lock AccountLockOpCode[AccountLockOpCode["Add"] = 1] = "Add"; AccountLockOpCode[AccountLockOpCode["Remove"] = 2] = "Remove"; AccountLockOpCode[AccountLockOpCode["Transfer"] = 3] = "Transfer"; AccountLockOpCode[AccountLockOpCode["Governing"] = 100] = "Governing"; })(AccountLockOpCode = ScriptEngine.AccountLockOpCode || (ScriptEngine.AccountLockOpCode = {})); ScriptEngine.explainAccountLockOpCode = (opCode) => { switch (opCode) { case AccountLockOpCode.Add: return 'AddAcctLock'; case AccountLockOpCode.Remove: return 'RemoveAcctLock'; case AccountLockOpCode.Transfer: return 'TransferAcctLock'; case AccountLockOpCode.Governing: return 'GovernAcctLock'; } }; function getRandomInt(max) { return Math.floor(Math.random() * Math.floor(max)); } function getRandomInt64() { return getRandomInt(9007199254740992); } class DecodeError extends Error { constructor(message) { super(message); // 'Error' breaks prototype chain here Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain } } class EncodeError extends Error { constructor(message) { super(message); // 'Error' breaks prototype chain here Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain } } function IsScriptEngineData(hexStr) { let str = hexStr; if (hexStr.startsWith('0x')) { str = hexStr.replace('0x', ''); } const enginePrefix = ScriptEngine.SCRIPT_ENGINE_PREFIX; const dataPrefix = ScriptEngine.SCRIPT_DATA_PREFIX; return str.startsWith(enginePrefix + dataPrefix); } ScriptEngine.IsScriptEngineData = IsScriptEngineData; // ScriptData encode/decode function encodeScriptData(moduleID, body) { switch (moduleID) { case ModuleID.Staking: if (!(body instanceof StakingBody)) { throw new EncodeError('module is set to staking, but no staking body is provided'); } return new ScriptData(moduleID, body.encode()).encode(); case ModuleID.Auction: if (!(body instanceof AuctionBody)) { throw new EncodeError('module is set to auction, but no auction body is provided'); } return new ScriptData(moduleID, body.encode()).encode(); default: throw new EncodeError(`unrecognized moduleID: ${moduleID}`); } } ScriptEngine.encodeScriptData = encodeScriptData; function decodeScriptData(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } let hexStr = buf.toString('hex'); const sePrefixStr = ScriptEngine.SCRIPT_ENGINE_PREFIX; const sdPrefixStr = ScriptEngine.SCRIPT_DATA_PREFIX; if (hexStr.startsWith(sePrefixStr)) { hexStr = hexStr.substring(sePrefixStr.length); } if (!hexStr.startsWith(sdPrefixStr)) { throw new DecodeError('could not decode script data: 0x' + buf.toString('hex')); } const truncated = Buffer.from(hexStr.substring(sdPrefixStr.length), 'hex'); const sd = new rlp_1.RLP(ScriptEngine.ScriptDataProfile).decode(truncated); let action = ''; switch (sd.header.modId) { case ModuleID.AccountLock: const alb = decodeAccountLockBody(sd.payload); action = ScriptEngine.explainAccountLockOpCode(alb.opCode); return new DecodedScriptData(sd, action, alb); case ModuleID.Auction: const ab = decodeAuctionBody(sd.payload); action = ScriptEngine.explainAuctionOpCode(ab.opCode, ab.option); return new DecodedScriptData(sd, action, ab); case ModuleID.Staking: const sb = decodeStakingBody(sd.payload); action = ScriptEngine.explainStakingOpCode(sb.opCode); return new DecodedScriptData(sd, action, sb); } return new DecodedScriptData(sd, ''); } // end of Script Data encode/decode ScriptEngine.decodeScriptData = decodeScriptData; // Staking Body decode function decodeStakingBody(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } const sb = new rlp_1.RLP(ScriptEngine.StakingBodyProfile).decode(buf); let extra = undefined; if (sb.opCode === StakingOpCode.Governing) { try { extra = decodeStakingGoverningV2Extra(sb.extra); } catch (e) { extra = decodeStakingGoverningExtra(sb.extra); } } if (sb.opCode === StakingOpCode.DelegateStats) { extra = decodeStakingStatExtra(sb.extra); } return new DecodedStakingBody(sb, extra); } ScriptEngine.decodeStakingBody = decodeStakingBody; // Auction Body decode function decodeAuctionBody(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } return new rlp_1.RLP(ScriptEngine.AuctionBodyProfile).decode(buf); } ScriptEngine.decodeAuctionBody = decodeAuctionBody; // Account Lock Body decode function decodeAccountLockBody(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } return new rlp_1.RLP(ScriptEngine.AccountLockBodyProfile).decode(buf); } ScriptEngine.decodeAccountLockBody = decodeAccountLockBody; // Staking Governing Extra decode function decodeStakingGoverningExtra(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } return new rlp_1.RLP(ScriptEngine.StakingGoverningExtraProfile).decode(buf); } ScriptEngine.decodeStakingGoverningExtra = decodeStakingGoverningExtra; // Staking Governing Extra decode function decodeStakingGoverningV2Extra(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } return new rlp_1.RLP(ScriptEngine.StakingGoverningV2ExtraProfile).decode(buf); } ScriptEngine.decodeStakingGoverningV2Extra = decodeStakingGoverningV2Extra; // Staking Statistics Extra decode function decodeStakingStatExtra(input) { let buf; if (typeof input === 'string') { buf = Buffer.from(input.replace('0x', ''), 'hex'); } else { buf = input; } return new rlp_1.RLP(ScriptEngine.InfractionProfile).decode(buf); } ScriptEngine.decodeStakingStatExtra = decodeStakingStatExtra; // Auction Tx decode function getAuctionTxFromAuctionBody(body) { if (body.opCode === AuctionOpCode.Bid) { return new AuctionTx(body.bidder, body.amount, body.option, body.timestamp, body.nonce); } return undefined; } ScriptEngine.getAuctionTxFromAuctionBody = getAuctionTxFromAuctionBody; // ------------------------------------------------ // SCRIPT DATA // ------------------------------------------------ ScriptEngine.ScriptDataProfile = { name: 'scriptDataProfile', kind: [ { name: 'header', kind: [ { name: 'version', kind: new rlp_1.RLP.NumericKind() }, { name: 'modId', kind: new rlp_1.RLP.NumericKind() }, ], }, { name: 'payload', kind: new rlp_1.RLP.HexKind() }, ], }; class ScriptDataHeader { constructor(version, modId) { this.version = version; this.modId = modId; } } ScriptEngine.ScriptDataHeader = ScriptDataHeader; class DecodedScriptData { constructor(data, action, body = undefined) { this.header = Object.assign({}, data.header); this.payload = data.payload; this.action = action; this.body = body; } } ScriptEngine.DecodedScriptData = DecodedScriptData; class ScriptData { constructor(modId, payload) { this.header = new ScriptDataHeader(ScriptEngine.SCRIPT_ENGINE_VERSION, modId); this.payload = payload; } encode() { return ('0x' + ScriptEngine.SCRIPT_ENGINE_PREFIX + ScriptEngine.SCRIPT_DATA_PREFIX + new rlp_1.RLP(ScriptEngine.ScriptDataProfile).encode(this).toString('hex')); } } ScriptEngine.ScriptData = ScriptData; // ------------------------------------------ // STAKING // ------------------------------------------ ScriptEngine.StakingGoverningExtraProfile = { name: 'stakingGoverningExtraProfile', kind: { item: [ { name: 'address', kind: new rlp_1.RLP.HexKind() }, { name: 'amount', kind: new rlp_1.RLP.NumericKind() }, ], }, }; ScriptEngine.StakingGoverningV2ExtraProfile = { name: 'stakingGoverningV2ExtraProfile', kind: { item: [ { name: 'address', kind: new rlp_1.RLP.HexKind() }, { name: 'distAmount', kind: new rlp_1.RLP.NumericKind() }, { name: 'autobidAmount', kind: new rlp_1.RLP.NumericKind() }, ], }, }; class RewardInfo { constructor(address, amount) { this.address = address; this.amount = amount; } } ScriptEngine.RewardInfo = RewardInfo; class RewardInfoV2 { constructor(address, distAmount, autobidAmount) { this.address = address; this.distAmount = distAmount; this.autobidAmount = autobidAmount; } } ScriptEngine.RewardInfoV2 = RewardInfoV2; class RoundInfo { constructor(epoch, round) { this.epoch = epoch; this.round = round; } } ScriptEngine.RoundInfo = RoundInfo; class HeightInfo { constructor(epoch, height) { this.epoch = epoch; this.height = height; } } ScriptEngine.HeightInfo = HeightInfo; class MissingLeader { constructor(counter, info) { this.counter = counter; this.info = info; } } ScriptEngine.MissingLeader = MissingLeader; class MissingProposer { constructor(counter, info) { this.counter = counter; this.info = info; } } ScriptEngine.MissingProposer = MissingProposer; class MissingVoter { constructor(counter, info) { this.counter = counter; this.info = info; } } ScriptEngine.MissingVoter = MissingVoter; class DoubleSign { constructor(counter, info) { this.counter = counter; this.info = info; } } ScriptEngine.DoubleSign = DoubleSign; class Infraction { constructor(missingLeader, missingProposer, missingVoter, doubleSign) { this.missingLeader = missingLeader; this.missingProposer = missingProposer; this.missingVoter = missingVoter; this.doubleSign = doubleSign; } encode() { return '0x' + new rlp_1.RLP(ScriptEngine.InfractionProfile).encode(this).toString('hex'); } } ScriptEngine.Infraction = Infraction; ScriptEngine.MissingLeaderProfile = { name: 'missingLeaderProfile', kind: [ { name: 'counter', kind: new rlp_1.RLP.NumericKind() }, { name: 'info', kind: { item: [ { name: 'epoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'height', kind: new rlp_1.RLP.NumericKind() }, ], }, }, ], }; ScriptEngine.MissingProposerProfile = { name: 'missingProposerProfile', kind: [ { name: 'counter', kind: new rlp_1.RLP.NumericKind() }, { name: 'info', kind: { item: [ { name: 'epoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'round', kind: new rlp_1.RLP.NumericKind() }, ], }, }, ], }; ScriptEngine.MissingVoterProfile = { name: 'missingVoterProfile', kind: [ { name: 'counter', kind: new rlp_1.RLP.NumericKind() }, { name: 'info', kind: { item: [ { name: 'epoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'round', kind: new rlp_1.RLP.NumericKind() }, ], }, }, ], }; ScriptEngine.DoubleSignProfile = { name: 'doubleSignProfile', kind: [ { name: 'counter', kind: new rlp_1.RLP.NumericKind() }, { name: 'info', kind: { item: [ { name: 'epoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'round', kind: new rlp_1.RLP.NumericKind() }, ], }, }, ], }; ScriptEngine.InfractionProfile = { name: 'infractionProfile', kind: [ScriptEngine.MissingLeaderProfile, ScriptEngine.MissingProposerProfile, ScriptEngine.MissingVoterProfile, ScriptEngine.DoubleSignProfile], }; ScriptEngine.StakingBodyProfile = { name: 'stakingBodyProfile', kind: [ { name: 'opCode', kind: new rlp_1.RLP.NumericKind() }, { name: 'version', kind: new rlp_1.RLP.NumericKind() }, { name: 'option', kind: new rlp_1.RLP.NumericKind() }, { name: 'holderAddr', kind: new rlp_1.RLP.HexKind() }, { name: 'candidateAddr', kind: new rlp_1.RLP.HexKind() }, { name: 'candidateName', kind: new rlp_1.RLP.TextKind() }, { name: 'candidateDescription', kind: new rlp_1.RLP.TextKind() }, { name: 'candidatePubKey', kind: new rlp_1.RLP.TextKind() }, { name: 'candidateIP', kind: new rlp_1.RLP.TextKind() }, { name: 'candidatePort', kind: new rlp_1.RLP.NumericKind() }, { name: 'bucketID', kind: new rlp_1.RLP.HexKind() }, { name: 'amount', kind: new rlp_1.RLP.NumericKind() }, { name: 'token', kind: new rlp_1.RLP.NumericKind() }, { name: 'autobid', kind: new rlp_1.RLP.NumericKind() }, { name: 'timestamp', kind: new rlp_1.RLP.NumericKind() }, { name: 'nonce', kind: new rlp_1.RLP.NumericKind() }, { name: 'extra', kind: new rlp_1.RLP.HexKind() }, ], }; ScriptEngine.BucketIDProfile = { name: 'bucketID', kind: [ { name: 'owner', kind: new rlp_1.RLP.HexKind() }, { name: 'nonce', kind: new rlp_1.RLP.NumericKind() }, { name: 'timestamp', kind: new rlp_1.RLP.NumericKind() }, ], }; class DecodedStakingBody { constructor(sb, extra) { this.opCode = sb.opCode; this.version = sb.version; this.option = sb.option; this.holderAddr = sb.holderAddr; this.candidateAddr = sb.candidateAddr; this.candidateName = sb.candidateName; this.candidateDescription = sb.candidateDescription; this.candidatePubKey = sb.candidatePubKey; this.candidateIP = sb.candidateIP; this.candidatePort = sb.candidatePort; this.bucketID = sb.bucketID; this.amount = sb.amount; this.token = sb.token; this.autobid = sb.autobid; this.timestamp = sb.timestamp; this.nonce = sb.nonce; this.extra = extra; } } ScriptEngine.DecodedStakingBody = DecodedStakingBody; class StakingBody { constructor(op, option, holderAddr, candidateAddr, candidateName, candidateDescription, candidatePubKey, candidateIP, candidatePort, bucketID, amount, token, autobid, timestamp = 0, nonce = 0) { this.opCode = op; this.version = ScriptEngine.STAKING_VERSION; this.option = option; // set autobid to be in range [0,100] let autobidVal = autobid; if (autobid > 100) { autobidVal = 100; } if (autobid < 0) { autobidVal = 0; } this.autobid = autobidVal; let holderAddrStr = holderAddr; let candidateAddrStr = candidateAddr; let bucketIDStr = bucketID; if (holderAddrStr === '' || holderAddrStr === '0x') { holderAddrStr = ScriptEngine.EMPTY_ADDRESS; } if (candidateAddrStr === '' || candidateAddrStr === '0x') { candidateAddrStr = ScriptEngine.EMPTY_ADDRESS; } if (bucketIDStr === '' || bucketIDStr === '0x') { bucketIDStr = ScriptEngine.EMPTY_BYTE32; } this.holderAddr = holderAddr; this.candidateAddr = candidateAddr; this.candidateName = candidateName; this.candidateDescription = candidateDescription; this.candidatePubKey = candidatePubKey; this.candidateIP = candidateIP; this.candidatePort = candidatePort; this.bucketID = bucketID; this.amount = amount.toString(); this.token = token; if (timestamp != 0) { this.timestamp = timestamp; } else { this.timestamp = Math.ceil(new Date().getTime() / 1000); } if (nonce != 0) { this.nonce = nonce; } else { this.nonce = getRandomInt64(); } this.extra = ''; } encode() { return '0x' + new rlp_1.RLP(ScriptEngine.StakingBodyProfile).encode(this).toString('hex'); } } ScriptEngine.StakingBody = StakingBody; /** * @deprecated * @param sb * @returns */ function jsonFromStakingBody(sb) { return Object.assign(Object.assign({}, sb), { amount: new bignumber_js_1.default(sb.amount).toFixed() }); } ScriptEngine.jsonFromStakingBody = jsonFromStakingBody; function getBoundData(option, holderAddr, candidateAddr, amount, timestamp = 0, nonce = 0, autobid = 0) { const body = new StakingBody(StakingOpCode.Bound, option, holderAddr, candidateAddr, '', // name '', // desc '', // pubkey '', // ip 0, // port ScriptEngine.EMPTY_BYTE32, // bucket id amount, Token.MeterGov, autobid, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); } ScriptEngine.getBoundData = getBoundData; function getUnboundData(holderAddr, stakingIDStr, amount, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.Unbound, StakingOption.Empty, holderAddr, ScriptEngine.EMPTY_ADDRESS, // candidate addr '', // name '', // desc '', // pubkey '', // ip 0, // port stakingIDStr, // bucket id amount, Token.MeterGov, 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); } ScriptEngine.getUnboundData = getUnboundData; function getBucketAddData(holderAddr, bucketID, amount, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.BucketUpdate, BucketUpdateOption.Add, holderAddr, holderAddr, '', // name '', // desc '', // '', // ip 0, // port bucketID, // bucket id amount.toString(), Token.MeterGov, 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); } ScriptEngine.getBucketAddData = getBucketAddData; function getBucketSubData(holderAddr, bucketID, amount, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.BucketUpdate, BucketUpdateOption.Sub, holderAddr, holderAddr, '', // name '', // desc '', // '', // ip 0, // port bucketID, amount.toString(), Token.MeterGov, 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); } ScriptEngine.getBucketSubData = getBucketSubData; function getCandidateData( // omitted option, every bucket is forever holderAddr, candidateName, candidateDescription, candidatePubKey, candidateIP, candidatePort, amount, commission, timestamp = 0, nonce = 0, autobid = 0) { let option = 0; if (commission >= 100 && commission <= 1000) { option = commission * 1e5; } const body = new StakingBody(StakingOpCode.Candidate, option, holderAddr, holderAddr, candidateName, candidateDescription, candidatePubKey, candidateIP, candidatePort, ScriptEngine.EMPTY_BYTE32, // bucket id amount.toString(), Token.MeterGov, autobid, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); // return body.encode(); } ScriptEngine.getCandidateData = getCandidateData; function getUncandidateData(candidateAddr, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.Uncandidate, StakingOption.Empty, ScriptEngine.EMPTY_ADDRESS, candidateAddr, // candidate addr '', // name '', // desc '', // pubkey '', // ip 0, // port ScriptEngine.EMPTY_BYTE32, // bucket id 0, // amount Token.MeterGov, // token 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); } ScriptEngine.getUncandidateData = getUncandidateData; function getDelegateData(holderAddr, candidateAddr, bucketID, amount, timestamp = 0, nonce = 0, autobid = 0) { const body = new StakingBody(StakingOpCode.Delegate, StakingOption.Empty, holderAddr, candidateAddr, '', // name '', // desc '', // pubkey '', // ip 0, // port bucketID, // bucket id amount.toString(), Token.MeterGov, autobid, timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); // return body.encode(); } ScriptEngine.getDelegateData = getDelegateData; function getUndelegateData(holderAddr, stakingIDStr, amount, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.Undelegate, StakingOption.Empty, holderAddr, ScriptEngine.EMPTY_ADDRESS, // candidate addr '', // name '', // desc '', // pubkey '', // ip 0, // port stakingIDStr, // bucket id amount.toString(), Token.MeterGov, 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); // return body.encode(); } ScriptEngine.getUndelegateData = getUndelegateData; function getCandidateUpdateData(holderAddr, candidateName, candidateDescription, candidatePubKey, candidateIP, candidatePort, commission, timestamp = 0, nonce = 0, autobid = 0) { let option = 0; if (commission >= 100 && commission <= 1000) { option = commission * 1e5; } const body = new StakingBody(StakingOpCode.CandidateUpdate, option, holderAddr, holderAddr, candidateName, candidateDescription, candidatePubKey, candidateIP, candidatePort, ScriptEngine.EMPTY_BYTE32, // bucket id 0, Token.MeterGov, autobid, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); // return body.encode(); } ScriptEngine.getCandidateUpdateData = getCandidateUpdateData; function getBailOutData(holderAddr, timestamp = 0, nonce = 0) { const body = new StakingBody(StakingOpCode.BailOut, StakingOption.Empty, holderAddr, holderAddr, '', // name '', // desc '', // pubkey '', // ip 0, // port ScriptEngine.EMPTY_BYTE32, // bucket id '0', // amount Token.MeterGov, 0, // autobid timestamp, nonce); return new ScriptData(ModuleID.Staking, body.encode()).encode(); // return body.encode(); } ScriptEngine.getBailOutData = getBailOutData; // ------------------------------------------ // AUCTION // ------------------------------------------ ScriptEngine.AuctionControlBlockProfile = { name: 'auctionControlBlock', kind: [ { name: 'startHeight', kind: new rlp_1.RLP.NumericKind() }, { name: 'startEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'endHeight', kind: new rlp_1.RLP.NumericKind() }, { name: 'endEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'rlsdMTRG', kind: new rlp_1.RLP.NumericKind() }, { name: 'rsvdMTRG', kind: new rlp_1.RLP.NumericKind() }, { name: 'rsvdPrice', kind: new rlp_1.RLP.NumericKind() }, { name: 'createTime', kind: new rlp_1.RLP.NumericKind() }, ], }; class AuctionControlBlock { constructor(startHeight, startEpoch, endHeight, endEpoch, rlsdMTRG, rsvdMTRG, rsvdPrice, createTime) { this.startHeight = startHeight; this.startEpoch = startEpoch; this.endHeight = endHeight; this.endEpoch = endEpoch; this.rlsdMTRG = rlsdMTRG.toString(); this.rsvdMTRG = rsvdMTRG.toString(); this.rsvdPrice = rsvdPrice.toString(); this.createTime = createTime; } ID() { const bytes = new rlp_1.RLP(ScriptEngine.AuctionControlBlockProfile).encode(this); const idBuf = blake.blake2bHex(bytes, null, 32); return '0x' + idBuf.toString('hex'); } } ScriptEngine.AuctionControlBlock = AuctionControlBlock; ScriptEngine.AuctionTxProfile = { name: 'acutionTx', kind: [ { name: 'address', kind: new rlp_1.RLP.BufferKind() }, { name: 'amount', kind: new rlp_1.RLP.NumericKind() }, { name: 'type', kind: new rlp_1.RLP.NumericKind() }, { name: 'timestamp', kind: new rlp_1.RLP.NumericKind() }, { name: 'nonce', kind: new rlp_1.RLP.NumericKind() }, ], }; class AuctionTx { constructor(address, amount, type, timestamp, nonce) { this.address = Buffer.from(address.replace('0x', ''), 'hex'); this.amount = amount.toString(); this.type = type; this.timestamp = timestamp; this.nonce = nonce.toString(); } ID() { const bytes = new rlp_1.RLP(ScriptEngine.AuctionTxProfile).encode(this); const idBuf = blake.blake2bHex(bytes, null, 32); return '0x' + idBuf.toString('hex'); } } ScriptEngine.AuctionTx = AuctionTx; ScriptEngine.AuctionBodyProfile = { name: 'auctionBody', kind: [ { name: 'opCode', kind: new rlp_1.RLP.NumericKind() }, { name: 'version', kind: new rlp_1.RLP.NumericKind() }, { name: 'option', kind: new rlp_1.RLP.NumericKind() }, { name: 'startHeight', kind: new rlp_1.RLP.NumericKind() }, { name: 'startEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'endHeight', kind: new rlp_1.RLP.NumericKind() }, { name: 'endEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'sequence', kind: new rlp_1.RLP.NumericKind() }, { name: 'auctionID', kind: new rlp_1.RLP.HexKind() }, { name: 'bidder', kind: new rlp_1.RLP.HexKind() }, { name: 'amount', kind: new rlp_1.RLP.NumericKind() }, { name: 'reserveAmount', kind: new rlp_1.RLP.NumericKind() }, { name: 'token', kind: new rlp_1.RLP.NumericKind() }, { name: 'timestamp', kind: new rlp_1.RLP.NumericKind() }, { name: 'nonce', kind: new rlp_1.RLP.NumericKind() }, ], }; class AuctionBody { constructor(opCode, option, auctionID, bidder, amount, timestamp = 0, nonce = 0) { let bidderStr = bidder; let auctionIDStr = auctionID; if (bidderStr === '' || bidderStr === '0x') { bidderStr = ScriptEngine.EMPTY_ADDRESS; } if (auctionIDStr === '' || auctionIDStr === '0x') { auctionIDStr = ScriptEngine.EMPTY_BYTE32; } this.opCode = opCode; this.version = ScriptEngine.AUCTION_VERSION; this.option = option; this.startHeight = 0; this.startEpoch = 0; this.endHeight = 0; this.endEpoch = 0; this.sequence = 0; this.auctionID = auctionID; this.bidder = bidder; this.amount = amount.toString(); this.reserveAmount = '0'; this.token = Token.Meter; if (timestamp != 0) { this.timestamp = timestamp; } else { this.timestamp = Math.ceil(new Date().getTime() / 1000); } if (nonce != 0) { this.nonce = nonce; } else { this.nonce = getRandomInt64(); } } encode() { return '0x' + new rlp_1.RLP(ScriptEngine.AuctionBodyProfile).encode(this).toString('hex'); } } ScriptEngine.AuctionBody = AuctionBody; /** * @deprecated * @param ab * @returns */ function jsonFromAuctionBody(ab) { return Object.assign(Object.assign({}, ab), { amount: new bignumber_js_1.default(ab.amount).toFixed(), reserveAmount: new bignumber_js_1.default(ab.reserveAmount).toFixed() }); } ScriptEngine.jsonFromAuctionBody = jsonFromAuctionBody; function getBidData(bidder, amount, timestamp = 0, nonce = 0) { const body = new AuctionBody(AuctionOpCode.Bid, AuctionOption.Userbid, ScriptEngine.EMPTY_BYTE32, bidder, amount, timestamp, nonce); return new ScriptData(ModuleID.Auction, body.encode()).encode(); } ScriptEngine.getBidData = getBidData; // ------------------------------------------ // ACCOUNT LOCK // ------------------------------------------ ScriptEngine.AccountLockBodyProfile = { name: 'accountLockBodyProfile', kind: [ { name: 'opCode', kind: new rlp_1.RLP.NumericKind() }, { name: 'version', kind: new rlp_1.RLP.NumericKind() }, { name: 'option', kind: new rlp_1.RLP.NumericKind() }, { name: 'lockEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'releaseEpoch', kind: new rlp_1.RLP.NumericKind() }, { name: 'fromAddr', kind: new rlp_1.RLP.HexKind() }, { name: 'toAddr', kind: new rlp_1.RLP.HexKind() }, { name: 'meterAmount', kind: new rlp_1.RLP.NumericKind() }, { name: 'meterGovAmount', kind: new rlp_1.RLP.NumericKind() }, { name: 'memo', kind: new rlp_1.RLP.TextKind() }, ], }; class AccountLockBody { constructor(op, lockEpoch, releaseEpoch, fromAddr, toAddr, meterAmount, meterGovAmount, memo) { this.opCode = op; this.version = ScriptEngine.STAKING_VERSION; this.option = 0; let fromAddrStr = fromAddr; let toAddrStr = toAddr; if (fromAddrStr === '' || fromAddrStr === '0x') { fromAddrStr = ScriptEngine.EMPTY_ADDRESS; } if (toAddrStr === '' || toAddrStr === '0x') { toAddrStr = ScriptEngine.EMPTY_ADDRESS; } this.fromAddr = fromAddr; this.toAddr = toAddr; this.lockEpoch = lockEpoch; this.releaseEpoch = releaseEpoch; this.meterAmount = meterAmount.toString(); this.meterGovAmount = meterGovAmount.toString(); this.memo = memo; } encode() { return '0x' + new rlp_1.RLP(ScriptEngine.AccountLockBodyProfile).encode(this).toString('hex'); } } ScriptEngine.AccountLockBody = AccountLockBody; /** * @deprecated * @param alb * @returns */ function jsonFromAccountLockBody(alb) { return Object.assign(Object.assign({}, alb), { meterAmount: new bignumber_js_1.default(alb.meterAmount).toFixed(), meterGovAmount: new bignumber_js_1.default(alb.meterGovAmount).toFixed() }); } ScriptEngine.jsonFromAccountLockBody = jsonFromAccountLockBody; function getLockedTransferData(lockEpoch, releaseEpoch, fromAddr, toAddr, meterAmount, meterGovAmount, memo) { const body = new AccountLockBody(AccountLockOpCode.Transfer, lockEpoch, releaseEpoch, fromAddr, toAddr, meterAmount, meterGovAmount, memo); return new ScriptData(ModuleID.AccountLock, body.encode()).encode(); } ScriptEngine.getLockedTransferData = getLockedTransferData; function getBucketID(owner, nonce, timestamp) { const bytes = new rlp_1.RLP(ScriptEngine.BucketIDProfile).encode({ owner, nonce, timestamp, }); const idBuf = blake.blake2bHex(bytes, null, 32); return '0x' + idBuf.toString('hex'); } ScriptEngine.getBucketID = getBucketID; })(ScriptEngine = exports.ScriptEngine || (exports.ScriptEngine = {})); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0RW5naW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3NjcmlwdEVuZ2luZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwrQkFBNEI7QUFDNUIsZ0VBQXFDO0FBQ3JDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNqQywrQkFBNEI7QUFFNUIsSUFBaUIsWUFBWSxDQXM2QzVCO0FBdDZDRCxXQUFpQixZQUFZO0lBQ2QsaUNBQW9CLEdBQUcsVUFBVSxDQUFDO0lBQ2xDLGtDQUFxQixHQUFHLENBQUMsQ0FBQztJQUMxQiwrQkFBa0IsR0FBRyxVQUFVLENBQUM7SUFDaEMsNEJBQWUsR0FBRyxDQUFDLENBQUM7SUFDcEIsNEJBQWUsR0FBRyxDQUFDLENBQUM7SUFDcEIsMEJBQWEsR0FBRyw0Q0FBNEMsQ0FBQztJQUM3RCx5QkFBWSxHQUFHLG9FQUFvRSxDQUFDO0lBRWpHLElBQVksUUFJWDtJQUpELFdBQVksUUFBUTtRQUNsQixnREFBYyxDQUFBO1FBQ2QsZ0RBQWMsQ0FBQTtRQUNkLHdEQUFrQixDQUFBO0lBQ3BCLENBQUMsRUFKVyxRQUFRLEdBQVIscUJBQVEsS0FBUixxQkFBUSxRQUluQjtJQUVELElBQVksS0FHWDtJQUhELFdBQVksS0FBSztRQUNmLG1DQUFTLENBQUE7UUFDVCx5Q0FBWSxDQUFBO0lBQ2QsQ0FBQyxFQUhXLEtBQUssR0FBTCxrQkFBSyxLQUFMLGtCQUFLLFFBR2hCO0lBRUQsSUFBWSxhQWFYO0lBYkQsV0FBWSxhQUFhO1FBQ3ZCLG1EQUFTLENBQUE7UUFDVCx1REFBVyxDQUFBO1FBQ1gsMkRBQWEsQ0FBQTtRQUNiLCtEQUFlLENBQUE7UUFDZix5REFBWSxDQUFBO1FBQ1osNkRBQWMsQ0FBQTtRQUNkLHVFQUFtQixDQUFBO1FBQ25CLGlFQUFnQixDQUFBO1FBQ2hCLHFFQUFtQixDQUFBO1FBQ25CLHlEQUFhLENBQUE7UUFDYixxRUFBbUIsQ0FBQTtRQUNu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