revamped account/account and account/wallet

pull/21/head
Wen Zhang 5 years ago committed by Ganesha Upadhyaya
parent 1d37b68d79
commit 40fc994fae
  1. 175
      packages/harmony-account/src/account.ts
  2. 18
      packages/harmony-account/src/hdnode.ts
  3. 155
      packages/harmony-account/src/wallet.ts
  4. 2
      packages/harmony-contract/src/events/eventFactory.ts
  5. 1
      packages/harmony-network/src/index.ts
  6. 1
      packages/harmony-network/src/messenger/responseMiddleware.ts
  7. 1
      packages/harmony-network/src/rpcMethod/net.ts
  8. 2
      packages/harmony-network/src/rpcMethod/rpc.ts
  9. 1
      packages/harmony-network/src/types.ts
  10. 1
      packages/harmony-transaction/src/abstractTransaction.ts
  11. 1
      packages/harmony-transaction/src/index.ts
  12. 1
      packages/harmony-transaction/src/shardingTransaction.ts
  13. 1
      packages/harmony-transaction/src/types.ts

@ -32,55 +32,136 @@ import { defaultMessenger } from './utils';
class Account {
/**
* @function new static method create account
* @return {Account} Account instance
* static method create account
*
* @example
* ```javascript
* const account = new Account();
* console.log(account);
* ```
*/
static new(): Account {
const newAcc = new Account()._new();
return newAcc;
}
/**
* @function add static method add a private key to Account
* Static Method: add a private key to Account
* @param {string} key - private Key
* @return {Account} Account instance
*
* @example
* ```javascript
* const account = new Account.add(key_1);
* console.log(account);
* ```
*/
static add(key: string): Account {
const newAcc = new Account()._import(key);
return newAcc;
}
/**@hidden */
privateKey?: string;
/**@hidden */
publicKey?: string;
/**@hidden */
address?: string;
/**@hidden */
balance?: string = '0';
/**@hidden */
nonce?: number = 0;
/**@hidden */
shardID: number;
/**@hidden */
shards: Shards;
/**@hidden */
messenger: Messenger;
/**@hidden */
encrypted: boolean = false;
/**
* @function checksumAddress checsumAddress getter
* @return {string} get the checksumAddress
* check sum address
*
* @example
* ```javascript
* console.log(account.checksumAddress);
* ```
*/
get checksumAddress(): string {
return this.address ? getAddress(this.address).checksum : '';
}
/**
* Get bech32 Address
*
* @example
* ```javascript
* console.log(account.bech32Address);
* ```
*/
get bech32Address(): string {
return this.address ? getAddress(this.address).bech32 : '';
}
/**
* get Bech32 TestNet Address
*
* @example
* ```javascript
* console.log(account.bech32TestNetAddress);
* ```
*/
get bech32TestNetAddress(): string {
return this.address ? getAddress(this.address).bech32TestNet : '';
}
/**
* @function getShardsCount getShards number with this Account
* @return {number} shard size
* get Shards number with this Account
*
* @example
* ```javascript
* console.log(account.getShardsCount);
* ```
*/
get getShardsCount(): number {
return this.shards.size;
}
/**
* Generate an account object
*
* @param key import an existing privateKey, or create a random one
* @param messenger you can setMessage later, or set message on `new`
*
* @example
* ```javascript
* // import the Account class
* const { Account } = require('@harmony-js/account');
*
* // Messenger is optional, by default, we have a defaultMessenger
* // If you like to change, you will import related package here.
* const { HttpProvider, Messenger } = require('@harmony-js/network');
* const { ChainType, ChainID } = require('@harmony-js/utils');
*
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Harmony, // if you are connected to Harmony's blockchain
* ChainID.HmyLocal, // check if the chainId is correct
* )
*
* // setMessenger later
* const randomAccount = new Account()
* randomAccount.setMessenger(customMessenger)
*
* // or you can set messenger on `new`
* const randomAccountWithCustomMessenger = new Account(undefined, customMessenger)
*
* // NOTED: Key with or without `0x` are accepted, makes no different
* // NOTED: DO NOT import `mnemonic phrase` using `Account` class, use `Wallet` instead
* const myPrivateKey = '0xe19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930'
* const myAccountWithMyPrivateKey = new Account(myPrivateKey)
* ```
*/
constructor(key?: string, messenger: Messenger = defaultMessenger) {
this.messenger = messenger;
if (!key) {
@ -126,12 +207,16 @@ class Account {
}
/**
* Get the account balance
*
* @param blockNumber by default, it's `latest`
*
* @example
* ```javascript
* account.getBalance().then((value) => {
* console.log(value);
* });
* ```
* const helloworld = 'helloworld';
* const abcde = 'dceba'
* ```
* @return {type} {hahahhahaah}
*/
async getBalance(blockNumber: string = 'latest'): Promise<object> {
try {
@ -174,7 +259,6 @@ class Account {
/**
* @function updateShards
* @return {Promise<string>} {description}
*/
async updateBalances(blockNumber: string = 'latest'): Promise<void> {
// this.messenger.setShardingProviders();
@ -256,6 +340,16 @@ class Account {
return transaction;
}
}
/**
* This function is still in development, coming soon!
*
* @param staking
* @param updateNonce
* @param encodeMode
* @param blockNumber
* @param shardID
*/
async signStaking(
staking: StakingTransaction,
updateNonce: boolean = true,
@ -309,10 +403,40 @@ class Account {
return staking;
}
}
/**
* @param messenger
*
* @example
* ```javascript
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Harmony, // if you are connected to Harmony's blockchain
* ChainID.HmyLocal, // check if the chainId is correct
* )
*
* // to create an Account with random privateKey
* // and you can setMessenger later
* const randomAccount = new Account()
* randomAccount.setMessenger(customMessenger)
* ```
*/
setMessenger(messenger: Messenger) {
this.messenger = messenger;
}
/**
* Get account address from shard ID
* @param shardID
*
* @example
* ```javascript
* console.log(account.getAddressFromShardID(0));
*
* > one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7-0
* ```
*/
getAddressFromShardID(shardID: number) {
const shardObject = this.shards.get(shardID);
if (shardObject) {
@ -321,6 +445,15 @@ class Account {
return undefined;
}
}
/**
* Get all shards' addresses from the account
*
* @example
* ```javascript
* console.log(account.getAddresses());
* ```
*/
getAddresses(): string[] {
const addressArray: string[] = [];
for (const [name, val] of this.shards) {
@ -330,6 +463,19 @@ class Account {
return addressArray;
}
/**
* Get the specific shard's balance
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @param blockNumber by default, it's `latest`
*
* @example
* ```
* account.getShardBalance().then((value) => {
* console.log(value);
* });
* ```
*/
async getShardBalance(shardID: number, blockNumber: string = 'latest') {
const balance = await this.messenger.send(
RPCMethod.GetBalance,
@ -357,9 +503,11 @@ class Account {
nonce: Number.parseInt(hexToNumber(nonce.result), 10),
};
}
/**
* @function _new private method create Account
* @return {Account} Account instance
* @ignore
*/
private _new(): Account {
const prv = generatePrivateKey();
@ -373,6 +521,7 @@ class Account {
* @function _import private method import a private Key
* @param {string} key - private key
* @return {Account} Account instance
* @ignore
*/
private _import(key: string): Account {
if (!isPrivateKey(key)) {

@ -19,16 +19,12 @@ import { Messenger, HttpProvider, WSProvider } from '@harmony-js/network';
import { Transaction, TxStatus, TransasctionReceipt } from '@harmony-js/transaction';
import { Account } from './account';
/**
* @hidden
*/
/** @hidden */
export interface WalletsInterfaces {
[key: string]: Account;
}
/**
* @hidden
*/
/** @hidden */
export interface Web3TxPrams {
id?: string;
from?: string;
@ -54,19 +50,29 @@ export class HDNode {
}
return bip39.validateMnemonic(phrase);
}
static generateMnemonic(): string {
return bip39.generateMnemonic();
}
public provider: HttpProvider | WSProvider;
public gasLimit: string;
public gasPrice: string;
public messenger: Messenger;
/** @hidden */
private shardID: number;
/** @hidden */
private hdwallet: hdkey | undefined;
/** @hidden */
private path: string;
/** @hidden */
private index: number;
/** @hidden */
private addressCount: number;
/** @hidden */
private addresses: string[];
/** @hidden */
private wallets: WalletsInterfaces;
constructor(

@ -17,21 +17,45 @@ class Wallet {
return bip39.generateMnemonic();
}
/** @hidden */
messenger: Messenger;
/** @hidden */
protected defaultSigner?: string;
/**
* @memberof Wallet
*
* @hidden
*/
private accountMap: Map<string, Account> = new Map();
/**
* @memberof Wallet
* get acounts addresses
*
* @return {string[]} accounts addresses
*
* @example
* ```javascript
* const wallet = new Wallet(customMessenger);
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* wallet.addByPrivateKey(key_1);
*
* console.log(wallet.accounts);
* ```
*/
get accounts(): string[] {
return [...this.accountMap.keys()];
}
/**
* get the signer of the account, by default, using the first account
*
* @example
* ```javascript
* const wallet = new Wallet(customMessenger);
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* wallet.addByPrivateKey(key_1);
*
* console.log(wallet.signer)
* ```
*/
get signer(): Account | undefined {
if (this.defaultSigner) {
return this.getAccount(this.defaultSigner);
@ -43,6 +67,23 @@ class Wallet {
}
}
/**
* @example
* ```
* const { Wallet } = require('@harmony-js/account');
* const { HttpProvider, Messenger } = require('@harmony-js/network');
* const { ChainType, ChainID } = require('@harmony-js/utils');
*
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Harmony, // if you are connected to Harmony's blockchain
* ChainID.HmyLocal, // check if the chainId is correct
* )
*
* const wallet = new Wallet(customMessenger);
* ```
*/
constructor(messenger: Messenger = defaultMessenger) {
this.messenger = messenger;
}
@ -56,11 +97,18 @@ class Wallet {
}
/**
* @function addByMnemonic
* @memberof Wallet
* @description add account using Mnemonic phrases
* Add account using Mnemonic phrases
* @param {string} phrase - Mnemonic phrase
* @param {index} index - index to hdKey root
*
* @example
* ```javascript
* const mnemonic_1 = 'urge clog right example dish drill card maximum mix bachelor section select';
* const wallet = new Wallet(customMessenger);
* wallet.addByMnemonic(mnemonic_1);
*
* console.log(wallet.accounts);
* ```
*/
addByMnemonic(phrase: string, index: number = 0) {
if (!this.isValidMnemonic(phrase)) {
@ -74,12 +122,19 @@ class Wallet {
const privateKey = childKey.privateKey.toString('hex');
return this.addByPrivateKey(privateKey);
}
/**
* @function addByPrivateKey
* @memberof Wallet
* @description add an account using privateKey
* Add an account using privateKey
*
* @param {string} privateKey - privateKey to add
* @return {Account} return added Account
*
* @example
* ```javascript
* const wallet = new Wallet(customMessenger);
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* console.log(wallet.addByPrivateKey(key_1));
* ```
*/
addByPrivateKey(privateKey: string): Account {
try {
@ -100,9 +155,7 @@ class Wallet {
}
/**
* @function addByKeyStore
* @memberof Wallet
* @description add an account using privateKey
* Add an account using privateKey
* @param {string} keyStore - keystore jsonString to add
* @param {string} password - password to decrypt the file
* @return {Account} return added Account
@ -127,9 +180,17 @@ class Wallet {
}
/**
* @function createAccount
* @description create a new account using Mnemonic
* create a new account using Mnemonic
* @return {Account} {description}
*
* @example
* ```javascript
* console.log(wallet.accounts);
* wallet.createAccount();
* wallet.createAccount();
*
* console.log(wallet.accounts);
* ````
*/
async createAccount(password?: string, options?: EncryptOptions): Promise<Account> {
const prv = generatePrivateKey();
@ -145,14 +206,21 @@ class Wallet {
}
/**
* @function encryptAccount
* @memberof Wallet
* @description to encrypt an account that lives in the wallet,
* To encrypt an account that lives in the wallet.
* if encrypted, returns original one, if not found, throw error
* @param {string} address - address in accounts
* @param {string} password - string that used to encrypt
* @param {EncryptOptions} options - encryption options
* @return {Promise<Account>}
*
* @example
* ```javascript
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* wallet.addByPrivateKey(key_1);
* wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345').then((value) => {
* console.log(value);
* })
* ```
*/
async encryptAccount(
address: string,
@ -173,14 +241,26 @@ class Wallet {
throw error;
}
}
/**
* @function decryptAccount
* @memberof Wallet
* @description to decrypt an account that lives in the wallet,if not encrypted, return original,
* To decrypt an account that lives in the wallet,if not encrypted, return original,
* if not found, throw error
* @param {string} address - address in accounts
* @param {string} password - string that used to encrypt
* @return {Promise<Account>}
*
* @example
* ```javascript
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* wallet.addByPrivateKey(key_1);
* wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345')
* .then(() => {
* wallet.decryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345')
* .then((value) =>{
* console.log(value);
* });
* });
* ```
*/
async decryptAccount(address: string, password: string): Promise<Account> {
try {
@ -200,11 +280,16 @@ class Wallet {
}
/**
* @function getAccount
* @memberof Wallet
* @description get Account instance using address as param
* Get Account instance using address as param
* @param {string} address - address hex
* @return {Account} Account instance which lives in Wallet
*
* @example
* ```
* const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* wallet.addByPrivateKey(key_1);
* console.log(wallet.getAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'));
* ```
*/
getAccount(address: string): Account | undefined {
return this.accountMap.get(getAddress(address).basicHex);
@ -223,10 +308,31 @@ class Wallet {
}
}
/**
* Set Customer Messenage
* @param messenger
*
* @example
* ```javascript
* const customMessenger = new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Harmony, // if you are connected to Harmony's blockchain
* ChainID.HmyLocal, // check if the chainId is correct
* )
* const wallet = new Wallet();
* wallet.setMessenger(customMessenger);
* console.log(wallet.messenger);
* ```
*/
setMessenger(messenger: Messenger): void {
this.messenger = messenger;
}
/**
* Set signer
*
* @param address one of the address in the accounts
*/
setSigner(address: string): void {
if (!isAddress(address) || !this.getAccount(address)) {
throw new Error('could not set signer');
@ -280,6 +386,7 @@ class Wallet {
throw new Error('sign transaction failed');
}
}
async signStaking(
staking: StakingTransaction,
account: Account | undefined = this.signer,
@ -329,12 +436,14 @@ class Wallet {
throw new Error('sign transaction failed');
}
}
/**
* @function isValidMnemonic
* @memberof Wallet
* @description check if Mnemonic is valid
* @param {string} phrase - Mnemonic phrase
* @return {boolean}
* @ignore
*/
private isValidMnemonic(phrase: string): boolean {
if (phrase.trim().split(/\s+/g).length < 12) {

@ -30,7 +30,7 @@ export class EventFactory {
const newObject: any = {};
newObject[key] = (params: any) =>
new EventMethod(
key,
key
// params,
this.map(this.abiModel, this.contract, params),
this.abiModel.getEvent(key),

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
import mitt from 'mitt';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
import { RPCResponseBody } from '../types';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
export const DEFAULT_TIMEOUT: number = 120000;

@ -3,6 +3,7 @@
* @module harmony-network
*/
/**@ignore */
export const enum RPCMethod {
// 1. hmy_getBlockByHash
GetBlockByHash = 'hmy_getBlockByHash',
@ -77,6 +78,7 @@ export const enum RPCMethod {
SendRawStakingTransaction = 'hmy_sendRawStakingTransaction',
}
/**@ignore */
export const enum RPCErrorCode {
// Standard JSON-RPC 2.0 errors
// RPC_INVALID_REQUEST is internally mapped to HTTP_BAD_REQUEST (400).

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
import { RPCMethod, RPCErrorCode } from './rpcMethod/rpc';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { Messenger } from '@harmony-js/network';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
export * from './factory';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { Messenger } from '@harmony-js/network';

@ -1,6 +1,7 @@
/**
* @packageDocumentation
* @module harmony-transaction
*
*/
import { BN, Signature } from '@harmony-js/crypto';

Loading…
Cancel
Save