commit
4ec08ce790
@ -0,0 +1,21 @@ |
||||
MIT License |
||||
|
||||
Copyright (c) 2019 suwei |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,27 @@ |
||||
{ |
||||
"name": "@harmony-js/staking", |
||||
"version": "0.1.29", |
||||
"description": "staking transaction package for harmony", |
||||
"main": "dist/index.js", |
||||
"node": "dist/index.js", |
||||
"browser": "dist/index.js", |
||||
"module": "dist/index.esm.js", |
||||
"jsnext:main": "dist/index.esm.js", |
||||
"typings": "dist/index.d.ts", |
||||
"types": "dist/index.d.ts", |
||||
"scripts": { |
||||
"test": "echo \"Error: no test specified\" && exit 1" |
||||
}, |
||||
"publishConfig": { |
||||
"access": "public" |
||||
}, |
||||
"author": "", |
||||
"license": "MIT", |
||||
"dependencies": { |
||||
"@harmony-js/crypto": "0.1.28", |
||||
"@harmony-js/network": "0.1.29", |
||||
"@harmony-js/utils": "0.1.28", |
||||
"text-encoding": "^0.7.0" |
||||
}, |
||||
"gitHead": "775e2ba36924fcffd8d2c0b73587b549ed90bb81" |
||||
} |
@ -0,0 +1 @@ |
||||
export * from './stakingTransaction'; |
@ -0,0 +1,356 @@ |
||||
// tslint:disable: max-classes-per-file
|
||||
|
||||
import { |
||||
encode, |
||||
arrayify, |
||||
hexlify, |
||||
stripZeros, |
||||
Signature, |
||||
splitSignature, |
||||
getAddress, |
||||
HarmonyAddress, |
||||
keccak256, |
||||
sign, |
||||
BN, |
||||
} from '@harmony-js/crypto'; |
||||
import { TextEncoder } from 'text-encoding'; |
||||
import { Unit, numberToHex } from '@harmony-js/utils'; |
||||
|
||||
export class StakingSettings { |
||||
public static PRECISION = 18; |
||||
} |
||||
|
||||
export const enum Directive { |
||||
DirectiveNewValidator, |
||||
DirectiveEditValidator, |
||||
DirectiveDelegate, |
||||
DirectiveRedelegate, |
||||
DirectiveUndelegate, |
||||
} |
||||
|
||||
export class StakingTransaction { |
||||
private directive: Directive; |
||||
private stakeMsg: NewValidator | EditValidator | Delegate | Redelegate | Undelegate; |
||||
private nonce: number | string; |
||||
private gasLimit: number | string; |
||||
private gasPrice: number | string; |
||||
private chainId: number; |
||||
private rawTransaction: string; |
||||
private unsignedRawTransaction: string; |
||||
private signature: Signature; |
||||
private from: string; |
||||
|
||||
constructor( |
||||
directive: Directive, |
||||
stakeMsg: NewValidator | EditValidator | Delegate | Redelegate | Undelegate, |
||||
nonce: number | string, |
||||
gasPrice: number | string, |
||||
gasLimit: number | string, |
||||
chainID: number, |
||||
v: number, |
||||
r: string, |
||||
s: string, |
||||
) { |
||||
this.directive = directive; |
||||
this.stakeMsg = stakeMsg; |
||||
this.nonce = nonce; |
||||
this.gasLimit = gasLimit; |
||||
this.gasPrice = gasPrice; |
||||
this.rawTransaction = '0x'; |
||||
this.unsignedRawTransaction = '0x'; |
||||
this.signature = { |
||||
r, |
||||
s, |
||||
recoveryParam: 0, |
||||
v, |
||||
}; |
||||
this.chainId = chainID; |
||||
this.from = '0x'; |
||||
} |
||||
|
||||
encode(): [string, any[]] { |
||||
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; |
||||
// TODO: temporary hack for converting 0x00 to 0x
|
||||
if (!this.directive) { |
||||
raw.push('0x'); |
||||
} else { |
||||
raw.push(hexlify(this.directive)); |
||||
} |
||||
raw.push(this.stakeMsg.encode()); |
||||
raw.push(hexlify(this.nonce)); |
||||
raw.push(hexlify(this.gasPrice)); |
||||
raw.push(hexlify(this.gasLimit)); |
||||
if (this.chainId != null && this.chainId !== 0) { |
||||
raw.push(hexlify(this.chainId)); |
||||
raw.push('0x'); |
||||
raw.push('0x'); |
||||
} |
||||
return [encode(raw), raw]; |
||||
} |
||||
|
||||
rlpSign(prv: string): [Signature, string] { |
||||
const [unsignedRawTransaction, raw] = this.encode(); |
||||
const signature = sign(keccak256(unsignedRawTransaction), prv); |
||||
const signed = this.getRLPSigned(raw, signature); |
||||
return [signature, signed]; |
||||
} |
||||
|
||||
getRLPSigned(raw: any[], signature: Signature): string { |
||||
const sig = splitSignature(signature); |
||||
let v = 27 + (sig.recoveryParam || 0); |
||||
raw.pop(); |
||||
raw.pop(); |
||||
raw.pop(); |
||||
v += this.chainId * 2 + 8; |
||||
|
||||
raw.push(hexlify(v)); |
||||
raw.push(stripZeros(arrayify(sig.r) || [])); |
||||
raw.push(stripZeros(arrayify(sig.s) || [])); |
||||
|
||||
return encode(raw); |
||||
} |
||||
setUnsigned(unSigned: string) { |
||||
this.unsignedRawTransaction = unSigned; |
||||
} |
||||
setRawTransaction(rawTransaction: string) { |
||||
this.rawTransaction = rawTransaction; |
||||
} |
||||
setSignature(signature: Signature) { |
||||
this.signature = { |
||||
r: signature.r, |
||||
s: signature.s, |
||||
v: signature.v, |
||||
recoveryParam: signature.recoveryParam, |
||||
}; |
||||
} |
||||
setNonce(nonce: number) { |
||||
this.nonce = nonce; |
||||
} |
||||
setFromAddress(address: string) { |
||||
this.from = address; |
||||
} |
||||
getUnsignedRawTransaction() { |
||||
return this.unsignedRawTransaction; |
||||
} |
||||
getRawTransaction() { |
||||
return this.rawTransaction; |
||||
} |
||||
getSignature() { |
||||
return this.signature; |
||||
} |
||||
|
||||
getFromAddress() { |
||||
return this.from; |
||||
} |
||||
} |
||||
|
||||
export class Description { |
||||
name: string; |
||||
identity: string; |
||||
website: string; |
||||
securityContact: string; |
||||
details: string; |
||||
|
||||
constructor( |
||||
name: string, |
||||
identity: string, |
||||
website: string, |
||||
securityContact: string, |
||||
details: string, |
||||
) { |
||||
this.name = name; |
||||
this.identity = identity; |
||||
this.website = website; |
||||
this.securityContact = securityContact; |
||||
this.details = details; |
||||
} |
||||
|
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
const enc = new TextEncoder(); |
||||
raw.push(enc.encode(this.name)); |
||||
raw.push(enc.encode(this.identity)); |
||||
raw.push(enc.encode(this.website)); |
||||
raw.push(enc.encode(this.securityContact)); |
||||
raw.push(enc.encode(this.details)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class Decimal { |
||||
value: BN; |
||||
constructor(value: number, precision: number) { |
||||
if (precision > StakingSettings.PRECISION) { |
||||
throw new Error( |
||||
`too much precision: ${precision}, should be less than ${StakingSettings.PRECISION}`, |
||||
); |
||||
} |
||||
const zerosToAdd = StakingSettings.PRECISION - precision; |
||||
const multiplier = Math.pow(10, zerosToAdd); |
||||
// (value * multiplier).toString();
|
||||
this.value = new Unit((value * multiplier).toString()).asWei().toWei(); |
||||
} |
||||
|
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
raw.push(numberToHex(this.value)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class CommissionRate { |
||||
rate: Decimal; |
||||
maxRate: Decimal; |
||||
maxChangeRate: Decimal; |
||||
constructor(rate: Decimal, maxRate: Decimal, maxChangeRate: Decimal) { |
||||
this.rate = rate; |
||||
this.maxRate = maxRate; |
||||
this.maxChangeRate = maxChangeRate; |
||||
} |
||||
|
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; |
||||
raw.push(this.rate.encode()); |
||||
raw.push(this.maxRate.encode()); |
||||
raw.push(this.maxChangeRate.encode()); |
||||
// console.log(decode(encode(raw)));
|
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class NewValidator { |
||||
description: Description; |
||||
commission: CommissionRate; |
||||
minSelfDelegation: number; |
||||
stakingAddress: string; |
||||
pubKey: string; |
||||
amount: number; |
||||
constructor( |
||||
description: Description, |
||||
commission: CommissionRate, |
||||
minSelfDelegation: number, |
||||
stakingAddress: string, |
||||
pubKey: string, |
||||
amount: number, |
||||
) { |
||||
this.description = description; |
||||
this.commission = commission; |
||||
this.minSelfDelegation = minSelfDelegation; |
||||
this.stakingAddress = stakingAddress; |
||||
this.pubKey = pubKey; |
||||
this.amount = amount; |
||||
} |
||||
|
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; |
||||
raw.push(this.description.encode()); |
||||
raw.push(this.commission.encode()); |
||||
raw.push(hexlify(this.minSelfDelegation)); |
||||
raw.push(hexlify(normalizeAddress(this.stakingAddress))); |
||||
raw.push(this.pubKey); |
||||
raw.push(hexlify(this.amount)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class EditValidator { |
||||
description: Description; |
||||
stakingAddress: string; |
||||
commissionRate: Decimal; |
||||
minSelfDelegation: number; |
||||
constructor( |
||||
description: Description, |
||||
stakingAddress: string, |
||||
commissionRate: Decimal, |
||||
minSelfDelegation: number, |
||||
) { |
||||
this.description = description; |
||||
this.stakingAddress = stakingAddress; |
||||
this.commissionRate = commissionRate; |
||||
this.minSelfDelegation = minSelfDelegation; |
||||
} |
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array | Array<string | Uint8Array>> = []; |
||||
raw.push(this.description.encode()); |
||||
raw.push(hexlify(normalizeAddress(this.stakingAddress))); |
||||
raw.push(this.commissionRate.encode()); |
||||
raw.push(hexlify(this.minSelfDelegation)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class Delegate { |
||||
delegatorAddress: string; |
||||
validatorAddress: string; |
||||
amount: number; |
||||
constructor(delegatorAddress: string, validatorAddress: string, amount: number) { |
||||
this.delegatorAddress = delegatorAddress; |
||||
this.validatorAddress = validatorAddress; |
||||
this.amount = amount; |
||||
} |
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
raw.push(hexlify(normalizeAddress(this.delegatorAddress))); |
||||
raw.push(hexlify(normalizeAddress(this.validatorAddress))); |
||||
raw.push(hexlify(this.amount)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class Redelegate { |
||||
delegatorAddress: string; |
||||
validatorSrcAddress: string; |
||||
validatorDstAddress: string; |
||||
amount: number; |
||||
constructor( |
||||
delegatorAddress: string, |
||||
validatorSrcAddress: string, |
||||
validatorDstAddress: string, |
||||
amount: number, |
||||
) { |
||||
this.delegatorAddress = delegatorAddress; |
||||
this.validatorSrcAddress = validatorSrcAddress; |
||||
this.validatorDstAddress = validatorDstAddress; |
||||
this.amount = amount; |
||||
} |
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
raw.push(hexlify(normalizeAddress(this.delegatorAddress))); |
||||
raw.push(hexlify(normalizeAddress(this.validatorSrcAddress))); |
||||
raw.push(hexlify(normalizeAddress(this.validatorDstAddress))); |
||||
raw.push(hexlify(this.amount)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export class Undelegate { |
||||
delegatorAddress: string; |
||||
validatorAddress: string; |
||||
amount: number; |
||||
constructor(delegatorAddress: string, validatorAddress: string, amount: number) { |
||||
this.delegatorAddress = delegatorAddress; |
||||
this.validatorAddress = validatorAddress; |
||||
this.amount = amount; |
||||
} |
||||
encode(): any[] { |
||||
const raw: Array<string | Uint8Array> = []; |
||||
raw.push(hexlify(normalizeAddress(this.delegatorAddress))); |
||||
raw.push(hexlify(normalizeAddress(this.validatorAddress))); |
||||
raw.push(hexlify(this.amount)); |
||||
return raw; |
||||
} |
||||
} |
||||
|
||||
export function normalizeAddress(address: string) { |
||||
if (address === '0x') { |
||||
return '0x'; |
||||
} else if ( |
||||
HarmonyAddress.isValidChecksum(address) || |
||||
HarmonyAddress.isValidBech32(address) || |
||||
HarmonyAddress.isValidBech32TestNet(address) |
||||
) { |
||||
return getAddress(address).checksum; |
||||
} else { |
||||
throw new Error(`Address format is not supported`); |
||||
} |
||||
} |
@ -0,0 +1,162 @@ |
||||
import { getAddressFromPrivateKey } from '@harmony-js/crypto'; |
||||
import { isValidAddress } from '@harmony-js/utils'; |
||||
|
||||
import { |
||||
NewValidator, |
||||
EditValidator, |
||||
Delegate, |
||||
Redelegate, |
||||
Undelegate, |
||||
Directive, |
||||
StakingTransaction, |
||||
Description, |
||||
CommissionRate, |
||||
Decimal, |
||||
} from '../src/stakingTransaction'; |
||||
|
||||
import testTransactions from './transactions.json'; |
||||
|
||||
describe('test sign staking transaction', () => { |
||||
it('should test sign new validator staking transaction', () => { |
||||
const testTx: any = testTransactions[0]; |
||||
const address = getAddressFromPrivateKey(testTx.privateKey); |
||||
expect(isValidAddress(address)).toEqual(true); |
||||
const desc: Description = new Description( |
||||
testTx.description.name, |
||||
testTx.description.identity, |
||||
testTx.description.website, |
||||
testTx.description.securityContact, |
||||
testTx.description.details, |
||||
); |
||||
const commission: CommissionRate = new CommissionRate( |
||||
new Decimal(testTx.commission.rate, 0), |
||||
new Decimal(testTx.commission.maxRate, 0), |
||||
new Decimal(testTx.commission.maxChangeRate, 0), |
||||
); |
||||
const stakeMsg: NewValidator = new NewValidator( |
||||
desc, |
||||
commission, |
||||
testTx.minSelfDelegation, |
||||
testTx.stakingAddress, |
||||
testTx.pubKey, |
||||
testTx.amount, |
||||
); |
||||
const stakingTx: StakingTransaction = new StakingTransaction( |
||||
Directive.DirectiveNewValidator, |
||||
stakeMsg, |
||||
testTx.nonce, |
||||
testTx.gasPrice, |
||||
testTx.gasLimit, |
||||
testTx.chainID, |
||||
testTx.chainID, |
||||
'', |
||||
'', |
||||
); |
||||
const signed = stakingTx.rlpSign(testTx.privateKey); |
||||
expect(signed[1]).toEqual(testTx.encoded); |
||||
}); |
||||
it('should test sign edit validator staking transaction', () => { |
||||
const testTx: any = testTransactions[1]; |
||||
const address = getAddressFromPrivateKey(testTx.privateKey); |
||||
expect(isValidAddress(address)).toEqual(true); |
||||
const desc: Description = new Description( |
||||
testTx.description.name, |
||||
testTx.description.identity, |
||||
testTx.description.website, |
||||
testTx.description.securityContact, |
||||
testTx.description.details, |
||||
); |
||||
const stakeMsg: EditValidator = new EditValidator( |
||||
desc, |
||||
testTx.stakingAddress, |
||||
new Decimal(testTx.commissionRate, 0), |
||||
testTx.minSelfDelegation, |
||||
); |
||||
const stakingTx: StakingTransaction = new StakingTransaction( |
||||
Directive.DirectiveEditValidator, |
||||
stakeMsg, |
||||
testTx.nonce, |
||||
testTx.gasPrice, |
||||
testTx.gasLimit, |
||||
testTx.chainID, |
||||
testTx.chainID, |
||||
'', |
||||
'', |
||||
); |
||||
const signed = stakingTx.rlpSign(testTx.privateKey); |
||||
expect(signed[1]).toEqual(testTx.encoded); |
||||
}); |
||||
it('should test sign delegate staking transaction', () => { |
||||
const testTx: any = testTransactions[2]; |
||||
const address = getAddressFromPrivateKey(testTx.privateKey); |
||||
expect(isValidAddress(address)).toEqual(true); |
||||
const stakeMsg: Delegate = new Delegate( |
||||
testTx.delegatorAddress, |
||||
testTx.validatorAddress, |
||||
testTx.amount, |
||||
); |
||||
|
||||
const stakingTx: StakingTransaction = new StakingTransaction( |
||||
Directive.DirectiveDelegate, |
||||
stakeMsg, |
||||
testTx.nonce, |
||||
testTx.gasPrice, |
||||
testTx.gasLimit, |
||||
testTx.chainID, |
||||
testTx.chainID, |
||||
'', |
||||
'', |
||||
); |
||||
const signed = stakingTx.rlpSign(testTx.privateKey); |
||||
expect(signed[1]).toEqual(testTx.encoded); |
||||
}); |
||||
it('should test sign redelegate staking transaction', () => { |
||||
const testTx: any = testTransactions[3]; |
||||
const address = getAddressFromPrivateKey(testTx.privateKey); |
||||
expect(isValidAddress(address)).toEqual(true); |
||||
const stakeMsg: Redelegate = new Redelegate( |
||||
testTx.delegatorAddress, |
||||
testTx.validatorSrcAddress, |
||||
testTx.validatorDstAddress, |
||||
testTx.amount, |
||||
); |
||||
|
||||
const stakingTx: StakingTransaction = new StakingTransaction( |
||||
Directive.DirectiveRedelegate, |
||||
stakeMsg, |
||||
testTx.nonce, |
||||
testTx.gasPrice, |
||||
testTx.gasLimit, |
||||
testTx.chainID, |
||||
testTx.chainID, |
||||
'', |
||||
'', |
||||
); |
||||
const signed = stakingTx.rlpSign(testTx.privateKey); |
||||
expect(signed[1]).toEqual(testTx.encoded); |
||||
}); |
||||
it('should test sign undelegate staking transaction', () => { |
||||
const testTx: any = testTransactions[4]; |
||||
const address = getAddressFromPrivateKey(testTx.privateKey); |
||||
expect(isValidAddress(address)).toEqual(true); |
||||
const stakeMsg: Undelegate = new Undelegate( |
||||
testTx.delegatorAddress, |
||||
testTx.validatorAddress, |
||||
testTx.amount, |
||||
); |
||||
|
||||
const stakingTx: StakingTransaction = new StakingTransaction( |
||||
Directive.DirectiveUndelegate, |
||||
stakeMsg, |
||||
testTx.nonce, |
||||
testTx.gasPrice, |
||||
testTx.gasLimit, |
||||
testTx.chainID, |
||||
testTx.chainID, |
||||
'', |
||||
'', |
||||
); |
||||
const signed = stakingTx.rlpSign(testTx.privateKey); |
||||
expect(signed[1]).toEqual(testTx.encoded); |
||||
}); |
||||
}); |
@ -0,0 +1,93 @@ |
||||
[ |
||||
{ |
||||
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", |
||||
"chainID": "0x2", |
||||
"description": { |
||||
"name": "Alice", |
||||
"identity": "alice", |
||||
"website": "alice.harmony.one", |
||||
"securityContact": "Bob", |
||||
"details": "Don't mess with me!!!" |
||||
}, |
||||
"commission": { |
||||
"rate": "100", |
||||
"maxRate": "150", |
||||
"maxChangeRate": "5" |
||||
}, |
||||
"minSelfDelegation": "0xa", |
||||
"stakingAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"pubKey": "0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611", |
||||
"amount": "0x64", |
||||
"nonce": "0x2", |
||||
"gasPrice": "0x", |
||||
"gasLimit": "0x64", |
||||
"encoded": "0xf8ec80f8a3f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121e0ca89056bc75e2d63100000ca890821ab0d4414980000c9884563918244f400000a94ebcd16e8c1d8f493ba04e99a56474122d81a9c58b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b622476086116402806428a00b1a797d11f7b0dad42abd66c542fab8af0f028b7159bb70e44fe68b2e4d9f2ca07b223662bdb4e1a084f8c506095886a1f5eda051927fab3516ab9258efc34cd7", |
||||
"v": "28", |
||||
"r": "0x0b1a797d11f7b0dad42abd66c542fab8af0f028b7159bb70e44fe68b2e4d9f2c", |
||||
"s": "0x7b223662bdb4e1a084f8c506095886a1f5eda051927fab3516ab9258efc34cd7" |
||||
}, |
||||
{ |
||||
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", |
||||
"chainID": "0x2", |
||||
"description": { |
||||
"name": "Alice", |
||||
"identity": "alice", |
||||
"website": "alice.harmony.one", |
||||
"securityContact": "Bob", |
||||
"details": "Don't mess with me!!!" |
||||
}, |
||||
"stakingAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"commissionRate": "100", |
||||
"minSelfDelegation": "0xa", |
||||
"nonce": "0x2", |
||||
"gasPrice": "0x", |
||||
"gasLimit": "0x64", |
||||
"encoded": "0xf8a401f85bf83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d6521212194ebcd16e8c1d8f493ba04e99a56474122d81a9c58ca89056bc75e2d631000000a02806428a071b68b38864e75af60bf05e52b53278e864dbf2eb4a33adeacaa6e1b31f21e59a01ee06acb4d2bc22105454a79ef089fc0794ddba6e2849d9e4236180b47e973ed", |
||||
"v": "28", |
||||
"r": "0x71b68b38864e75af60bf05e52b53278e864dbf2eb4a33adeacaa6e1b31f21e59", |
||||
"s": "0x1ee06acb4d2bc22105454a79ef089fc0794ddba6e2849d9e4236180b47e973ed" |
||||
}, |
||||
{ |
||||
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", |
||||
"chainID": "0x2", |
||||
"delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"amount": "0xa", |
||||
"nonce": "0x2", |
||||
"gasPrice": "0x", |
||||
"gasLimit": "0x64", |
||||
"encoded": "0xf87302eb94ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806428a0ada9a8fb49eb3cd74f0f861e16bc1f1d56a0c6e3c25b0391f9e07a7963317e80a05c28dbc41763dc2391263e1aae30f842f90734d7ec68cee2352af0d4b0662b54", |
||||
"v": "28", |
||||
"r": "0xada9a8fb49eb3cd74f0f861e16bc1f1d56a0c6e3c25b0391f9e07a7963317e80", |
||||
"s": "0x5c28dbc41763dc2391263e1aae30f842f90734d7ec68cee2352af0d4b0662b54" |
||||
}, |
||||
{ |
||||
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", |
||||
"chainID": "0x2", |
||||
"delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"validatorSrcAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"validatorDstAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"amount": "0xa", |
||||
"nonce": "0x2", |
||||
"gasPrice": "0x", |
||||
"gasLimit": "0x64", |
||||
"encoded": "0xf88903f84094ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806428a0c479121bf1ea02fa1052a4d54743703fa6eeb16e50ff002d34fcfde736c21d75a07a1b9dac1761ab9fb38cadcdd4b0b28aafc39d1707e913f6b758e05e09b1e517", |
||||
"v": "28", |
||||
"r": "0xc479121bf1ea02fa1052a4d54743703fa6eeb16e50ff002d34fcfde736c21d75", |
||||
"s": "0x7a1b9dac1761ab9fb38cadcdd4b0b28aafc39d1707e913f6b758e05e09b1e517" |
||||
}, |
||||
{ |
||||
"privateKey": "4edef2c24995d15b0e25cbd152fb0e2c05d3b79b9c2afd134e6f59f91bf99e48", |
||||
"chainID": "0x2", |
||||
"delegatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"validatorAddress": "one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9", |
||||
"amount": "0xa", |
||||
"nonce": "0x2", |
||||
"gasPrice": "0x", |
||||
"gasLimit": "0x64", |
||||
"encoded": "0xf87304eb94ebcd16e8c1d8f493ba04e99a56474122d81a9c5894ebcd16e8c1d8f493ba04e99a56474122d81a9c580a02806427a0d6af2488d3b45658f37ff6bb89f7eaa86f7c1dfce19a68697e778be28efd2320a05b9837bd5c7041318859f9fb444a255f32f4d7e7b49f18830ba75abecdc02390", |
||||
"v": "27", |
||||
"r": "0xd6af2488d3b45658f37ff6bb89f7eaa86f7c1dfce19a68697e778be28efd2320", |
||||
"s": "0x5b9837bd5c7041318859f9fb444a255f32f4d7e7b49f18830ba75abecdc02390" |
||||
} |
||||
] |
@ -0,0 +1,3 @@ |
||||
{ |
||||
"extends": "../tsconfig.test.json" |
||||
} |
@ -0,0 +1,13 @@ |
||||
{ |
||||
"extends": "../../tsconfig.base.json", |
||||
"compilerOptions": { |
||||
"rootDir": "src", |
||||
"outDir": "dist" |
||||
}, |
||||
"include": ["src", "../../typings/**/*.d.ts"], |
||||
"references": [ |
||||
{ "path": "../harmony-utils" }, |
||||
{ "path": "../harmony-crypto" }, |
||||
{ "path": "../harmony-network" } |
||||
] |
||||
} |
@ -0,0 +1,5 @@ |
||||
{ |
||||
"extends": "../../tsconfig.test.json", |
||||
"include": ["src", "test", "../../typings/**/*.d.ts"], |
||||
"references": [] |
||||
} |
@ -1,12 +1,13 @@ |
||||
{ |
||||
"files": [], |
||||
"references": [ |
||||
{"path": "packages/harmony-utils"}, |
||||
{"path": "packages/harmony-crypto"}, |
||||
{"path": "packages/harmony-network"}, |
||||
{"path": "packages/harmony-transaction"}, |
||||
{"path": "packages/harmony-account"}, |
||||
{"path": "packages/harmony-contract"}, |
||||
{"path": "packages/harmony-core"} |
||||
{ "path": "packages/harmony-utils" }, |
||||
{ "path": "packages/harmony-crypto" }, |
||||
{ "path": "packages/harmony-network" }, |
||||
{ "path": "packages/harmony-staking" }, |
||||
{ "path": "packages/harmony-transaction" }, |
||||
{ "path": "packages/harmony-account" }, |
||||
{ "path": "packages/harmony-contract" }, |
||||
{ "path": "packages/harmony-core" } |
||||
] |
||||
} |
||||
|
Loading…
Reference in new issue