added assert object

@types
neeboo 6 years ago
parent e7ace6f172
commit aad1b492cb
  1. 8
      examples/testNode.js
  2. 36
      packages/harmony-account/src/account.ts
  3. 13
      packages/harmony-core/src/core.ts
  4. 13
      packages/harmony-core/src/types.ts
  5. 3
      packages/harmony-network/package.json
  6. 28
      packages/harmony-network/src/blockchain/blockchain.ts
  7. 44
      packages/harmony-network/src/blockchain/rpc.ts
  8. 11
      packages/harmony-network/src/blockchain/rpcBuilder.ts
  9. 2
      packages/harmony-network/src/messenger/messenger.ts
  10. 1
      packages/harmony-utils/src/index.ts
  11. 116
      packages/harmony-utils/src/utils.ts
  12. 15
      packages/harmony-utils/src/validators.ts

@ -124,9 +124,9 @@ const acc = wallet.addByPrivateKey(
// console.log(getContractAddress(acc.publicKey, 248));
const harmony = new Harmony('https://dev-api.zilliqa.com');
// const harmony = new Harmony('https://dev-api.zilliqa.com');
const file =
'{"version":3,"id":"05D302EE-23DC-48C4-B89C-CAAAC1C780C4","x-ethers":{"gethFilename":"UTC--2018-01-26T20-25-02.0Z--15db397ed5f682acb22b0afc6c8de4cdfbda7cbc","mnemonicCiphertext":"b92c7c3da540ae7beee55365fb330c33","mnemonicCounter":"a65d689a73c096025f2acae3f7068510","client":"ethers/iOS","version":"0.1"},"Crypto":{"ciphertext":"fa6ff2374087a089ec9fcba3bc21389f5e26ec2932c95b608ebe0218efab83c6","cipherparams":{"iv":"5ddca45b254406516ca2c97d18d5dfd9"},"kdf":"scrypt","kdfparams":{"r":8,"p":1,"n":262144,"dklen":32,"salt":"864a474f8586ab0fa97ed9240ae6227b2b22b48bdf298137c355e4a07eb19831"},"mac":"eaa89325acedbf88c0893e53c8c8d426b590655746c66da9cd76e4f72d84084f","cipher":"aes-128-ctr"},"address":"15db397ed5f682acb22b0afc6c8de4cdfbda7cbc"}';
// const file =
// '{"version":3,"id":"05D302EE-23DC-48C4-B89C-CAAAC1C780C4","x-ethers":{"gethFilename":"UTC--2018-01-26T20-25-02.0Z--15db397ed5f682acb22b0afc6c8de4cdfbda7cbc","mnemonicCiphertext":"b92c7c3da540ae7beee55365fb330c33","mnemonicCounter":"a65d689a73c096025f2acae3f7068510","client":"ethers/iOS","version":"0.1"},"Crypto":{"ciphertext":"fa6ff2374087a089ec9fcba3bc21389f5e26ec2932c95b608ebe0218efab83c6","cipherparams":{"iv":"5ddca45b254406516ca2c97d18d5dfd9"},"kdf":"scrypt","kdfparams":{"r":8,"p":1,"n":262144,"dklen":32,"salt":"864a474f8586ab0fa97ed9240ae6227b2b22b48bdf298137c355e4a07eb19831"},"mac":"eaa89325acedbf88c0893e53c8c8d426b590655746c66da9cd76e4f72d84084f","cipher":"aes-128-ctr"},"address":"15db397ed5f682acb22b0afc6c8de4cdfbda7cbc"}';
const acc2 = new Account().fromFile(file, 'password').then(console.log);
// const acc2 = new Account().fromFile(file, 'password').then(console.log);

@ -13,7 +13,7 @@ import {
import { isPrivateKey, add0xToString, hexToNumber } from '@harmony/utils';
import { Transaction } from '@harmony/transaction';
import { Messenger, RPCMethod } from '@harmony/network';
import { Shards, ShardId } from './types';
import { Shards } from './types';
import { RLPSign } from './utils';
class Account {
@ -68,20 +68,6 @@ class Account {
}
}
/**
* @function addShard add shard to this Account
* @param {ShardId} id - ShardId to the Account
*/
addShard(id: ShardId): void {
if (this.shards && this.shards.has('default')) {
this.shards.set(id, '');
} else {
throw new Error(
'This account has no default shard or shard is not exist',
);
}
}
async toFile(password: string, options?: EncryptOptions): Promise<string> {
if (this.privateKey && isPrivateKey(this.privateKey)) {
const file = await encrypt(this.privateKey, password, options);
@ -115,10 +101,10 @@ class Account {
*/
async getBalance(): Promise<object> {
if (this.messenger) {
const result = await this.messenger.send(
RPCMethod.GetBalance,
const result = await this.messenger.send(RPCMethod.GetBalance, [
this.address,
);
'latest',
]);
if (result.responseType === 'result') {
this.balance = hexToNumber(result.balance);
this.nonce = Number.parseInt(hexToNumber(result.nonce), 10);
@ -199,6 +185,20 @@ class Account {
this.shards = new Map().set('default', '');
return this;
}
// /**
// * @function addShard add shard to this Account
// * @param {ShardId} id - ShardId to the Account
// */
// private addShard(id: ShardId): void {
// if (this.shards && this.shards.has('default')) {
// this.shards.set(id, '');
// } else {
// throw new Error(
// 'This account has no default shard or shard is not exist',
// );
// }
// }
}
export { Account };

@ -2,10 +2,19 @@ import * as crypto from '@harmony/crypto';
import * as utils from '@harmony/utils';
import { HttpProvider, Messenger, Blockchain } from '@harmony/network';
import { TransactionFactory } from '@harmony/transaction';
import { Wallet } from '@harmony/account';
import { TransactionFactory, Transaction } from '@harmony/transaction';
import { Wallet, Account } from '@harmony/account';
class Harmony {
Modules = {
HttpProvider,
Messenger,
Blockchain,
TransactionFactory,
Wallet,
Transaction,
Account,
};
messenger: Messenger;
transactions: TransactionFactory;
wallet: Wallet;

@ -0,0 +1,13 @@
import { HttpProvider, Messenger, Blockchain } from '@harmony/network';
import { TransactionFactory, Transaction } from '@harmony/transaction';
import { Wallet, Account } from '@harmony/account';
export interface HarmonyModule {
HttpProvider: HttpProvider;
Messenger: Messenger;
Blockchain: Blockchain;
TransactionFactory: TransactionFactory;
Wallet: Wallet;
Transaction: Transaction;
Account: Account;
}

@ -14,6 +14,7 @@
"author": "neeboo@firestack.one",
"license": "ISC",
"dependencies": {
"cross-fetch": "^3.0.2"
"cross-fetch": "^3.0.2",
"@harmony/utils": "^0.0.1"
}
}

@ -1,5 +1,6 @@
import { RPCMethod } from './rpc';
import { Messenger } from '../messenger/messenger';
import { assertObject, AssertType } from '@harmony/utils';
class Blockchain {
messenger: Messenger;
@ -8,15 +9,26 @@ class Blockchain {
this.messenger = messenger;
}
getBalance = async (address: string) => {
const result = await this.messenger.send(RPCMethod.GetBalance, address);
@assertObject({
address: ['isAddress', AssertType.required],
blockNumber: ['isHex', AssertType.optional],
tag: ['isString', AssertType.optional],
})
async getBalance({
address,
blockNumber,
tag = 'latest',
}: {
address: string;
blockNumber: string;
tag: string;
}) {
const result = await this.messenger.send(RPCMethod.GetBalance, [
address,
blockNumber || tag,
]);
return result;
};
getLatestBlock = async () => {
const result = await this.messenger.send(RPCMethod.GetLatestBlock, '');
return result;
};
}
}
export { Blockchain };

@ -1,18 +1,34 @@
export const enum RPCMethod {
// account related
FetchBalance = 'FetchBalance',
GetBalance = 'GetBalance',
// block info related
GetLatestBlock = 'GetLatestBlock',
GetBlock = 'GetBlock',
GetEstimtedGas = 'GetEstimatedGas',
GetLatestTransactions = 'GetLatestTransactions',
GetLatestDSBlocks = 'GetLatestDSBlocks',
// transaction related
SendTransaction = 'SendTransaction',
SendTransactionToShard = 'SendTransactionToShard',
SendTransactionToBlock = 'SendTransactionToBlock',
GetTransaction = 'GetTransaction',
// 1. hmy_getBlockByHash
GetBlockByHash = 'hmy_getBlockByHash',
// 2. hmy_getBlockByNumber
GetBlockByNumber = 'hmy_getBlockByNumber',
// 3. hmy_getBlockTransactionCountByHash
GetBlockTransactionCountByHash = 'hmy_getBlockTransactionCountByHash',
// 4. hmy_getBlockTransactionCountByNumber
GetBlockTransactionCountByNumber = 'hmy_getBlockTransactionCountByNumber',
// 5. hmy_getCode
GetCode = 'hmy_getCode',
// 6. hmy_getTransactionByBlockHashAndIndex
GetTransactionByBlockHashAndIndex = 'hmy_getTransactionByBlockHashAndIndex',
// 7. hmy_getTransactionByBlockNumberAndIndex
GetTransactionByBlockNumberAndIndex = 'hmy_getTransactionByBlockNumberAndIndex',
// 8. hmy_getTransactionByHash
GetTransactionByHash = 'hmy_getTransactionByHash',
// 9. hmy_syncing
Syncing = 'hmy_syncing',
// 10. net_peerCount
PeerCount = 'net_peerCount',
// 11. hmy_getBalance
GetBalance = 'hmy_getBalance',
// 12. hmy_getStorageAt
GetStorageAt = 'hmy_getStorageAt',
// 13. hmy_getTransactionCount
GetTransactionCount = 'hmy_getTransactionCount',
// 14. hmy_sendTransaction
SendTransaction = 'hmy_sendTransaction',
// 15. hmy_sendRawTransaction
SendRawTransaction = 'hmy_sendRawTransaction',
}
export const enum RPCErrorCode {

@ -26,7 +26,7 @@ class JsonRpc {
*/
toPayload = (
method: RPCMethod,
params: string,
params: string | undefined | any[],
): RPCRequestPayload<object> => {
// FIXME: error to be done by shared/errors
if (!method) throw new Error('jsonrpc method should be specified!');
@ -34,11 +34,18 @@ class JsonRpc {
// advance message ID
this.messageId += 1;
const sendParams =
params === undefined
? []
: typeof params === 'string'
? [params]
: [...params];
return {
jsonrpc: '2.0',
id: this.messageId,
method,
params: params !== undefined ? [params] : [],
params: sendParams,
};
};
}

@ -79,7 +79,7 @@ class Messenger {
* @param {Object} params - RPC method params
* @return {Object} RPC result
*/
send = async (method: RPCMethod, params: any) => {
send = async (method: RPCMethod, params?: string | any[] | undefined) => {
this.providerCheck();
try {
const payload = this.JsonRpc.toPayload(method, params);

@ -1,2 +1,3 @@
export * from './validators';
export * from './transformers';
export * from './utils';

@ -0,0 +1,116 @@
import {
isNumber,
isString,
isBoolean,
isArray,
isJsonString,
isHex,
isObject,
isFunction,
isPublicKey,
isPrivateKey,
isAddress,
} from './validators';
export const enum AssertType {
required = 'required',
optional = 'optional',
}
export const validatorArray: any = {
isNumber: [isNumber],
isString: [isString],
isBoolean: [isBoolean],
isArray: [isArray],
isJsonString: [isJsonString],
isObject: [isObject],
isFunction: [isFunction],
isHex: [isHex],
isPublicKey: [isPublicKey],
isPrivateKey: [isPrivateKey],
isAddress: [isAddress],
};
export function validateArgs(
args: any,
requiredArgs: any,
optionalArgs: any,
): boolean {
for (const key in requiredArgs) {
if (args[key] !== undefined) {
// tslint:disable-next-line: prefer-for-of
for (let i = 0; i < requiredArgs[key].length; i += 1) {
if (typeof requiredArgs[key][i] !== 'function') {
throw new Error('Validator is not a function');
}
if (!requiredArgs[key][i](args[key])) {
throw new Error(
`Validation failed for ${key},should be validated by ${
requiredArgs[key][i].validator
}`,
);
}
}
} else {
throw new Error(`Key not found: ${key}`);
}
}
for (const key in optionalArgs) {
if (args[key]) {
// tslint:disable-next-line: prefer-for-of
for (let i = 0; i < optionalArgs[key].length; i += 1) {
if (typeof optionalArgs[key][i] !== 'function') {
throw new Error('Validator is not a function');
}
if (!optionalArgs[key][i](args[key])) {
throw new Error(
`Validation failed for ${key},should be validated by ${
optionalArgs[key][i].validator
}`,
);
}
}
}
}
return true;
}
export function generateValidateObjects(validatorObject: {
[x: string]: any[];
}) {
const requiredArgs: any = {};
const optionalArgs: any = {};
for (const index in validatorObject) {
if (index !== undefined) {
const newObjectKey = index;
const newObjectValid = validatorObject[index][0];
const isRequired = validatorObject[index][1];
if (isRequired === AssertType.required) {
requiredArgs[newObjectKey] = validatorArray[newObjectValid];
} else {
optionalArgs[newObjectKey] = validatorArray[newObjectValid];
}
}
}
return { requiredArgs, optionalArgs };
}
const assertObject = (input: any) => (
target: any,
key: any,
descriptor: PropertyDescriptor,
) => {
const { requiredArgs, optionalArgs } = generateValidateObjects(input);
const original = descriptor.value;
function interceptor(this: any, ...args: any[]) {
validateArgs(args[0], requiredArgs, optionalArgs);
return original.apply(this, args);
}
descriptor.value = interceptor;
return descriptor;
};
export { assertObject };

@ -1,18 +1,22 @@
export const isKeyString = (keyString: string, lengh: number): boolean => {
return !!keyString.replace('0x', '').match(`^[0-9a-fA-F]{${lengh}}$`);
};
isKeyString.validator = 'isKeyString';
export const isAddress = (address: string): boolean => {
return isKeyString(address, 40);
};
isAddress.validator = 'isAddress';
export const isPrivateKey = (privateKey: string): boolean => {
return isKeyString(privateKey, 64);
};
isPrivateKey.validator = 'isPrivateKey';
export const isPublicKey = (publicKey: string): boolean => {
return isKeyString(publicKey, 66);
};
isPublicKey.validator = 'isPublicKey';
/**
* [isNumber verify param is a Number]
@ -22,6 +26,7 @@ export const isPublicKey = (publicKey: string): boolean => {
export const isNumber = (obj: any): boolean => {
return obj === +obj;
};
isNumber.validator = 'isNumber';
/**
* [isNumber verify param is a Number]
@ -32,6 +37,8 @@ export const isInt = (obj: any): boolean => {
return isNumber(obj) && Number.isInteger(obj);
};
isInt.validator = 'isInt';
/**
* [isString verify param is a String]
* @param {any} obj [value]
@ -41,6 +48,7 @@ export const isString = (obj: any): boolean => {
return obj === `${obj}`;
};
isString.validator = 'isString';
/**
* [isBoolean verify param is a Boolean]
* @param {any} obj [value]
@ -50,6 +58,7 @@ export const isBoolean = (obj: any): boolean => {
return obj === !!obj;
};
isBoolean.validator = 'isBoolean';
/**
* [isArray verify param input is an Array]
* @param {any} obj [value]
@ -59,6 +68,7 @@ export const isArray = (obj: any): boolean => {
return Array.isArray(obj);
};
isArray.validator = 'isArray';
/**
* [isJson verify param input is a Json]
* @param {any} obj [value]
@ -71,6 +81,7 @@ export const isJsonString = (obj: any): boolean => {
return false;
}
};
isJsonString.validator = 'isJsonString';
/**
* [isObject verify param is an Object]
@ -80,6 +91,7 @@ export const isJsonString = (obj: any): boolean => {
export const isObject = (obj: any): boolean => {
return obj !== null && !Array.isArray(obj) && typeof obj === 'object';
};
isObject.validator = 'isObject';
/**
* [isFunction verify param is a Function]
@ -90,6 +102,7 @@ export const isObject = (obj: any): boolean => {
export const isFunction = (obj: any): boolean => {
return typeof obj === 'function';
};
isFunction.validator = 'isFunction';
export const isHex = (obj: any): boolean => {
if (!isString(obj)) {
@ -100,3 +113,5 @@ export const isHex = (obj: any): boolean => {
isNumber(Number.parseInt(`${obj}`.toLowerCase().replace('0x', ''), 16))
);
};
isHex.validator = 'isHex';

Loading…
Cancel
Save