@meterio/devkit
Version:
Typescript library to aid DApp development on Meter network
1,070 lines • 95.5 kB
JavaScript
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0RW5naW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3NjcmlwdEVuZ2luZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwrQkFBNEI7QUFDNUIsZ0VBQXFDO0FBQ3JDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNqQywrQkFBNEI7QUFFNUIsSUFBaUIsWUFBWSxDQXM2QzVCO0FBdDZDRCxXQUFpQixZQUFZO0lBQ2QsaUNBQW9CLEdBQUcsVUFBVSxDQUFDO0lBQ2xDLGtDQUFxQixHQUFHLENBQUMsQ0FBQztJQUMxQiwrQkFBa0IsR0FBRyxVQUFVLENBQUM7SUFDaEMsNEJBQWUsR0FBRyxDQUFDLENBQUM7SUFDcEIsNEJBQWUsR0FBRyxDQUFDLENBQUM7SUFDcEIsMEJBQWEsR0FBRyw0Q0FBNEMsQ0FBQztJQUM3RCx5QkFBWSxHQUFHLG9FQUFvRSxDQUFDO0lBRWpHLElBQVksUUFJWDtJQUpELFdBQVksUUFBUTtRQUNsQixnREFBYyxDQUFBO1FBQ2QsZ0RBQWMsQ0FBQTtRQUNkLHdEQUFrQixDQUFBO0lBQ3BCLENBQUMsRUFKVyxRQUFRLEdBQVIscUJBQVEsS0FBUixxQkFBUSxRQUluQjtJQUVELElBQVksS0FHWDtJQUhELFdBQVksS0FBSztRQUNmLG1DQUFTLENBQUE7UUFDVCx5Q0FBWSxDQUFBO0lBQ2QsQ0FBQyxFQUhXLEtBQUssR0FBTCxrQkFBSyxLQUFMLGtCQUFLLFFBR2hCO0lBRUQsSUFBWSxhQWFYO0lBYkQsV0FBWSxhQUFhO1FBQ3ZCLG1EQUFTLENBQUE7UUFDVCx1REFBVyxDQUFBO1FBQ1gsMkRBQWEsQ0FBQTtRQUNiLCtEQUFlLENBQUE7UUFDZix5REFBWSxDQUFBO1FBQ1osNkRBQWMsQ0FBQTtRQUNkLHVFQUFtQixDQUFBO1FBQ25CLGlFQUFnQixDQUFBO1FBQ2hCLHFFQUFtQixDQUFBO1FBQ25CLHlEQUFhLENBQUE7UUFDYixxRUFBbUIsQ0FBQTtRQUNuQiwrREFBaUIsQ0FBQTtJQUNuQixDQUFDLEVBYlcsYUFBYSxHQUFiLDBCQUFhLEtBQWIsMEJBQWEsUUFheEI7SUFFWSxnQ0FBbUIsR0FBRztRQUNqQyxTQUFTLEVBQUUsS0FBSztRQUNoQixNQUFNLEVBQUU7WUFDTixFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDMUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQzlFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUM1RSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7U0FDNUU7UUFDRCxJQUFJLEVBQUUsa0JBQWtCO1FBQ3hCLElBQUksRUFBRSxPQUFPO0tBQ2QsQ0FBQztJQUVXLGlDQUFvQixHQUFHO1FBQ2xDLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLE1BQU0sRUFBRTtZQUNOLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUMxRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7U0FDL0U7UUFDRCxJQUFJLEVBQUUsbUJBQW1CO1FBQ3pCLElBQUksRUFBRSxPQUFPO0tBQ2QsQ0FBQztJQUVXLG1DQUFzQixHQUFHO1FBQ3BDLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLE1BQU0sRUFBRTtZQUNOLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUMxRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDOUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQzVFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtTQUM1RTtRQUNELElBQUksRUFBRSxxQkFBcUI7UUFDM0IsSUFBSSxFQUFFLE9BQU87S0FDZCxDQUFDO0lBRVcsaUNBQW9CLEdBQUc7UUFDbEMsU0FBUyxFQUFFLEtBQUs7UUFDaEIsTUFBTSxFQUFFO1lBQ04sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQzFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUMvRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7U0FDOUU7UUFDRCxJQUFJLEVBQUUsbUJBQW1CO1FBQ3pCLElBQUksRUFBRSxPQUFPO0tBQ2QsQ0FBQztJQUVXLHdDQUEyQixHQUFHO1FBQ3pDLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLE1BQU0sRUFBRTtZQUNOLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtZQUMxRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDL0UsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQzVFLEVBQUUsT0FBTyxFQUFFLEtBQU