updating staking datastructures

datastructure-update
Ganesha Upadhyaya 5 years ago
parent 8148f89f3e
commit b7852bb9c5
  1. 163
      packages/harmony-staking/src/stakingTransaction.ts
  2. 114
      packages/harmony-staking/test/testSign.test.ts
  3. 55
      packages/harmony-staking/test/transactions.json

@ -1,36 +1,37 @@
// tslint:disable: max-classes-per-file // tslint:disable: max-classes-per-file
import { import {
encode,
arrayify, arrayify,
BN,
encode,
hexlify, hexlify,
stripZeros,
Signature,
splitSignature,
keccak256, keccak256,
sign, sign,
BN, Signature,
splitSignature,
stripZeros,
} from '@harmony-js/crypto'; } from '@harmony-js/crypto';
import { TextEncoder } from 'text-encoding';
import { Unit, numberToHex } from '@harmony-js/utils';
import { Messenger, RPCMethod } from '@harmony-js/network'; import { Messenger, RPCMethod } from '@harmony-js/network';
import { defaultMessenger, TxStatus, TransactionBase } from '@harmony-js/transaction'; import { defaultMessenger, TransactionBase, TxStatus } from '@harmony-js/transaction';
import { numberToHex, Unit } from '@harmony-js/utils';
import { TextEncoder } from 'text-encoding';
export class StakingSettings { export class StakingSettings {
public static PRECISION = 18; public static PRECISION = 18;
public static MAX_DECIMAL = 1000000000000000000;
} }
export const enum Directive { export const enum Directive {
DirectiveNewValidator, DirectiveCreateValidator,
DirectiveEditValidator, DirectiveEditValidator,
DirectiveDelegate, DirectiveDelegate,
DirectiveRedelegate,
DirectiveUndelegate, DirectiveUndelegate,
DirectiveCollectRewards,
} }
export class StakingTransaction extends TransactionBase { export class StakingTransaction extends TransactionBase {
private directive: Directive; private directive: Directive;
private stakeMsg: NewValidator | EditValidator | Delegate | Redelegate | Undelegate; private stakeMsg: CreateValidator | EditValidator | Delegate | Undelegate | CollectRewards;
private nonce: number | string; private nonce: number | string;
private gasLimit: number | string; private gasLimit: number | string;
private gasPrice: number | string; private gasPrice: number | string;
@ -42,7 +43,7 @@ export class StakingTransaction extends TransactionBase {
constructor( constructor(
directive: Directive, directive: Directive,
stakeMsg: NewValidator | EditValidator | Delegate | Redelegate | Undelegate, stakeMsg: CreateValidator | EditValidator | Delegate | Undelegate | CollectRewards,
nonce: number | string, nonce: number | string,
gasPrice: number | string, gasPrice: number | string,
gasLimit: number | string, gasLimit: number | string,
@ -234,16 +235,53 @@ export class Description {
export class Decimal { export class Decimal {
value: BN; value: BN;
constructor(value: number, precision: number) {
if (precision > StakingSettings.PRECISION) { constructor(value: string) {
if (value.length == 0) {
throw new Error(`decimal string is empty`);
}
var value1 = value;
if (value[0] == '-') {
throw new Error(`decimal fraction should be be between [0, 1]`);
}
if (value[0] == '+') {
value1 = value.substr(1);
}
if (value1.length == 0) {
throw new Error(`decimal string is empty`);
}
const spaced = value1.split(' ');
if (spaced.length > 1) {
throw new Error(`bad decimal string`);
}
const splitted = value1.split('.');
var len = 0;
var combinedStr = splitted[0];
if (splitted.length == 2) {
len = splitted[1].length;
if (len == 0 || combinedStr.length == 0) {
throw new Error(`bad decimal length`);
}
if (splitted[1][0] == '-') {
throw new Error(`bad decimal string`);
}
combinedStr += splitted[1];
} else if (splitted.length > 2) {
throw new Error(`too many periods to be a decimal string`);
}
if (len > StakingSettings.PRECISION) {
throw new Error( throw new Error(
`too much precision: ${precision}, should be less than ${StakingSettings.PRECISION}`, `too much precision: precision should be less than ${StakingSettings.PRECISION}`,
); );
} }
const zerosToAdd = StakingSettings.PRECISION - precision; const zerosToAdd = StakingSettings.PRECISION - len;
const multiplier = Math.pow(10, zerosToAdd); combinedStr += '0'.repeat(zerosToAdd);
// (value * multiplier).toString(); combinedStr = combinedStr.replace(/^0+/, '');
this.value = new Unit((value * multiplier).toString()).asWei().toWei(); const val = new Unit(combinedStr).asWei().toWei();
if (val.gt(new Unit(StakingSettings.MAX_DECIMAL.toString()).asWei().toWei())) {
throw new Error(`too large decimal fraction`);
}
this.value = val;
} }
encode(): any[] { encode(): any[] {
@ -268,68 +306,91 @@ export class CommissionRate {
raw.push(this.rate.encode()); raw.push(this.rate.encode());
raw.push(this.maxRate.encode()); raw.push(this.maxRate.encode());
raw.push(this.maxChangeRate.encode()); raw.push(this.maxChangeRate.encode());
// console.log(decode(encode(raw)));
return raw; return raw;
} }
} }
export class NewValidator { export class CreateValidator {
validatorAddress: string;
description: Description; description: Description;
commission: CommissionRate; commissionRates: CommissionRate;
minSelfDelegation: number; minSelfDelegation: number;
stakingAddress: string; maxTotalDelegation: number;
pubKey: string; slotPubKeys: string[];
amount: number; amount: number;
constructor( constructor(
validatorAddress: string,
description: Description, description: Description,
commission: CommissionRate, commissionRates: CommissionRate,
minSelfDelegation: number, minSelfDelegation: number,
stakingAddress: string, maxTotalDelegation: number,
pubKey: string, slotPubKeys: string[],
amount: number, amount: number,
) { ) {
this.validatorAddress = validatorAddress;
this.description = description; this.description = description;
this.commission = commission; this.commissionRates = commissionRates;
this.minSelfDelegation = minSelfDelegation; this.minSelfDelegation = minSelfDelegation;
this.stakingAddress = stakingAddress; this.maxTotalDelegation = maxTotalDelegation;
this.pubKey = pubKey; this.slotPubKeys = slotPubKeys;
this.amount = amount; this.amount = amount;
} }
encode(): any[] { encode(): any[] {
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = [];
raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorAddress)));
raw.push(this.description.encode()); raw.push(this.description.encode());
raw.push(this.commission.encode()); raw.push(this.commissionRates.encode());
raw.push(hexlify(this.minSelfDelegation)); raw.push(hexlify(this.minSelfDelegation));
raw.push(hexlify(TransactionBase.normalizeAddress(this.stakingAddress))); raw.push(hexlify(this.maxTotalDelegation));
raw.push(this.pubKey); raw.push(this.encodeArr());
raw.push(hexlify(this.amount)); raw.push(hexlify(this.amount));
return raw; return raw;
} }
encodeArr(): any[] {
var raw: Array<string | Uint8Array | Array<string | Uint8Array>> = [];
this.slotPubKeys.forEach((pubKey) => {
raw.push(pubKey);
});
return raw;
}
} }
export class EditValidator { export class EditValidator {
validatorAddress: string;
description: Description; description: Description;
stakingAddress: string;
commissionRate: Decimal; commissionRate: Decimal;
minSelfDelegation: number; minSelfDelegation: number;
maxTotalDelegation: number;
slotKeyToRemove: string;
slotKeyToAdd: string;
constructor( constructor(
validatorAddress: string,
description: Description, description: Description,
stakingAddress: string,
commissionRate: Decimal, commissionRate: Decimal,
minSelfDelegation: number, minSelfDelegation: number,
maxTotalDelegation: number,
slotKeyToRemove: string,
slotKeyToAdd: string,
) { ) {
this.validatorAddress = validatorAddress;
this.description = description; this.description = description;
this.stakingAddress = stakingAddress;
this.commissionRate = commissionRate; this.commissionRate = commissionRate;
this.minSelfDelegation = minSelfDelegation; this.minSelfDelegation = minSelfDelegation;
this.maxTotalDelegation = maxTotalDelegation;
this.slotKeyToRemove = slotKeyToRemove;
this.slotKeyToAdd = slotKeyToAdd;
} }
encode(): any[] { encode(): any[] {
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = [];
raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorAddress)));
raw.push(this.description.encode()); raw.push(this.description.encode());
raw.push(hexlify(TransactionBase.normalizeAddress(this.stakingAddress)));
raw.push(this.commissionRate.encode()); raw.push(this.commissionRate.encode());
raw.push(hexlify(this.minSelfDelegation)); raw.push(hexlify(this.minSelfDelegation));
raw.push(hexlify(this.maxTotalDelegation));
raw.push(this.slotKeyToRemove);
raw.push(this.slotKeyToAdd);
return raw; return raw;
} }
} }
@ -352,46 +413,32 @@ export class Delegate {
} }
} }
export class Redelegate { export class Undelegate {
delegatorAddress: string; delegatorAddress: string;
validatorSrcAddress: string; validatorAddress: string;
validatorDstAddress: string;
amount: number; amount: number;
constructor( constructor(delegatorAddress: string, validatorAddress: string, amount: number) {
delegatorAddress: string,
validatorSrcAddress: string,
validatorDstAddress: string,
amount: number,
) {
this.delegatorAddress = delegatorAddress; this.delegatorAddress = delegatorAddress;
this.validatorSrcAddress = validatorSrcAddress; this.validatorAddress = validatorAddress;
this.validatorDstAddress = validatorDstAddress;
this.amount = amount; this.amount = amount;
} }
encode(): any[] { encode(): any[] {
const raw: Array<string | Uint8Array> = []; const raw: Array<string | Uint8Array> = [];
raw.push(hexlify(TransactionBase.normalizeAddress(this.delegatorAddress))); raw.push(hexlify(TransactionBase.normalizeAddress(this.delegatorAddress)));
raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorSrcAddress))); raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorAddress)));
raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorDstAddress)));
raw.push(hexlify(this.amount)); raw.push(hexlify(this.amount));
return raw; return raw;
} }
} }
export class Undelegate { export class CollectRewards {
delegatorAddress: string; delegatorAddress: string;
validatorAddress: string; constructor(delegatorAddress: string) {
amount: number;
constructor(delegatorAddress: string, validatorAddress: string, amount: number) {
this.delegatorAddress = delegatorAddress; this.delegatorAddress = delegatorAddress;
this.validatorAddress = validatorAddress;
this.amount = amount;
} }
encode(): any[] { encode(): any[] {
const raw: Array<string | Uint8Array> = []; const raw: Array<string | Uint8Array> = [];
raw.push(hexlify(TransactionBase.normalizeAddress(this.delegatorAddress))); raw.push(hexlify(TransactionBase.normalizeAddress(this.delegatorAddress)));
raw.push(hexlify(TransactionBase.normalizeAddress(this.validatorAddress)));
raw.push(hexlify(this.amount));
return raw; return raw;
} }
} }

@ -1,10 +1,8 @@
import { getAddressFromPrivateKey } from '@harmony-js/crypto';
import { isValidAddress, ChainType, ChainID } from '@harmony-js/utils';
// tslint:disable-next-line: no-implicit-dependencies // tslint:disable-next-line: no-implicit-dependencies
import { Wallet } from '@harmony-js/account'; import { Wallet } from '@harmony-js/account';
import { getAddressFromPrivateKey } from '@harmony-js/crypto';
import { HttpProvider, Messenger } from '@harmony-js/network'; import { HttpProvider, Messenger } from '@harmony-js/network';
import { ChainID, ChainType, isValidAddress } from '@harmony-js/utils';
// tslint:disable-next-line: no-implicit-dependencies // tslint:disable-next-line: no-implicit-dependencies
import fetch from 'jest-fetch-mock'; import fetch from 'jest-fetch-mock';
@ -17,11 +15,11 @@ const msgHttp = new Messenger(http, ChainType.Harmony, ChainID.HmyLocal);
const walletHttp = new Wallet(msgHttp); const walletHttp = new Wallet(msgHttp);
import { import {
NewValidator, CreateValidator,
EditValidator, EditValidator,
Delegate, Delegate,
Redelegate,
Undelegate, Undelegate,
CollectRewards,
Directive, Directive,
StakingTransaction, StakingTransaction,
Description, Description,
@ -36,7 +34,7 @@ describe('test sign staking transaction', () => {
fetch.resetMocks(); fetch.resetMocks();
// jest.clearAllTimers(); // jest.clearAllTimers();
}); });
it('should test sign new validator staking transaction', () => { it('should test sign create validator staking transaction', () => {
const testTx: any = testTransactions[0]; const testTx: any = testTransactions[0];
const address = getAddressFromPrivateKey(testTx.privateKey); const address = getAddressFromPrivateKey(testTx.privateKey);
expect(isValidAddress(address)).toEqual(true); expect(isValidAddress(address)).toEqual(true);
@ -47,21 +45,22 @@ describe('test sign staking transaction', () => {
testTx.description.securityContact, testTx.description.securityContact,
testTx.description.details, testTx.description.details,
); );
const commission: CommissionRate = new CommissionRate( const commissionRates: CommissionRate = new CommissionRate(
new Decimal(testTx.commission.rate, 0), new Decimal(testTx.commissionRates.rate),
new Decimal(testTx.commission.maxRate, 0), new Decimal(testTx.commissionRates.maxRate),
new Decimal(testTx.commission.maxChangeRate, 0), new Decimal(testTx.commissionRates.maxChangeRate),
); );
const stakeMsg: NewValidator = new NewValidator( const stakeMsg: CreateValidator = new CreateValidator(
testTx.validatorAddress,
desc, desc,
commission, commissionRates,
testTx.minSelfDelegation, testTx.minSelfDelegation,
testTx.stakingAddress, testTx.maxTotalDelegation,
testTx.pubKey, testTx.slotPubKeys,
testTx.amount, testTx.amount,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveNewValidator, Directive.DirectiveCreateValidator,
stakeMsg, stakeMsg,
testTx.nonce, testTx.nonce,
testTx.gasPrice, testTx.gasPrice,
@ -86,10 +85,13 @@ describe('test sign staking transaction', () => {
testTx.description.details, testTx.description.details,
); );
const stakeMsg: EditValidator = new EditValidator( const stakeMsg: EditValidator = new EditValidator(
testTx.validatorAddress,
desc, desc,
testTx.stakingAddress, new Decimal(testTx.commissionRate),
new Decimal(testTx.commissionRate, 0),
testTx.minSelfDelegation, testTx.minSelfDelegation,
testTx.maxTotalDelegation,
testTx.slotKeyToRemove,
testTx.slotKeyToAdd,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveEditValidator, Directive.DirectiveEditValidator,
@ -129,19 +131,18 @@ describe('test sign staking transaction', () => {
const signed = stakingTx.rlpSign(testTx.privateKey); const signed = stakingTx.rlpSign(testTx.privateKey);
expect(signed[1]).toEqual(testTx.encoded); expect(signed[1]).toEqual(testTx.encoded);
}); });
it('should test sign redelegate staking transaction', () => { it('should test sign undelegate staking transaction', () => {
const testTx: any = testTransactions[3]; const testTx: any = testTransactions[3];
const address = getAddressFromPrivateKey(testTx.privateKey); const address = getAddressFromPrivateKey(testTx.privateKey);
expect(isValidAddress(address)).toEqual(true); expect(isValidAddress(address)).toEqual(true);
const stakeMsg: Redelegate = new Redelegate( const stakeMsg: Undelegate = new Undelegate(
testTx.delegatorAddress, testTx.delegatorAddress,
testTx.validatorSrcAddress, testTx.validatorAddress,
testTx.validatorDstAddress,
testTx.amount, testTx.amount,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveRedelegate, Directive.DirectiveUndelegate,
stakeMsg, stakeMsg,
testTx.nonce, testTx.nonce,
testTx.gasPrice, testTx.gasPrice,
@ -154,18 +155,14 @@ describe('test sign staking transaction', () => {
const signed = stakingTx.rlpSign(testTx.privateKey); const signed = stakingTx.rlpSign(testTx.privateKey);
expect(signed[1]).toEqual(testTx.encoded); expect(signed[1]).toEqual(testTx.encoded);
}); });
it('should test sign undelegate staking transaction', () => { it('should test sign collect rewards staking transaction', () => {
const testTx: any = testTransactions[4]; const testTx: any = testTransactions[4];
const address = getAddressFromPrivateKey(testTx.privateKey); const address = getAddressFromPrivateKey(testTx.privateKey);
expect(isValidAddress(address)).toEqual(true); expect(isValidAddress(address)).toEqual(true);
const stakeMsg: Undelegate = new Undelegate( const stakeMsg: CollectRewards = new CollectRewards(testTx.delegatorAddress);
testTx.delegatorAddress,
testTx.validatorAddress,
testTx.amount,
);
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveUndelegate, Directive.DirectiveCollectRewards,
stakeMsg, stakeMsg,
testTx.nonce, testTx.nonce,
testTx.gasPrice, testTx.gasPrice,
@ -178,7 +175,7 @@ describe('test sign staking transaction', () => {
const signed = stakingTx.rlpSign(testTx.privateKey); const signed = stakingTx.rlpSign(testTx.privateKey);
expect(signed[1]).toEqual(testTx.encoded); expect(signed[1]).toEqual(testTx.encoded);
}); });
it('should test sign new validator staking transaction using wallet', async () => { it('should test sign create validator staking transaction using wallet', async () => {
const testTx: any = testTransactions[0]; const testTx: any = testTransactions[0];
const responses = [ const responses = [
{ {
@ -202,21 +199,22 @@ describe('test sign staking transaction', () => {
testTx.description.securityContact, testTx.description.securityContact,
testTx.description.details, testTx.description.details,
); );
const commission: CommissionRate = new CommissionRate( const commissionRates: CommissionRate = new CommissionRate(
new Decimal(testTx.commission.rate, 0), new Decimal(testTx.commissionRates.rate),
new Decimal(testTx.commission.maxRate, 0), new Decimal(testTx.commissionRates.maxRate),
new Decimal(testTx.commission.maxChangeRate, 0), new Decimal(testTx.commissionRates.maxChangeRate),
); );
const stakeMsg: NewValidator = new NewValidator( const stakeMsg: CreateValidator = new CreateValidator(
testTx.validatorAddress,
desc, desc,
commission, commissionRates,
testTx.minSelfDelegation, testTx.minSelfDelegation,
testTx.stakingAddress, testTx.maxTotalDelegation,
testTx.pubKey, testTx.slotPubKeys,
testTx.amount, testTx.amount,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveNewValidator, Directive.DirectiveCreateValidator,
stakeMsg, stakeMsg,
0, 0,
testTx.gasPrice, testTx.gasPrice,
@ -255,10 +253,13 @@ describe('test sign staking transaction', () => {
testTx.description.details, testTx.description.details,
); );
const stakeMsg: EditValidator = new EditValidator( const stakeMsg: EditValidator = new EditValidator(
testTx.validatorAddress,
desc, desc,
testTx.stakingAddress, new Decimal(testTx.commissionRate),
new Decimal(testTx.commissionRate, 0),
testTx.minSelfDelegation, testTx.minSelfDelegation,
testTx.maxTotalDelegation,
testTx.slotKeyToRemove,
testTx.slotKeyToAdd,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveEditValidator, Directive.DirectiveEditValidator,
@ -313,8 +314,9 @@ describe('test sign staking transaction', () => {
const signedStaking: StakingTransaction = await account.signStaking(stakingTx); const signedStaking: StakingTransaction = await account.signStaking(stakingTx);
expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded); expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded);
}); });
it('should test sign redelegate staking transaction using wallet', async () => { it('should test sign undelegate staking transaction using wallet', async () => {
const testTx: any = testTransactions[3]; const testTx: any = testTransactions[3];
const responses = [ const responses = [
{ {
jsonrpc: '2.0', jsonrpc: '2.0',
@ -329,16 +331,14 @@ describe('test sign staking transaction', () => {
].map((res) => [JSON.stringify(res)] as [string]); ].map((res) => [JSON.stringify(res)] as [string]);
fetch.mockResponses(...responses); fetch.mockResponses(...responses);
const stakeMsg: Undelegate = new Undelegate(
const stakeMsg: Redelegate = new Redelegate(
testTx.delegatorAddress, testTx.delegatorAddress,
testTx.validatorSrcAddress, testTx.validatorAddress,
testTx.validatorDstAddress,
testTx.amount, testTx.amount,
); );
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveRedelegate, Directive.DirectiveUndelegate,
stakeMsg, stakeMsg,
0, 0,
testTx.gasPrice, testTx.gasPrice,
@ -350,11 +350,13 @@ describe('test sign staking transaction', () => {
); );
const account: any = walletHttp.addByPrivateKey(testTx.privateKey); const account: any = walletHttp.addByPrivateKey(testTx.privateKey);
const signedStaking: StakingTransaction = await account.signStaking(stakingTx); const signedStaking: StakingTransaction = await account.signStaking(stakingTx);
expect(signedStaking.getFromAddress()).toEqual(account.bech32Address);
expect(signedStaking.getSignature()).toBeTruthy();
expect(signedStaking.getUnsignedRawTransaction()).toBeTruthy();
expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded); expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded);
}); });
it('should test sign undelegate staking transaction using wallet', async () => { it('should test sign collect rewards staking transaction using wallet', async () => {
const testTx: any = testTransactions[4]; const testTx: any = testTransactions[4];
const responses = [ const responses = [
{ {
jsonrpc: '2.0', jsonrpc: '2.0',
@ -369,14 +371,11 @@ describe('test sign staking transaction', () => {
].map((res) => [JSON.stringify(res)] as [string]); ].map((res) => [JSON.stringify(res)] as [string]);
fetch.mockResponses(...responses); fetch.mockResponses(...responses);
const stakeMsg: Undelegate = new Undelegate(
testTx.delegatorAddress, const stakeMsg: CollectRewards = new CollectRewards(testTx.delegatorAddress);
testTx.validatorAddress,
testTx.amount,
);
const stakingTx: StakingTransaction = new StakingTransaction( const stakingTx: StakingTransaction = new StakingTransaction(
Directive.DirectiveUndelegate, Directive.DirectiveCollectRewards,
stakeMsg, stakeMsg,
0, 0,
testTx.gasPrice, testTx.gasPrice,
@ -388,9 +387,6 @@ describe('test sign staking transaction', () => {
); );
const account: any = walletHttp.addByPrivateKey(testTx.privateKey); const account: any = walletHttp.addByPrivateKey(testTx.privateKey);
const signedStaking: StakingTransaction = await account.signStaking(stakingTx); const signedStaking: StakingTransaction = await account.signStaking(stakingTx);
expect(signedStaking.getFromAddress()).toEqual(account.bech32Address);
expect(signedStaking.getSignature()).toBeTruthy();
expect(signedStaking.getUnsignedRawTransaction()).toBeTruthy();
expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded); expect(signedStaking.getRawTransaction()).toEqual(testTx.encoded);
}); });
}); });

@ -2,6 +2,7 @@
{ {
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", "privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48",
"chainID": "0x2", "chainID": "0x2",
"validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"description": { "description": {
"name": "Alice", "name": "Alice",
"identity": "alice", "identity": "alice",
@ -9,26 +10,29 @@
"securityContact": "Bob", "securityContact": "Bob",
"details": "Don't mess with me!!!" "details": "Don't mess with me!!!"
}, },
"commission": { "commissionRates": {
"rate": "100", "rate": "0.1",
"maxRate": "150", "maxRate": "0.9",
"maxChangeRate": "5" "maxChangeRate": "0.05"
}, },
"minSelfDelegation": "0xa", "minSelfDelegation": "0xa",
"stakingAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", "maxTotalDelegation": "0x0bb8",
"pubKey": "0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611", "slotPubKeys": [
"0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611"
],
"amount": "0x64", "amount": "0x64",
"nonce": "0x2", "nonce": "0x2",
"gasPrice": "0x", "gasPrice": "0x",
"gasLimit": "0x64", "gasLimit": "0x64",
"encoded": "0xf8ec80f8a3f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121e0ca89056bc75e2d63100000ca890821ab0d4414980000c9884563918244f400000a94ebcd16e8c1d8f493ba04e99a56474122d81a9c58b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b622476086116402806428a00b1a797d11f7b0dad42abd66c542fab8af0f028b7159bb70e44fe68b2e4d9f2ca07b223662bdb4e1a084f8c506095886a1f5eda051927fab3516ab9258efc34cd7", "encoded": "0xf8ed80f8a494ebcd16e8c1d8f493ba04e99a56474122d81a9c58f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500000a820bb8f1b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b622476086116402806428a0476e8a0fe478e0d03ff10222d4d590bca8cee3ec51b830f4fc4a8bee5d0e9d28a03b2be18e73b2f99d7e2691485a0e166f28e62815079c126e68f876dc97339f8f",
"v": "28", "v": "28",
"r": "0x0b1a797d11f7b0dad42abd66c542fab8af0f028b7159bb70e44fe68b2e4d9f2c", "r": "0x476e8a0fe478e0d03ff10222d4d590bca8cee3ec51b830f4fc4a8bee5d0e9d28",
"s": "0x7b223662bdb4e1a084f8c506095886a1f5eda051927fab3516ab9258efc34cd7" "s": "0x3b2be18e73b2f99d7e2691485a0e166f28e62815079c126e68f876dc97339f8f"
}, },
{ {
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", "privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48",
"chainID": "0x2", "chainID": "0x2",
"validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"description": { "description": {
"name": "Alice", "name": "Alice",
"identity": "alice", "identity": "alice",
@ -36,16 +40,18 @@
"securityContact": "Bob", "securityContact": "Bob",
"details": "Don't mess with me!!!" "details": "Don't mess with me!!!"
}, },
"stakingAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", "commissionRate": "0.1",
"commissionRate": "100",
"minSelfDelegation": "0xa", "minSelfDelegation": "0xa",
"maxTotalDelegation": "0x0bb8",
"slotKeyToRemove": "0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611",
"slotKeyToAdd": "0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611",
"nonce": "0x2", "nonce": "0x2",
"gasPrice": "0x", "gasPrice": "0x",
"gasLimit": "0x64", "gasLimit": "0x64",
"encoded": "0xf8a401f85bf83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d6521212194ebcd16e8c1d8f493ba04e99a56474122d81a9c58ca89056bc75e2d631000000a02806428a071b68b38864e75af60bf05e52b53278e864dbf2eb4a33adeacaa6e1b31f21e59a01ee06acb4d2bc22105454a79ef089fc0794ddba6e2849d9e4236180b47e973ed", "encoded": "0xf9010801f8bf94ebcd16e8c1d8f493ba04e99a56474122d81a9c58f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121c988016345785d8a00000a820bb8b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b6224760861102806427a05e54b55272f6bf5ffeca10d85976749d6b844cc9f30ba3285b9ab8a82d53e3e3a03ce04d9a9f834e20b22aa918ead346c84a04b1504fe3ff9e38f21c5e5712f013",
"v": "28", "v": "27",
"r": "0x71b68b38864e75af60bf05e52b53278e864dbf2eb4a33adeacaa6e1b31f21e59", "r": "0x5e54b55272f6bf5ffeca10d85976749d6b844cc9f30ba3285b9ab8a82d53e3e3",
"s": "0x1ee06acb4d2bc22105454a79ef089fc0794ddba6e2849d9e4236180b47e973ed" "s": "0x3ce04d9a9f834e20b22aa918ead346c84a04b1504fe3ff9e38f21c5e5712f013"
}, },
{ {
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", "privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48",
@ -65,29 +71,26 @@
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", "privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48",
"chainID": "0x2", "chainID": "0x2",
"delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", "delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"validatorSrcAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", "validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"validatorDstAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"amount": "0xa", "amount": "0xa",
"nonce": "0x2", "nonce": "0x2",
"gasPrice": "0x", "gasPrice": "0x",
"gasLimit": "0x64", "gasLimit": "0x64",
"encoded": "0xf88903f84094ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806428a0c479121bf1ea02fa1052a4d54743703fa6eeb16e50ff002d34fcfde736c21d75a07a1b9dac1761ab9fb38cadcdd4b0b28aafc39d1707e913f6b758e05e09b1e517", "encoded": "0xf87303eb94ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806428a05bf8c653567defe2c3728732bc9d67dd099a977df91c740a883fd89e03abb6e2a05202c4b51652d5144c6a30d14d1a7a316b5a4a6b49be985b4bc6980e49f7acb7",
"v": "28", "v": "28",
"r": "0xc479121bf1ea02fa1052a4d54743703fa6eeb16e50ff002d34fcfde736c21d75", "r": "0x5bf8c653567defe2c3728732bc9d67dd099a977df91c740a883fd89e03abb6e2",
"s": "0x7a1b9dac1761ab9fb38cadcdd4b0b28aafc39d1707e913f6b758e05e09b1e517" "s": "0x5202c4b51652d5144c6a30d14d1a7a316b5a4a6b49be985b4bc6980e49f7acb7"
}, },
{ {
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", "privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48",
"chainID": "0x2", "chainID": "0x2",
"delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", "delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9",
"amount": "0xa",
"nonce": "0x2", "nonce": "0x2",
"gasPrice": "0x", "gasPrice": "0x",
"gasLimit": "0x64", "gasLimit": "0x64",
"encoded": "0xf87304eb94ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806427a0d6af2488d3b45658f37ff6bb89f7eaa86f7c1dfce19a68697e778be28efd2320a05b9837bd5c7041318859f9fb444a255f32f4d7e7b49f18830ba75abecdc02390", "encoded": "0xf85d04d594ebcd16e8c1d8f493ba04e99a56474122d81a9c5802806428a04c15c72f42577001083a9c7ff9d9724077aec704a524e53dc7c9afe97ca4e625a055c13ea17c3efd1cd91f2988c7e7673950bac5a08c174f2d0af27a82039f1e3d",
"v": "27", "v": "28",
"r": "0xd6af2488d3b45658f37ff6bb89f7eaa86f7c1dfce19a68697e778be28efd2320", "r": "0x4c15c72f42577001083a9c7ff9d9724077aec704a524e53dc7c9afe97ca4e625",
"s": "0x5b9837bd5c7041318859f9fb444a255f32f4d7e7b49f18830ba75abecdc02390" "s": "0x55c13ea17c3efd1cd91f2988c7e7673950bac5a08c174f2d0af27a82039f1e3d"
} }
] ]

Loading…
Cancel
Save