Merge pull request #21 from harmony-one/doc

[test] recover from PR #17
return-interface
Leo Chen 5 years ago committed by GitHub
commit ce39d112f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 100
      docs/README.md
  2. 11
      package.json
  3. 22
      packages/harmony-account/README.md
  4. 274
      packages/harmony-account/guide.ts
  5. 187
      packages/harmony-account/src/account.ts
  6. 17
      packages/harmony-account/src/hdnode.ts
  7. 6
      packages/harmony-account/src/index.ts
  8. 6
      packages/harmony-account/src/types.ts
  9. 6
      packages/harmony-account/src/utils.ts
  10. 160
      packages/harmony-account/src/wallet.ts
  11. 2
      packages/harmony-account/tsconfig.json
  12. 301
      packages/harmony-contract/src/abi/abiCoder.ts
  13. 10
      packages/harmony-contract/src/abi/api.ts
  14. 6
      packages/harmony-contract/src/abi/index.ts
  15. 10
      packages/harmony-contract/src/abi/utils.ts
  16. 6
      packages/harmony-contract/src/contract.ts
  17. 5
      packages/harmony-contract/src/contractFactory.ts
  18. 5
      packages/harmony-contract/src/events/event.ts
  19. 6
      packages/harmony-contract/src/events/eventFactory.ts
  20. 13
      packages/harmony-contract/src/index.ts
  21. 5
      packages/harmony-contract/src/methods/method.ts
  22. 13
      packages/harmony-contract/src/methods/methodFactory.ts
  23. 6
      packages/harmony-contract/src/models/AbiItemModel.ts
  24. 6
      packages/harmony-contract/src/models/AbiModel.ts
  25. 6
      packages/harmony-contract/src/models/types.ts
  26. 12
      packages/harmony-contract/src/utils/decoder.ts
  27. 6
      packages/harmony-contract/src/utils/encoder.ts
  28. 25
      packages/harmony-contract/src/utils/formatter.ts
  29. 10
      packages/harmony-contract/src/utils/mapper.ts
  30. 6
      packages/harmony-contract/src/utils/options.ts
  31. 6
      packages/harmony-contract/src/utils/status.ts
  32. 5
      packages/harmony-contract/test/abiCoder.test.ts
  33. 52188
      packages/harmony-contract/test/fixtures/abiv2.ts
  34. 663
      packages/harmony-core/src/blockchain.ts
  35. 126
      packages/harmony-core/src/harmony.ts
  36. 79
      packages/harmony-core/src/harmonyExtension.ts
  37. 6
      packages/harmony-core/src/index.ts
  38. 8
      packages/harmony-core/src/truffleProvider.ts
  39. 6
      packages/harmony-core/src/types.ts
  40. 6
      packages/harmony-core/src/util.ts
  41. 47
      packages/harmony-core/test/blockchain.test.ts
  42. 129
      packages/harmony-crypto/src/address.ts
  43. 12
      packages/harmony-crypto/src/bech32.ts
  44. 6
      packages/harmony-crypto/src/bytes.ts
  45. 118
      packages/harmony-crypto/src/errors.ts
  46. 6
      packages/harmony-crypto/src/index.ts
  47. 6
      packages/harmony-crypto/src/keccak256.ts
  48. 5
      packages/harmony-crypto/src/keyTool.ts
  49. 12
      packages/harmony-crypto/src/keystore.ts
  50. 17
      packages/harmony-crypto/src/random.ts
  51. 24
      packages/harmony-crypto/src/rlp.ts
  52. 5
      packages/harmony-crypto/src/signature.ts
  53. 6
      packages/harmony-crypto/src/types.ts
  54. 5
      packages/harmony-crypto/test/address.test.ts
  55. 5
      packages/harmony-crypto/test/bytes.test.ts
  56. 5
      packages/harmony-crypto/test/keccak256.test.ts
  57. 5
      packages/harmony-crypto/test/keyTool.test.ts
  58. 5
      packages/harmony-crypto/test/rlp.test.ts
  59. 6
      packages/harmony-network/src/index.ts
  60. 55
      packages/harmony-network/src/messenger/messenger.ts
  61. 19
      packages/harmony-network/src/messenger/responseMiddleware.ts
  62. 16
      packages/harmony-network/src/providers/baseProvider.ts
  63. 6
      packages/harmony-network/src/providers/baseSocket.ts
  64. 21
      packages/harmony-network/src/providers/defaultFetcher.ts
  65. 5
      packages/harmony-network/src/providers/emitter.ts
  66. 6
      packages/harmony-network/src/providers/http.ts
  67. 5
      packages/harmony-network/src/providers/provider.ts
  68. 5
      packages/harmony-network/src/providers/ws.ts
  69. 18
      packages/harmony-network/src/rpcMethod/builder.ts
  70. 10
      packages/harmony-network/src/rpcMethod/net.ts
  71. 26
      packages/harmony-network/src/rpcMethod/rpc.ts
  72. 8
      packages/harmony-network/src/subscriptions/LogSub.ts
  73. 9
      packages/harmony-network/src/subscriptions/NewHeadersSub.ts
  74. 9
      packages/harmony-network/src/subscriptions/NewPendingTransactionsSub.ts
  75. 5
      packages/harmony-network/src/subscriptions/Subscription.ts
  76. 6
      packages/harmony-network/src/subscriptions/SyncingSub.ts
  77. 18
      packages/harmony-network/src/tracker/baseTracker.ts
  78. 10
      packages/harmony-network/src/tracker/pollingTracker.ts
  79. 10
      packages/harmony-network/src/tracker/subscribeTracker.ts
  80. 6
      packages/harmony-network/src/types.ts
  81. 6
      packages/harmony-network/src/util.ts
  82. 7
      packages/harmony-staking/src/factory.ts
  83. 6
      packages/harmony-staking/src/index.ts
  84. 10
      packages/harmony-staking/src/stakingTransaction.ts
  85. 7
      packages/harmony-staking/test/testSign.test.ts
  86. 6
      packages/harmony-transaction/src/abstractTransaction.ts
  87. 52
      packages/harmony-transaction/src/factory.ts
  88. 6
      packages/harmony-transaction/src/index.ts
  89. 6
      packages/harmony-transaction/src/shardingTransaction.ts
  90. 115
      packages/harmony-transaction/src/transaction.ts
  91. 6
      packages/harmony-transaction/src/transactionBase.ts
  92. 87
      packages/harmony-transaction/src/types.ts
  93. 6
      packages/harmony-transaction/src/utils.ts
  94. 6
      packages/harmony-transaction/test/testSend.test.ts
  95. 6
      packages/harmony-transaction/test/testSign.test.ts
  96. 130
      packages/harmony-utils/src/chain.ts
  97. 4
      packages/harmony-utils/src/errors.ts
  98. 6
      packages/harmony-utils/src/index.ts
  99. 6
      packages/harmony-utils/src/tools.ts
  100. 28
      packages/harmony-utils/src/transformers.ts
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,100 @@
# Harmony JS-SDK Documentation
## [CLICK ME!!](https://harmony-js-sdk-doc.s3-us-west-1.amazonaws.com/index.html) to see the documentation
# metaDocumentation
## Summary
The following content demonstrate how to generate our documentation!
## Step 1: Generate Documentation
### Introduction of TypeDoc
[TypeDoc is used to generate HTML](https://typedoc.org/api/index.html)
> See [TypeDoc command line arguments](https://typedoc.org/guides/options/), to understand how to use them.
> Using `typedoc --help` to see them
>
> **For example:**
> `typedoc --name <Name>` to set the name of header
> `typedoc --theme <default | minimal | path/to/theme>` to set the theme of documation
> `typedoc --readme <path/to/readme | none>` path to readme file that should be displayed on the index page.
> `typedoc --ignoreCompilerErrors` Should TypeDoc generate documentation pages even after the compiler has returned errors?
### Install TypeDoc
Local installation (prefered)
```
$ npm install typedoc --save-dev
```
Golbal CLI installation
```
$ npm install --global typedoc
```
### Install Environemnt
```
$ npm install
```
### Generate HTML
```
$ cd docs
$ npx typedoc --out ./build ../packages/ --ignoreCompilerErrors --theme default --name Harmony_SDK_Doc --readme ../README.md
```
### See the generated doc at local
>open the `index.html` under the path `sdk/docs/build/index.html`
## Step 2: Deploy on AWS (harmony core only!)
### Create an AWS s3 bucket
Actually, there are just two points needed!
1. Create an AWS S3 bucket, **UNCHECK** `Block all public access`
2. Put the files into the bucket, and set the **public permission** to `Grant public read access to this object(s)`
### Method 1: Use Console
[Here](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html) is the documentation of AWS, just follow it!
>Don't forget the two points mentioned above
### Method 2: Use AWS CLI
Reference: [AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html)
If you have never used AWS CLI, you need follow these to set up your environment first!
- [Install the AWS CLI version 1](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html)
- [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)
After that, use AWS CLI to do following
1. Create a Bucket
```
aws s3 mb s3://harmony-js-sdk-doc
```
2. List all buckets you have created
```
aws s3 ls
```
3. Uploade the files into bucket
```
$ cd build
$ aws s3 cp ./ s3://your-bucket-name --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --recursive
```
Here is some explanations
> **./account**
> the path of folder which we want to upload
>
> **s3://harmony-js-sdk-doc**
> the bucket name on AWS S3
>
> **--grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers**
> Grant read access to all user
>
> **--recursive**
> Command is performed on all files or objects under the specified directory or prefix.
4. Open the folder in S3 bucket and find `index.html`, get the
`Object URL`, then make it public!

@ -125,8 +125,9 @@
"tslib": "^1.11.1",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0",
"typedoc": "^0.15.0",
"typedoc-plugin-markdown": "^2.1.0",
"typedoc": "^0.17.0-3",
"typedoc-plugin-external-module-name": "^3.0.0",
"typedoc-plugin-no-inherit": "^1.1.10",
"typescript": "^3.8.3",
"typescript-json-schema": "^0.36.0",
"webpack": "^4.20.2",
@ -140,5 +141,9 @@
}
},
"name": "harmony-sdk-core",
"dependencies": {}
"dependencies": {
"@harmony-js/core": "^0.1.36",
"tslib": "^1.10.0",
"typedoc-plugin-internal-external": "^2.1.1"
}
}

@ -1,15 +1,15 @@
1. [About This Package](#about-this-package)
2. [Usage of Account](#usage-of-account)
1. [Dependencies](#dependencies)
2. [Examples](#examples)
1. [Create a random account](#create-a-random-account)
2. [Import an existing privateKey to create Account](#import-an-existing-privatekey-to-create-account)
3. [Encrypt/Export keyStore file, Decrypt/Import keyStore file](#encryptexport-keystore-file-decryptimport-keystore-file)
4. [Address format getter](#address-format-getter)
5. [Sign a transaction](#sign-a-transaction)
3. [Usage of Wallet](#usage-of-wallet)
1. [Dependencies](#dependencies-1)
- [About This Package](#about-this-package)
- [Usage of Account](#usage-of-account)
- [Dependencies](#dependencies)
- [Examples](#examples)
- [Create a random account](#create-a-random-account)
- [Import an existing privateKey to create Account](#import-an-existing-privatekey-to-create-account)
- [Encrypt/Export keyStore file, Decrypt/Import keyStore file](#encryptexport-keystore-file-decryptimport-keystore-file)
- [Address format getter](#address-format-getter)
- [Sign a transaction](#sign-a-transaction)
- [Usage of Wallet](#usage-of-wallet)
- [Dependencies](#dependencies-1)
# About This Package

@ -0,0 +1,274 @@
/**
## About This Package
`@harmony-js/account` is dealing with account related features.
Developers can use this package to:
- Create `Account` instance
- Create `Wallet` instance
- Sign `Transaction`
- Convert address format
- Manage `privateKey` or `mnemonic phrases` and do the `encrypt` and `decrypt` job
There are 2 main classes in this package, `Account` and `Wallet`.
- The `Account` class is basic instance that contains most features mentioned above.
- The `Wallet` class is class that stores all `Account` instance, you can do CRUD on it.
## Usage of Account
### Dependencies
- @harmony-js/network
- @harmony-js/staking
- @harmony-js/transaction
- @harmony-js/utils
### Examples
Create a random account
```javascript
// import the Account class
import {Account} from '@harmony-js/account'
// Messenger is optional, by default, we have a defaultMessenger
// If you like to change, you will import related package here.
import { HttpProvider, Messenger } from '@harmony-js/network';
import { ChainType, ChainID } from '@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
)
// to create an Account with random privateKey
// and you can setMessenger later
const randomAccount = new Account()
randomAccount.setMessenger(customMessenger)
// or you can set messenger on `new`
const randomAccountWithCustomMessenger = new Account(undefined, customMessenger)
// you can display the account
console.log({randomAccount,randomAccountWithCustomMessenger})
// or you can use static method to create an Account
const staticCreatedAccount = Account.new()
// but you have to set messenger manually after
staticCreatedAccount.setMessenger(customMessenger)
console.log({staticCreatedAccount})
```
### Import an existing privateKey to create Account
```typescript
// import the Account class
import {Account} from '@harmony-js/account'
// 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)
// you can also import privateKey use static method
const myAccountWithMyPrivateKeyUsingStatic = Account.add(myPrivateKey)
console.log({ myAccountWithMyPrivateKey, myAccountWithMyPrivateKeyUsingStatic })
```
### Encrypt/Export keyStore file, Decrypt/Import keyStore file
```typescript
// import the Account class
import {Account} from '@harmony-js/account'
// suppose we have an account
const myPrivateKey = '0xe19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930'
const myAccountWithMyPrivateKey = new Account(myPrivateKey)
// suppose we have a password, and we want to encrypt the account above
const myStrongPassword = '123'
async function encryptAndDecrypt(password) {
// we get the privateKey before encrypted as comparison
const unencryptedPrivateKey = myAccountWithMyPrivateKey.privateKey
// export the account to keyStore string, which will make the privateKey encrpyted
const keyStoreFile = await myAccountWithMyPrivateKey.toFile(password)
// exported keyStoreFile
console.log({ keyStoreFile })
// see if the account is encrypted
console.log(`Is this account encrypted? \n ${myAccountWithMyPrivateKey.encrypted}`)
// keystore file should be equal to encrypted privateKey
console.log(
`Is privateKey equal to keyStore string? \n ${keyStoreFile ===
myAccountWithMyPrivateKey.privateKey}`,
)
}
encryptAndDecrypt(myStrongPassword)
// suppose we have keyStorefile, in this example, we just use same password and keystore string encrypted above
const someKeyStoreFile =
'{"version":3,"id":"62326332-3139-4839-b534-656134623066","address":"1fe3da351d9fc0c4f02de5412ad7def8aee956c5","Crypto":{"ciphertext":"b86ab81682c9f5a35738ad9bd38cd9b46c1b852ef33f16dd83068f79e20d5531","cipherparams":{"iv":"44efb5a514f34968e92cafad80566487"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"d70ae1f311601562113f98c8ebe382f52a332dca1588886e5ea91e2f8a647134","n":8192,"r":8,"p":1,"dklen":32},"mac":"7b63e4e31a75a22b7091291bb58302655b738539ef3e30b30a7a7f170f6163ef"}}'
async function importKeyStoreFileAndDecrypt(keyStoreFile, password) {
// import keyStore string and provide the password, remember to make a new Account first
const importedAccount = await Account.new().fromFile(keyStoreFile, password)
// the account should decypted which `Account.encrypted` is false
console.log(`Is this account encrypted? \n ${importedAccount.encrypted}`)
// see if the privatekey is equal to unencrypted one?
console.log(
`Is the account recovered from keystore? \n ${importedAccount.privateKey === myPrivateKey}`,
)
}
importKeyStoreFileAndDecrypt(someKeyStoreFile, myStrongPassword)
```
### Address format getter
```typescript
// import the Account class
import {Account} from '@harmony-js/account'
// suppose we have an account
const myPrivateKey = '0xe19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930'
const myAccountWithMyPrivateKey = new Account(myPrivateKey)
// Account.address is bytes20/base16 address
console.log(myAccountWithMyPrivateKey.address)
// Account.bech32Address is bech32 format address, in Harmony, it's `one1` prefixed
console.log(myAccountWithMyPrivateKey.bech32Address)
// Account.bech32TestNetAddress is bech32 format address, in Harmony, it's `tone1` prefixed, used in testnet
console.log(myAccountWithMyPrivateKey.bech32TestNetAddress)
// Account.checksumAddress is checksumed address from base16
console.log(myAccountWithMyPrivateKey.checksumAddress)
```
### Sign a transaction
```typescript
// import the Account class
import {Account} from '@harmony-js/account'
// import Transaction class from '@harmony-js/transaction'
import {Transaction} from '@harmony-js/transaction'
// Messenger is optional, by default, we have a defaultMessenger
// If you like to change, you will import related package here.
import { HttpProvider, Messenger } from '@harmony-js/network';
import { ChainType, ChainID, Unit } from '@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
)
// suppose we have an account
const myPrivateKey = '0xe19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930'
const myAccountWithMyPrivateKey = new Account(myPrivateKey)
const txnObject = {
// token send to
to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
// amount to send
value: '1000000000000000000000',
// gas limit, you can use string or use BN value
gasLimit: '210000',
// send token from shardID
shardID: 0,
// send token to toShardID
toShardID: 0,
// gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
gasPrice: new Unit('100').asGwei().toWei(),
// if you set nonce manually here, and remember, the `updateNonce` of `Account.signTransaction` should be set to false
nonce: 0,
};
const txn = new Transaction(txnObject, customMessenger);
async function signTheTxn() {
// Account.signTransaction(transaction: Transaction, updateNonce?: boolean, encodeMode?: string, blockNumber?: string): Promise<Transaction>
// If the 2nd parameter `updateNonce` is set to true, it will query and update account's nonce before it signs
const signedTxn = await myAccountWithMyPrivateKey.signTransaction(txn, false, 'rlp', 'latest');
// see if the transaction is signed
console.log(`\n see if transaction is signed: \n ${signedTxn.isSigned()} \n`);
// get the tranaction bytes
console.log(`\n the signed bytes is: \n ${signedTxn.getRawTransaction()} \n`);
return signTheTxn;
}
signTheTxn();
```
## Usage of Wallet
### Dependencies
- @harmony-js/crypto
- @harmony-js/network
- @harmony-js/staking
- @harmony-js/transaction
- @harmony-js/utils
```typescript
// constructor
const { Wallet } = require('@harmony-js/account');
const wallet = new Wallet(customMessenger);
// get signer
const wallet = new Wallet(customMessenger);
const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
console.log(wallet.addByPrivateKey(key_1));
console.log(wallet.signer)
// createAccount
console.log(wallet.accounts);
wallet.createAccount();
wallet.createAccount();
console.log(wallet.accounts);
// encryptAccount
const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
wallet.addByPrivateKey(key_1);
wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345').then((value) => {
console.log(value);
})
// decrptAccount
const key_1 = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
wallet.addByPrivateKey(key_1);
wallet.encryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345').then(() => {
wallet.decryptAccount('one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7', '12345').then((value) => {
console.log(value);
})
});
```
*
* @packageDocumentation
* @module harmony-account
*/
/**@ignore */
export interface README {}

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-account
*
*/
import {
generatePrivateKey,
getAddressFromPrivateKey,
@ -26,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) {
@ -120,8 +207,16 @@ class Account {
}
/**
* @function getBalance get Account's balance
* @return {type} {description}
* Get the account balance
*
* @param blockNumber by default, it's `latest`
*
* @example
* ```javascript
* account.getBalance().then((value) => {
* console.log(value);
* });
* ```
*/
async getBalance(blockNumber: string = 'latest'): Promise<object> {
try {
@ -164,7 +259,6 @@ class Account {
/**
* @function updateShards
* @return {Promise<string>} {description}
*/
async updateBalances(blockNumber: string = 'latest'): Promise<void> {
// this.messenger.setShardingProviders();
@ -183,6 +277,9 @@ class Account {
}
}
/**
* @function signTransaction
*/
async signTransaction(
transaction: Transaction,
updateNonce: boolean = true,
@ -243,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,
@ -296,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) {
@ -308,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) {
@ -317,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,
@ -344,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();
@ -360,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)) {
@ -380,4 +542,7 @@ class Account {
}
}
/**
* This comment _supports_ [Markdown](https://marked.js.org/)
*/
export { Account };

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-account
*/
import { bip39, hdkey, getAddress, BN, Signature } from '@harmony-js/crypto';
import {
HDPath,
@ -14,10 +19,12 @@ import { Messenger, HttpProvider, WSProvider } from '@harmony-js/network';
import { Transaction, TxStatus, TransasctionReceipt } from '@harmony-js/transaction';
import { Account } from './account';
/** @hidden */
export interface WalletsInterfaces {
[key: string]: Account;
}
/** @hidden */
export interface Web3TxPrams {
id?: string;
from?: string;
@ -43,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(

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-account
* @ignore
*/
export * from './account';
export * from './wallet';
export * from './types';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-account
* @hidden
*/
/**
* test type docs
*/

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-account
* @hidden
*/
import { HttpProvider, Messenger } from '@harmony-js/network';
import { ChainType, ChainID } from '@harmony-js/utils';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-account
*/
import { bip39, hdkey, EncryptOptions, getAddress, generatePrivateKey } from '@harmony-js/crypto';
import { Messenger } from '@harmony-js/network';
import { isPrivateKey, isAddress, ChainType } from '@harmony-js/utils';
@ -12,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);
@ -38,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;
}
@ -51,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)) {
@ -69,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 {
@ -95,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
@ -122,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();
@ -140,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,
@ -168,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 {
@ -195,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);
@ -218,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');
@ -275,6 +386,7 @@ class Wallet {
throw new Error('sign transaction failed');
}
}
async signStaking(
staking: StakingTransaction,
account: Account | undefined = this.signer,
@ -324,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) {

@ -4,7 +4,7 @@
"rootDir": "src",
"outDir": "dist"
},
"include": ["src", "../../typings/**/*.d.ts"],
"include": ["src", "../../typings/**/*.d.ts", "aaa.ts"],
"references": [
{ "path": "../harmony-crypto" },
{ "path": "../harmony-utils" },

@ -1,3 +1,115 @@
/**
* ## About this package
*
* `@harmony-js/contract` makes it easy to interact with smart contract on the Harmony Blockchain. This allows you to interact with smart contracts as if they were JavaScript objects.
*
* ## How to use this package
*
* ### Deploy a contract to blockchain
* ```javascript
* // Step 1: Use Solidity to build a sample contract instance
* contract Inbox {
* string public message;
* constructor() public {
* message = "hello";
* }
* function setMessage(string memory newMessage) public {
* message = newMessage;
* }
* }
*
* // Step 2: Use truffle to compile the contract
* $ truffle compile
*
* // Step 3: Use truffle to deploy the contract (by truffle)
* $ truffle migrate --network local --reset
* $ truffle migrate --network testnet --reset
* ```
* [Tutorial: using truffle to compile and deploy smart-contract](https://github.com/harmony-one/HRC/tree/master/examples/dapp_Lottery)
*
* ### Interact with the contract
* ```javascript
* // Step 1: create a harmony instance
* const { Harmony } = require('@harmony-js/core');
* const { ChainID, ChainType } = require('@harmony-js/utils');
* const hmy = new Harmony(
* // let's assume we deploy smart contract to this end-point URL
* 'https://api.s0.b.hmny.io'
* {
* chainType: ChainType.Harmony,
* chainId: ChainID.HmyLocal,
* }
* )
*
* // Step 2: get a contract instance
* const getContractInstance = (hmy, artifact) => {
* return hmy.contracts.createContract(artifact.abi, address);
* }
* const inbox = getContractInstance(hmy, inboxJson)
*
* // Step 3: interact with the instance
* // Example 1: methods.myMethod.call()
* const message = await inbox.methods.message().call();
* console.log(message);
*
* // Example 2: methods.myMethod.send()
* inbox.methods.setMessage('666').send({
* gasLimit: '1000001',
* gasPrice: new hmy.utils.Unit('10').asGwei().toWei(),
* });
* ```
*
* ### Integrate MathWallet
* Using MathWallet to sign Transaction
* ```javascript
* // Step 0: set up MathWallet extension on Chrome
*
* // Step 1: Create a harmonyExtension instance
* const { Harmony, HarmonyExtension } = require('@harmony-js/core');
* let hmyEx, ExContract;
* export const initExtension = async() => {
* hmyEx = await new HarmonyExtension(window.harmony);
*
* exContract = hmyEx.contracts.createContract(abi, address);
* return exContract;
* };
*
* // Step 2: interact with hmyEx instance
* // wait for hmy inject into window
* async componentDidMount() {
* ...
* await waitForInjected()
* ...
* }
* // Example: methods.myMethod.send()
* onSubmit = async event => {
* const exContract = await initExtension()
* await exContract.methods.Mymethod().send({
* value: new hmy.utils.Unit('1').asOne().toWei(),
* })
* }
*
* // wait for injected
* export const waitForInjected = () => new Promise((resolve) => {
* const check = () => {
* if (!window.harmony) setTimeout(check, 250);
* else resolve(window.harmony);
* }
* check();
* });
* ```
*
* ## [More Examples: HRC repo](https://github.com/harmony-one/HRC/tree/master/examples)
* - Lottery
* - HRC 20
* - HRC 721
* - Node-dao
* - Node-faucet
*
* @packageDocumentation
* @module harmony-contract
*/
// this file is mainly ported from `ethers.js`, but done some fixes
// 1. added bytesPadRight support
// 2. ts-lint
@ -21,19 +133,23 @@ import {
} from '@harmony-js/crypto';
import { hexToBN, defineReadOnly } from '@harmony-js/utils';
/** @hidden */
const NegativeOne: BN = new BN(-1);
/** @hidden */
const One: BN = new BN(1);
// const Two: BN = new BN(2);
/** @hidden */
const Zero: BN = new BN(0);
const HashZero =
'0x0000000000000000000000000000000000000000000000000000000000000000';
/** @hidden */
const HashZero = '0x0000000000000000000000000000000000000000000000000000000000000000';
/** @hidden */
const MaxUint256: BN = hexToBN(
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
);
/** @hidden */
export type CoerceFunc = (type: string, value: any) => any;
/** @hidden */
export interface ParamType {
name?: string;
type: string;
@ -43,6 +159,7 @@ export interface ParamType {
// @TODO: should this just be a combined Fragment?
/** @hidden */
export interface EventFragment {
type: string;
name: string;
@ -52,6 +169,7 @@ export interface EventFragment {
inputs: ParamType[];
}
/** @hidden */
export interface FunctionFragment {
type: string;
name: string;
@ -68,15 +186,15 @@ export interface FunctionFragment {
}
///////////////////////////////
/** @hidden */
const paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
/** @hidden */
const paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
/** @hidden */
const paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
export const defaultCoerceFunc: CoerceFunc = (
type: string,
value: any,
): any => {
/** @hidden */
export const defaultCoerceFunc: CoerceFunc = (type: string, value: any): any => {
const match = type.match(paramTypeNumber);
if (match && parseInt(match[2], 10) <= 48) {
// return value.toNumber();
@ -91,9 +209,12 @@ export const defaultCoerceFunc: CoerceFunc = (
///////////////////////////////////
// Parsing for Solidity Signatures
/** @hidden */
const regexParen = new RegExp('^([^)(]*)\\((.*)\\)([^)(]*)$');
/** @hidden */
const regexIdentifier = new RegExp('^[A-Za-z_][A-Za-z0-9_]*$');
/** @hidden */
function verifyType(type: string): string {
// These need to be transformed to their full description
if (type.match(/^uint($|[^1-9])/)) {
@ -105,6 +226,7 @@ function verifyType(type: string): string {
return type;
}
/** @hidden */
interface ParseState {
allowArray?: boolean;
allowName?: boolean;
@ -113,6 +235,7 @@ interface ParseState {
readArray?: boolean;
}
/** @hidden */
interface ParseNode {
parent?: any;
type?: string;
@ -122,6 +245,7 @@ interface ParseNode {
components?: any[];
}
/** @hidden */
function parseParam(param: string, allowIndexed?: boolean): ParamType {
const originalParam = param;
// tslint:disable-next-line: no-shadowed-variable
@ -155,9 +279,7 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType {
node.type = verifyType(node.type);
}
node.components = [
{ type: '', name: '', parent: node, state: { allowType: true } },
];
node.components = [{ type: '', name: '', parent: node, state: { allowType: true } }];
node = node.components[0];
break;
@ -298,6 +420,7 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType {
}
// @TODO: Better return type
/** @hidden */
function parseSignatureEvent(fragment: string): EventFragment {
const abi: EventFragment = {
anonymous: false,
@ -338,15 +461,18 @@ function parseSignatureEvent(fragment: string): EventFragment {
return abi;
}
/** @hidden */
export function parseParamType(type: string): ParamType {
return parseParam(type, true);
}
// @TODO: Allow a second boolean to expose names
/** @hidden */
export function formatParamType(paramType: ParamType): string {
return getParamCoder(defaultCoerceFunc, paramType).type;
}
/** @hidden */
function parseSignatureFunction(fragment: string): FunctionFragment {
const abi: FunctionFragment = {
constant: false,
@ -415,7 +541,7 @@ function parseSignatureFunction(fragment: string): FunctionFragment {
// We have outputs
if (comps.length > 1) {
const right = comps[1].match(regexParen);
if (right === null || (right[1].trim() !== '' || right[3].trim() !== '')) {
if (right === null || right[1].trim() !== '' || right[3].trim() !== '') {
throw new Error('unexpected tokens');
}
@ -439,20 +565,13 @@ function parseSignatureFunction(fragment: string): FunctionFragment {
}
// @TODO: Allow a second boolean to expose names and modifiers
export function formatSignature(
fragment: EventFragment | FunctionFragment,
): string {
return (
fragment.name +
'(' +
fragment.inputs.map((i) => formatParamType(i)).join(',') +
')'
);
/** @hidden */
export function formatSignature(fragment: EventFragment | FunctionFragment): string {
return fragment.name + '(' + fragment.inputs.map((i) => formatParamType(i)).join(',') + ')';
}
export function parseSignature(
fragment: string,
): EventFragment | FunctionFragment {
/** @hidden */
export function parseSignature(fragment: string): EventFragment | FunctionFragment {
if (typeof fragment === 'string') {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment.replace(/\s/g, ' ');
@ -477,11 +596,13 @@ export function parseSignature(
///////////////////////////////////
// Coders
/** @hidden */
interface DecodedResult {
consumed: number;
value: any;
}
/** @hidden */
abstract class Coder {
readonly coerceFunc: CoerceFunc;
readonly name: string;
@ -508,6 +629,7 @@ abstract class Coder {
// Clones the functionality of an existing Coder, but without a localName
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderAnonymous extends Coder {
private coder: Coder;
constructor(coder: Coder) {
@ -523,6 +645,7 @@ class CoderAnonymous extends Coder {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderNull extends Coder {
constructor(coerceFunc: CoerceFunc, localName: string) {
super(coerceFunc, 'null', '', localName, false);
@ -545,15 +668,11 @@ class CoderNull extends Coder {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderNumber extends Coder {
readonly size: number;
readonly signed: boolean;
constructor(
coerceFunc: CoerceFunc,
size: number,
signed: boolean,
localName: string,
) {
constructor(coerceFunc: CoerceFunc, size: number, signed: boolean, localName: string) {
const name = (signed ? 'int' : 'uint') + size * 8;
super(coerceFunc, name, name, localName, false);
@ -597,15 +716,11 @@ class CoderNumber extends Coder {
decode(data: Uint8Array, offset: number): DecodedResult {
if (data.length < offset + 32) {
throwError(
'insufficient data for ' + this.name + ' type',
INVALID_ARGUMENT,
{
arg: this.localName,
coderType: this.name,
value: hexlify(data.slice(offset, offset + 32)),
},
);
throwError('insufficient data for ' + this.name + ' type', INVALID_ARGUMENT, {
arg: this.localName,
coderType: this.name,
value: hexlify(data.slice(offset, offset + 32)),
});
}
const junkLength = 32 - this.size;
const dataValue = hexlify(data.slice(offset + junkLength, offset + 32));
@ -624,6 +739,8 @@ class CoderNumber extends Coder {
};
}
}
/** @hidden */
const uint256Coder = new CoderNumber(
(type: string, value: any) => {
return value;
@ -634,6 +751,7 @@ const uint256Coder = new CoderNumber(
);
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderBoolean extends Coder {
constructor(coerceFunc: CoerceFunc, localName: string) {
super(coerceFunc, 'bool', 'bool', localName, false);
@ -665,6 +783,7 @@ class CoderBoolean extends Coder {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderFixedBytes extends Coder {
readonly length: number;
constructor(coerceFunc: CoerceFunc, length: number, localName: string) {
@ -711,15 +830,13 @@ class CoderFixedBytes extends Coder {
return {
consumed: 32,
value: this.coerceFunc(
this.name,
hexlify(data.slice(offset, offset + this.length)),
),
value: this.coerceFunc(this.name, hexlify(data.slice(offset, offset + this.length))),
};
}
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderAddress extends Coder {
constructor(coerceFunc: CoerceFunc, localName: string) {
super(coerceFunc, 'address', 'address', localName, false);
@ -756,6 +873,7 @@ class CoderAddress extends Coder {
}
}
/** @hidden */
function _encodeDynamicBytes(value: Uint8Array): Uint8Array {
const dataLength = 32 * Math.ceil(value.length / 32);
const padding = new Uint8Array(dataLength - value.length);
@ -763,11 +881,8 @@ function _encodeDynamicBytes(value: Uint8Array): Uint8Array {
return concat([uint256Coder.encode(new BN(value.length)), value, padding]);
}
function _decodeDynamicBytes(
data: Uint8Array,
offset: number,
localName: string,
): DecodedResult {
/** @hidden */
function _decodeDynamicBytes(data: Uint8Array, offset: number, localName: string): DecodedResult {
if (data.length < offset + 32) {
throwError('insufficient data for dynamicBytes length', INVALID_ARGUMENT, {
arg: localName,
@ -803,6 +918,7 @@ function _decodeDynamicBytes(
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderDynamicBytes extends Coder {
constructor(coerceFunc: CoerceFunc, localName: string) {
super(coerceFunc, 'bytes', 'bytes', localName, true);
@ -829,6 +945,7 @@ class CoderDynamicBytes extends Coder {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderString extends Coder {
constructor(coerceFunc: CoerceFunc, localName: string) {
super(coerceFunc, 'string', 'string', localName, true);
@ -852,10 +969,12 @@ class CoderString extends Coder {
}
}
/** @hidden */
function alignSize(size: number): number {
return 32 * Math.ceil(size / 32);
}
/** @hidden */
function pack(coders: Coder[], values: any[]): Uint8Array {
if (Array.isArray(values)) {
// do nothing
@ -920,11 +1039,8 @@ function pack(coders: Coder[], values: any[]): Uint8Array {
return data;
}
function unpack(
coders: Coder[],
data: Uint8Array,
offset: number,
): DecodedResult {
/** @hidden */
function unpack(coders: Coder[], data: Uint8Array, offset: number): DecodedResult {
const baseOffset = offset;
let consumed = 0;
const value: any = [];
@ -971,15 +1087,11 @@ function unpack(
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderArray extends Coder {
readonly coder: Coder;
readonly length: number;
constructor(
coerceFunc: CoerceFunc,
coder: Coder,
length: number,
localName: string,
) {
constructor(coerceFunc: CoerceFunc, coder: Coder, length: number, localName: string) {
const type = coder.type + '[' + (length >= 0 ? length : '') + ']';
const dynamic = length === -1 || coder.dynamic;
super(coerceFunc, 'array', type, localName, dynamic);
@ -1033,15 +1145,11 @@ class CoderArray extends Coder {
try {
decodedLength = uint256Coder.decode(data, offset);
} catch (error) {
throwError(
'insufficient data for dynamic array length',
INVALID_ARGUMENT,
{
arg: this.localName,
coderType: 'array',
value: error.value,
},
);
throwError('insufficient data for dynamic array length', INVALID_ARGUMENT, {
arg: this.localName,
coderType: 'array',
value: error.value,
});
}
try {
count = decodedLength.value.toNumber();
@ -1069,6 +1177,7 @@ class CoderArray extends Coder {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
class CoderTuple extends Coder {
readonly coders: Coder[];
constructor(coerceFunc: CoerceFunc, coders: Coder[], localName: string) {
@ -1098,6 +1207,7 @@ class CoderTuple extends Coder {
}
}
/** @hidden */
function splitNesting(value: string): any[] {
value = value.trim();
@ -1131,6 +1241,7 @@ function splitNesting(value: string): any[] {
}
// @TODO: Is there a way to return "class"?
/** @hidden */
const paramTypeSimple: { [key: string]: any } = {
address: CoderAddress,
bool: CoderBoolean,
@ -1138,6 +1249,7 @@ const paramTypeSimple: { [key: string]: any } = {
bytes: CoderDynamicBytes,
};
/** @hidden */
function getTupleParamCoder(
coerceFunc: CoerceFunc,
components: any[],
@ -1154,6 +1266,7 @@ function getTupleParamCoder(
return new CoderTuple(coerceFunc, coders, localName);
}
/** @hidden */
function getParamCoder(coerceFunc: CoerceFunc, param: ParamType | any): any {
const coder = paramTypeSimple[param.type];
if (coder) {
@ -1168,12 +1281,7 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType | any): any {
value: param,
});
}
return new CoderNumber(
coerceFunc,
size / 8,
matcher[1] === 'int',
param.name || '',
);
return new CoderNumber(coerceFunc, size / 8, matcher[1] === 'int', param.name || '');
}
const matcher2 = param.type.match(paramTypeBytes);
@ -1194,20 +1302,11 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType | any): any {
param = shallowCopy(param);
param.type = matcher3[1];
param = deepCopy(param);
return new CoderArray(
coerceFunc,
getParamCoder(coerceFunc, param),
size,
param.name || '',
);
return new CoderArray(coerceFunc, getParamCoder(coerceFunc, param), size, param.name || '');
}
if (param.type.substring(0, 5) === 'tuple') {
return getTupleParamCoder(
coerceFunc,
param.components || [],
param.name || '',
);
return getTupleParamCoder(coerceFunc, param.components || [], param.name || '');
}
if (param.type === '') {
@ -1220,6 +1319,7 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType | any): any {
});
}
/** @hidden */
export enum UnicodeNormalizationForm {
current = '',
NFC = 'NFC',
@ -1228,6 +1328,7 @@ export enum UnicodeNormalizationForm {
NFKD = 'NFKD',
}
/** @hidden */
export function toUtf8Bytes(
str: string,
form: UnicodeNormalizationForm = UnicodeNormalizationForm.current,
@ -1271,6 +1372,7 @@ export function toUtf8Bytes(
}
// http://stackoverflow.com/questions/13356493/decode-utf-8-with-javascript#13691499
/** @hidden */
export function toUtf8String(bytes: Arrayish, ignoreErrors?: boolean): string {
bytes = arrayify(bytes) || new Uint8Array();
@ -1307,9 +1409,7 @@ export function toUtf8String(bytes: Arrayish, ignoreErrors?: boolean): string {
} else {
if (!ignoreErrors) {
if ((c & 0xc0) === 0x80) {
throw new Error(
'invalid utf8 byte sequence; unexpected continuation byte',
);
throw new Error('invalid utf8 byte sequence; unexpected continuation byte');
}
throw new Error('invalid utf8 byte sequence; invalid prefix');
}
@ -1350,9 +1450,7 @@ export function toUtf8String(bytes: Arrayish, ignoreErrors?: boolean): string {
if (res === null) {
if (!ignoreErrors) {
throw new Error(
'invalid utf8 byte sequence; invalid continuation byte',
);
throw new Error('invalid utf8 byte sequence; invalid continuation byte');
}
continue;
}
@ -1387,15 +1485,13 @@ export function toUtf8String(bytes: Arrayish, ignoreErrors?: boolean): string {
}
res -= 0x10000;
result += String.fromCharCode(
((res >> 10) & 0x3ff) + 0xd800,
(res & 0x3ff) + 0xdc00,
);
result += String.fromCharCode(((res >> 10) & 0x3ff) + 0xd800, (res & 0x3ff) + 0xdc00);
}
return result;
}
/** @hidden */
export function formatBytes32String(text: string): string {
// Get the bytes
const bytes = toUtf8Bytes(text);
@ -1409,6 +1505,7 @@ export function formatBytes32String(text: string): string {
return hexlify(concat([bytes, HashZero]).slice(0, 32));
}
/** @hidden */
export function parseBytes32String(bytes: Arrayish): string {
const data = arrayify(bytes) || new Uint8Array();
@ -1430,10 +1527,12 @@ export function parseBytes32String(bytes: Arrayish): string {
return toUtf8String(data.slice(0, length));
}
/** @hidden */
export function isType(object: any, type: string): boolean {
return object && object._ethersType === type;
}
/** @hidden */
export function shallowCopy(object: any): any {
const result: any = {};
// tslint:disable-next-line: forin
@ -1443,12 +1542,14 @@ export function shallowCopy(object: any): any {
return result;
}
/** @hidden */
const opaque: { [key: string]: boolean } = {
boolean: true,
number: true,
string: true,
};
/** @hidden */
export function deepCopy(object: any, frozen?: boolean): any {
// Opaque objects are not mutable, so safe to copy by assignment
if (object === undefined || object === null || opaque[typeof object]) {
@ -1502,6 +1603,7 @@ export function deepCopy(object: any, frozen?: boolean): any {
}
// tslint:disable-next-line: max-classes-per-file
/** @hidden */
export class AbiCoder {
coerceFunc: CoerceFunc;
constructor(coerceFunc?: CoerceFunc) {
@ -1537,9 +1639,7 @@ export class AbiCoder {
coders.push(getParamCoder(this.coerceFunc, typeObject));
}, this);
const encodedArray = new CoderTuple(this.coerceFunc, coders, '_').encode(
values,
);
const encodedArray = new CoderTuple(this.coerceFunc, coders, '_').encode(values);
return hexlify(encodedArray);
}
@ -1565,4 +1665,5 @@ export class AbiCoder {
}
}
/** @hidden */
export const defaultAbiCoder: AbiCoder = new AbiCoder();

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { AbiCoder as ABICoder, ParamType, toUtf8Bytes } from './abiCoder';
import { isObject, isArray } from '@harmony-js/utils';
import { keccak256, Arrayish } from '@harmony-js/crypto';
@ -124,9 +130,7 @@ export class AbiCoderClass {
decodedValue = values[index];
returnValues[itemKey] = bnToString(decodedValue);
returnValues[nonIndexedInputItems[index].name] = bnToString(
decodedValue,
);
returnValues[nonIndexedInputItems[index].name] = bnToString(decodedValue);
});
}

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { AbiCoderClass } from './api';
import { AbiCoder as EtherCoder } from './abiCoder';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { isObject, isArray } from '@harmony-js/utils';
import { BN } from '@harmony-js/crypto';
@ -16,9 +22,7 @@ export const flattenTypes = (includeTuple: any, puts: any[]) => {
puts.forEach((param: any) => {
if (typeof param.components === 'object') {
if (param.type.substring(0, 5) !== 'tuple') {
throw new Error(
'components found but type is not tuple; report on GitHub',
);
throw new Error('components found but type is not tuple; report on GitHub');
}
let suffix = '';
const arrayBracket = param.type.indexOf('[');

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
*
*/
import { Wallet } from '@harmony-js/account';
import { Messenger } from '@harmony-js/network';
import { Transaction } from '@harmony-js/transaction';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-contract
*/
import { Wallet } from '@harmony-js/account';
import { Contract } from './contract';
import { ContractOptions } from './utils/options';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-contract
*/
import { LogSub } from '@harmony-js/network';
import { AbiItemModel } from '../models/types';
import { Contract } from '../contract';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { isArray } from '@harmony-js/utils';
import { AbiCoderClass } from '../abi/api';
import { AbiModel, AbiItemModel } from '../models/types';

@ -1,10 +1,11 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
export * from './abi/index';
export {
toUtf8Bytes,
toUtf8String,
formatBytes32String,
parseBytes32String,
} from './abi/abiCoder';
export { toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String } from './abi/abiCoder';
export { Contract } from './contract';
export { ContractFactory } from './contractFactory';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-contract
*/
import { Wallet } from '@harmony-js/account';
import { TransactionFactory, Transaction, TxStatus } from '@harmony-js/transaction';
import { RPCMethod, getResultForData, Emitter } from '@harmony-js/network';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { AbiCoderClass } from '../abi/api';
import { AbiModel } from '../models/types';
import { Contract } from '../contract';
@ -21,12 +27,7 @@ export class MethodFactory {
this.methodKeys.forEach((key: string) => {
const newObject: any = {};
newObject[key] = (...params: any[]) =>
new ContractMethod(
key,
params,
this.abiModel.getMethod(key),
this.contract,
);
new ContractMethod(key, params, this.abiModel.getMethod(key), this.contract);
Object.assign(this.contract.methods, newObject);
});

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { isArray } from '@harmony-js/utils';
import { AbiItemModel, AbiOutput, AbiInput } from './types';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { AbiItemModel } from './types';
export class AbiModel {

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
// defined by web3.js
// fixed
export interface AbiModel {

@ -1,11 +1,13 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { AbiItemModel } from '../models/types';
import { AbiCoderClass } from '../abi/api';
export const decode = (
abiCoder: AbiCoderClass,
abiItemModel: AbiItemModel,
response: any,
) => {
export const decode = (abiCoder: AbiCoderClass, abiItemModel: AbiItemModel, response: any) => {
let argumentTopics = response.topics;
if (!abiItemModel.anonymous) {

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { isArray } from '@harmony-js/utils';
import { AbiItemModel } from '../models/types';
import { AbiCoderClass } from '../abi/api';

@ -1,9 +1,10 @@
import {
hexlify,
isHexString,
keccak256,
toChecksumAddress,
} from '@harmony-js/crypto';
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { hexlify, isHexString, keccak256, toChecksumAddress } from '@harmony-js/crypto';
import {
numberToHex,
isArray,
@ -92,11 +93,7 @@ export const outputLogFormatter = (log: any) => {
};
export const inputBlockNumberFormatter = (blockNumber: any) => {
if (
blockNumber === undefined ||
blockNumber === null ||
isPredefinedBlockNumber(blockNumber)
) {
if (blockNumber === undefined || blockNumber === null || isPredefinedBlockNumber(blockNumber)) {
return blockNumber;
}
@ -112,11 +109,7 @@ export const inputBlockNumberFormatter = (blockNumber: any) => {
};
export const isPredefinedBlockNumber = (blockNumber: string) => {
return (
blockNumber === 'latest' ||
blockNumber === 'pending' ||
blockNumber === 'earliest'
);
return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';
};
export const inputAddressFormatter = (address: string) => {

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
import { isArray } from '@harmony-js/utils';
import { AbiItem } from '../models/AbiItemModel';
import { AbiModel } from '../models/AbiModel';
@ -86,9 +92,7 @@ export const abiMapper = (abi: any[], abiCoder: AbiCoderClass): AbiModel => {
export const isConstant = (abiItem: AbiItemModel) => {
return (
abiItem.stateMutability === 'view' ||
abiItem.stateMutability === 'pure' ||
abiItem.constant
abiItem.stateMutability === 'view' || abiItem.stateMutability === 'pure' || abiItem.constant
);
};

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
export interface ContractOptions {
data?: string;
shardID?: number;

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-contract
* @hidden
*/
export enum ContractStatus {
INITIALISED = 'initialised',
TESTED = 'tested',

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import { AbiCoder } from '../src/abi/abiCoder';
import { BN } from '@harmony-js/crypto';
import { isArray } from '@harmony-js/utils';

File diff suppressed because one or more lines are too long

@ -1,3 +1,88 @@
/**
* ## About this package
*
* `@harmony-js/core` is collection of modules to guide user to interacte with harmony blockchian.
*
* Develops can use this package to:
* - Create a `harmony` instance
* - Create a `harmonyExtension` instance, which support fo `MathWallet`
* - Get block and transaction by hash or blocknumber
* - Send transaction
* - Get balance of address
*
* ## How to use `@harmony-core`
* ### Dependencies
* - @harmony-js/core
* - @harmony-js/utils
*
* ### Step 1: Initialize the Harmony instance
* Before using harmony-core package, you should initialize the Harmony instance
* ```javascript
* // import or require Harmony class
* const { Harmony } = require('@harmony-js/core');
* // import or require settings
* const { ChainID, ChainType } = require('@harmony-js/utils');
*
* // initialize the Harmony instance
* const hmy = new Harmony(
* // rpc url
* 'https://api.s0.b.hmny.io/',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
* ```
*
* ### Step 2: Use the instance to call specific functions
* Example 1: get balance
* ```javascript
* // get balance
* hmy.blockchain.getBalance({
* address: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7',
* blockNumber: 'latest'
* }).then((value) => {
* console.log(value.result);
* });
* ```
*
* Example 2: send transaction
* ```
* // add privateKey to wallet
* const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* hmy.wallet.addByPrivateKey(privateKey);
*
* async function transfer() {
* const txn = hmy.transactions.newTx({
* // token send to
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* // amount to send
* value: '10000',
* // gas limit, you can use string
* gasLimit: '210000',
* // send token from shardID
* shardID: 0,
* // send token to toShardID
* toShardID: 0,
* // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
*
* // sign the transaction use wallet;
* const signedTxn = await hmy.wallet.signTransaction(txn);
* const txnHash = await hmy.blockchain.sendTransaction(signedTxn);
* console.log(txnHash.result);
* }
*
* transfer();
* ```
*
* @packageDocumentation
* @module harmony-core
*/
import {
RPCMethod,
Messenger,
@ -22,14 +107,29 @@ import { Transaction } from '@harmony-js/transaction';
import { StakingTransaction } from '@harmony-js/staking';
class Blockchain {
/**
* @hidden
*/
messenger: Messenger;
/**
* @hidden
*/
constructor(messenger: Messenger) {
this.messenger = messenger;
}
/**
* @hidden
*/
setMessenger(messenger: Messenger) {
this.messenger = messenger;
}
/**
*
* @hidden
*/
getRpcResult(result: any) {
if (result instanceof ResponseMiddleware) {
return result.getRaw;
@ -39,7 +139,30 @@ class Blockchain {
}
/**
* Get the balance of an address at a given block.
*
* @param address the address to get the balance of.
* @param blockNumber (option) If you pass this parameter it will not use the default block set with `DefaultBlockParams.latest`
* @param shardID (option) If you pass this parameter it will not use the default block set with `this.messenger.currentShard`
*
* @returns The current balance for the given address in wei.
*
* @hint
* ```
* the third param `shardID` is binding with the endpoint
* shard 0: localhost:9500
* shard 1: localhost:9501
* ```
*
* @example
* ```javascript
* hmy.blockchain.getBalance({
* address: 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7',
* blockNumber: 'latest'
* }).then(value => {
* console.log(value.result);
* });
* ```
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
@ -64,6 +187,26 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns the current block number.
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @return `Promise` - The number of the most recent block.
*
* @hint
* ```
* the third param `shardID` is binding with the endpoint
* shard 0: localhost:9500
* shard 1: localhost:9501
* ```
*
* @example
* ```javascript
* hmy.blockchain.getBlockNumber().then((value) => {
* console.log(value.result);
* });
* ```
*/
async getBlockNumber(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.BlockNumber,
@ -73,8 +216,23 @@ class Blockchain {
);
return this.getRpcResult(result);
}
/**
* Returns a block matching the block Hash.
*
* @param blockHash the block hash
* @param returnObject By default it is `true`, Features in development, IGNORE it!
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - The block object
*
* @example
* ```javascript
* hmy.blockchain.getBlockByHash({
* blockHash: '0x9cd821b576efdff61280e8857ef218fb2cff8db0cf0fb27dfceef7237042b79e',
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
blockHash: ['isHash', AssertType.required],
@ -100,7 +258,21 @@ class Blockchain {
}
/**
* Returns a block matching the block Number.
*
* @param blockNumber the block number
* @param returnObject By default it is `true`, Features in development, IGNORE it!
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - The block object
*
* @example
* ```javascript
* hmy.blockchain.getBlockByNumber({
* blockNumber: '0x89',
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
blockNumber: ['isBlockNumber', AssertType.optional],
@ -125,6 +297,22 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns the number of transaction in a given block.
*
* @param blockHash the block number Hash
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - The number of transactions in the given block.
*
* @example
* ```javascript
* hmy.blockchain.getBlockTransactionCountByHash({
* blockHash: '0x4142514a238157e7fe57b9d54abedb33943507fa15b3799954c273a12705ced1'
* }).then((value) => {
* console.log(value):
* });
* ```
*/
@assertObject({
blockHash: ['isHash', AssertType.required],
shardID: ['isNumber', AssertType.optional],
@ -145,6 +333,22 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns the number of transaction in a given block.
*
* @param blockNumber the block number Hash
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - The number of transactions in the given block.
*
* @example
* ```javascript
* hmy.blockchain.getBlockTransactionCountByNumber({
* blockNumber: '0x2403C'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
blockNumber: ['isBlockNumber', AssertType.required],
shardID: ['isNumber', AssertType.optional],
@ -166,7 +370,22 @@ class Blockchain {
}
/**
* Returns a transaction based on a block hash and the transactions index position.
*
* @param blockHash the block number Hash
* @param index The transactions index position. **Hex Number**
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - A transaction object
*
* @example
* ```javascript
* hmy.blockchain.getTransactionByBlockHashAndIndex({
* blockHash: '0x4142514a238157e7fe57b9d54abedb33943507fa15b3799954c273a12705ced1',
* index: '0x0'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
blockHash: ['isHash', AssertType.required],
@ -191,6 +410,24 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns a transaction based on a block number and the transactions index position.
*
* @param blockNumber the block number
* @param index The transactions index position. **Hex Number**
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - A transaction object
*
* @example
* ```javascript
* hmy.blockchain.getTransactionByBlockNumberAndIndex({
* blockNumber: '0x2403C',
* index: '0x0'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
blockNumber: ['isBlockNumber', AssertType.optional],
index: ['isHex', AssertType.required],
@ -214,6 +451,22 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns a transaction matching the given transaction hash.
*
* @param txnHash The transaction hash
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - A transaction object
*
* @example
* ```javascript
* hmy.blockchain.getTransactionByHash({
* txnHash: '0x146a0cf7e8da45b44194207c4e7785564527059483b765f9a04424554443b224'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
txnHash: ['isHash', AssertType.required],
shardID: ['isNumber', AssertType.optional],
@ -235,7 +488,20 @@ class Blockchain {
}
/**
* Returns the receipt of a transaction by transaction hash.
*
* @param txnHash The transaction hash
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - A transaction receipt object, or `null` when no receipt was found
*
* @example
* ```javascript
* hmy.blockchain.getTransactionReceipt({
* txnHash: '0x146a0cf7e8da45b44194207c4e7785564527059483b765f9a04424554443b224'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
txnHash: ['isString', AssertType.required],
@ -257,6 +523,24 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Get transaction recepit from cross shard transaction
*
* @param txnHash The transaction hash
* @param shardID the shard id of receiver's address
* @returns `Promise` - A transaction receipt object, or `null` when no receipt was found
*
* @example
* ```javascript
* // This transaction sends from shard 0 to shard 1
* hmy.blockchain.getCxReceiptByHash({
* txnHash: '0x7fae9252fbda68d718e610bc10cf2b5c6a9cafb42d4a6b9d6e392c77d587b9ea',
* shardID: 1,
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
txnHash: ['isString', AssertType.required],
shardID: ['isNumber', AssertType.required],
@ -270,8 +554,24 @@ class Blockchain {
);
return this.getRpcResult(result);
}
/**
* Get the code at a specific address.
*
* @param address The address to get the code from (eg:smart contract)
* @param blockNumber (OPTIONAL) If you pass this parameter it will not use the default block
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @return `Promise` - The data at given `address`
*
* @example
* ```javascript
* hmy.blockchain.getCode({
* address: '0x08AE1abFE01aEA60a47663bCe0794eCCD5763c19',
* blockNumber: 'latest'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
@ -296,17 +596,57 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Get the number of peers connected to.
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - number of peer count
*
* @example
* ```javascript
* hmy.blockchain.net_peerCount().then((value) => {
* console.log(value.result);
* });
* ```
*/
async net_peerCount(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(RPCMethod.PeerCount, [], 'net', shardID);
return this.getRpcResult(result);
}
/**
* Get the version of net.
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - the current version.
*
* @example
* ```javascript
* hmy.blockchain.net_version().then((value) => {
* console.log(value.result);
* });
* ```
*/
async net_version(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(RPCMethod.NetVersion, [], 'net', shardID);
return this.getRpcResult(result);
}
/**
* Get the protocal version.
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @returns `Promise` - the current protocol version.
*
* @example
* ```javascript
* hmy.blockchain.getProtocolVersion().then((value) => {
* console.log(value.result);
* });
* ```
*/
async getProtocolVersion(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.ProtocolVersion,
@ -317,6 +657,24 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Get the storage at a specific position of an address
*
* @param address The address to get the storage from
* @param position The index position of the storage
* @param blockNumber by default it's `latest`.
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* hmy.blockchain.getStorageAt({
* address: 'one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g',
* position: '0x0'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
position: ['isHex', AssertType.required],
@ -343,6 +701,23 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Get the numbers of transactions sent from this address.
*
* @param address The address to get the numbers of transactions from
* @param blockNumber by default it's `latest`
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @return `Promise` - The number of transactions sent from the given address.
*
* @example
* ```javascript
* hmy.blockchain.getTransactionCount({
* address: "one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g"
* }).then((value) => {
* console.log(value.result);
* });
* ```
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
blockNumber: ['isBlockNumber', AssertType.optional],
@ -366,6 +741,18 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Get the sharding structure of current network
*
* @return `Promise` - The sharding structure of current network.
*
* @example
* ```javascript
* hmy.blockchain.getShardingStructure().then((value) => {
* console.log(value);
* });
* ```
*/
async getShardingStructure() {
const result = await this.messenger.send(
RPCMethod.GetShardingStructure,
@ -375,6 +762,43 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Sends a signed transaction to the network.
*
* @param transaction `Object` - The transaction object to send:
* @return The **callbalck** will return the 32 bytes transaction hash
*
* @example
* ```javascript
* // add privateKey to wallet
* const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* hmy.wallet.addByPrivateKey(privateKey);
*
* async function transfer() {
* const txn = hmy.transactions.newTx({
* // token send to
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* // amount to send
* value: '10000',
* // gas limit, you can use string
* gasLimit: '210000',
* // send token from shardID
* shardID: 0,
* // send token to toShardID
* toShardID: 0,
* // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
*
* // sign the transaction use wallet;
* const signedTxn = await hmy.wallet.signTransaction(txn);
* const txnHash = await hmy.blockchain.sendTransaction(signedTxn);
* console.log(txnHash.result);
* }
*
* transfer();
* ```
*/
async sendTransaction(transaction: Transaction) {
if (!transaction.isSigned() || !transaction) {
throw new Error('transaction is not signed or not exist');
@ -390,6 +814,45 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Sends a raw transaction to the network.
*
* @param transaction `Object` - The transaction object to send:
* @return The **callbalck** will return the 32 bytes transaction hash
*
* @example
* ```javascript
* // add privateKey to wallet
* const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* hmy.wallet.addByPrivateKey(privateKey);
*
* async function transfer() {
* const txn = hmy.transactions.newTx({
* // token send to
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* // amount to send
* value: '10000',
* // gas limit, you can use string
* gasLimit: '210000',
* // send token from shardID
* shardID: 0,
* // send token to toShardID
* toShardID: 0,
* // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
*
* // sign the transaction use wallet;
* const signedTxn = await hmy.wallet.signTransaction(txn);
* recovered = signedTxn.recover(signedTxn.rawTransaction);
*
* const txnHash = await hmy.blockchain.sendRawTransaction(recovered);
* console.log(txnHash);
* }
*
* transfer();
* ```
*/
async sendRawTransaction(transaction: Transaction) {
if (!transaction.isSigned() || !transaction) {
throw new Error('transaction is not signed or not exist');
@ -400,6 +863,43 @@ class Blockchain {
}
}
/**
* send a transaction and check whether it exists
*
* @param transaction `Object` - The transaction object to send:
* @return The **callbalck** will return the 32 bytes transaction hash
*
* @example
* ```javascript
* // add privateKey to wallet
* const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
* hmy.wallet.addByPrivateKey(privateKey);
*
* async function transfer() {
* const txn = hmy.transactions.newTx({
* // token send to
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* // amount to send
* value: '10000',
* // gas limit, you can use string
* gasLimit: '210000',
* // send token from shardID
* shardID: 0,
* // send token to toShardID
* toShardID: 0,
* // gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
*
* // sign the transaction use wallet;
* const signedTxn = await hmy.wallet.signTransaction(txn);
* const txnHash = await hmy.blockchain.createObservedTransaction(signedTxn);
* console.log(txnHash);
* }
*
* transfer();
* ```
*/
createObservedTransaction(transaction: Transaction) {
try {
transaction.sendTransaction().then((response: any) => {
@ -415,6 +915,17 @@ class Blockchain {
}
}
/**
* send raw staking transaction
*
* @param staking
* @ignore
*
* @warning
* ```
* At present, this function is not implement yet, will Coming soon!!!
* ```
*/
async sendRawStakingTransaction(staking: StakingTransaction) {
if (!staking.isSigned() || !staking) {
throw new Error('staking transaction is not signed or not exist');
@ -424,6 +935,18 @@ class Blockchain {
return result;
}
}
/**
* send raw staking transaction and check whether it exists
*
* @param staking
* @ignore
*
* @warning
* ```
* At present, this function is not implement yet, will Coming soon!!!
* ```
*/
createObservedStakingTransaction(staking: StakingTransaction) {
try {
staking.sendTransaction().then((response: any) => {
@ -439,6 +962,29 @@ class Blockchain {
}
}
/**
* Executes a message call or transaction and returns the amount of the gas used.
*
* @param to the address will send to
* @param data the data will send to that address
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @return `promise` - the used gas for the simulated call/transaction.
*
* @warning
* ```
* At present, this function hmy_estimateGas is not implement yet, will Coming soon!!!
* ```
*
* @example
* ```javascript
* hmy.blockchain.estimateGas({
* to: 'one1d0kw95t6kkljmkk9vu0zv25jraut8ngv5vrs5g',
* data: '0xc6888fa10000000000000000000000000000000000000000000000000000000000000003'
* }).then((value) => {
* console.log(value);
* });
* ```
*/
@assertObject({
to: ['isValidAddress', AssertType.optional],
data: ['isHex', AssertType.optional],
@ -462,6 +1008,19 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Returns the current gas price oracle. The gas price is determined by the last few blocks median gas price.
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @return `promise` - Number string of the current gas price in wei.
*
* @example
* ```javascript
* hmy.blockchain.gasPrice().then((value) => {
* console.log(value);
* });
* ```
*/
async gasPrice(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.GasPrice,
@ -472,6 +1031,23 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Executes a message call transaction,
* which is directly executed in the VM of the node, but never mined into the blockchain.
*
* @param payload some data you want put into these fucntions
* @param blockNumber by default it's `latest`
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* hmy.blockchain.call({
* to: "0x08AE1abFE01aEA60a47663bCe0794eCCD5763c19",
* }).then((value) => {
* console.log(value);
* });
* ```
*/
async call({
payload,
blockNumber = DefaultBlockParams.latest,
@ -490,6 +1066,28 @@ class Blockchain {
return this.getRpcResult(result);
}
/**
* Return new pending Transactions
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* const hmy = new Harmony(
* // rpc url
* 'ws://api.s0.b.hmny.io/',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
*
* const tmp = hmy.blockchain.newPendingTransactions();
* console.log(tmp)
* ```
*/
newPendingTransactions(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new NewPendingTransactions(this.messenger, shardID);
@ -498,6 +1096,27 @@ class Blockchain {
}
}
/**
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* const hmy = new Harmony(
* // rpc url
* 'ws://api.s0.b.hmny.io/',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
*
* const tmp = hmy.blockchain.newBlockHeaders();
* console.log(tmp)
* ```
*/
newBlockHeaders(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new NewHeaders(this.messenger, shardID);
@ -506,6 +1125,27 @@ class Blockchain {
}
}
/**
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* const hmy = new Harmony(
* // rpc url
* 'ws://api.s0.b.hmny.io/',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
*
* const tmp = hmy.blockchain.syncing();
* console.log(tmp)
* ```
*/
syncing(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new Syncing(this.messenger, shardID);
@ -514,6 +1154,29 @@ class Blockchain {
}
}
/**
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
*
* @example
* ```javascript
* const hmy = new Harmony(
* // rpc url
* 'ws://api.s0.b.hmny.io/',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
*
* const tmp = hmy.blockchain.logs({
* from: '0x12'
* });
* console.log(tmp)
* ```
*/
logs(options: any, shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new LogSub(options, this.messenger, shardID);

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-core
*/
import * as crypto from '@harmony-js/crypto';
import * as utils from '@harmony-js/utils';
@ -10,6 +15,7 @@ import { Blockchain } from './blockchain';
import { HarmonyConfig } from './util';
export class Harmony extends utils.HarmonyCore {
/**@ignore*/
Modules = {
HttpProvider,
WSProvider,
@ -23,17 +29,57 @@ export class Harmony extends utils.HarmonyCore {
Account,
Contract,
};
/**@ignore*/
messenger: Messenger;
/**@ignore*/
transactions: TransactionFactory;
/**@ignore*/
stakings: StakingFactory;
/**@ignore*/
wallet: Wallet;
/**@ignore*/
blockchain: Blockchain;
/**@ignore*/
contracts: ContractFactory;
/**@ignore*/
crypto: any;
/**@ignore*/
utils: any;
/**@ignore*/
defaultShardID?: number;
/**@ignore*/
private provider: HttpProvider | WSProvider;
/**
* Create a harmony instance
*
* @param url The end-points of the hmy blockchain
* @param config set up `ChainID` and `ChainType`, typically we can use the default values
*
* @example
* ```
* // import or require Harmony class
* const { Harmony } = require('@harmony-js/core');
*
* // import or require settings
* const { ChainID, ChainType } = require('@harmony-js/utils');
*
* // Initialize the Harmony instance
* const hmy = new Harmony(
* // rpc url:
* // local: http://localhost:9500
* // testnet: https://api.s0.b.hmny.io/
* // mainnet: https://api.s0.t.hmny.io/
* 'http://localhost:9500',
* {
* // chainType set to Harmony
* chainType: ChainType.Harmony,
* // chainType set to HmyLocal
* chainId: ChainID.HmyLocal,
* },
* );
* ```
*/
constructor(
url: string,
config: HarmonyConfig = {
@ -59,28 +105,106 @@ export class Harmony extends utils.HarmonyCore {
this.setShardID(this.defaultShardID);
}
}
/**
* Will change the provider for its module.
*
* @param provider a valid provider, you can replace it with your own working node
*
* @example
* ```javascript
* const tmp = hmy.setProvider('http://localhost:9500');
* ```
*/
public setProvider(provider: string | HttpProvider | WSProvider): void {
this.provider = new Provider(provider).provider;
this.messenger.setProvider(this.provider);
this.setMessenger(this.messenger);
}
/**
* set the chainID
*
* @hint
* ```
* Default = 0,
* EthMainnet = 1,
Morden = 2,
Ropsten = 3,
Rinkeby = 4,
RootstockMainnet = 30,
RootstockTestnet = 31,
Kovan = 42,
EtcMainnet = 61,
EtcTestnet = 62,
Geth = 1337,
Ganache = 0,
HmyMainnet = 1,
HmyTestnet = 2,
HmyLocal = 2,
HmyPangaea = 3
* ```
* @param chainId
*
* @example
* ```
* hmy.setChainId(2);
* ```
*/
public setChainId(chainId: utils.ChainID) {
this.chainId = chainId;
this.messenger.setChainId(this.chainId);
this.setMessenger(this.messenger);
}
/**
* Change the Shard ID
*
* @example
* ```
* hmy.setShardID(2);
* ```
*/
public setShardID(shardID: number) {
this.defaultShardID = shardID;
this.messenger.setDefaultShardID(this.defaultShardID);
this.setMessenger(this.messenger);
}
/**
* set the chainType
*
* @param chainType `hmy` or `eth`
*
* @example
* ```
* // set chainType to hmy
* hmy.setChainType('hmy');
* // set chainType to eth
* hmy.setChainType('eth');
* ```
*/
public setChainType(chainType: utils.ChainType) {
this.chainType = chainType;
this.messenger.setChainType(this.chainType);
this.setMessenger(this.messenger);
}
/**
* Set the sharding Structure
*
* @param shardingStructures The array of information of sharding structures
*
* @example
* ```javascript
* hmy.shardingStructures([
* {"current":true,"http":"http://127.0.0.1:9500",
* "shardID":0,"ws":"ws://127.0.0.1:9800"},
* {"current":false,"http":"http://127.0.0.1:9501",
* "shardID":1,"ws":"ws://127.0.0.1:9801"}
* ]);
* ```
*/
public shardingStructures(shardingStructures: ShardingItem[]) {
for (const shard of shardingStructures) {
const shardID =
@ -94,6 +218,8 @@ export class Harmony extends utils.HarmonyCore {
}
this.setMessenger(this.messenger);
}
/**@ignore*/
private setMessenger(messenger: Messenger) {
this.blockchain.setMessenger(messenger);
this.wallet.setMessenger(messenger);

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-core
*/
import {
HttpProvider,
WSProvider,
@ -15,20 +20,24 @@ import { Blockchain } from './blockchain';
import { ContractFactory } from '@harmony-js/contract';
import { HarmonyConfig } from './util';
/** @hidden */
export enum ExtensionType {
MathWallet = 'MathWallet',
}
/** @hidden */
export interface ExtensionAccount {
address: 'string';
name: 'string';
}
/** @hidden */
export interface ExtensionNetwork {
chain_url: string;
net_version: number;
}
/** @hidden */
export interface ExtensionInterface {
signTransaction: (
transaction: Transaction,
@ -44,17 +53,41 @@ export interface ExtensionInterface {
}
export class HarmonyExtension {
/**@ignore*/
extensionType: ExtensionType | null;
/**@ignore*/
wallet: ExtensionInterface;
/**@ignore*/
provider: HttpProvider | WSProvider;
/**@ignore*/
messenger: Messenger;
/**@ignore*/
blockchain: Blockchain;
/**@ignore*/
transactions: TransactionFactory;
/**@ignore*/
contracts: ContractFactory;
/**@ignore*/
crypto: any;
/**@ignore*/
utils: any;
/**@ignore*/
defaultShardID?: number;
/**
* Create an blockchain instance support wallet injection
*
* @param wallet could be MathWallet instance
* @param config (optional), using default `Chain_Id` and `Chain_Type`
*
* @example
* ```javascript
* // Using Mathwallet instance
* export const initEx = async() => {
* hmyEx = new HarmonyExtension(window.harmony);
* }
* ```
*/
constructor(
wallet: ExtensionInterface,
config: HarmonyConfig = {
@ -81,12 +114,31 @@ export class HarmonyExtension {
this.crypto = crypto;
this.utils = utils;
}
/**
* Will change the provider for its module.
*
* @param provider a valid provider, you can replace it with your own working node
*
* @example
* ```javascript
* const tmp = hmyEx.setProvider('http://localhost:9500');
* ```
*/
public setProvider(provider: string | HttpProvider | WSProvider): void {
this.provider = new Provider(provider).provider;
this.messenger.setProvider(this.provider);
this.setMessenger(this.messenger);
}
/**
* Change the Shard ID
*
* @example
* ```
* hmyEx.setShardID(2);
* ```
*/
public setShardID(shardID: number) {
this.defaultShardID = shardID;
this.messenger.setDefaultShardID(this.defaultShardID);
@ -139,12 +191,37 @@ export class HarmonyExtension {
}
return;
}
/**
* Get the wallet account
*
* @example
* ```javascript
* const account = hmyEx.login();
* console.log(account);
* ```
*/
public async login() {
const account = await this.wallet.getAccount();
// Use address
return account;
}
/**
* Set the sharding Structure
*
* @param shardingStructures The array of information of sharding structures
*
* @example
* ```javascript
* hmyEx.shardingStructures([
* {"current":true,"http":"http://127.0.0.1:9500",
* "shardID":0,"ws":"ws://127.0.0.1:9800"},
* {"current":false,"http":"http://127.0.0.1:9501",
* "shardID":1,"ws":"ws://127.0.0.1:9801"}
* ]);
* ```
*/
public shardingStructures(shardingStructures: ShardingItem[]) {
for (const shard of shardingStructures) {
const shardID =
@ -158,6 +235,8 @@ export class HarmonyExtension {
}
this.setMessenger(this.messenger);
}
/**@ignore*/
private setMessenger(messenger: Messenger) {
this.blockchain.setMessenger(messenger);
this.wallet.messenger = messenger;

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-core
* @hidden
*/
export * from './harmony';
export * from './blockchain';
export * from './truffleProvider';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-core
* @hidden
*/
import {
HttpProvider,
WSProvider,
@ -21,11 +27,13 @@ export interface HDOptions {
index: number;
addressCount: number;
}
export interface ChainOptions {
shardID: number;
chainType: ChainType;
chainId: ChainID;
}
export interface TransactionOptions {
gasLimit: string;
gasPrice: string;

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-core
* @hidden
*/
import { HttpProvider, Messenger } from '@harmony-js/network';
import { TransactionFactory, Transaction } from '@harmony-js/transaction';
import { Wallet, Account } from '@harmony-js/account';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-core
* @hidden
*/
import { ChainType, ChainID, defaultConfig } from '@harmony-js/utils';
import { Harmony } from './harmony';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
// tslint:disable-next-line: no-implicit-dependencies
import fetch from 'jest-fetch-mock';
import { Blockchain } from '../src/blockchain';
@ -36,25 +41,19 @@ describe('test Blockchain', () => {
extraData: '0x',
gasLimit: '0x254a0e6f8',
gasUsed: '0x22da16',
hash:
'0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
hash: '0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
miner: '0x0000000000000000000000000000000000000000',
mixHash:
'0x0000000000000000000000000000000000000000000000000000000000000000',
mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
nonce: '0x0000000000000000',
number: '0x0',
parentHash:
'0x057e52af22d94cd40626d1e157e3468219d8236847c13bb3aa11f31fd6c4e71a',
receiptsRoot:
'0xf9c8a65a3224a4c6e6ae3b9f0ee992c4cefdbe4db318c4ec52880e324f1b77bd',
parentHash: '0x057e52af22d94cd40626d1e157e3468219d8236847c13bb3aa11f31fd6c4e71a',
receiptsRoot: '0xf9c8a65a3224a4c6e6ae3b9f0ee992c4cefdbe4db318c4ec52880e324f1b77bd',
size: '0x2de9',
stateRoot:
'0x112322fee869910b9a0e390ae536addca7a2a82bac7c17a61ed43a715e845218',
stateRoot: '0x112322fee869910b9a0e390ae536addca7a2a82bac7c17a61ed43a715e845218',
timestamp: 1556265598,
transactionsRoot:
'0x7687794ce8479d36c1a6d8b161dca37d90bd824da1c36d6d8f33f7bf4015c1d0',
transactionsRoot: '0x7687794ce8479d36c1a6d8b161dca37d90bd824da1c36d6d8f33f7bf4015c1d0',
uncles: [],
},
};
@ -73,14 +72,12 @@ describe('test Blockchain', () => {
expect(res3.result.timestamp).toEqual(1556265598);
const res4 = await bc.getBlockByHash({
blockHash:
'0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
blockHash: '0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
});
expect(res4.responseType).toEqual('raw');
expect(res4.result.size).toEqual('0x2de9');
const res5 = await bc.getBlockByHash({
blockHash:
'0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
blockHash: '0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
returnObject: true,
});
expect(res5.responseType).toEqual('raw');
@ -94,14 +91,12 @@ describe('test Blockchain', () => {
jsonrpc: '2.0',
id: 1,
result: {
blockHash:
'0x359036996c7ad7fdaa42b18de2fc157ae97d4cd3f32c688af349225f7e8f8fc6',
blockHash: '0x359036996c7ad7fdaa42b18de2fc157ae97d4cd3f32c688af349225f7e8f8fc6',
blockNumber: '0x1',
from: '0x15a128e599b74842bccba860311efa92991bffb5',
gas: '0x81650',
gasPrice: '0x0',
hash:
'0x9a71ea0839511c95b0818bd54a38ab56a05337a8282245d853d0ae3a1aedd7da',
hash: '0x9a71ea0839511c95b0818bd54a38ab56a05337a8282245d853d0ae3a1aedd7da',
input:
'0x6080604052678ac7230489e80000600155600280546001600160a01b0319163317905561014d806100316000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806327c78c421461003b5780634ddd108a14610063575b600080fd5b6100616004803603602081101561005157600080fd5b50356001600160a01b031661007d565b005b61006b61011c565b60408051918252519081900360200190f35b6002546001600160a01b0316331461009457600080fd5b600154303110156100a457600080fd5b6001600160a01b03811660009081526020819052604090205460ff16156100ca57600080fd5b6001600160a01b038116600081815260208190526040808220805460ff1916600190811790915554905181156108fc0292818181858888f19350505050158015610118573d6000803e3d6000fd5b5050565b30319056fea165627a7a72305820b83c347551d539b44b318fb7b4601a635a7d3a6d7063d11e6e05e4886b6d88050029',
nonce: '0x0',
@ -117,16 +112,14 @@ describe('test Blockchain', () => {
runMocks(mockRpcResponse, 4);
const res1 = await bc.getTransactionByHash({
txnHash:
'0x9a71ea0839511c95b0818bd54a38ab56a05337a8282245d853d0ae3a1aedd7da',
txnHash: '0x9a71ea0839511c95b0818bd54a38ab56a05337a8282245d853d0ae3a1aedd7da',
});
expect(res1.responseType).toEqual('raw');
expect(res1.result.blockHash).toEqual(
'0x359036996c7ad7fdaa42b18de2fc157ae97d4cd3f32c688af349225f7e8f8fc6',
);
const res2 = await bc.getTransactionByBlockHashAndIndex({
blockHash:
'0x359036996c7ad7fdaa42b18de2fc157ae97d4cd3f32c688af349225f7e8f8fc6',
blockHash: '0x359036996c7ad7fdaa42b18de2fc157ae97d4cd3f32c688af349225f7e8f8fc6',
index: '0x0',
});
expect(res2.responseType).toEqual('raw');
@ -161,8 +154,7 @@ describe('test Blockchain', () => {
runMocks(mockRpcResponse, 5);
const res1 = await bc.getBlockTransactionCountByHash({
blockHash:
'0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
blockHash: '0x7e1ef610f700805b93cf85b1e55bce84fcbd04373252a968755366a8d2215424',
});
expect(res1.result).toEqual('0x65');
try {
@ -223,8 +215,7 @@ describe('test Blockchain', () => {
const mockRpcResponse = {
jsonrpc: '2.0',
id: 1,
result:
'0x0000000000000000000000000000000000000000000000000000000000000000',
result: '0x0000000000000000000000000000000000000000000000000000000000000000',
};
// set mocks to test methods
runMocks(mockRpcResponse, 2);

@ -1,27 +1,74 @@
/**
* @packageDocumentation
* @module harmony-crypto
*/
import { isAddress, isBech32Address, isBech32TestNetAddress } from '@harmony-js/utils';
import { toChecksumAddress } from './keyTool';
import { fromBech32, toBech32, HRP, tHRP } from './bech32';
/**
* ### How to use it?
*
* ```
* // Step 1: import the class
* const { HarmonyAddress } = require('@harmony-js/crypto');
*
* // Step 2: call functions
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const res = HarmonyAddress.isValidBech32(addr);
* console.log(res);
* ```
*/
export class HarmonyAddress {
// static validator
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const res = HarmonyAddress.isValidBech32(addr);
* console.log(res);
* ```
*/
static isValidBasic(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.basic;
}
// static validator
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const res = HarmonyAddress.isValidChecksum(addr);
* console.log(res);
* ```
*/
static isValidChecksum(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.checksum;
}
// static validator
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const res = HarmonyAddress.isValidBech32(addr);
* console.log(res);
* ```
*/
static isValidBech32(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.bech32;
}
// static validator
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const res = HarmonyAddress.isValidBech32TestNet(addr);
* console.log(res);
* ```
*/
static isValidBech32TestNet(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.bech32TestNet;
@ -29,16 +76,53 @@ export class HarmonyAddress {
raw: string;
basic: string;
/**
* get basicHex of the address
*
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const instance = new HarmonyAddress(addr);
* console.log(instance.basicHex);
* ```
*/
get basicHex() {
return `0x${this.basic}`;
}
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const instance = new HarmonyAddress(addr);
* console.log(instance.checksum);
* ```
*/
get checksum() {
return toChecksumAddress(`0x${this.basic}`);
}
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const instance = new HarmonyAddress(addr);
* console.log(instance.bech32);
* ```
*/
get bech32() {
return toBech32(this.basic, HRP);
}
/**
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const instance = new HarmonyAddress(addr);
* console.log(instance.bech32TestNet);
* ```
*/
get bech32TestNet() {
return toBech32(this.basic, tHRP);
}
@ -48,6 +132,19 @@ export class HarmonyAddress {
this.basic = this.getBasic(this.raw);
}
/**
* Check whether the address has an valid address format
*
* @param addr string, the address
*
* @example
* ```
* const addr = 'one103q7qe5t2505lypvltkqtddaef5tzfxwsse4z7'
* const instance = new HarmonyAddress(addr);
* const res = instance.getBasic(addr);
* console.log(res)
* ```
*/
private getBasic(addr: string) {
const basicBool = isAddress(addr);
const bech32Bool = isBech32Address(addr);
@ -71,6 +168,30 @@ export class HarmonyAddress {
}
}
/**
* Using this function to get Harmony format address
*
* @param address
*
* @example
* ```javascript
* const { Harmony } = require('@harmony-js/core');
* const { ChainID, ChainType } = require('@harmony-js/utils');
* const { randomBytes } = require('@harmony-js/crypto')
*
* const hmy = new Harmony(
* 'http://localhost:9500',
* {
* chainType: ChainType.Harmony,
* chainId: ChainID.HmyLocal,
* },
* );
*
* const bytes = randomBytes(20);
* const hAddress = hmy.crypto.getAddress(bytes);
* console.log(hAddress)
* ```
*/
export function getAddress(address: string) {
try {
return new HarmonyAddress(address);

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @hidden
*/
import { isAddress } from '@harmony-js/utils';
import { toChecksumAddress } from './keyTool';
@ -192,11 +198,7 @@ export const toBech32 = (address: string, useHRP: string = HRP): string => {
throw new Error('Invalid address format.');
}
const addrBz = convertBits(
Buffer.from(address.replace('0x', ''), 'hex'),
8,
5,
);
const addrBz = convertBits(Buffer.from(address.replace('0x', ''), 'hex'), 8, 5);
if (addrBz === null) {
throw new Error('Could not convert byte Buffer to 5-bit Buffer');

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @hidden
*/
// This file is ported from ether.js/src.ts/utils/bytes.ts
// and done some fixes

@ -1,13 +1,83 @@
/**
* ## About this package
*
* `@harmony-js/crypot` provides a series of functions to deal with keys
*
* ## How to use this package
*
* ### Create a Harmony Instance
* ```javascript
* const { Harmony } = require('@harmony-js/core');
* const { ChainID, ChainType } = require('@harmony-js/utils');
*
* const hmy = new Harmony(
* 'http://localhost:9500',
* {
* chainType: ChainType.Harmony,
* chainId: ChainID.HmyLocal,
* },
* );
* ```
*
* ### Some examples
*
* ```javascript
* // randomBytes
* const bytes = hmy.crypto.randomBytes(20);
* console.log(bytes)
*
* // encryptPhrase
* const myPhrase = hmy.wallet.newMnemonic();
* const pwd = '1234';
* hmy.crypto.encryptPhrase(myPhrase, pwd).then((value) => {
* console.log(value);
* })
*
* // decryptThePhrase
* hmy.crypto.encryptPhrase(myPhrase, pwd).then((keystore) => {
* hmy.crypto.decryptPhrase(JSON.parse(keystore), pwd).then((value) => {
* console.log(value);
* })
* })
*
* // generatePrivateKey
* const privateKey = hmy.crypto.generatePrivateKey();
* console.log(privateKey)
*
* // getPubkeyFromPrivateKey
* const publicKey = hmy.crypto.getPubkeyFromPrivateKey(privateKey);
* console.log(publicKey);
*
* // getAddressFromPrivateKey
* const address = hmy.crypto.getAddressFromPrivateKey(privateKey);
* console.log(address);
*
* // getAddressFromPublicKey
* const address = hmy.crypto.getAddressFromPublicKey(publicKey);
* console.log(address);
*
* // toChecksumAddress
* const checksumAddr = hmy.crypto.toChecksumAddress(address);
* console.log(checksumAddr);
* ```
*
* @packageDocumentation
* @module harmony-crypto
*/
// This file is ported from ether.js/src.ts/errors.ts
// Unknown Error
/** @hidden */
export const UNKNOWN_ERROR = 'UNKNOWN_ERROR';
// Not implemented
/** @hidden */
export const NOT_IMPLEMENTED = 'NOT_IMPLEMENTED';
// Missing new operator to an object
// - name: The name of the class
/** @hidden */
export const MISSING_NEW = 'MISSING_NEW';
// Call exception
@ -18,55 +88,63 @@ export const MISSING_NEW = 'MISSING_NEW';
// - errorSignature?: The EIP848 error signature
// - errorArgs?: The EIP848 error parameters
// - reason: The reason (only for EIP848 "Error(string)")
/** @hidden */
export const CALL_EXCEPTION = 'CALL_EXCEPTION';
// Invalid argument (e.g. value is incompatible with type) to a function:
// - argument: The argument name that was invalid
// - value: The value of the argument
/** @hidden */
export const INVALID_ARGUMENT = 'INVALID_ARGUMENT';
// Missing argument to a function:
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
/** @hidden */
export const MISSING_ARGUMENT = 'MISSING_ARGUMENT';
// Too many arguments
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
/** @hidden */
export const UNEXPECTED_ARGUMENT = 'UNEXPECTED_ARGUMENT';
// Numeric Fault
// - operation: the operation being executed
// - fault: the reason this faulted
/** @hidden */
export const NUMERIC_FAULT = 'NUMERIC_FAULT';
// Insufficien funds (< value + gasLimit * gasPrice)
// - transaction: the transaction attempted
/** @hidden */
export const INSUFFICIENT_FUNDS = 'INSUFFICIENT_FUNDS';
// Nonce has already been used
// - transaction: the transaction attempted
/** @hidden */
export const NONCE_EXPIRED = 'NONCE_EXPIRED';
// The replacement fee for the transaction is too low
// - transaction: the transaction attempted
/** @hidden */
export const REPLACEMENT_UNDERPRICED = 'REPLACEMENT_UNDERPRICED';
// Unsupported operation
// - operation
/** @hidden */
export const UNSUPPORTED_OPERATION = 'UNSUPPORTED_OPERATION';
// tslint:disable-next-line: variable-name
/** @hidden */
let _permanentCensorErrors = false;
// tslint:disable-next-line: variable-name
/** @hidden */
let _censorErrors = false;
// @TODO: Enum
export function throwError(
message: string,
code: string | null | undefined,
params: any,
): never {
/** @hidden */
export function throwError(message: string, code: string | null | undefined, params: any): never {
if (_censorErrors) {
throw new Error('unknown error');
}
@ -105,17 +183,15 @@ export function throwError(
throw error;
}
/** @hidden */
export function checkNew(self: any, kind: any): void {
if (!(self instanceof kind)) {
throwError('missing new', MISSING_NEW, { name: kind.name });
}
}
export function checkArgumentCount(
count: number,
expectedCount: number,
suffix?: string,
): void {
/** @hidden */
export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void {
if (!suffix) {
suffix = '';
}
@ -133,6 +209,7 @@ export function checkArgumentCount(
}
}
/** @hidden */
export function setCensorship(censorship: boolean, permanent?: boolean): void {
if (_permanentCensorErrors) {
throwError('error censorship permanent', UNSUPPORTED_OPERATION, {
@ -144,6 +221,7 @@ export function setCensorship(censorship: boolean, permanent?: boolean): void {
_permanentCensorErrors = !!permanent;
}
/** @hidden */
export function checkNormalize(): void {
try {
// Make sure all forms of normalization are supported
@ -155,21 +233,18 @@ export function checkNormalize(): void {
}
});
if (
String.fromCharCode(0xe9).normalize('NFD') !==
String.fromCharCode(0x65, 0x0301)
) {
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
throw new Error('broken implementation');
}
} catch (error) {
throwError(
'platform missing String.prototype.normalize',
UNSUPPORTED_OPERATION,
{ operation: 'String.prototype.normalize', form: error.message },
);
throwError('platform missing String.prototype.normalize', UNSUPPORTED_OPERATION, {
operation: 'String.prototype.normalize',
form: error.message,
});
}
}
/** @hidden */
const LogLevels: { [name: string]: number } = {
debug: 1,
default: 2,
@ -178,8 +253,10 @@ const LogLevels: { [name: string]: number } = {
error: 4,
off: 5,
};
/** @hidden */
let LogLevel = LogLevels.default;
/** @hidden */
export function setLogLevel(logLevel: string): void {
const level = LogLevels[logLevel];
if (level == null) {
@ -189,6 +266,7 @@ export function setLogLevel(logLevel: string): void {
LogLevel = level;
}
/** @hidden */
function log(logLevel: string, args: [any?, ...any[]]): void {
if (LogLevel > LogLevels[logLevel]) {
return;
@ -196,10 +274,12 @@ function log(logLevel: string, args: [any?, ...any[]]): void {
console.log.apply(console, args);
}
/** @hidden */
export function warn(...args: [any?, ...any[]]): void {
log('warn', args);
}
/** @hidden */
export function info(...args: [any?, ...any[]]): void {
log('info', args);
}

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @ignore
*/
import hdkey from 'hdkey';
import bip39 from 'bip39';
import BN from 'bn.js';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @ignore
*/
// this file is ported from 'ether.js' and done some fixes
import * as sha3 from 'js-sha3';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-crypto
*/
import elliptic from 'elliptic';
import * as bytes from './bytes';
import * as errors from './errors';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-crypto
*/
import aes from 'aes-js';
// import scrypt from 'scrypt.js';
import scrypt from 'scrypt-shim';
@ -10,6 +15,7 @@ import { concat, hexToIntArray } from './bytes';
import { keccak256 } from './keccak256';
import { KDF, KDFParams, EncryptOptions, PBKDF2Params, ScryptParams, Keystore } from './types';
/** @hidden */
const DEFAULT_ALGORITHM = 'aes-128-ctr';
/**
@ -134,6 +140,9 @@ export const decrypt = async (keystore: Keystore, password: string): Promise<str
return decrypted;
};
/**
* encrypt Phrase
*/
export const encryptPhrase = async (
phrase: string,
password: string,
@ -183,6 +192,9 @@ export const encryptPhrase = async (
});
};
/**
* decrypt phrase
*/
export const decryptPhrase = async (keystore: Keystore, password: string): Promise<string> => {
const result = await decrypt(keystore, password);
return Buffer.from(result.replace('0x', ''), 'hex').toString();

@ -1,18 +1,19 @@
/**
* @function randomBytes
* @description Uses JS-native CSPRNG to generate a specified number of bytes.
* NOTE: this method throws if no PRNG is available.
* @packageDocumentation
* @module harmony-crypto
*/
/**
* Uses JS-native CSPRNG to generate a specified number of bytes.
* @NOTE
* this method throws if no PRNG is available.
* @param {Number} bytes bytes number to generate
* @return {String} ramdom hex string
*/
export const randomBytes = (bytes: number): string => {
let randBz: number[] | Uint8Array;
if (
typeof window !== 'undefined' &&
window.crypto &&
window.crypto.getRandomValues
) {
if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
randBz = window.crypto.getRandomValues(new Uint8Array(bytes));
} else if (typeof require !== 'undefined') {
randBz = require('crypto').randomBytes(bytes);

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @hidden
*/
// this file is ported from https://github.com/ethers-io/ethers.js/blob/master/src.ts/utils/rlp.ts
// and done some fixes
import { arrayify, hexlify, Arrayish } from './bytes';
@ -11,11 +17,7 @@ function arrayifyInteger(value: number): number[] {
return result;
}
function unarrayifyInteger(
data: Uint8Array,
offset: number,
length: number,
): number {
function unarrayifyInteger(data: Uint8Array, offset: number, length: number): number {
let result = 0;
for (let i = 0; i < length; i++) {
result = result * 256 + data[offset + i];
@ -89,10 +91,7 @@ function _decodeChildren(
}
// returns { consumed: number, result: Object }
function _decode(
data: Uint8Array,
offset: number,
): { consumed: number; result: any } {
function _decode(data: Uint8Array, offset: number): { consumed: number; result: any } {
if (data.length === 0) {
throw new Error('invalid rlp data');
}
@ -109,12 +108,7 @@ function _decode(
throw new Error('to short');
}
return _decodeChildren(
data,
offset,
offset + 1 + lengthLength,
lengthLength + length,
);
return _decodeChildren(data, offset, offset + 1 + lengthLength, lengthLength + length);
} else if (data[offset] >= 0xc0) {
const length = data[offset] - 0xc0;
if (offset + 1 + length > data.length) {

@ -2,3 +2,8 @@
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
/**
* @packageDocumentation
* @ignore
*/

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-crypto
* @ignore
*/
export type KDF = 'pbkdf2' | 'scrypt';
export interface PBKDF2Params {

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import { getAddress, HarmonyAddress } from '../src/address';
import { randomBytes } from '../src/random';
import { toBech32, fromBech32, HRP, tHRP } from '../src/bech32';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import * as bytes from '../src/bytes';
describe('Bytes', () => {

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import * as hash from '../src/keccak256';
import hashes from './fixtures/hashes.json';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import * as keys from '../src/keyTool';
import { isPrivateKey, isAddress, isPublicKey } from '@harmony-js/utils';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @ignore
*/
import * as rlp from '../src/rlp';
import cases from './fixtures/rlpcoder.json';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
import mitt from 'mitt';
export { mitt };
// provider related

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { HarmonyCore, ChainType, isString, ChainID, defaultConfig } from '@harmony-js/utils';
import { JsonRpc } from '../rpcMethod/builder';
import { ResponseMiddleware } from './responseMiddleware';
@ -7,6 +12,7 @@ import { WSProvider } from '../providers/ws';
import { RPCMethod } from '../rpcMethod/rpc';
import { SubscribeReturns, ShardingItem } from '../types';
/** @hidden */
export interface ShardingProvider {
current: boolean;
shardID: number;
@ -15,11 +21,19 @@ export interface ShardingProvider {
}
/**
* @class Messenger
* @description Messenger instance
* @param {HttpProvider} provider HttpProvider
* @param {Object} config config object
* @return {Messenger} Messenger instance
* ## How to Create a Massage
* @example
* ```
* 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
* )
* ```
*/
class Messenger extends HarmonyCore {
provider: HttpProvider | WSProvider;
@ -73,13 +87,27 @@ class Messenger extends HarmonyCore {
this.shardProviders = new Map();
// this.setShardingProviders();
}
/**
* @example
* ```
* customMessenger.currentShard
* ```
*/
get currentShard(): number {
return this.getCurrentShardID() || this.defaultShardID || 0;
}
/**
* @example
* ```
* customMessenger.shardCount
* ```
*/
get shardCount(): number {
return this.shardProviders.size;
}
/**
* @function send
* @memberof Messenger.prototype
@ -151,6 +179,7 @@ class Messenger extends HarmonyCore {
* @memberof Messenger
* @param {any} middleware - middle ware for req
* @param {String} method - method name
* @hidden
*/
setReqMiddleware(middleware: any, method = '*', provider: HttpProvider | WSProvider) {
provider.middlewares.request.use(middleware, method);
@ -162,6 +191,7 @@ class Messenger extends HarmonyCore {
* @memberof Messenger
* @param {any} middleware - middle ware for req
* @param {String} method - method name
* @hidden
*/
setResMiddleware(middleware: any, method = '*', provider: HttpProvider | WSProvider) {
provider.middlewares.response.use(middleware, method);
@ -284,6 +314,13 @@ class Messenger extends HarmonyCore {
return;
}
}
/**
* @example
* ```
* hmy.messenger.getShardProvider()
* ```
*/
getShardProvider(shardID: number): HttpProvider | WSProvider {
const provider = this.shardProviders.get(shardID);
if (provider) {
@ -293,6 +330,14 @@ class Messenger extends HarmonyCore {
}
return this.provider;
}
/**
* @example
* ```
* hmy.messenger.getCurrentShardID()
* ```
*/
getCurrentShardID() {
for (const shard of this.shardProviders) {
if (

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { RPCResponseBody } from '../types';
import { isObject } from '@harmony-js/utils';
/**
@ -19,15 +25,11 @@ class ResponseMiddleware {
}
get getResult() {
return isObject(this.result)
? { ...this.result, responseType: 'result' }
: this.result;
return isObject(this.result) ? { ...this.result, responseType: 'result' } : this.result;
}
get getError() {
return isObject(this.error)
? { ...this.error, responseType: 'error' }
: this.error;
return isObject(this.error) ? { ...this.error, responseType: 'error' } : this.error;
}
get getRaw() {
@ -37,10 +39,7 @@ class ResponseMiddleware {
getResponseType(): string {
if (this.error) {
return 'error';
} else if (
this.result ||
(this.result === null && this.result !== undefined)
) {
} else if (this.result || (this.result === null && this.result !== undefined)) {
return 'result';
} else {
return 'raw';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { ReqMiddleware, ResMiddleware, MiddlewareType } from '../types';
import { RPCMethod } from '../rpcMethod/rpc';
@ -28,11 +34,7 @@ class BaseProvider {
this.url = url;
}
protected pushMiddleware(
fn: any,
type: MiddlewareType,
match: string | RPCMethod | RegExp,
) {
protected pushMiddleware(fn: any, type: MiddlewareType, match: string | RPCMethod | RegExp) {
if (type !== MiddlewareType.REQ && type !== MiddlewareType.RES) {
throw new Error('Please specify the type of middleware being added');
}
@ -44,9 +46,7 @@ class BaseProvider {
this.resMiddleware.set(match, [...current, <ResMiddleware>fn]);
}
}
protected getMiddleware(
method: RPCMethod | string,
): [ReqMiddleware[], ResMiddleware[]] {
protected getMiddleware(method: RPCMethod | string): [ReqMiddleware[], ResMiddleware[]] {
const requests: ReqMiddleware[] = [];
const responses: ResMiddleware[] = [];

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { isWs } from '@harmony-js/utils';
import mitt from 'mitt';
import { BaseProvider } from './baseProvider';

@ -1,13 +1,16 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import fetch from 'cross-fetch';
import { RPCRequest, RPCResponseBody, RPCError, RPCResult } from '../types';
export const fetchRPC = {
requestHandler: (request: RPCRequest<any[]>, headers: any) =>
fetch(request.url, {
method:
request.options && request.options.method
? request.options.method
: 'POST',
method: request.options && request.options.method ? request.options.method : 'POST',
cache: 'no-cache',
mode: 'cors',
redirect: 'follow',
@ -15,16 +18,10 @@ export const fetchRPC = {
body: JSON.stringify(request.payload),
headers: {
...headers,
...(request.options && request.options.headers
? request.options.headers
: {}),
...(request.options && request.options.headers ? request.options.headers : {}),
},
}),
responseHandler: (
response: Response,
request: RPCRequest<any>,
handler: any,
) =>
responseHandler: (response: Response, request: RPCRequest<any>, handler: any) =>
response
.json()
.then((body: RPCResponseBody<RPCResult, RPCError>) => {

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import mitt from 'mitt';
class Emitter {

@ -1,9 +1,15 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { BaseProvider } from './baseProvider';
import { fetchRPC } from './defaultFetcher';
import { composeMiddleware, performRPC, DEFAULT_TIMEOUT, DEFAULT_HEADERS } from '../rpcMethod/net';
import { RPCRequestPayload } from '../types';
/** @hidden */
const defaultOptions = {
method: 'POST',
timeout: DEFAULT_TIMEOUT,

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { HttpProvider } from './http';
import { WSProvider } from './ws';
import { defaultConfig, isHttp, isWs } from '@harmony-js/utils';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
// TODO: implement Websocket Provider
import { w3cwebsocket as W3CWebsocket } from 'websocket';
import {

@ -1,5 +1,11 @@
import {RPCRequestPayload} from '../types';
import {RPCMethod} from './rpc';
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { RPCRequestPayload } from '../types';
import { RPCMethod } from './rpc';
/**
* @class JsonRpc
* @description json rpc instance
@ -37,11 +43,7 @@ class JsonRpc {
this.messageId += 1;
const sendParams =
params === undefined
? []
: typeof params === 'string'
? [params]
: [...params];
params === undefined ? [] : typeof params === 'string' ? [params] : [...params];
return {
jsonrpc: '2.0',
@ -52,4 +54,4 @@ class JsonRpc {
};
}
export {JsonRpc};
export { JsonRpc };

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
export const DEFAULT_TIMEOUT: number = 120000;
export const DEFAULT_HEADERS: object = { 'Content-Type': 'application/json' };
@ -21,9 +27,7 @@ export const performRPC = async (request: any, handler: any, fetcher: any) => {
try {
const response = await _fetch(
fetcher.requestHandler(request, DEFAULT_HEADERS),
request.options && request.options.timeout
? request.options.timeout
: DEFAULT_TIMEOUT,
request.options && request.options.timeout ? request.options.timeout : DEFAULT_TIMEOUT,
);
return fetcher.responseHandler(response, request, handler);
} catch (err) {

@ -1,3 +1,28 @@
/**
* ## About this package
*
* `@harmony-js/network` provides functions to handle messenger, providers and subscriptions...
*
* ## How to use this package
*
* ### 1. Create a Message
* ```javascript
* 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
* )
* ```
*
* @packageDocumentation
* @module harmony-network
*/
/**@ignore */
export const enum RPCMethod {
// 1. hmy_getBlockByHash
GetBlockByHash = 'hmy_getBlockByHash',
@ -72,6 +97,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,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { Messenger } from '../messenger/messenger';
import { SubscriptionMethod } from './Subscription';
import { RPCMethod } from '../rpcMethod/rpc';
@ -11,7 +16,8 @@ export class LogSub extends SubscriptionMethod {
async subscribe() {
if (
(this.options.fromBlock && this.options.fromBlock !== 'latest') ||
(this.options.fromBlock === 0 || this.options.fromBlock === '0x')
this.options.fromBlock === 0 ||
this.options.fromBlock === '0x'
) {
try {
const getPastLogs = await this.messenger.send(

@ -1,6 +1,15 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { Messenger } from '../messenger/messenger';
import { SubscriptionMethod } from './Subscription';
/**
* ### Description:
* Subscribes to incoming block headers. This can be used as timer to check for changes on the blockchain.
*/
export class NewHeaders extends SubscriptionMethod {
constructor(messenger: Messenger, shardID: number = 0) {
super('newHeads', undefined, messenger, shardID);

@ -1,6 +1,15 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { Messenger } from '../messenger/messenger';
import { SubscriptionMethod } from './Subscription';
/**
* ### Description:
* Subscribes to incoming pending transactions
*/
export class NewPendingTransactions extends SubscriptionMethod {
constructor(messenger: Messenger, shardID: number = 0) {
super('newPendingTransactions', undefined, messenger, shardID);

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-network
*/
import { Messenger } from '../messenger/messenger';
import { RPCMethod } from '../rpcMethod/rpc';
import { WSProvider } from '../providers/ws';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { Messenger } from '../messenger/messenger';
import { SubscriptionMethod } from './Subscription';

@ -1,10 +1,15 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { isHex, hexToNumber } from '@harmony-js/utils';
import { Emitter } from '../providers/emitter';
const sec = 1000;
const calculateSum = (accumulator: number, currentValue: number) =>
accumulator + currentValue;
const calculateSum = (accumulator: number, currentValue: number) => accumulator + currentValue;
const blockTrackerEvents = ['sync', 'latest'];
export class BaseBlockTracker extends Emitter {
@ -55,9 +60,7 @@ export class BaseBlockTracker extends Emitter {
return this._currentBlock;
}
// wait for a new latest block
const latestBlock = await new Promise((resolve) =>
this.once('latest', resolve),
);
const latestBlock = await new Promise((resolve) => this.once('latest', resolve));
// return newly set current block
return latestBlock;
}
@ -169,10 +172,7 @@ export class BaseBlockTracker extends Emitter {
// clear any existing timeout
this._cancelBlockResetTimeout();
// clear latest block when stale
this._blockResetTimeout = setTimeout(
this._resetCurrentBlock,
this._blockResetDuration,
);
this._blockResetTimeout = setTimeout(this._resetCurrentBlock, this._blockResetDuration);
// nodejs - dont hold process open
if (this._blockResetTimeout.unref) {
this._blockResetTimeout.unref();

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { BaseBlockTracker } from './baseTracker';
import { Messenger } from '../messenger/messenger';
import { RPCMethod } from '../rpcMethod/rpc';
@ -83,9 +89,7 @@ export class PollingBlockTracker extends BaseBlockTracker {
await timeout(this._pollingInterval, !this._keepEventLoopActive);
} catch (err) {
const newErr = new Error(
`PollingBlockTracker - encountered an error while attempting to update latest block:\n${
err.stack
}`,
`PollingBlockTracker - encountered an error while attempting to update latest block:\n${err.stack}`,
);
try {
this.emit('error', newErr);

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { Messenger } from '../messenger/messenger';
import { WSProvider } from '../providers/ws';
import { BaseBlockTracker } from './baseTracker';
@ -35,9 +41,7 @@ export class SubscribeBlockTracker extends BaseBlockTracker {
if (blockNumber.isError()) {
throw blockNumber.message;
} else if (blockNumber.isResult()) {
const subs = await this.messenger.subscribe(RPCMethod.Subscribe, [
'newHeads',
]);
const subs = await this.messenger.subscribe(RPCMethod.Subscribe, ['newHeads']);
this.subscriptionId = subs;
subs[0].onData(this._handleSubData);

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @ignore
*/
import { RPCMethod, RPCErrorCode } from './rpcMethod/rpc';
export type ReqMiddleware = Map<string | RPCMethod | RegExp, any[]>;

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-network
* @hidden
*/
import { ResponseMiddleware } from './messenger/responseMiddleware';
/**

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-staking
*/
import { Messenger } from '@harmony-js/network';
import { Signature } from '@harmony-js/crypto';
@ -16,6 +21,7 @@ import {
import { Unit } from '@harmony-js/utils';
import { TxStatus } from '@harmony-js/transaction';
/** @hidden */
export interface DescriptionInterface {
name: string;
identity: string;
@ -24,6 +30,7 @@ export interface DescriptionInterface {
details: string;
}
/** @hidden */
export interface CommissionRateInterface {
rate: string;
maxRate: string;

@ -1,2 +1,8 @@
/**
* @packageDocumentation
* @module harmony-staking
* @ignore
*/
export * from './stakingTransaction';
export * from './factory';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-staking
*/
// tslint:disable: max-classes-per-file
import {
@ -16,11 +21,13 @@ import { defaultMessenger, TransactionBase, TxStatus } from '@harmony-js/transac
import { numberToHex, Unit } from '@harmony-js/utils';
import { TextEncoder } from 'text-encoding';
/** @hidden */
export class StakingSettings {
public static PRECISION = 18;
public static MAX_DECIMAL = 1000000000000000000;
}
/** @hidden */
export const enum Directive {
DirectiveCreateValidator,
DirectiveEditValidator,
@ -201,6 +208,7 @@ export class StakingTransaction extends TransactionBase {
}
}
/** @hidden */
export class Description {
name: string;
identity: string;
@ -234,6 +242,7 @@ export class Description {
}
}
/** @hidden */
export class Decimal {
value: BN;
@ -292,6 +301,7 @@ export class Decimal {
}
}
/** @hidden */
export class CommissionRate {
rate: Decimal;
maxRate: Decimal;

@ -1,4 +1,9 @@
// tslint:disable-next-line: no-implicit-dependencies
/**
* @packageDocumentation
* @module harmony-staking
* @ignore
*/
import { Wallet } from '@harmony-js/account';
import { getAddressFromPrivateKey } from '@harmony-js/crypto';
import { HttpProvider, Messenger } from '@harmony-js/network';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { Messenger } from '@harmony-js/network';
import { TxStatus } from './types';

@ -1,3 +1,10 @@
/**
* ## hhahaha
*
* @packageDocumentation
* @module harmony-transaction
*/
import { getContractAddress, getAddress } from '@harmony-js/crypto';
import { Messenger } from '@harmony-js/network';
import { Transaction } from './transaction';
@ -20,6 +27,30 @@ export class TransactionFactory {
this.messenger = messenger;
}
/**
* Create a new Transaction
* @params
* ```
* // to: Address of the receiver
* // value: value transferred in wei
* // gasLimit: the maximum gas would pay, can use string
* // shardID: send token from shardID
* // toShardId: send token to shardID
* // gasPrice: you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
* ```
*
* @example
* ```javascript
* const txn = hmy.transactions.newTx({
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* value: '10000',
* gasLimit: '210000',
* shardID: 0,
* toShardID: 0,
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
* ```
*/
newTx(txParams?: TxParams | any, sharding: boolean = false): Transaction {
if (!sharding) {
return new Transaction(txParams, this.messenger, TxStatus.INTIALIZED);
@ -27,10 +58,31 @@ export class TransactionFactory {
return new ShardingTransaction(txParams, this.messenger, TxStatus.INTIALIZED);
}
/**
* clone the transaction
*
* @param transaction
*
* @example
* ```javascript
* const cloneTxn = hmy.transactions.clone(txn);
* console.log(cloneTxn)
* ```
*/
clone(transaction: Transaction): Transaction {
return new Transaction(transaction.txParams, this.messenger, TxStatus.INTIALIZED);
}
/**
*
* @example
* ```javascript
* txHash = '0xf8698085174876e8008252088080949d72989b68777a1f3ffd6f1db079f1928373ee52830186a08027a0ab8229ff5d5240948098f26372eaed9ab2e9be23e8594b08e358ca56a47f8ae9a0084e5c4d1fec496af444423d8a714f65c079260ff01a1be1de7005dd424adf44'
*
* const recoverTx = hmy.transactions.recover(txHash);
* console.log(recoverTx);
* ```
*/
recover(txHash: string): Transaction {
const newTxn = new Transaction({}, this.messenger, TxStatus.INTIALIZED);
newTxn.recover(txHash);

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
export * from './factory';
export * from './transaction';
export * from './shardingTransaction';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { Messenger } from '@harmony-js/network';
import { AddressSuffix } from '@harmony-js/utils';
import { Transaction } from './transaction';

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-transaction
*/
import {
BN,
encode,
@ -21,21 +26,53 @@ import {
import { TransactionBase } from './transactionBase';
class Transaction extends TransactionBase {
/** @hidden */
private from: string;
/** @hidden */
private nonce: number | string;
/** @hidden */
private to: string;
// private shardID: number | string;
/** @hidden */
private toShardID: number | string;
/** @hidden */
private gasLimit: BN;
/** @hidden */
private gasPrice: BN;
/** @hidden */
private data: string;
/** @hidden */
private value: BN;
/** @hidden */
private chainId: number;
/** @hidden */
private rawTransaction: string;
/** @hidden */
private unsignedRawTransaction: string;
/** @hidden */
private signature: Signature;
// constructor
/**
*
* @Params
* ```javascript
* id: string;
from: string;
to: string;
nonce: number | string;
gasLimit: number | string | BN;
gasPrice: number | string | BN;
shardID: number | string;
toShardID: number | string;
data: string;
value: number | string | BN;
chainId: number;
rawTransaction: string;
unsignedRawTransaction: string;
signature: Signature;
receipt?: TransasctionReceipt;
* ```
*/
constructor(
params?: TxParams | any,
messenger: Messenger = defaultMessenger,
@ -82,6 +119,14 @@ class Transaction extends TransactionBase {
this.cxStatus = this.isCrossShard() ? TxStatus.INTIALIZED : TxStatus.NONE;
}
/**
*
* @example
* ```javascript
* const unsigned = txn.getRLPUnsigned(txn);
* console.log(unsigned);
* ```
*/
getRLPUnsigned(): [string, any[]] {
const raw: Array<string | Uint8Array> = [];
@ -138,10 +183,17 @@ class Transaction extends TransactionBase {
return encode(raw);
}
/**
* @example
* ```javascript
* console.log(txn.getRawTransaction());
* ```
*/
getRawTransaction(): string {
return this.rawTransaction;
}
/** @hidden */
recover(rawTransaction: string): Transaction {
// temp setting to be compatible with eth
const recovered =
@ -152,7 +204,16 @@ class Transaction extends TransactionBase {
this.setParams(recovered);
return this;
}
// use when using eth_sendTransaction
/**
* get the payload of transaction
*
* @example
* ```
* const payload = txn.txPayload;
* console.log(payload);
* ```
*/
get txPayload() {
return {
from: this.txParams.from || '0x',
@ -167,6 +228,15 @@ class Transaction extends TransactionBase {
};
}
/**
* get transaction params
*
* @example
* ```
* const txParams = txn.txParams;
* console.log(txParams)
* ```
*/
get txParams(): TxParams {
return {
id: this.id || '0x',
@ -185,6 +255,28 @@ class Transaction extends TransactionBase {
signature: this.signature || '0x',
};
}
/**
* set the params to the txn
*
* @example
* ```
* txn.setParams({
* to: 'one1ew56rqrucu6p6n598fmjmnfh8dd4xpg6atne9c',
* value: '1200',
* gasLimit: '230000',
* shardID: 1,
* toShardID: 0,
* gasPrice: new hmy.utils.Unit('101').asGwei().toWei(),
* signature: {
* r: '0xd693b532a80fed6392b428604171fb32fdbf953728a3a7ecc7d4062b1652c042',
* s: '0x24e9c602ac800b983b035700a14b23f78a253ab762deab5dc27e3555a750b354',
* v: 0
* },
* });
* console.log(txn);
* ```
*/
setParams(params: TxParams) {
this.id = params && params.id ? params.id : '0x';
this.from = params && params.from ? params.from : '0x';
@ -225,6 +317,7 @@ class Transaction extends TransactionBase {
}
}
/** @hidden */
map(fn: any) {
const newParams = fn(this.txParams);
this.setParams(newParams);
@ -232,10 +325,28 @@ class Transaction extends TransactionBase {
return this;
}
/**
* Check whether the transaction is cross shard
*
* @example
* ```javascript
* console.log(txn.isCrossShard());
* ```
*/
isCrossShard(): boolean {
return new BN(this.txParams.shardID).toString() !== new BN(this.txParams.toShardID).toString();
}
/**
*
* @example
* ```
* txn.sendTransaction().then((value) => {
* console.log(value);
* });
* ```
*/
async sendTransaction(): Promise<[Transaction, string]> {
if (this.rawTransaction === 'tx' || this.rawTransaction === undefined) {
throw new Error('Transaction not signed');

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { BN, getAddress, HarmonyAddress } from '@harmony-js/crypto';
import { hexToNumber } from '@harmony-js/utils';
import { Messenger, RPCMethod, Emitter, HttpProvider, NewHeaders } from '@harmony-js/network';

@ -1,4 +1,91 @@
/**
* ## About this package
*
* `@harmony-js/transaction` provides the functions to build transactions
*
* Develop can use this package to:
* - build a transaction offline!
* - set params of transaction
* -
*
* ## How to use this package
* ### Step 1: create a Harmony Instance
* ```javascript
* const { Harmony } = require('@harmony-js/core');
* const { ChainID, ChainType } = require('@harmony-js/utils');
* const { BN } = require('@harmony-js/crypto');
*
* const hmy = new Harmony(
* 'http://localhost:9500',
* {
* chainType: ChainType.Harmony,
* chainId: ChainID.HmyLocal,
* },
* );
* ```
*
* ### Step 2: build a transaction
* ```javascript
* const txn = hmy.transactions.newTx({
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* value: '10000',
* gasLimit: '210000',
* shardID: 0,
* toShardID: 0,
* gasPrice: new hmy.utils.Unit('100').asGwei().toWei(),
* });
* ```
*
* ## some important information
* Transaction Parameters
* ```java
* // interface TxParams
* id: string;
* from: string;
* to: string;
* nonce: number | string;
* gasLimit: number | string | BN;
* gasPrice: number | string | BN;
* shardID: number | string;
* toShardID: number | string;
* data: string;
* value: number | string | BN;
* chainId: number;
* rawTransaction: string;
* unsignedRawTransaction: string;
* signature: Signature;
* receipt?: TransasctionReceipt;
* ```
*
* Transaction Receipt
* ```java
* // interface TransasctionReceipt
* transactionHash: string;
* transactionIndex: string;
* blockHash: string;
* blockNumber: string; // 11
* from: string;
* to: string;
* gasUsed: string;
* cumulativeGasUsed: string; // 13244
* contractAddress?: string | null; // or null, if none was created
* logs: any[];
* logsBloom: string; // 256 byte bloom filter
* v: string;
* r: string;
* s: string;
* responseType?: string;
* byzantium?: boolean;
* status?: string; // post Byzantium will return `0x0` or `0x1`
* root?: string; // pre Byzantium will return `root`
* ```
*
* @packageDocumentation
* @module harmony-transaction
*/
import { BN, Signature } from '@harmony-js/crypto';
export interface TxParams {
id: string;
from: string;

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @hidden
*/
import { hexToNumber, isHex, isAddress, strip0x, ChainType } from '@harmony-js/utils';
import {
decode,

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @ignore
*/
import { TransactionFactory, Transaction, TxStatus } from '../src';
// tslint:disable-next-line: no-implicit-dependencies
import { Wallet } from '@harmony-js/account';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-transaction
* @ignore
*/
import { Transaction } from '../src/transaction';
import { RLPSign } from '../src/utils';
import { TxStatus } from '../src/types';

@ -1,3 +1,129 @@
/**
* ## About this package
*
* `@harmony-js/util` provides utility functions for Harmony dapps and other `harmony-js` packages
*
* Develop can use this package to:
* - Transform the unit of token (fromWei, toWei...)
* - Convert variable to different type (hexToBN, numberToHex...)
* - Check validators information (isAddress, isPublicKey, isBlockNumber...)
*
* ## How to use this package
*
* ### Step 1: create a Harmony Instance
* ```javascript
* const { Harmony } = require('@harmony-js/core');
* const { ChainID, ChainType } = require('@harmony-js/utils');
* const { BN } = require('@harmony-js/crypto');
*
* const hmy = new Harmony(
* 'http://localhost:9500',
* {
* chainType: ChainType.Harmony,
* chainId: ChainID.HmyLocal,
* },
* );
* ```
*
* ### Step 2: Select and call functions
* Here are some examples:
*
* ```javascript
* // numberToString
* const num = 123;
* const str = hmy.utils.numberToString(num)
* console.log(str);
*
* // add0xToString
* const str = '12345';
* const expected = hmy.utils.add0xToString(str)
* console.log(expected);
*
* // fromWei
* const Wei = new BN('1000000000000000000');
* const expected = hmy.utils.fromWei(Wei, hmy.utils.Units.one);
* console.log(expected);
*
* // toWei
* const one = new BN('1');
* const expected = hmy.utils.toWei(one, hmy.utils.Units.one);
* const num = hmy.utils.numToStr(expected);
* console.log(num);
* ```
*
* ### Step 3: Using unit class to convet the token unit
* ```javascript
* // convert one to Gwei
* const one = new hmy.utils.Unit('1').asOne();
* const oneToGwei = one.toGwei();
* console.log(oneToGwei);
* ```
*
* ## Some Important consts and Enums
* ### Chain Type
* ```javascript
* Harmony = 'hmy',
* Ethereum = 'eth',
* ```
*
* ### Chain ID
* ```javascript
* Default = 0,
EthMainnet = 1,
Morden = 2,
Ropsten = 3,
Rinkeby = 4,
RootstockMainnet = 30,
RootstockTestnet = 31,
Kovan = 42,
EtcMainnet = 61,
EtcTestnet = 62,
Geth = 1337,
Ganache = 0,
HmyMainnet = 1,
HmyTestnet = 2,
HmyLocal = 2,
HmyPangaea = 3,
* ```
*
* ### Default Config
* ```javascript
* export const defaultConfig = {
* Default: {
* Chain_ID: ChainID.HmyLocal,
* Chain_Type: ChainType.Harmony,
* Chain_URL: 'http://localhost:9500',
* Network_ID: 'Local',
* },
* DefaultWS: {
* Chain_ID: ChainID.HmyLocal,
* Chain_Type: ChainType.Harmony,
* Chain_URL: 'ws://localhost:9800',
* Network_ID: 'LocalWS',
* },
* };
* ```
*
* ### Unit Map
* ```
* [Units.wei, '1'], // 1 wei
* [Units.Kwei, '1000'], // 1e3 wei
* [Units.Mwei, '1000000'], // 1e6 wei
* [Units.Gwei, '1000000000'], // 1e9 wei
* [Units.szabo, '1000000000000'], // 1e12 wei
* [Units.finney, '1000000000000000'], // 1e15 wei
* [Units.ether, '1000000000000000000'], // 1e18 wei
* [Units.one, '1000000000000000000'], // 1e18 wei
* [Units.Kether, '1000000000000000000000'], // 1e21 wei
* [Units.Mether, '1000000000000000000000000'], // 1e24 wei
* [Units.Gether, '1000000000000000000000000000'], // 1e27 wei
* [Units.Tether, '1000000000000000000000000000000'], // 1e30 wei
* ```
*
* @packageDocumentation
* @module harmony-utils
*/
export const enum ChainType {
Harmony = 'hmy',
Ethereum = 'eth',
@ -22,6 +148,7 @@ export const enum ChainID {
HmyPangaea = 3,
}
/** @hidden */
export const defaultConfig = {
Default: {
Chain_ID: ChainID.HmyLocal,
@ -37,6 +164,7 @@ export const defaultConfig = {
},
};
/** @hidden */
export abstract class HarmonyCore {
chainType: ChainType;
chainId: ChainID;
@ -68,6 +196,8 @@ export abstract class HarmonyCore {
}
}
/** @hidden */
export const HDPath = `m/44'/1023'/0'/0/`;
/** @hidden */
export const AddressSuffix = '-';

@ -0,0 +1,4 @@
/**
* @packageDocumentation
* @ignore
*/

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-utils
* @ignore
*/
export * from './validators';
export * from './transformers';
export * from './utils';

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module harmony-utils
* @hidden
*/
export function defineReadOnly(object: any, name: string, value: any): void {
Object.defineProperty(object, name, {
enumerable: true,

@ -1,3 +1,8 @@
/**
* @packageDocumentation
* @module harmony-utils
*/
import BN from 'bn.js';
import { isString, isNumber, isHex } from './validators';
@ -16,6 +21,7 @@ export const enum Units {
Tether = 'Tether',
}
/** @hidden */
export const unitMap = new Map([
[Units.wei, '1'],
[Units.Kwei, '1000'], // 1e3 wei
@ -31,10 +37,14 @@ export const unitMap = new Map([
[Units.Tether, '1000000000000000000000000000000'], // 1e30 wei
]);
/** @hidden */
const DEFAULT_OPTIONS = {
pad: false,
};
/**
* Convert Number to String
*/
export const numberToString = (obj: BN | number | string, radix: number = 10): string => {
if (BN.isBN(obj)) {
return obj.toString(radix);
@ -47,6 +57,9 @@ export const numberToString = (obj: BN | number | string, radix: number = 10): s
}
};
/**
* Convert Number to String
*/
export const numToStr = (input: any) => {
if (typeof input === 'string') {
if (!input.match(/^-?[0-9.]+$/)) {
@ -80,6 +93,9 @@ export const strip0x = (obj: string): string => {
return obj.toLowerCase().replace('0x', '');
};
/**
* Convert number to hex
*/
export const numberToHex = (obj: any): string => {
try {
return add0xToString(numberToString(obj, 16));
@ -88,6 +104,9 @@ export const numberToHex = (obj: any): string => {
}
};
/**
* Convert hex to Decimal number
*/
export const hexToNumber = (hex: string): string => {
if (isHex(hex) && hex[0] !== '-') {
return new BN(strip0x(hex), 'hex').toString();
@ -99,6 +118,9 @@ export const hexToNumber = (hex: string): string => {
}
};
/**
* Convert hex to Big Number
*/
export const hexToBN = (hex: string): BN => {
if (isHex(hex) && hex[0] !== '-') {
return new BN(strip0x(hex), 'hex');
@ -110,6 +132,9 @@ export const hexToBN = (hex: string): BN => {
}
};
/**
* Converts any ONE value into wei
*/
export const toWei = (input: BN | string, unit: Units): BN => {
try {
let inputStr = numToStr(input);
@ -168,6 +193,9 @@ export const toWei = (input: BN | string, unit: Units): BN => {
}
};
/**
* Converts any wei value into a ONE value.
*/
export const fromWei = (wei: BN | string, unit: Units, options: any = DEFAULT_OPTIONS): string => {
try {
const weiBN: BN = !BN.isBN(wei) ? new BN(wei) : wei;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save