Compare commits

...

143 Commits

Author SHA1 Message Date
nico 18da2be63d woop 8 months ago
Ganesha Upadhyaya d580e4a659
Delete .env 2 years ago
Ganesha Upadhyaya 5eddd0feb2 v0.1.58 2 years ago
Artem 71304c22ad
Replace scrypt-shim with scrypt.js; add test (#128) 2 years ago
Ganesha Upadhyaya 3c7061887f
Merge pull request #79 from harmony-one/dependabot/npm_and_yarn/y18n-3.2.2 4 years ago
Ganesha Upadhyaya e3d04c6383
Merge pull request #81 from vinyl704/patch-1 4 years ago
Ganesha Upadhyaya 0c7337918d
Merge pull request #82 from isaacadams/feature/add-get-blocks-rpc 4 years ago
Ganesha Upadhyaya e364c4ffea
Merge pull request #84 from polymorpher/fix-hd-node 4 years ago
Aaron Li baaa09e41f better hdnode constructor 4 years ago
Aaron Li f29f2586dd optionally generateMnemonic during HDNode creation; Fix a bug with setSigner 4 years ago
Isaac Adams 87d5f999ab from and to should be validated as block numbers 4 years ago
Isaac Adams 42d6400ee1 blockargs can be optional 4 years ago
Isaac Adams 75a7118e1b adding get blocks method based on API docs 4 years ago
vinyl704 9d13ab257c
fixed typo on line 121 4 years ago
dependabot[bot] 21be4e3fe3
Bump y18n from 3.2.1 to 3.2.2 4 years ago
Ganesha Upadhyaya 99a827782f v0.1.57 4 years ago
Ganesha Upadhyaya 2acbadf97a
Merge pull request #70 from SebastianJ/fix-nonce-hex-bug 4 years ago
Sebastian Johnsson 99bd7ad3d5 Fix OneWallet compatibility for nonces returned as numbers instead of hex 4 years ago
Ganesha Upadhyaya a60117ceac
Merge pull request #68 from harmony-one/dependabot/npm_and_yarn/ini-1.3.8 4 years ago
Ganesha Upadhyaya 4099a321f3
Update README.md 4 years ago
dependabot[bot] 6ab7227ef3
Bump ini from 1.3.5 to 1.3.8 4 years ago
Ganesha Upadhyaya 8f8e17fdae v0.1.56 4 years ago
Ganesha Upadhyaya 2762c8edbf audit fixes 4 years ago
Ganesha Upadhyaya 2a3ad781b6 add missing link 4 years ago
Ganesha Upadhyaya aea4ca0cc7 minor updates 4 years ago
Ganesha Upadhyaya 13c0830916 adding more examples and links 4 years ago
Ganesha Upadhyaya a7979a569f adding more examples 4 years ago
Ganesha Upadhyaya 1b6e351aa8 add token faucet app demo 4 years ago
PeekPI 6e2c1e7653
fixes issue: https://github.com/harmony-one/harmony/issues/3450 (#66) 4 years ago
peekpi d5feeb8d78 fixed testcase error 4 years ago
peekpi 4261bc15bb Merge remote-tracking branch 'origin/master' 4 years ago
peekpi 9aefc978f6 fixes issue: https://github.com/harmony-one/harmony/issues/3450 4 years ago
peekpi 95453ee2e7 handle integer result returned by 'hmy_getAccountNonce' 4 years ago
Ganesha Upadhyaya caa57d360d update latest docs url 4 years ago
Ganesha Upadhyaya bc2d3a6e8d remove .env and .env.sample 4 years ago
Ganesha Upadhyaya 73b97c7d07 removing examples, all of them are available inside package-level documentation 4 years ago
Ganesha Upadhyaya cc4872a9f9 update sdk api reference 4 years ago
Ganesha Upadhyaya c6fbf597a5
Merge pull request #61 from harmony-one/dependabot/npm_and_yarn/packages/harmony-contract/node-fetch-2.6.1 4 years ago
Ganesha Upadhyaya 995f6b8f40
Merge pull request #62 from harmony-one/dependabot/npm_and_yarn/packages/harmony-account/node-fetch-2.6.1 4 years ago
Ganesha Upadhyaya 6bcac8640e
Merge pull request #63 from harmony-one/dependabot/npm_and_yarn/packages/harmony-core/node-fetch-2.6.1 4 years ago
PeekPI cdf471b830
accept hex string as input of type 'uin256' (#64) 4 years ago
lixp f0e8056f84 accept hex string as input of type 'uin256' 4 years ago
lixp 1b977860ad Merge remote-tracking branch 'origin/master' 4 years ago
PeekPI 93393dc36c
use 'hmy_getAccountNonce' to update Nonce (#60) 4 years ago
Ganesha Upadhyaya aaf148c1af
Merge pull request #49 from harmony-one/dependabot/npm_and_yarn/packages/harmony-crypto/elliptic-6.5.3 4 years ago
dependabot[bot] f125047487
Bump node-fetch from 2.6.0 to 2.6.1 in /packages/harmony-contract 4 years ago
dependabot[bot] e4f72e293e
Bump node-fetch from 2.6.0 to 2.6.1 in /packages/harmony-account 4 years ago
dependabot[bot] 1c47f9c713
Bump node-fetch from 2.6.0 to 2.6.1 in /packages/harmony-core 4 years ago
Ganesha Upadhyaya 85e0e76dc0
Merge pull request #50 from harmony-one/dependabot/npm_and_yarn/elliptic-6.5.3 4 years ago
Ganesha Upadhyaya 7a8c0f9699
Merge pull request #53 from harmony-one/dependabot/npm_and_yarn/examples/elliptic-6.5.3 4 years ago
Ganesha Upadhyaya cda12363c9
Merge pull request #54 from harmony-one/dependabot/npm_and_yarn/packages/harmony-transaction/node-fetch-2.6.1 4 years ago
Ganesha Upadhyaya fb2fe2925b
Merge pull request #55 from harmony-one/dependabot/npm_and_yarn/packages/harmony-staking/node-fetch-2.6.1 4 years ago
lixp a7e248a433 Merge remote-tracking branch 'origin/master' 4 years ago
PeekPI 08d8f5aaf4
fixes #30 (#59) 4 years ago
lixp fd2481aa35 1. fixes #30 4 years ago
lixp cf6fd13b86 Merge remote-tracking branch 'origin/master' 4 years ago
PeekPI 794a590238
support 'fallback' and 'receive' of solidity (#51) 4 years ago
PeekPI cc4df6b24e
Merge branch 'master' into master 4 years ago
dependabot[bot] 43eb47107a
Bump elliptic from 6.5.2 to 6.5.3 4 years ago
dependabot[bot] 2a118ebb7f
Bump node-fetch from 2.6.0 to 2.6.1 in /packages/harmony-staking 4 years ago
dependabot[bot] c8e1e7503c
Bump elliptic from 6.5.2 to 6.5.3 in /packages/harmony-crypto 4 years ago
dependabot[bot] a81045946a
Bump node-fetch from 2.6.0 to 2.6.1 in /packages/harmony-transaction 4 years ago
dependabot[bot] 26e38e9e35
Bump elliptic from 6.5.2 to 6.5.3 in /examples 4 years ago
Ganesha Upadhyaya c49abc5691 v0.1.55 4 years ago
Ganesha Upadhyaya ca83e5477c
Merge pull request #52 from SebastianJ/expose-raw-abi 4 years ago
Sebastian Johnsson 14fb03f3f2 Expose the raw abi 4 years ago
lixp 40e0db00c5 Merge remote-tracking branch 'origin/master' 4 years ago
lixp 4e111973b9 support 'fallback' and 'receive' of solidity 4 years ago
Dennis Won 463cfdfb68 udpate package lock json files by running npm install 4 years ago
Dennis Won 4033b3f971 v0.1.54 4 years ago
Dennis Won 018c2626fe package-lock.json should not be ignored by gitignore 4 years ago
Dennis Won b63aae6bfb revert manual package.json versions bump 4 years ago
Ganesha Upadhyaya aa1b811830 Merge pull request #45 from peekpi/master 4 years ago
Jong Hyuck Won 2a1bcbbbbb
Merge pull request #48 from harmony-one/enum 4 years ago
Dennis Won e571c4bedc change const enums exports to enum 4 years ago
Jong Hyuck Won d34f347e9e
Merge pull request #47 from harmony-one/e2e 4 years ago
Dennis Won b6a9e4cc85 fix broken e2e test 4 years ago
lixp 6a0163eef4 Merge branch 'master' into methodcall 4 years ago
Ganesha Upadhyaya 7dd958349b
Merge pull request #42 from HiroKryptor/master 4 years ago
lixp 9aa0985993 if outputs of a contract method is empty, don't treat the etmpty return data as revert 4 years ago
lixp 7d5e968ce1 handle the revert message 4 years ago
Ganesha Upadhyaya 17bcd47f37 v0.1.53 4 years ago
Ganesha Upadhyaya 8bced38228 Revert "Merge pull request #43 from jelly-swap/fix-event-decoding" 4 years ago
Hiro 084bcbb5db
Add check id is hash in case RPCMethod return error 4 years ago
Ganesha Upadhyaya 8136549b75 v0.1.52 4 years ago
Ganesha Upadhyaya 15c4b11502
Merge pull request #43 from jelly-swap/fix-event-decoding 4 years ago
kraikov 059e067b23 Start the topic count from 1. 4 years ago
Hirokryptor 3bfe0deb4e Fix Uncaught (in promise) User rejected sign transaction request 4 years ago
lixp 0bf2f24333 1. accept ONE format address as contract method parameter 4 years ago
Ganesha Upadhyaya 3f6005764d v0.1.51 4 years ago
Ganesha Upadhyaya cb45ce9744 fixing the GC overflow issue 4 years ago
Ganesha Upadhyaya 76661bf654 v0.1.50 4 years ago
Ganesha Upadhyaya 802beb1898 fixing event subscription 4 years ago
Ganesha Upadhyaya e26885932f
Merge pull request #35 from jelly-swap/resolve-tx-without-confirmation 4 years ago
kraikov 6043cafe3e The default value of waitConfirm set to true. 4 years ago
kraikov b17cedfa1a Optionally resolve send transaction's promise before confirmation. 4 years ago
Ganesha Upadhyaya 1878e7a2c9 v0.1.49 4 years ago
Ganesha Upadhyaya 0575f19c15 fixing truffle provider bug due to changed rpc response that includes miner one address 4 years ago
Ganesha Upadhyaya 03206de34d cleanup 4 years ago
Ganesha Upadhyaya 4ebe736137 v0.1.48 4 years ago
raptor1001 2d6d151f36
Merge pull request #34 from harmony-one/add_onewallet_extension 4 years ago
Raptor 1aa1736a2b Add logout function 4 years ago
Ganesha Upadhyaya 074a3db5d9
Update README.md 4 years ago
Ganesha Upadhyaya 736625c177
Merge pull request #27 from harmony-one/truffle_provider 4 years ago
Ganesha Upadhyaya ebb16df6cb
Update README.md 4 years ago
Ganesha Upadhyaya 7bdf2c0dca Improve README with clear examples throughout packages 4 years ago
Ganesha Upadhyaya 24876f57a5 v0.1.47 4 years ago
coolcottontail bf83596c22
Merge pull request #33 from harmony-one/add_onewallet_extension 4 years ago
Raptor c7fd30ec3f Integrated the onewallet extension 4 years ago
neeboo bbcb1af037 fix(truffle_provider):remove prefix conditionly 5 years ago
Ganesha Upadhyaya f90792fd91 v0.1.46 5 years ago
PeekPI ab95524bd0
Contract (#25) 5 years ago
Ganesha Upadhyaya a35db780ae v0.1.45 5 years ago
Ganesha Upadhyaya 56606e9365 v0.1.44 5 years ago
neeboo 4dff73db61 WIP(truffle_provider):add web3_clientVersion as mock result 5 years ago
Ganesha Upadhyaya 87c8df983a
Merge pull request #14 from harmony-one/mattlockyer-patch-1 5 years ago
Jong Hyuck Won 0e1a4ba6e5
Merge pull request #22 from harmony-one/return-interface 5 years ago
Ganesha Upadhyaya a5b0bf7d0f minor 5 years ago
Ganesha Upadhyaya f0c1c5ed9b add return object interface test 5 years ago
Ganesha Upadhyaya f4f645b639 [harmony-account] make getBalance return Balance interface instead of object 5 years ago
Leo Chen ce39d112f3
Merge pull request #21 from harmony-one/doc 5 years ago
Wen Zhang 4217f89fdf update readme 5 years ago
Wen Zhang 70311ff629 update the readme of generating doc 5 years ago
Wen Zhang 7ed3b6d8b7 add documentation to @harmony-js/contract 5 years ago
Wen Zhang 3411de5cf8 revamped crypto, network, transaction 5 years ago
Wen Zhang 95474d74fe finish package '@harmony-js/utils' 5 years ago
Wen Zhang 61a8b8e7c0 Cleaned up the redundant content of the remaining 6 packages 5 years ago
Wen Zhang 40fc994fae revamped account/account and account/wallet 5 years ago
Wen Zhang 1d37b68d79 Finished revamped the package: harmony-core 5 years ago
Wen Zhang 2d637dede9 hierarchy rebuild and APIs revamped 5 years ago
Wen Zhang fddea85f1f revamped functions in harmony-core/src/blockchain.ts 5 years ago
Wen Zhang 47672bcd68 create first comment example: blockchain.getBalance 5 years ago
Wen Zhang a9e825f0e3 beautify index page and simplify the navigation bar, add annotation to each page for next comments work 5 years ago
Wen Zhang ff6c207e9e fixed some description error 5 years ago
Wen Zhang bb9a818295 Finished draft sdk documentation! update README 5 years ago
Dennis Won bdcfbf0f80 v0.1.43 5 years ago
Dennis Won 3c7e080a7d dependency lib updates for harmony account package 5 years ago
Dennis Won 6547152ba6 update dependencies versions with new packages releases 5 years ago
Dennis Won 2d2effaade v0.1.40 5 years ago
Dennis Won 9879a43b16 re-add files to git for gitignore 5 years ago
Jong Hyuck Won 51d46f22a0
Merge pull request #19 from harmony-one/crypto_fix 5 years ago
Matt Lockyer c5b154ed2b
Better fix for this 5 years ago
Matt Lockyer 6d85dbf4ef
Fixes error when logs returns undefined 5 years ago
  1. 5
      .env.example
  2. 9
      .gitignore
  3. 2
      .travis.yml
  4. 275
      README.md
  5. 70
      RELEASE.md
  6. 100
      TYPEDOC.md
  7. 0
      docs/README.md
  8. 24
      e2e/fixtures/transactions.json
  9. 161
      e2e/src/blockchain.e2e.ts
  10. 29
      e2e/src/harmony.ts
  11. 147
      e2e/src/transaction.e2e.ts
  12. 282
      e2e/src/txn_rpc.e2e.ts
  13. 39
      e2e/src/woop.ts
  14. 16
      e2e/tsconfig.json
  15. 31
      examples/balance.js
  16. 45
      examples/import_keystore.js
  17. 14
      examples/package.json
  18. 79
      examples/staking_create.js
  19. 172
      examples/staking_delegate.js
  20. 74
      examples/staking_test.js
  21. 177
      examples/staking_transfer.js
  22. 173
      examples/staking_undelegate.js
  23. 31
      examples/test.js
  24. 40
      examples/test2.js
  25. 153
      examples/transfer.js
  26. 151
      examples/transfer_dev.js
  27. 137
      examples/transfer_local.js
  28. 16
      gulpfile.js
  29. 2
      lerna.json
  30. 1081
      log.txt
  31. 44661
      package-lock.json
  32. 24
      package.json
  33. 12
      packages/README.md
  34. 259
      packages/harmony-account/README.md
  35. 8
      packages/harmony-account/src/utils.ts
  36. 15
      packages/harmony-account/tsconfig.json
  37. 0
      packages/harmony-contract/README.md
  38. 10
      packages/harmony-contract/src/index.ts
  39. 20683
      packages/harmony-contract/test/fixtures/abiv2.ts
  40. 0
      packages/harmony-core/README.md
  41. 30
      packages/harmony-core/package.json
  42. 526
      packages/harmony-core/src/blockchain.ts
  43. 103
      packages/harmony-core/src/harmony.ts
  44. 5
      packages/harmony-core/src/index.ts
  45. 25
      packages/harmony-core/src/types.ts
  46. 16
      packages/harmony-core/tsconfig.json
  47. 0
      packages/harmony-crypto/README.md
  48. 80
      packages/harmony-crypto/src/address.ts
  49. 0
      packages/harmony-network/README.md
  50. 100
      packages/harmony-network/src/rpcMethod/rpc.ts
  51. 0
      packages/harmony-staking/README.md
  52. 2
      packages/harmony-staking/src/index.ts
  53. 0
      packages/harmony-transaction/README.md
  54. 39
      packages/harmony-transaction/src/factory.ts
  55. 48
      packages/harmony-transaction/src/types.ts
  56. 0
      packages/harmony-utils/README.md
  57. 73
      packages/harmony-utils/src/chain.ts
  58. 0
      packages/harmony-utils/src/errors.ts
  59. 0
      packages/woop-account/LICENSE
  60. 210
      packages/woop-account/README.md
  61. 218
      packages/woop-account/guide.ts
  62. 29
      packages/woop-account/package.json
  63. 290
      packages/woop-account/src/account.ts
  64. 46
      packages/woop-account/src/hdnode.ts
  65. 6
      packages/woop-account/src/index.ts
  66. 6
      packages/woop-account/src/types.ts
  67. 14
      packages/woop-account/src/utils.ts
  68. 176
      packages/woop-account/src/wallet.ts
  69. 36
      packages/woop-account/test/testAccount.test.ts
  70. 15
      packages/woop-account/tsconfig.json
  71. 0
      packages/woop-account/tsconfig.test.json
  72. 1187
      packages/woop-contract/Counter.json
  73. 0
      packages/woop-contract/LICENSE
  74. 147
      packages/woop-contract/README.md
  75. 18
      packages/woop-contract/package.json
  76. 353
      packages/woop-contract/src/abi/abiCoder.ts
  77. 14
      packages/woop-contract/src/abi/api.ts
  78. 6
      packages/woop-contract/src/abi/index.ts
  79. 14
      packages/woop-contract/src/abi/utils.ts
  80. 21
      packages/woop-contract/src/contract.ts
  81. 7
      packages/woop-contract/src/contractFactory.ts
  82. 7
      packages/woop-contract/src/events/event.ts
  83. 10
      packages/woop-contract/src/events/eventFactory.ts
  84. 11
      packages/woop-contract/src/index.ts
  85. 174
      packages/woop-contract/src/methods/method.ts
  86. 21
      packages/woop-contract/src/methods/methodFactory.ts
  87. 8
      packages/woop-contract/src/models/AbiItemModel.ts
  88. 28
      packages/woop-contract/src/models/AbiModel.ts
  89. 6
      packages/woop-contract/src/models/types.ts
  90. 12
      packages/woop-contract/src/utils/decoder.ts
  91. 17
      packages/woop-contract/src/utils/encoder.ts
  92. 27
      packages/woop-contract/src/utils/formatter.ts
  93. 19
      packages/woop-contract/src/utils/mapper.ts
  94. 6
      packages/woop-contract/src/utils/options.ts
  95. 6
      packages/woop-contract/src/utils/status.ts
  96. 9
      packages/woop-contract/test/abiCoder.test.ts
  97. 31505
      packages/woop-contract/test/fixtures/abiv2.ts
  98. 10
      packages/woop-contract/tsconfig.json
  99. 0
      packages/woop-contract/tsconfig.test.json
  100. 0
      packages/woop-core/LICENSE
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,5 +0,0 @@
GENESIS_PRIV_KEY=45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e
HTTP_PROVIDER=http://localhost:9500
CHAIN_TYPE=hmy
CHAIN_ID=2

9
.gitignore vendored

@ -5,12 +5,7 @@
*.tsbuildinfo
.vscode/
# package.json
package-lock.json
packages/*/package-lock.json
/packages/*/package-lock.json
# babel
packages/*/babel.rc
# lerna
@ -82,4 +77,4 @@ buck-out/
*.jsbundle
# Jest coverage
coverage/
coverage/

@ -2,7 +2,7 @@ language: node_js
sudo: true
dist: trusty
node_js:
- 10
- 16
branches:
except:
- /^v[0-9]/

@ -1,42 +1,25 @@
[![npm version](https://img.shields.io/npm/v/@harmony-js/core.svg?style=flat-square)](https://www.npmjs.com/package/@harmony-js/core)
[![Build Status](https://travis-ci.com/FireStack-Lab/Harmony-sdk-core.svg?branch=master)](https://travis-ci.com/FireStack-Lab/Harmony-sdk-core)
# Woop JavaScript SDK
[![npm version](https://img.shields.io/npm/v/@woop-js/core.svg?style=flat-square)](https://www.npmjs.com/package/@woop-js/core)
[![Build Status](https://travis-ci.com/FireStack-Lab/Woop-sdk-core.svg?branch=master)](https://travis-ci.com/FireStack-Lab/Woop-sdk-core)
1. [About this SDK](#about-this-sdk)
2. [How to Install](#how-to-install)
1. [Enviorment requirement](#enviorment-requirement)
2. [Install from npm/yarn](#install-from-npmyarn)
3. [Quick start](#quick-start)
3. [Build from source files](#build-from-source-files)
1. [Install `lerna` and `typescript` globally](#install-lerna-and-typescript-globally)
2. [Bootstrap and build](#bootstrap-and-build)
3. [Bundle](#bundle)
4. [Tests](#tests)
1. [Unit tests](#unit-tests)
2. [e2e tests](#e2e-tests)
5. [More examples](#more-examples)
6. [Release Note](#release-note)
1. [Before Release](#before-release)
2. [Publish to npm using `dev:publish`](#publish-to-npm-using-devpublish)
3. [Publish to npm with `lerna`](#publish-to-npm-with-lerna)
This is the Woop Javascript SDK which provides an easier way to interact with Woop blockchain.
# About this SDK
Please read the [documentation](https://jssdk.doc.hmny.io/) for full API doc.
A Harmony's blockchain javascript library, which provides an easier way to interact with Harmony's blockchain.
The SDK includes following packages with package-level documentation and examples inside each package.
This libraries contains a few packages.
1. [@woop-js/core](https://github.com/woop-chain/sdk/tree/master/packages/woop-core)
2. [@woop-js/account](https://github.com/woop-chain/sdk/tree/master/packages/woop-account)
3. [@woop-js/crypto](https://github.com/woop-chain/sdk/tree/master/packages/woop-crypto)
4. [@woop-js/network](https://github.com/woop-chain/sdk/tree/master/packages/woop-network)
5. [@woop-js/utils](https://github.com/woop-chain/sdk/tree/master/packages/woop-utils)
6. [@woop-js/transaction](https://github.com/woop-chain/sdk/tree/master/packages/woop-transaction)
7. [@woop-js/contract](https://github.com/woop-chain/sdk/tree/master/packages/woop-contract)
8. [@woop-js/staking](https://github.com/woop-chain/sdk/tree/master/packages/woop-staking)
1. [@harmony-js/core](https://github.com/harmony-one/sdk/tree/master/packages/harmony-core)
2. [@harmony-js/account](https://github.com/harmony-one/sdk/tree/master/packages/harmony-account)
3. [@harmony-js/crypto](https://github.com/harmony-one/sdk/tree/master/packages/harmony-crypto)
4. [@harmony-js/network](https://github.com/harmony-one/sdk/tree/master/packages/harmony-network)
5. [@harmony-js/utils](https://github.com/harmony-one/sdk/tree/master/packages/harmony-utils)
6. [@harmony-js/transaction](https://github.com/harmony-one/sdk/tree/master/packages/harmony-transaction)
7. [@harmony-js/contract](https://github.com/harmony-one/sdk/tree/master/packages/harmony-contract)
8. [@harmony-js/staking](https://github.com/harmony-one/sdk/tree/master/packages/harmony-contract)
# How to Install
# Installation
This library works on both nodejs and browser. Please use it according to your use case.
@ -52,10 +35,10 @@ This library works on both nodejs and browser. Please use it according to your u
```bash
# npm
npm install @harmony-js/core@next
npm install @woop-js/core@next
# yarn
yarn add @harmony-js/core@next
yarn add @woop-js/core@next
# tslib is required, we'd better install it as well
npm install tslib
@ -63,141 +46,7 @@ yarn add tslib
```
## Quick start
1. You need Harmony local testnet running.
instruction here:[harmony-one/harmony](https://github.com/harmony-one/harmony)
2. Run this example under nodejs enviorment.
```javascript
// import or require Harmony class
const { Harmony } = require('@harmony-js/core');
// import or require settings
const { ChainID, ChainType } = require('@harmony-js/utils');
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
'http://localhost:9500',
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyLocal,
},
);
// 2. get wallet ready
// specify the privateKey
const privateKey = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
// add privateKey to wallet
const sender = harmony.wallet.addByPrivateKey(privateKey);
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local testnet
// We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
// 4. get transaction payload ready
async function transfer() {
// run set sharding first, if you want to make a cross-shard transaction
await setSharding();
const txn = harmony.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 harmony.utils.Unit('100').asGwei().toWei(),
});
// sign the transaction use wallet;
const signedTxn = await harmony.wallet.signTransaction(txn);
// Now you can use `Transaction.observed()` to listen events
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// send the txn, get [Transaction, transactionHash] as result
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// to confirm the result if it is already there
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
if (!confiremdTxn.isCrossShard()) {
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
}
if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Cross-Shard transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
}
transfer();
```
# Build from source files
# Building from source files
## Install `lerna` and `typescript` globally
@ -212,7 +61,7 @@ yarn bootstrap
## Bundle
build `umd` and `esm` version javascript for each sub-packages, which can be accessed by `import` or `require`
Build `umd` and `esm` version javascript for each sub-packages, which can be accessed by `import` or `require`
```bash
yarn dist
@ -220,98 +69,20 @@ yarn dist
All files are exported in `packages/dist` folder, use `**.esm.js` or `**.umd.js` format
# Tests
# Running Tests
## Unit tests
```bash
yarn test:src
```
## e2e tests
**Contantly updating now, please get back later**
1. edit `.env` file if you have custom setting
2. run harmony node locally, follow this instruction : https://github.com/harmony-one/harmony)
3. wait for 1-2 mins, and run this:
1. Remove the `'cross-fetch': 'jest-fetch-mock'` line from `scripts/jest/jest.e2e.config.js`
1. Run woop node locally, follow the instructions: https://github.com/woop-chain/woop
1. Wait for 1-2 mins, and run this:
```bash
yarn build && yarn test:e2e
```
# More examples
* [dapp-examples](https://github.com/harmony-one/dapp-examples)
# Release Note
## Before Release
1. Build source first
```bash
yarn build:ts
```
2. Run unit tests
```bash
yarn test:src
```
3. Run e2e tests
```bash
yarn test:e2e
```
4. Clean and build bundle
```bash
yarn dist
```
## Publish to npm using `dev:publish`
The packages is to be published to npm, using `@next` tag using script in `package.json`
Follow steps below to publish a npm verion using `@next` tag
1. Commit all changes to github master
2. Run publish script
```bash
yarn dev:publish
```
3. Select version and confirm all prompts with `Y`
4. See version changes in `npmjs.com`
This will not change the release version of current npm packages(currently 0.0.7), developers have to use `@next` to install from npm.
For example.
```bash
npm install @harmony-js/core@next
```
## Publish to npm with `lerna`
Follow steps below to publish a npm verion with latest version
1. Commit all changes to github master
2. Run `lerna publish`, `lerna` is required globally.
```bash
lerna publish
```
3. Select version and confirm all prompts with `Y`
4. See version changes in `npmjs.com`
This will change the release version of current npm packages to the latest version, developers can install from npm directly
For example.
```bash
npm install @harmony-js/core
```

@ -0,0 +1,70 @@
# Release Guidelines
## Before Release
1. Build source first
```bash
yarn build:ts
```
2. Run unit tests
```bash
yarn test:src
```
3. Run e2e tests
```bash
yarn test:e2e
```
4. Clean and build bundle
```bash
yarn dist
```
## Publish to npm using `dev:publish`
The packages is to be published to npm, using `@next` tag using script in `package.json`
Follow steps below to publish a npm verion using `@next` tag
1. Commit all changes to github master
2. Run publish script
```bash
yarn dev:publish
```
3. Select version and confirm all prompts with `Y`
4. See version changes in `npmjs.com`
This will not change the release version of current npm packages(currently 0.0.7), developers have to use `@next` to install from npm.
For example.
```bash
npm install @woop-js/core@next
```
## Publish to npm with `lerna`
Follow steps below to publish a npm verion with latest version
1. Commit all changes to github master
2. Run `lerna publish`, `lerna` is required globally.
```bash
lerna publish
```
3. Select version and confirm all prompts with `Y`
4. See version changes in `npmjs.com`
This will change the release version of current npm packages to the latest version, developers can install from npm directly
For example.
```bash
npm install @woop-js/core
```

@ -0,0 +1,100 @@
# Woop JS-SDK Documentation
## [CLICK ME!!](https://woop-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 Woop_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 (woop 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://woop-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://woop-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!

@ -110,5 +110,29 @@
"gasPrice": "0x174876e800",
"rawTransaction": "0xf8690985174876e8008252088080949d72989b68777a1f3ffd6f1db079f1928373ee52830f42408028a022efd1decb6e80e88fd33f5e189f48105acc72f7e302931221183f86ca8a7015a02001dee44471a5397a4579f733b3a13a86ba1d6c78ad3312187513d6a424f72b"
}
],
"hashes": [
"0x5aE91eCA3BF7CB97FCd1305bD6e030e24bda9bbfED3b8c741Efe808e8D4F95Ff",
"0xf4CA9DdED0bC36B5AFBCf4fC6De082DFd0F7FCFad1c2aFC1aF52d16d9Dbd733f",
"0x56C2408c5F58ac9aDFE824B7755f3b54CB0848c7A837Ea1CC5a0FdB521D4A1a2",
"0xACFD09AD729E0C9f23EC9eEf27CC68bA37D7EE9D53aABace2dDD42616Eb8351A",
"0xB8baee4EfB120254Afab3092c8Ccc458fF49eBda12ead9950CD39ac8Bb26D4C1",
"0x412D8DBF0BC3dCAf91A0339EEadd1EEB44b44cD0cEBFaea0d35656d31F96Dde9",
"0xbbeDcd6e4dCDef0c666C0C0c7914ba1E5617F8d57ddc40C32cCb31D4BC5CAfBF",
"0x6E008bEbC8F2CE750d208dbF987edEf7476DcFDF8Eb8607f3B3c2E1ce8675ba9",
"0x0Ff0AcBD45cdDf3A8A148eb2F4Fe6dBf74B422eabdD0766ba9284f0Fe8F6dc8a",
"0x7FDCEE6B5EEf5C3F82B2Ffe8a088E0d3d485bEbBcdBCac16ECCb9d1cbfe50c91"
],
"blockHashes": [
"0x9dD4e063d8cc7A6Fe74a0E3AC4feD5F84eB8Bdc4647Ba8DAd651FD1b4a3979cE",
"0xEF5F7D7ca60bE76c1Cc5aADD8DC9e1bC0F7a3BCD0EEDA6e9Cca0EACAd99BE3Bb",
"0x4261B409CCcDA3ab97aABCFe8dECCfd65D1aB9Bb536dD57Fdafd191FC6BbFbbc",
"0x1fb05a17794cAd1ac025469eA1Bf5af4F33f9bdbD3c0e14bCeca323BC5DF0EC3",
"0xEA405dB5dc0E7e2DB2CfdBf272DCeAf69E9CDa2DFD47229b38A3C5b7b9cc41fB",
"0xCC1ADfef1bb2E496A3BbDb181ec5c8EA047AE340FaD6fF4FeF3CCE452c1975B6",
"0x80dffAe15B6619Cc7aD74Bc132C1b29EFc38B8d8CAD1AfbDb9E37f7357E2EBe4",
"0x6BcB9858d8cCE9de2a6ECd6392A5eC712be9b4A79F6Cf84De8aa5ae9C04f60A8",
"0xB6De43A866dFcE1f7AA7DA0E8e9eb7Fe545cB6becF7cf5fdC564B22C4cBb72b9",
"0xc4b4CeAEAEadADfa8CbCcDeFdcBaBeF999dBF42D14C9AFEDd1de2956B571CebD"
]
}

@ -1,88 +1,169 @@
import {harmony} from './harmony';
import fetch from 'jest-fetch-mock';
import { woop, checkCalledMethod } from './woop';
import demoAccounts from '../fixtures/testAccount.json';
import { RPCMethod } from '@woop-js/network';
const bc = harmony.blockchain;
const bc = woop.blockchain;
const testAccount = demoAccounts.Accounts[1];
describe('e2e test blockchain', () => {
beforeEach(() => {
fetch.resetMocks();
});
// net_*
it('should test net_peerCount', async () => {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x0"}),
);
const peerCount = await bc.net_peerCount();
expect(harmony.utils.isHex(peerCount.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.PeerCount)).toEqual(true);
expect(woop.utils.isHex(peerCount.result)).toEqual(true);
});
it('should test net_version', async () => {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "5"}),
);
const netVersion = await bc.net_version();
const versionNumber = parseInt(netVersion.result as string, 10);
expect(netVersion.result).toEqual(`${versionNumber}`);
expect(checkCalledMethod(0, RPCMethod.NetVersion)).toEqual(true);
});
it('should test hmy_protocolVersion', async () => {
it('should test wiki_protocolVersion', async () => {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x10"}),
);
const protocolVersion = await bc.getProtocolVersion();
expect(harmony.utils.isHex(protocolVersion.result)).toEqual(true);
expect(woop.utils.isHex(protocolVersion.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.ProtocolVersion)).toEqual(true);
});
// block chain info
it('should test hmy_blockNumber', async () => {
it('should test wiki_blockNumber', async () => {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x10"}),
);
const res = await bc.getBlockNumber();
expect(res.responseType).toEqual('raw');
expect(harmony.utils.isHex(res.result)).toEqual(true);
expect(woop.utils.isHex(res.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.BlockNumber)).toEqual(true);
});
it('should test hmy_getBlockByNumber', async () => {
const res = await bc.getBlockByNumber({blockNumber: 'latest'});
it('should test wiki_getBlockByNumber', async () => {
fetch.mockResponse(
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"size": "0x1",
"difficulty": 5,
"extraData": "0x",
"gasLimit": "0x80",
"gasUsed": "0x40",
"hash": "0x8a3390ab500Fbca6514eB326d2fcD9B3BFCFbA7DA392593cB4885b8e3399a2D8",
"logsBloom": "0x0",
"miner": "one155jp2y76nazx8uw5sa94fr0m4s5aj8e5xm6fu3",
"mixHash": "0x3A7c1Ae14AfecFf55Da298F66b75F4FfB771c3EaBDeAa267FF33A77d4d0be220",
"nonce": 1,
"number": "0x1",
"parentHash": "0x7CebC07e456F0bCD09dbc9A6f271074d93E27B40A4C67Dcc402e6513e12B9aF9",
"receiptsRoot": "0x02B82e11eDC07775Dc6fCF706be2cdAF9165750Ea7bC1B3Eb48ea16Bb3072F4D",
"stateRoot": "0xAaDc89C8bA4e3fCfC140cFcc8D3efD3BE7a49ab31534A5a3F0E1DEA09aae0f4a",
"timestamp": "0x62c44c0a",
"transactionsRoot": "0xc4bfa888fDCC8ca70E2b0CcdCEcc2fF545acCC2D655Ba33DaF4aBc31cFDBd9Ac",
"uncles": []
}
}),
);
const res = await bc.getBlockByNumber({ blockNumber: 'latest' });
const size = res.result.size;
expect(res.responseType).toEqual('raw');
expect(harmony.utils.isHex(size)).toEqual(true);
expect(woop.utils.isHex(size)).toEqual(true);
expect(checkBlockData(res.result)).toEqual(true);
const res2 = await bc.getBlockByNumber({blockNumber: res.result.number});
const res2 = await bc.getBlockByNumber({ blockNumber: res.result.number });
expect(res2.responseType).toEqual('raw');
expect(harmony.utils.isHex(res2.result.size)).toEqual(true);
expect(woop.utils.isHex(res2.result.size)).toEqual(true);
expect(checkBlockData(res2.result)).toEqual(true);
const res3 = await bc.getBlockByNumber({returnObject: true});
const res3 = await bc.getBlockByNumber({ returnObject: true });
expect(res3.responseType).toEqual('raw');
expect(checkBlockData(res3.result)).toEqual(true);
for(let i = 0; i < 3; i++) {
expect(checkCalledMethod(i, RPCMethod.GetBlockByNumber)).toEqual(true);
}
});
it('should test hmy_getBlockByHash', async () => {
const latestBlock = await bc.getBlockByNumber({blockNumber: 'latest'});
const res = await bc.getBlockByHash({blockHash: latestBlock.result.hash});
it('should test wiki_getBlockByHash', async () => {
fetch.mockResponse(
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"size": "0x1",
"difficulty": 5,
"extraData": "0x",
"gasLimit": "0x80",
"gasUsed": "0x40",
"hash": "0x8a3390ab500Fbca6514eB326d2fcD9B3BFCFbA7DA392593cB4885b8e3399a2D8",
"logsBloom": "0x0",
"miner": "one155jp2y76nazx8uw5sa94fr0m4s5aj8e5xm6fu3",
"mixHash": "0x3A7c1Ae14AfecFf55Da298F66b75F4FfB771c3EaBDeAa267FF33A77d4d0be220",
"nonce": 1,
"number": "0x1",
"parentHash": "0x7CebC07e456F0bCD09dbc9A6f271074d93E27B40A4C67Dcc402e6513e12B9aF9",
"receiptsRoot": "0x02B82e11eDC07775Dc6fCF706be2cdAF9165750Ea7bC1B3Eb48ea16Bb3072F4D",
"stateRoot": "0xAaDc89C8bA4e3fCfC140cFcc8D3efD3BE7a49ab31534A5a3F0E1DEA09aae0f4a",
"timestamp": "0x62c44c0a",
"transactionsRoot": "0xc4bfa888fDCC8ca70E2b0CcdCEcc2fF545acCC2D655Ba33DaF4aBc31cFDBd9Ac",
"uncles": []
}
}),
);
const latestBlock = await bc.getBlockByNumber({ blockNumber: 'latest' });
const res = await bc.getBlockByHash({ blockHash: latestBlock.result.hash });
expect(res.responseType).toEqual('raw');
expect(latestBlock.result.hash).toEqual(res.result.hash);
expect(harmony.utils.isHex(res.result.size)).toEqual(true);
expect(woop.utils.isHex(res.result.size)).toEqual(true);
expect(checkBlockData(res.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.GetBlockByNumber)).toEqual(true);
expect(checkCalledMethod(1, RPCMethod.GetBlockByHash)).toEqual(true);
});
// account related
it('should test hmy_getBalance', async () => {
const balance = await bc.getBalance({address: testAccount.Address});
expect(harmony.utils.isHex(balance.result)).toEqual(true);
it('should test wiki_getBalance', async () => {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x10"}),
);
const balance = await bc.getBalance({ address: testAccount.Address });
expect(woop.utils.isHex(balance.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.GetBalance)).toEqual(true);
});
});
function checkBlockData(data: any) {
return harmony.utils.validateArgs(
return woop.utils.validateArgs(
data,
{
difficulty: [harmony.utils.isNumber],
difficulty: [woop.utils.isNumber],
// tslint:disable-next-line: no-shadowed-variable
extraData: [(data: any) => data === '0x' || harmony.utils.isHex(data)],
gasLimit: [harmony.utils.isHex],
gasUsed: [harmony.utils.isHex],
hash: [harmony.utils.isHash],
logsBloom: [harmony.utils.isHex],
miner: [harmony.utils.isAddress],
mixHash: [harmony.utils.isHash],
nonce: [harmony.utils.isNumber],
number: [harmony.utils.isHex],
parentHash: [harmony.utils.isHash],
receiptsRoot: [harmony.utils.isHash],
size: [harmony.utils.isHex],
stateRoot: [harmony.utils.isHash],
timestamp: [harmony.utils.isHex],
transactionsRoot: [harmony.utils.isHash],
uncles: [harmony.utils.isArray],
extraData: [(data: any) => data === '0x' || woop.utils.isHex(data)],
gasLimit: [woop.utils.isHex],
gasUsed: [woop.utils.isHex],
hash: [woop.utils.isHash],
logsBloom: [woop.utils.isHex],
miner: [woop.utils.isBech32Address],
mixHash: [woop.utils.isHash],
nonce: [woop.utils.isNumber],
number: [woop.utils.isHex],
parentHash: [woop.utils.isHash],
receiptsRoot: [woop.utils.isHash],
size: [woop.utils.isHex],
stateRoot: [woop.utils.isHash],
timestamp: [woop.utils.isHex],
transactionsRoot: [woop.utils.isHash],
uncles: [woop.utils.isArray],
},
{transactions: [harmony.utils.isArray]},
{ transactions: [woop.utils.isArray] },
);
}
}

@ -1,29 +0,0 @@
// tslint:disable-next-line: no-implicit-dependencies
import { Harmony } from '@harmony-js/core';
// tslint:disable-next-line: no-implicit-dependencies
import { ChainType } from '@harmony-js/utils';
// tslint:disable-next-line: no-implicit-dependencies
import { Account } from '@harmony-js/account';
const CHAIN_ID: number = parseInt(process.env.CHAIN_ID as string, 10);
const CHAIN_TYPE: string = process.env.CHAIN_TYPE as string;
const HTTP_PROVIDER: string = process.env.HTTP_PROVIDER as string;
const GENESIS_PRIV_KEY: string = process.env.GENESIS_PRIV_KEY as string;
let chainType: ChainType = ChainType.Harmony;
if (CHAIN_TYPE === 'hmy') {
chainType = ChainType.Harmony;
} else if (CHAIN_TYPE === 'eth') {
chainType = ChainType.Ethereum;
}
export const harmony: Harmony = new Harmony(HTTP_PROVIDER, {
chainId: CHAIN_ID,
chainType,
chainUrl: HTTP_PROVIDER,
});
export const myAccount: Account = harmony.wallet.addByPrivateKey(
GENESIS_PRIV_KEY,
);

@ -1,15 +1,20 @@
import { harmony } from './harmony';
import fetch from 'jest-fetch-mock';
import { woop, checkCalledMethod } from './woop';
// tslint:disable-next-line: no-implicit-dependencies
import { Transaction, TxStatus } from '@harmony-js/transaction';
import { Transaction, TxStatus } from '@woop-js/transaction';
// tslint:disable-next-line: no-implicit-dependencies
import { isHash, numberToHex } from '@harmony-js/utils';
import { isHash, numberToHex } from '@woop-js/utils';
import txnJsons from '../fixtures/transactions.json';
import demoAccounts from '../fixtures/testAccount.json';
import { RPCMethod } from '@woop-js/network';
const receiver = demoAccounts.Accounts[3];
jest.useRealTimers();
describe('test Transaction using SDK', () => {
beforeEach(() => {
fetch.resetMocks();
});
let signed: Transaction;
let sent: Transaction;
let txId: string;
@ -18,7 +23,7 @@ describe('test Transaction using SDK', () => {
const txns = txnJsons.transactions;
// tslint:disable-next-line: prefer-for-of
for (let i = 0; i < txns.length; i += 1) {
const newTxn = harmony.transactions.newTx();
const newTxn = woop.transactions.newTx();
newTxn.recover(txns[i].rawTransaction);
expect(newTxn.txParams.from).toEqual(txns[i].senderAddress);
@ -31,25 +36,63 @@ describe('test Transaction using SDK', () => {
});
it('should test signTransaction', async () => {
const txnObject = {
to: harmony.crypto.getAddress(receiver.Address).bech32,
to: woop.crypto.getAddress(receiver.Address).bech32,
value: '0x64',
gasLimit: '210000',
gasPrice: new harmony.utils.Unit('100').asGwei().toWei(),
gasPrice: new woop.utils.Unit('100').asGwei().toWei(),
};
const txn = harmony.transactions.newTx(txnObject);
signed = await harmony.wallet.signTransaction(txn);
const txn = woop.transactions.newTx(txnObject);
signed = await woop.wallet.signTransaction(txn, undefined, undefined, false);
expect(signed.isSigned()).toEqual(true);
});
it('should send transaction', async () => {
fetch.mockResponseOnce(
JSON.stringify({
"jsonrpc": "2.0", "id": 1,
"result": "0x323A2B2C81d8948E5109FC32f9d0e4e6d178d14cC732C8E0a7Af74E81C7653eA"
}),
);
const [sentTxn, id] = await signed.sendTransaction();
expect(sentTxn.isPending()).toEqual(true);
expect(harmony.utils.isHash(id)).toEqual(true);
expect(woop.utils.isHash(id)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.SendRawTransaction)).toEqual(true);
txId = id;
sent = sentTxn;
});
it('should confirm a transaction', async () => {
fetch.mockResponses(
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x1"}),
{ status: 200 },
],
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x2"}),
{ status: 200 },
],
[
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"contractAddress": null,
"blockNumber": woop.utils.numberToHex(2),
"from": woop.wallet.accounts[0],
"gasUsed": woop.utils.numberToHex(5),
"cumulativeGasUsed": woop.utils.numberToHex(5),
"logs": [],
"logsBloom": woop.utils.numberToHex(5),
"shardID": 0,
"to": demoAccounts.Accounts[3].Address,
"transactionHash": "0x8c26EFdb6e4cAC6F8BeACE59F52fd95beD4Bfbfa8fF30F4a7cEd511fE5f869d9",
"transactionIndex": woop.utils.numberToHex(10),
"blockHash": "0xFECCCCBFd5AC71902BcfE65dDB0b88EEbbD15AD6cDAE7A9FAEb773bF827320fd",
}
}),
{status: 200},
]
)
const toConfirm = await sent.confirm(txId, 20, 1000);
expect(toConfirm.receipt !== undefined).toEqual(true);
expect(checkTransactionReceipt(toConfirm.receipt)).toEqual(true);
@ -58,16 +101,19 @@ describe('test Transaction using SDK', () => {
} else if (toConfirm.isRejected()) {
expect(toConfirm.txStatus).toEqual(TxStatus.REJECTED);
}
expect(checkCalledMethod(0, RPCMethod.BlockNumber)).toEqual(true);
expect(checkCalledMethod(1, RPCMethod.BlockNumber)).toEqual(true);
expect(checkCalledMethod(2, RPCMethod.GetTransactionReceipt)).toEqual(true);
});
it('should test transaction observed events', async () => {
const txnObject = {
to: harmony.crypto.getAddress(receiver.Address).bech32,
value: new harmony.utils.Unit('100').asGwei().toWei(),
gasLimit: new harmony.utils.Unit('210000').asWei().toWei(),
gasPrice: new harmony.utils.Unit('100').asGwei().toWei(),
to: woop.crypto.getAddress(receiver.Address).bech32,
value: new woop.utils.Unit('100').asGwei().toWei(),
gasLimit: new woop.utils.Unit('210000').asWei().toWei(),
gasPrice: new woop.utils.Unit('100').asGwei().toWei(),
};
const txn = harmony.transactions.newTx(txnObject);
const txn = woop.transactions.newTx(txnObject);
txn
.observed()
.on('transactionHash', (transactionHash) => {
@ -84,35 +130,78 @@ describe('test Transaction using SDK', () => {
.on('error', (error) => {
expect(error).toBeTruthy();
});
const txnSigned = await harmony.wallet.signTransaction(txn);
const txnSigned = await woop.wallet.signTransaction(txn, undefined, undefined, false);
fetch.mockResponseOnce(
JSON.stringify({
"jsonrpc": "2.0", "id": 1,
"result": "0x323A2B2C81d8948E5109FC32f9d0e4e6d178d14cC732C8E0a7Af74E81C7653eA"
}),
);
const [txnSent, id] = await txnSigned.sendTransaction();
expect(txnSent.txStatus).toEqual(TxStatus.PENDING);
expect(checkCalledMethod(0, RPCMethod.SendRawTransaction)).toEqual(true);
console.log('Here');
fetch.mockResponses(
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x1"}),
{ status: 200 },
],
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x2"}),
{ status: 200 },
],
[
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"contractAddress": null,
"blockNumber": woop.utils.numberToHex(2),
"from": woop.wallet.accounts[0],
"gasUsed": woop.utils.numberToHex(5),
"cumulativeGasUsed": woop.utils.numberToHex(5),
"logs": [],
"logsBloom": woop.utils.numberToHex(5),
"shardID": 0,
"to": demoAccounts.Accounts[3].Address,
"transactionHash": "0x8c26EFdb6e4cAC6F8BeACE59F52fd95beD4Bfbfa8fF30F4a7cEd511fE5f869d9",
"transactionIndex": woop.utils.numberToHex(10),
"blockHash": "0xFECCCCBFd5AC71902BcfE65dDB0b88EEbbD15AD6cDAE7A9FAEb773bF827320fd",
"status": "0x1",
}
}),
{status: 200},
]
);
await txnSigned.confirm(id);
expect(checkCalledMethod(1, RPCMethod.BlockNumber)).toEqual(true);
expect(checkCalledMethod(2, RPCMethod.BlockNumber)).toEqual(true);
expect(checkCalledMethod(3, RPCMethod.GetTransactionReceipt)).toEqual(true);
});
});
function checkTransactionReceipt(data: any) {
return harmony.utils.validateArgs(
return woop.utils.validateArgs(
data,
{
blockHash: [harmony.utils.isHash],
blockNumber: [harmony.utils.isHex],
blockHash: [woop.utils.isHash],
blockNumber: [woop.utils.isHex],
contractAddress: [
// tslint:disable-next-line: no-shadowed-variable
(data: any) => data === null || harmony.utils.isValidAddress,
(data: any) => data === null || woop.utils.isValidAddress,
],
cumulativeGasUsed: [harmony.utils.isHex],
from: [harmony.utils.isValidAddress],
gasUsed: [harmony.utils.isHex],
logs: [harmony.utils.isArray],
logsBloom: [harmony.utils.isHex],
cumulativeGasUsed: [woop.utils.isHex],
from: [woop.utils.isValidAddress],
gasUsed: [woop.utils.isHex],
logs: [woop.utils.isArray],
logsBloom: [woop.utils.isHex],
shardID: [harmony.utils.isNumber],
shardID: [woop.utils.isNumber],
// tslint:disable-next-line: no-shadowed-variable
to: [(data: any) => data === '0x' || harmony.utils.isValidAddress],
transactionHash: [harmony.utils.isHash],
transactionIndex: [harmony.utils.isHex],
to: [(data: any) => data === '0x' || woop.utils.isValidAddress],
transactionHash: [woop.utils.isHash],
transactionIndex: [woop.utils.isHex],
},
{ root: [harmony.utils.isHash] },
{ root: [woop.utils.isHash] },
);
}

@ -1,7 +1,9 @@
import { harmony } from './harmony';
import fetch from 'jest-fetch-mock';
import { woop, checkCalledMethod } from './woop';
import txnJsons from '../fixtures/transactions.json';
import { RPCMethod } from '@woop-js/network';
const messenger = harmony.messenger;
const messenger = woop.messenger;
interface TransactionInfo {
blockHash: string;
@ -10,23 +12,53 @@ interface TransactionInfo {
}
describe('e2e test transactions by RPC Method', () => {
beforeEach(() => {
fetch.resetMocks();
});
const txnHashesFixtures: any = [];
const transactionInfoList: any = [];
const { transactions, hashes, blockHashes } = txnJsons;
// net_*
it('should test hmy_sendRawTransaction', async () => {
const { transactions } = txnJsons;
for (const txn of transactions) {
const sent = await messenger.send('hmy_sendRawTransaction', txn.rawTransaction);
expect(harmony.utils.isHash(sent.result)).toEqual(true);
it('should test wiki_sendRawTransaction', async () => {
for(let index = 0; index < transactions.length; index++) {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": hashes[index]}),
);
const sent = await messenger.send('wiki_sendRawTransaction', transactions[index].rawTransaction);
expect(woop.utils.isHash(sent.result)).toEqual(true);
txnHashesFixtures.push(sent.result);
expect(checkCalledMethod(index, 'wiki_sendRawTransaction')).toEqual(true);
}
});
it('should test hmy_getTransactionByHash', async () => {
for (const txnHash of txnHashesFixtures) {
const txnDetail = await harmony.blockchain.getTransactionByHash({
txnHash,
it('should test wiki_getTransactionByHash', async () => {
for(let index: number = 0; index < txnHashesFixtures.length; index++) {
const txnHash = txnHashesFixtures[index];
fetch.mockResponseOnce(
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"hash": hashes[index],
"blockHash": blockHashes[index],
"blockNumber": woop.utils.numberToHex(index),
"transactionIndex": woop.utils.numberToHex(index),
"from": transactions[index].senderAddress,
"gas": transactions[index].gasLimit,
"gasPrice": transactions[index].gasPrice,
"input": "0x",
"nonce": transactions[index].nonce,
"to": transactions[index].receiverAddressBech32,
"value": transactions[index].value,
"v": woop.utils.numberToHex(index),
"r": woop.utils.numberToHex(index),
"s": woop.utils.numberToHex(index),
}
})
);
const txnDetail = await woop.blockchain.getTransactionByHash({
txnHash
});
expect(checkCalledMethod(index, RPCMethod.GetTransactionByHash)).toEqual(true);
if (txnDetail.result !== null) {
expect(checkTransactionDetail(txnDetail.result)).toEqual(true);
expect(txnDetail.result.hash).toEqual(txnHash);
@ -37,84 +69,194 @@ describe('e2e test transactions by RPC Method', () => {
index: txnDetail.result.transactionIndex,
};
transactionInfoList.push(transactionInfo);
} else {
fail(`txnDetail for ${txnHash} is null`);
}
}
});
it('should test hmy_getTransactionByBlockHashAndIndex', async () => {
for (const some of transactionInfoList) {
const transactionInfo: TransactionInfo = some;
const txnDetail: any = await harmony.blockchain.getTransactionByBlockHashAndIndex({
it('should test wiki_getTransactionByBlockHashAndIndex', async () => {
for (let index: number = 0; index < transactionInfoList.length; index++) {
fetch.mockResponseOnce((req) => {
if (!(Buffer.isBuffer(req.body))) {
fail("POST request body not a buffer");
}
const body: any = JSON.parse(req.body.toString());
// validate that the block hash is as expected
if (body.params[0] !== blockHashes[index]) {
fail(`Expected block hash ${blockHashes[index]} but got ${body.params[0]}`);
}
// validate that the transaction index is as expected
let expectedTransactionIndex: string = woop.utils.numberToHex(index);
if (expectedTransactionIndex !== body.params[1]) {
fail(`Expected transactionIndex ${expectedTransactionIndex} but got ${body.params[1]}`);
}
return Promise.resolve(JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"hash": hashes[index],
"blockHash": blockHashes[index],
"blockNumber": woop.utils.numberToHex(index),
"transactionIndex": woop.utils.numberToHex(index),
"from": transactions[index].senderAddress,
"gas": transactions[index].gasLimit,
"gasPrice": transactions[index].gasPrice,
"input": "0x",
"nonce": transactions[index].nonce,
"to": transactions[index].receiverAddressBech32,
"value": transactions[index].value,
"v": woop.utils.numberToHex(index),
"r": woop.utils.numberToHex(index),
"s": woop.utils.numberToHex(index),
}
}));
});
const transactionInfo: TransactionInfo = transactionInfoList[index];
const txnDetail: any = await woop.blockchain.getTransactionByBlockHashAndIndex({
blockHash: transactionInfo.blockHash,
index: transactionInfo.index,
});
expect(checkCalledMethod(index, RPCMethod.GetTransactionByBlockHashAndIndex)).toEqual(true);
if (txnDetail.result !== null) {
expect(checkTransactionDetail(txnDetail.result)).toEqual(true);
expect(txnDetail.result.blockHash).toEqual(transactionInfo.blockHash);
expect(txnDetail.result.transactionIndex).toEqual(transactionInfo.index);
} else {
fail(`txnDetail for ${transactionInfo.blockHash}_${transactionInfo.index} is null`);
}
}
});
it('should test hmy_getTransactionByBlockNumberAndIndex', async () => {
for (const some of transactionInfoList) {
const transactionInfo: TransactionInfo = some;
const txnDetail: any = await harmony.blockchain.getTransactionByBlockNumberAndIndex({
it('should test wiki_getTransactionByBlockNumberAndIndex', async () => {
for (let index: number = 0; index < transactionInfoList.length; index++) {
fetch.mockResponseOnce((req) => {
if (!(Buffer.isBuffer(req.body))) {
fail("POST request body not a buffer");
}
const body: any = JSON.parse(req.body.toString());
// validate that the block number is as expected
let expectedBlockNumber: string = woop.utils.numberToHex(index);
if (body.params[0] !== expectedBlockNumber) {
fail(`Expected block number ${index} but got ${body.params[0]}`);
}
// validate that the transaction index is as expected
let expectedTransactionIndex: string = woop.utils.numberToHex(index);
if (expectedTransactionIndex !== body.params[1]) {
fail(`Expected transactionIndex ${expectedTransactionIndex} but got ${body.params[1]}`);
}
return Promise.resolve(JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"hash": hashes[index],
"blockHash": blockHashes[index],
"blockNumber": woop.utils.numberToHex(index),
"transactionIndex": woop.utils.numberToHex(index),
"from": transactions[index].senderAddress,
"gas": transactions[index].gasLimit,
"gasPrice": transactions[index].gasPrice,
"input": "0x",
"nonce": transactions[index].nonce,
"to": transactions[index].receiverAddressBech32,
"value": transactions[index].value,
"v": woop.utils.numberToHex(index),
"r": woop.utils.numberToHex(index),
"s": woop.utils.numberToHex(index),
}
}));
});
const transactionInfo: TransactionInfo = transactionInfoList[index];
const txnDetail: any = await woop.blockchain.getTransactionByBlockNumberAndIndex({
blockNumber: transactionInfo.blockNumber,
index: transactionInfo.index,
});
expect(checkCalledMethod(index, RPCMethod.GetTransactionByBlockNumberAndIndex)).toEqual(true);
if (txnDetail.result !== null) {
expect(checkTransactionDetail(txnDetail.result)).toEqual(true);
expect(txnDetail.result.blockNumber).toEqual(transactionInfo.blockNumber);
expect(txnDetail.result.transactionIndex).toEqual(transactionInfo.index);
} else {
fail(`txnDetail for ${transactionInfo.blockNumber}_${transactionInfo.index} is null`);
}
}
});
it('should test hmy_getTransactionCountByHash', async () => {
it('should test wiki_getTransactionCountByHash', async () => {
for (const some of transactionInfoList) {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x1"}),
);
const transactionInfo: TransactionInfo = some;
const txnCount: any = await harmony.blockchain.getBlockTransactionCountByHash({
const txnCount: any = await woop.blockchain.getBlockTransactionCountByHash({
blockHash: transactionInfo.blockHash,
});
expect(harmony.utils.isHex(txnCount.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.GetBlockTransactionCountByHash)).toEqual(true);
expect(woop.utils.isHex(txnCount.result)).toEqual(true);
}
});
it('should test hmy_getTransactionCountByNumber', async () => {
it('should test wiki_getTransactionCountByNumber', async () => {
for (const some of transactionInfoList) {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x1"}),
);
const transactionInfo: TransactionInfo = some;
const txnCount: any = await harmony.blockchain.getBlockTransactionCountByNumber({
const txnCount: any = await woop.blockchain.getBlockTransactionCountByNumber({
blockNumber: transactionInfo.blockNumber,
});
expect(harmony.utils.isHex(txnCount.result)).toEqual(true);
expect(checkCalledMethod(0, RPCMethod.GetBlockTransactionCountByNumber)).toEqual(true);
expect(woop.utils.isHex(txnCount.result)).toEqual(true);
}
});
it('should test hmy_getTransactionReceipt', async () => {
const { transactions } = txnJsons;
it('should test wiki_getTransactionReceipt', async () => {
// tslint:disable-next-line: prefer-for-of
for (let i = 0; i < txnHashesFixtures.length; i += 1) {
const txnHash = txnHashesFixtures[i];
const receipt: any = await harmony.blockchain.getTransactionReceipt({
for (let index = 0; index < txnHashesFixtures.length; index += 1) {
const txnHash = txnHashesFixtures[index];
fetch.mockResponseOnce(
JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"result": {
"contractAddress": null,
"blockNumber": woop.utils.numberToHex(index),
"from": transactions[index].senderAddress,
"gasUsed": woop.utils.numberToHex(index),
"cumulativeGasUsed": woop.utils.numberToHex(index),
"logs": [],
"logsBloom": woop.utils.numberToHex(index),
"shardID": 0,
"to": transactions[index].receiverAddress,
"transactionHash": hashes[index],
"transactionIndex": woop.utils.numberToHex(index),
"blockHash": blockHashes[index]
}
})
);
const receipt: any = await woop.blockchain.getTransactionReceipt({
txnHash,
});
expect(checkCalledMethod(index, RPCMethod.GetTransactionReceipt)).toEqual(true);
if (receipt.result !== null) {
expect(checkTransactionReceipt(receipt.result)).toEqual(true);
expect(harmony.crypto.getAddress(receipt.result.from).checksum).toEqual(
transactions[i].senderAddress,
expect(woop.crypto.getAddress(receipt.result.from).checksum).toEqual(
transactions[index].senderAddress,
);
expect(harmony.crypto.getAddress(receipt.result.to).checksum).toEqual(
transactions[i].receiverAddress,
expect(woop.crypto.getAddress(receipt.result.to).checksum).toEqual(
transactions[index].receiverAddress,
);
expect(receipt.result.blockHash).toEqual(transactionInfoList[i].blockHash);
expect(receipt.result.blockNumber).toEqual(transactionInfoList[i].blockNumber);
expect(receipt.result.transactionIndex).toEqual(transactionInfoList[i].index);
expect(receipt.result.blockHash).toEqual(transactionInfoList[index].blockHash);
expect(receipt.result.blockNumber).toEqual(transactionInfoList[index].blockNumber);
expect(receipt.result.transactionIndex).toEqual(transactionInfoList[index].index);
} else {
fail(`receipt for ${txnHash} is null`);
}
}
});
it('should test hmy_getTransactionCount', async () => {
const { transactions } = txnJsons;
it('should test wiki_getTransactionCount', async () => {
for (let i = 0; i < transactionInfoList; i += 1) {
fetch.mockResponseOnce(
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x1"}),
);
const transactionInfo: TransactionInfo = transactionInfoList[i];
const nonce: any = await harmony.blockchain.getTransactionCount({
const nonce: any = await woop.blockchain.getTransactionCount({
address: transactions[i].senderAddressBech32,
blockNumber: transactionInfo.blockNumber,
});
@ -124,52 +266,52 @@ describe('e2e test transactions by RPC Method', () => {
});
function checkTransactionDetail(data: any) {
return harmony.utils.validateArgs(
return woop.utils.validateArgs(
data,
{
blockHash: [harmony.utils.isHash],
blockNumber: [harmony.utils.isHex],
blockHash: [woop.utils.isHash],
blockNumber: [woop.utils.isHex],
// tslint:disable-next-line: no-shadowed-variable
from: [harmony.utils.isValidAddress],
gas: [harmony.utils.isHex],
gasPrice: [harmony.utils.isHex],
hash: [harmony.utils.isHash],
from: [woop.utils.isValidAddress],
gas: [woop.utils.isHex],
gasPrice: [woop.utils.isHex],
hash: [woop.utils.isHash],
// tslint:disable-next-line: no-shadowed-variable
input: [(data: any) => data === '0x' || harmony.utils.isHex(data)],
nonce: [harmony.utils.isHex],
input: [(data: any) => data === '0x' || woop.utils.isHex(data)],
nonce: [woop.utils.isHex],
// tslint:disable-next-line: no-shadowed-variable
to: [(data: any) => data === '0x' || harmony.utils.isValidAddress(data)],
transactionIndex: [harmony.utils.isHex],
value: [harmony.utils.isHex],
v: [harmony.utils.isHex],
r: [harmony.utils.isHex],
s: [harmony.utils.isHex],
to: [(data: any) => data === '0x' || woop.utils.isValidAddress(data)],
transactionIndex: [woop.utils.isHex],
value: [woop.utils.isHex],
v: [woop.utils.isHex],
r: [woop.utils.isHex],
s: [woop.utils.isHex],
},
{},
);
}
function checkTransactionReceipt(data: any) {
return harmony.utils.validateArgs(
return woop.utils.validateArgs(
data,
{
blockNumber: [harmony.utils.isHex],
blockNumber: [woop.utils.isHex],
contractAddress: [
// tslint:disable-next-line: no-shadowed-variable
(data: any) => data === null || harmony.utils.isValidAddress,
(data: any) => data === null || woop.utils.isValidAddress,
],
cumulativeGasUsed: [harmony.utils.isHex],
from: [harmony.utils.isValidAddress],
gasUsed: [harmony.utils.isHex],
logs: [harmony.utils.isArray],
logsBloom: [harmony.utils.isHex],
cumulativeGasUsed: [woop.utils.isHex],
from: [woop.utils.isValidAddress],
gasUsed: [woop.utils.isHex],
logs: [woop.utils.isArray],
logsBloom: [woop.utils.isHex],
shardID: [harmony.utils.isNumber],
shardID: [woop.utils.isNumber],
// tslint:disable-next-line: no-shadowed-variable
to: [(data: any) => data === '0x' || harmony.utils.isValidAddress],
transactionHash: [harmony.utils.isHash],
transactionIndex: [harmony.utils.isHex],
to: [(data: any) => data === '0x' || woop.utils.isValidAddress],
transactionHash: [woop.utils.isHash],
transactionIndex: [woop.utils.isHex],
},
{ blockHash: [harmony.utils.isHash], root: [harmony.utils.isHash] },
{ blockHash: [woop.utils.isHash], root: [woop.utils.isHash] },
);
}

@ -0,0 +1,39 @@
import fetch from 'jest-fetch-mock';
// tslint:disable-next-line: no-implicit-dependencies
import { Woop } from '@woop-js/core';
// tslint:disable-next-line: no-implicit-dependencies
import { ChainType } from '@woop-js/utils';
// tslint:disable-next-line: no-implicit-dependencies
import { Account } from '@woop-js/account';
const CHAIN_ID: number = 2;
const CHAIN_TYPE: string = 'wiki';
const HTTP_PROVIDER: string = 'http://localhost:9500';
const GENESIS_PRIV_KEY: string = '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e';
let chainType: ChainType = ChainType.Woop;
if (CHAIN_TYPE === 'wiki') {
chainType = ChainType.Woop;
} else if (CHAIN_TYPE === 'eth') {
chainType = ChainType.Ethereum;
}
export const woop: Woop = new Woop(HTTP_PROVIDER, {
chainId: CHAIN_ID,
chainType,
chainUrl: HTTP_PROVIDER,
});
export const myAccount: Account = woop.wallet.addByPrivateKey(
GENESIS_PRIV_KEY,
);
export function checkCalledMethod(i: number, s: string) {
let params: (string | undefined) = fetch.mock.calls[i][1]?.body?.toString();
if (params) {
let method: string = JSON.parse(params).method;
return method === s;
}
return false;
}

@ -3,15 +3,17 @@
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"declarationDir": "dist"
"declarationDir": "dist",
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": ["src", "../typings/**/*.d.ts", "fixtures"],
"references": [
{ "path": "../packages/harmony-account" },
{ "path": "../packages/harmony-crypto" },
{ "path": "../packages/harmony-utils" },
{ "path": "../packages/harmony-network" },
{ "path": "../packages/harmony-transaction" },
{ "path": "../packages/harmony-contract" }
{ "path": "../packages/woop-account" },
{ "path": "../packages/woop-crypto" },
{ "path": "../packages/woop-utils" },
{ "path": "../packages/woop-network" },
{ "path": "../packages/woop-transaction" },
{ "path": "../packages/woop-contract" }
]
}

@ -1,31 +0,0 @@
const { Harmony } = require('@harmony-js/core');
// import or require settings
const { ChainID, ChainType } = require('@harmony-js/utils');
const URL_TESTNET = `https://api.s0.b.hmny.io`;
const URL_MAINNET = `https://api.s0.t.hmny.io`;
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
URL_TESTNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyTestnet,
},
);
harmony.blockchain
.getBalance({
address: `one1vjywuur8ckddmc4dsyx6qdgf590eu07ag9fg4a`,
})
.then((res) => {
console.log(new harmony.utils.Unit(res.result).asWei().toEther());
})
.catch((err) => {
console.log(err);
});

@ -1,45 +0,0 @@
// import the Account class
const { Account } = require('@harmony-js/account');
// suppose we have an account
const myPrivateKey = '0x831f0b3ff835d5ec4602878742fda25591b6d3bb2731366621ac83a05216bec8';
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":"38326265-6165-4961-a338-353063643962","address":"1cc87010760602a576455d6d2f03a3bf92d2c2ca","crypto":{"ciphertext":"a4ee9120b27ba66fb9d3fabd6372fa3a11060cf439a6a1777ced1e6253de8c29","cipherparams":{"iv":"c18772a882ac461fffd1971e9ec57861"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"da4efedeca407279be65e02fc94b7c4b7c74c3396447c71e659c74a73a5d9131","n":8192,"r":8,"p":1,"dklen":32},"mac":"547ee6616dcdf424273c113ceb00728ccdda17ff6449f2cb84a1a8352c87b4e6"}}';
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);

@ -1,14 +0,0 @@
{
"name": "example",
"version": "1.0.0",
"description": "",
"main": "test.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@harmony-js/core": "^0.1.32"
}
}

@ -1,79 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const {
StakingTransaction,
CreateValidator,
Delegate,
Undelegate,
CollectRewards,
StakingFactory,
} = require('@harmony-js/staking');
const harmony = new Harmony('http://localhost:9500', {
chainId: ChainID.HmyLocal,
chainType: ChainType.Harmony,
});
const stakingTxn = harmony.stakings
.createValidator({
validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
description: {
name: 'Alice',
identity: 'alice',
website: 'alice.harmony.one',
securityContact: 'Bob',
details: "Don't mess with me!!!",
},
commissionRate: {
rate: '0.1',
maxRate: '0.9',
maxChangeRate: '0.05',
},
minSelfDelegation: '0xa',
maxTotalDelegation: '0x0bb8',
slotPubKeys: [
'0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611',
],
amount: '0x64',
})
.setTxParams({
nonce: '0x2',
gasPrice: '0x',
gasLimit: '0x64',
chainId: 0,
})
.build();
stakingTxn
.sendTransaction()
.then(([stakingTxn, res]) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
// const delegateMsg = Delegate({
// delegatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// amount: '0xa',
// });
// const stakingTxn = StakingTransaction({
// directive: '0x2',
// stakeMsg: delegateMsg,
// nonce: '0x2',
// gasPrice: '0x',
// gasLimit: '0x64',
// chainId: 0,
// from: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// });
// stakingTxn
// .sendTransaction()
// .then((stakingTxn, res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });

@ -1,172 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const { Delegate, StakingTransaction, StakingFactory } = require('@harmony-js/staking'); //../packages/harmony-staking
const { TxStatus } = require('@harmony-js/transaction');
const LOCALNET = `http://localhost:9500`;
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
LOCALNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyLocal,
},
);
// 2. get wallet ready
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
const private = '63e35b761e9df0d50ddcdaa8e33c235b60c991bfed22925a12768b0c08ef822f';
// one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy
const sender = harmony.wallet.addByPrivateKey(private);
console.log(sender.address);
// const phrase =
// 'genius cable radar memory high catch blossom correct middle wish gentle
// fiscal';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
// const sender = harmony.wallet.addByMnemonic(phrase);
// let r =
// '0xf8f180f8a4940b585f8daefbc68a311fbd4cb20d9174ad174016f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500000a820bb8f1b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b6224760861164008080830927c028a064b1b835f5b70a72228920db24e44c0a57d954c1d3dcac3b33c79d9593f96191a05577fd05064a37043a33ff7febb67ab126a8e1f0b67c92b7cab793a87ddf2c82';
// const delegateMsg = new Delegate(
// 'one1pf75h0t4am90z8uv3y0dgunfqp4lj8wr3t5rsp', // from delegate command.
// 'one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy', // fd416cb87dcf8ed187e85545d7734a192fc8e976f5b540e9e21e896ec2bc25c3
// '0xde0b6b3a7640000', // 0x56BC75E2D63100000
// );
// // one12fuf7x9rgtdgqg7vgq0962c556m3p7afsxgvll;
// const stakingTxn = new StakingTransaction(
// '0x2',
// delegateMsg,
// '0x2',
// '0x',
// '0x0927c0',
// ChainID.HmyLocal,
// );
const stakingTxn = harmony.stakings
.delegate({
delegatorAddress: 'one1pf75h0t4am90z8uv3y0dgunfqp4lj8wr3t5rsp',
validatorAddress: 'one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy',
amount: '0xde0b6b3a7640000',
})
.setTxParams({ nonce: '0x2', gasPrice: '0x', gasLimit: '0x0927c0', chainId: ChainID.HmyLocal })
.build();
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local
// testnet We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
async function execute() {
await setSharding();
const signedTxn = await harmony.wallet.signStaking(stakingTxn);
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// console.log(signedTxn);
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// signedTxn.sendTransaction()
// .then(res => {
// console.log(res);
// })
// .catch(err => {
// console.log(err);
// });
// to confirm the result if it is already there
// console.log(txnHash);
console.log(sentTxn);
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
// if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
// console.log('--- Result ---');
// console.log('');
// console.log('Cross-Shard transaction');
// console.log(`${txnHash} is confirmed`);
// console.log('');
// process.exit();
// }
}
execute();
// const delegateMsg = Delegate({
// delegatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// amount: '0xa',
// });
// const stakingTxn = StakingTransaction({
// directive: '0x2',
// stakeMsg: delegateMsg,
// nonce: '0x2',
// gasPrice: '0x',
// gasLimit: '0x64',
// chainId: 0,
// from: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// });
// stakingTxn
// .sendTransaction()
// .then((stakingTxn, res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });

@ -1,74 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const { StakingFactory } = require('@harmony-js/staking');
const harmony = new Harmony('http://localhost:9500', {
chainId: ChainID.HmyLocal,
chainType: ChainType.Harmony,
});
const createMsg = {
validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
description: {
name: 'Alice',
identity: 'alice',
website: 'alice.harmony.one',
securityContact: 'Bob',
details: "Don't mess with me!!!",
},
commissionRate: {
rate: '0.1',
maxRate: '0.9',
maxChangeRate: '0.05',
},
minSelfDelegation: '0xa',
maxTotalDelegation: '0x0bb8',
slotPubKeys: [
'0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611',
],
amount: '0x64',
};
const stakingTxn = harmony.stakings
.createValidator(createMsg)
.setTxParams({
nonce: '0x2',
gasPrice: '0x',
gasLimit: '0x64',
chainId: 0,
})
.build();
stakingTxn
.sendTransaction()
.then(([stakingTxn, res]) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
// const delegateMsg = Delegate({
// delegatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// amount: '0xa',
// });
// const stakingTxn = StakingTransaction({
// directive: '0x2',
// stakeMsg: delegateMsg,
// nonce: '0x2',
// gasPrice: '0x',
// gasLimit: '0x64',
// chainId: 0,
// from: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// });
// stakingTxn
// .sendTransaction()
// .then((stakingTxn, res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });

@ -1,177 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const {
Description,
Decimal,
CommissionRate,
StakingTransaction,
CreateValidator,
} = require('@harmony-js/staking'); //../packages/harmony-staking
const { TxStatus } = require('@harmony-js/transaction');
const LOCALNET = `http://localhost:9500`;
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
LOCALNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyLocal,
},
);
// 2. get wallet ready
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
const private = 'fd416cb87dcf8ed187e85545d7734a192fc8e976f5b540e9e21e896ec2bc25c3';
const sender = harmony.wallet.addByPrivateKey(private);
// const phrase =
// 'genius cable radar memory high catch blossom correct middle wish gentle
// fiscal';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
// const sender = harmony.wallet.addByMnemonic(phrase);
const stakingTxn = harmony.stakings
.createValidator({
validatorAddress: 'one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy',
description: {
name: 'Alice',
identity: 'alice',
website: 'alice.harmony.one',
securityContact: 'Bob',
details: "Don't mess with me!!",
},
commissionRate: { rate: '0.1', maxRate: '0.9', maxChangeRate: '0.05' },
minSelfDelegation: '0x8AC7230489E80000',
maxTotalDelegation: '0xA2A15D09519BE00000',
slotPubKeys: [
'0xb9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b62247608611',
],
amount: '0x56BC75E2D63100000',
})
.setTxParams({
nonce: '0x2',
gasPrice: '0x',
gasLimit: '0x0927c0',
chainId: ChainID.HmyLocal,
})
.build();
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local
// testnet We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
async function execute() {
await setSharding();
const signedTxn = await harmony.wallet.signStaking(stakingTxn);
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// console.log(signedTxn);
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// signedTxn
// .sendTransaction()
// .then((res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });
// to confirm the result if it is already there
console.log(txnHash);
console.log(sentTxn);
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
// if (!confiremdTxn.isCrossShard()) {
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Staking transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
// }
// if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
// console.log('--- Result ---');
// console.log('');
// console.log('Cross-Shard transaction');
// console.log(`${txnHash} is confirmed`);
// console.log('');
// process.exit();
// }
}
execute();
// const delegateMsg = Delegate({
// delegatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// amount: '0xa',
// });
// const stakingTxn = StakingTransaction({
// directive: '0x2',
// stakeMsg: delegateMsg,
// nonce: '0x2',
// gasPrice: '0x',
// gasLimit: '0x64',
// chainId: 0,
// from: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// });
// stakingTxn
// .sendTransaction()
// .then((stakingTxn, res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });

@ -1,173 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const { Undelegate, StakingTransaction, StakingFactory } = require('@harmony-js/staking'); //../packages/harmony-staking
const { TxStatus } = require('@harmony-js/transaction');
const LOCALNET = `http://localhost:9500`;
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
LOCALNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyLocal,
},
);
// 2. get wallet ready
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
const private = '63e35b761e9df0d50ddcdaa8e33c235b60c991bfed22925a12768b0c08ef822f';
const sender = harmony.wallet.addByPrivateKey(private);
// const phrase =
// 'genius cable radar memory high catch blossom correct middle wish gentle
// fiscal';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
// const sender = harmony.wallet.addByMnemonic(phrase);
// let r =
// '0xf8f180f8a4940b585f8daefbc68a311fbd4cb20d9174ad174016f83885416c69636585616c69636591616c6963652e6861726d6f6e792e6f6e6583426f6295446f6e2774206d6573732077697468206d65212121ddc988016345785d8a0000c9880c7d713b49da0000c887b1a2bc2ec500000a820bb8f1b0b9486167ab9087ab818dc4ce026edb5bf216863364c32e42df2af03c5ced1ad181e7d12f0e6dd5307a73b6224760861164008080830927c028a064b1b835f5b70a72228920db24e44c0a57d954c1d3dcac3b33c79d9593f96191a05577fd05064a37043a33ff7febb67ab126a8e1f0b67c92b7cab793a87ddf2c82';
// const undelegateMsg = new Undelegate(
// 'one1pf75h0t4am90z8uv3y0dgunfqp4lj8wr3t5rsp', // signed should match this
// 'one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy',
// '0x16345785d8a0000',
// );
// const stakingTxn = new StakingTransaction(
// '0x3',
// undelegateMsg,
// '0x2',
// '0x',
// '0x0927c0',
// ChainID.HmyLocal,
// );
const stakingTxn = harmony.stakings
.undelegate({
delegatorAddress: 'one1pf75h0t4am90z8uv3y0dgunfqp4lj8wr3t5rsp',
validatorAddress: 'one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy',
amount: '0x16345785d8a0000',
})
.setTxParams({
nonce: '0x2',
gasPrice: '0x',
gasLimit: '0x0927c0',
chainId: ChainID.HmyLocal,
})
.build();
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local
// testnet We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
async function execute() {
await setSharding();
const signedTxn = await harmony.wallet.signStaking(stakingTxn);
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// console.log(signedTxn);
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// signedTxn.sendTransaction()
// .then(res => {
// console.log(res);
// })
// .catch(err => {
// console.log(err);
// });
// to confirm the result if it is already there
// console.log(txnHash);
console.log(sentTxn);
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
// if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
// console.log('--- Result ---');
// console.log('');
// console.log('Cross-Shard transaction');
// console.log(`${txnHash} is confirmed`);
// console.log('');
// process.exit();
// }
}
execute();
// const delegateMsg = Delegate({
// delegatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// validatorAddress: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// amount: '0xa',
// });
// const stakingTxn = StakingTransaction({
// directive: '0x2',
// stakeMsg: delegateMsg,
// nonce: '0x2',
// gasPrice: '0x',
// gasLimit: '0x64',
// chainId: 0,
// from: 'one1a0x3d6xpmr6f8wsyaxd9v36pytvp48zckswvv9',
// });
// stakingTxn
// .sendTransaction()
// .then((stakingTxn, res) => {
// console.log(res);
// })
// .catch((err) => {
// console.log(err);
// });

@ -1,31 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const { encryptPhrase, decryptPhrase } = require('@harmony-js/crypto');
const harmony = new Harmony('http://localhost:9500', { chainId: 2, chainType: 'hmy' });
const myPhrase = harmony.wallet.newMnemonic();
const pwd = '1234';
async function encryptThePhrase(phrase, pass) {
const result = await encryptPhrase(phrase, pass);
return result;
}
async function decryptThePhrase(keystore, pass) {
const result = await decryptPhrase(keystore, pass);
return result;
}
async function phraseKeyStore() {
const keyStore = await encryptThePhrase(myPhrase, pwd);
const recoveredPhrase = await decryptThePhrase(JSON.parse(keyStore), pwd);
return { myPhrase, keyStore, recoveredPhrase };
}
phraseKeyStore().then((result) => {
const { myPhrase, keyStore, recoveredPhrase } = result;
harmony.wallet.addByMnemonic(myPhrase);
console.log({ myPhrase, keyStore, recoveredPhrase });
console.log(harmony.wallet);
});

@ -1,40 +0,0 @@
const { Harmony } = require('@harmony-js/core');
const { ChainID, ChainType } = require('@harmony-js/utils');
const {
randomBytes,
generatePrivateKey,
getAddress,
getAddressFromPrivateKey,
encryptPhrase,
decryptPhrase,
} = require('@harmony-js/crypto');
const harmony = new Harmony('http://localhost:9500', { chainId: 2, chainType: 'hmy' });
const myPhrase = harmony.wallet.newMnemonic();
const pwd = '1234';
async function encryptThePhrase(phrase, pass) {
const result = await encryptPhrase(phrase, pass);
return result;
}
async function decryptThePhrase(keystore, pass) {
const result = await decryptPhrase(keystore, pass);
return result;
}
async function phraseKeyStore() {
const keyStore = await encryptThePhrase(myPhrase, pwd);
const recoveredPhrase = await decryptThePhrase(JSON.parse(keyStore), pwd);
return { myPhrase, keyStore, recoveredPhrase };
}
phraseKeyStore().then((result) => {
const { myPhrase, keyStore, recoveredPhrase } = result;
const anotherPhrase = 'wall public vague under poem acid jaguar describe net scene sponsor neck';
harmony.wallet.addByMnemonic(myPhrase);
harmony.wallet.addByMnemonic(anotherPhrase);
console.log({ myPhrase, keyStore, recoveredPhrase });
console.log(harmony.wallet);
});

@ -1,153 +0,0 @@
// import or require Harmony class
const { Harmony } = require('@harmony-js/core');
// import or require settings
const { ChainID, ChainType } = require('@harmony-js/utils');
const URL_TESTNET = `https://api.s0.b.hmny.io`;
const URL_MAINNET = `https://api.s0.t.hmny.io`;
const URL_PANGAEA = 'https://api.s0.pga.hmny.io';
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
URL_PANGAEA,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyPangaea,
},
);
// 2. get wallet ready
// one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg
const phrase = 'genius cable radar memory high catch blossom correct middle wish gentle fiscal';
// const phrase =
// 'resemble rent deposit unique garment ripple burst negative else decorate menu theme';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
const privateKey = '63e35b761e9df0d50ddcdaa8e33c235b60c991bfed22925a12768b0c08ef822f';
const sender = harmony.wallet.addByMnemonic(phrase);
const sender2 = harmony.wallet.addByPrivateKey(privateKey);
harmony.wallet.setSigner(sender2.address);
console.log('sender2Address is : ', sender2.bech32Address);
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local testnet
// We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
// 4. get transaction payload ready
async function transfer(receiver) {
// run set sharding first, if you want to make a cross-shard transaction
await setSharding();
//1e18
const txn = harmony.transactions.newTx({
// token send to
to: receiver,
// amount to send
value: '100000000',
// gas limit, you can use string
gasLimit: '210000',
// send token from shardID
shardID: 0,
// send token to toShardID
toShardID: 1,
// gas Price, you can use Unit class, and use Gwei, then remember to use toWei(), which will be transformed to BN
gasPrice: new harmony.utils.Unit('10').asGwei().toWei(),
});
// sign the transaction use wallet;
// This will happen at the chrome extension.
const signedTxn = await harmony.wallet.signTransaction(txn);
// Now you can use `Transaction.observed()` to listen events
// Frontend received back the signedTxn and do the followings to Send transaction.
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// send the txn, get [Transaction, transactionHash] as result
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// to confirm the result if it is already there
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
if (!confiremdTxn.isCrossShard()) {
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
console.log('please see detail in explorer:');
console.log('');
console.log('https://explorer.harmony.one/#/tx/' + txnHash);
console.log('');
process.exit();
}
}
if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Cross-Shard transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
console.log('please see detail in explorer:');
console.log('');
console.log('https://explorer.harmony.one/#/tx/' + txnHash);
console.log('');
process.exit();
}
}
// sending from one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg to one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
(async () => await transfer('one1pf75h0t4am90z8uv3y0dgunfqp4lj8wr3t5rsp'))();

@ -1,151 +0,0 @@
// import or require Harmony class
const { Harmony } = require('@harmony-js/core');
// import or require settings
const { ChainID, ChainType } = require('@harmony-js/utils');
// const URL_TESTNET = `https://api.s0.pga.hmny.io`;
const URL_MAINNET = `https://api.s0.t.hmny.io`;
// const LOCAL_TESTNET = `http://localhost:9500`;
const DEVNET = 'https://api.s0.pga.hmny.io';
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
DEVNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyPangaea,
},
);
// 2. get wallet ready
// one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg;
const phrase = 'genius cable radar memory high catch blossom correct middle wish gentle fiscal';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
// const sender = harmony.wallet.addByMnemonic(phrase);
// add privateKey to wallet
const private = '63e35b761e9df0d50ddcdaa8e33c235b60c991bfed22925a12768b0c08ef822f';
// one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy
const sender = harmony.wallet.addByPrivateKey(private);
// const sender = harmony.wallet.addByPrivateKey(
// 'fd416cb87dcf8ed187e85545d7734a192fc8e976f5b540e9e21e896ec2bc25c3',
// );
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local testnet
// We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
// 4. get transaction payload ready
async function transfer(receiver) {
// run set sharding first, if you want to make a cross-shard transaction
await setSharding();
//1e18
const txn = harmony.transactions.newTx({
// token send to
to: receiver,
// amount to send
value: '100000000000000000',
// 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 harmony.utils.Unit('100').asGwei().toWei(),
});
// sign the transaction use wallet;
// This will happen at the chrome extension.
const signedTxn = await harmony.wallet.signTransaction(txn);
// Now you can use `Transaction.observed()` to listen events
// Frontend received back the signedTxn and do the followings to Send transaction.
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// send the txn, get [Transaction, transactionHash] as result
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// to confirm the result if it is already there
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
// if (!confiremdTxn.isCrossShard()) {
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
console.log('please see detail in explorer:');
console.log('');
console.log('https://explorer.harmony.one/#/tx/' + txnHash);
console.log('');
process.exit();
}
// }
if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Cross-Shard transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
console.log('please see detail in explorer:');
console.log('');
console.log('https://explorer.harmony.one/#/tx/' + txnHash);
console.log('');
process.exit();
}
}
// sending from one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg to one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
(async () => await transfer('one1pdv9lrdwl0rg5vglh4xtyrv3wjk3wsqket7zxy'))();

@ -1,137 +0,0 @@
// import or require Harmony class
const { Harmony } = require('@harmony-js/core');
// import or require settings
const { ChainID, ChainType } = require('@harmony-js/utils');
//const URL_TESTNET = `https://api.s0.b.hmny.io`;
const URL_TESTNET = `localhost:9500`;
const URL_MAINNET = `https://api.s0.t.hmny.io`;
// 1. initialize the Harmony instance
const harmony = new Harmony(
// rpc url
URL_TESTNET,
{
// chainType set to Harmony
chainType: ChainType.Harmony,
// chainType set to HmyLocal
chainId: ChainID.HmyTestnet,
},
);
// 2. get wallet ready
// one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg
//const phrase = 'genius cable radar memory high catch blossom correct middle wish gentle fiscal';
// one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
// surge welcome lion goose gate consider taste injury health march debris kick
// add privateKey to wallet
//const sender = harmony.wallet.addByMnemonic(phrase);
// add privateKey to wallet
const private = 'fd416cb87dcf8ed187e85545d7734a192fc8e976f5b540e9e21e896ec2bc25c3';
const sender = harmony.wallet.addByPrivateKey(private);
// 3. get sharding info
async function setSharding() {
// Harmony is a sharded blockchain, each endpoint have sharding structure,
// However sharding structure is different between mainnet, testnet and local testnet
// We need to get sharding info before doing cross-shard transaction
const res = await harmony.blockchain.getShardingStructure();
harmony.shardingStructures(res.result);
}
// 4. get transaction payload ready
async function transfer(receiver) {
// run set sharding first, if you want to make a cross-shard transaction
await setSharding();
//1e18
const txn = harmony.transactions.newTx({
// token send to
to: receiver,
// amount to send
value: '100000000000000000',
// 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 harmony.utils.Unit('100').asGwei().toWei(),
});
// sign the transaction use wallet;
// This will happen at the chrome extension.
const signedTxn = await harmony.wallet.signTransaction(txn);
// Now you can use `Transaction.observed()` to listen events
// Frontend received back the signedTxn and do the followings to Send transaction.
signedTxn
.observed()
.on('transactionHash', (txnHash) => {
console.log('');
console.log('--- hash ---');
console.log('');
console.log(txnHash);
console.log('');
})
.on('receipt', (receipt) => {
console.log('');
console.log('--- receipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('cxReceipt', (receipt) => {
console.log('');
console.log('--- cxReceipt ---');
console.log('');
console.log(receipt);
console.log('');
})
.on('error', (error) => {
console.log('');
console.log('--- error ---');
console.log('');
console.log(error);
console.log('');
});
// send the txn, get [Transaction, transactionHash] as result
const [sentTxn, txnHash] = await signedTxn.sendTransaction();
// to confirm the result if it is already there
const confiremdTxn = await sentTxn.confirm(txnHash);
// if the transactino is cross-shard transaction
if (!confiremdTxn.isCrossShard()) {
if (confiremdTxn.isConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Normal transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
}
if (confiremdTxn.isConfirmed() && confiremdTxn.isCxConfirmed()) {
console.log('--- Result ---');
console.log('');
console.log('Cross-Shard transaction');
console.log(`${txnHash} is confirmed`);
console.log('');
process.exit();
}
}
// sending from one18n8e7472pg5fqvcfcr5hg0npquha24wsxmjheg to one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65
transfer('one1a2rhuaqjcvfu69met9sque2l3w5v9z6qcdcz65');

@ -4,14 +4,14 @@ const fs = require('fs');
const path = require('path');
const packages = [
'harmony-core',
'harmony-crypto',
'harmony-account',
'harmony-network',
'harmony-contract',
'harmony-utils',
'harmony-transaction',
'harmony-staking',
'woop-core',
'woop-crypto',
'woop-account',
'woop-network',
'woop-contract',
'woop-utils',
'woop-transaction',
'woop-staking',
];
task('cleanBrowser', async () => {

@ -2,5 +2,5 @@
"packages": ["packages/*"],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.1.36"
"version": "0.1.58"
}

1081
log.txt

File diff suppressed because it is too large Load Diff

44661
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
{
"description": "Root repository for the harmony-sdk-core",
"description": "Root repository for the woop-sdk-core",
"private": true,
"license": "MIT",
"workspaces": [
@ -89,14 +89,14 @@
"dotenv": "^6.0.0",
"fancy-log": "^1.3.2",
"fbjs-scripts": "^0.8.3",
"ganache-cli": "^6.4.3",
"ganache-cli": "^6.12.1",
"glob": "^7.1.3",
"glob-parent": "^3.1.0",
"gulp": "^4.0.0",
"gulp-typedoc": "^2.2.2",
"husky": "^1.1.2",
"jest": "^23.4.2",
"jest-fetch-mock": "^1.6.6",
"jest-fetch-mock": "^3.0.3",
"jest-json-schema": "^2.0.1",
"jest-watch-typeahead": "^0.2.0",
"jsdoc": "^3.6.3",
@ -107,7 +107,7 @@
"pretty-quick": "^1.8.0",
"protobufjs": "^6.8.8",
"rimraf": "^2.6.2",
"rollup": "^0.66.6",
"rollup": "1.26.3",
"rollup-plugin-alias": "^1.4.0",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-commonjs": "^9.2.0",
@ -117,17 +117,19 @@
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-typescript2": "^0.17.1",
"rollup-plugin-typescript2": "^0.29.0",
"solc": "^0.5.8",
"terser-webpack-plugin": "^2.1.2",
"ts-jest": "^23.1.3",
"ts-node": "^7.0.1",
"tslib": "^2.4.0",
"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",
"typescript-json-schema": "^0.43.0",
"webpack": "^4.20.2",
"webpack-command": "^0.4.1",
"webpack-node-externals": "^1.7.2",
@ -138,8 +140,10 @@
"pre-commit": "pretty-quick --staged"
}
},
"name": "harmony-sdk-core",
"name": "woop-sdk-core",
"dependencies": {
"tslib": "^1.11.1"
"@woop-js/core": "^0.1.36",
"tslib": "^2.4.0",
"typedoc-plugin-internal-external": "^2.1.1"
}
}

@ -0,0 +1,12 @@
# Packages available are:
1. [@woop-js/core](https://github.com/woop-chain/sdk/tree/master/packages/woop-core)
2. [@woop-js/account](https://github.com/woop-chain/sdk/tree/master/packages/woop-account)
3. [@woop-js/crypto](https://github.com/woop-chain/sdk/tree/master/packages/woop-crypto)
4. [@woop-js/network](https://github.com/woop-chain/sdk/tree/master/packages/woop-network)
5. [@woop-js/utils](https://github.com/woop-chain/sdk/tree/master/packages/woop-utils)
6. [@woop-js/transaction](https://github.com/woop-chain/sdk/tree/master/packages/woop-transaction)
7. [@woop-js/contract](https://github.com/woop-chain/sdk/tree/master/packages/woop-contract)
8. [@woop-js/staking](https://github.com/woop-chain/sdk/tree/master/packages/woop-staking)
<mark>Package level documentation and examples are inside each package</mark>

@ -1,259 +0,0 @@
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
`@harmony-js/account` is dealing with account related features.
Developers can use this packages 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
```typescript
// 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
import {Wallet} from '@harmony-js/account'
const wallet=new Wallet()
```

@ -1,8 +0,0 @@
import { HttpProvider, Messenger } from '@harmony-js/network';
import { ChainType, ChainID } from '@harmony-js/utils';
export const defaultMessenger = new Messenger(
new HttpProvider('http://localhost:9500'),
ChainType.Harmony,
ChainID.HmyLocal,
);

@ -1,15 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src", "../../typings/**/*.d.ts"],
"references": [
{ "path": "../harmony-crypto" },
{ "path": "../harmony-utils" },
{ "path": "../harmony-transaction" },
{ "path": "../harmony-staking" },
{ "path": "../harmony-network" }
]
}

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

File diff suppressed because one or more lines are too long

@ -1,30 +0,0 @@
{
"name": "@harmony-js/core",
"version": "0.1.36",
"description": "harmony core package",
"main": "dist/index.js",
"node": "dist/index.js",
"browser": "dist/index.js",
"module": "dist/index.esm.js",
"jsnext:main": "dist/index.esm.js",
"typings": "dist/index.d.ts",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"publishConfig": {
"access": "public"
},
"author": "neeboo@firestack.one",
"license": "MIT",
"dependencies": {
"@harmony-js/account": "0.1.36",
"@harmony-js/contract": "0.1.36",
"@harmony-js/crypto": "0.1.35",
"@harmony-js/network": "0.1.35",
"@harmony-js/staking": "0.1.36",
"@harmony-js/transaction": "0.1.35",
"@harmony-js/utils": "0.1.35"
},
"gitHead": "27bce049c8d99498f464ce2db4fc39e4000a5420"
}

@ -1,526 +0,0 @@
import {
RPCMethod,
Messenger,
ResponseMiddleware,
WSProvider,
NewPendingTransactions,
NewHeaders,
LogSub,
Syncing,
} from '@harmony-js/network';
import {
assertObject,
AssertType,
// HarmonyCore,
DefaultBlockParams,
} from '@harmony-js/utils';
import { getAddress } from '@harmony-js/crypto';
import { Transaction } from '@harmony-js/transaction';
import { StakingTransaction } from '@harmony-js/staking';
class Blockchain {
messenger: Messenger;
constructor(messenger: Messenger) {
this.messenger = messenger;
}
setMessenger(messenger: Messenger) {
this.messenger = messenger;
}
getRpcResult(result: any) {
if (result instanceof ResponseMiddleware) {
return result.getRaw;
} else {
return result;
}
}
/**
*
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
blockNumber: ['isBlockNumber', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getBalance({
address,
blockNumber = DefaultBlockParams.latest,
shardID = this.messenger.currentShard,
}: {
address: string;
blockNumber?: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetBalance,
[getAddress(address).checksum, blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
async getBlockNumber(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.BlockNumber,
[],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
/**
*
*/
@assertObject({
blockHash: ['isHash', AssertType.required],
returnObject: ['isBoolean', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getBlockByHash({
blockHash,
returnObject = true,
shardID = this.messenger.currentShard,
}: {
blockHash: string;
returnObject?: boolean;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetBlockByHash,
[blockHash, returnObject],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
/**
*
*/
@assertObject({
blockNumber: ['isBlockNumber', AssertType.optional],
returnObject: ['isBoolean', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getBlockByNumber({
blockNumber = DefaultBlockParams.latest,
returnObject = true,
shardID = this.messenger.currentShard,
}: {
blockNumber?: string;
returnObject?: boolean;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetBlockByNumber,
[blockNumber, returnObject],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
blockHash: ['isHash', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getBlockTransactionCountByHash({
blockHash,
shardID = this.messenger.currentShard,
}: {
blockHash: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetBlockTransactionCountByHash,
[blockHash],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
blockNumber: ['isBlockNumber', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getBlockTransactionCountByNumber({
blockNumber,
shardID = this.messenger.currentShard,
}: {
blockNumber: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetBlockTransactionCountByNumber,
[blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
/**
*
*/
@assertObject({
blockHash: ['isHash', AssertType.required],
index: ['isHex', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getTransactionByBlockHashAndIndex({
blockHash,
index,
shardID = this.messenger.currentShard,
}: {
blockHash: string;
index: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetTransactionByBlockHashAndIndex,
[blockHash, index],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
blockNumber: ['isBlockNumber', AssertType.optional],
index: ['isHex', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getTransactionByBlockNumberAndIndex({
blockNumber = DefaultBlockParams.latest,
index,
shardID = this.messenger.currentShard,
}: {
blockNumber?: string;
index: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetTransactionByBlockNumberAndIndex,
[blockNumber, index],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
txnHash: ['isHash', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getTransactionByHash({
txnHash,
shardID = this.messenger.currentShard,
}: {
txnHash: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetTransactionByHash,
[txnHash],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
/**
*
*/
@assertObject({
txnHash: ['isString', AssertType.required],
shardID: ['isNumber', AssertType.optional],
})
async getTransactionReceipt({
txnHash,
shardID = this.messenger.currentShard,
}: {
txnHash: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetTransactionReceipt,
[txnHash],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
txnHash: ['isString', AssertType.required],
shardID: ['isNumber', AssertType.required],
})
async getCxReceiptByHash({ txnHash, shardID }: { txnHash: string; shardID: number }) {
const result = await this.messenger.send(
RPCMethod.GetCXReceiptByHash,
[txnHash],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
/**
*
*/
@assertObject({
address: ['isValidAddress', AssertType.required],
blockNumber: ['isBlockNumber', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getCode({
address,
blockNumber = DefaultBlockParams.latest,
shardID = this.messenger.currentShard,
}: {
address: string;
blockNumber?: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetCode,
[getAddress(address).checksum, blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
async net_peerCount(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(RPCMethod.PeerCount, [], 'net', shardID);
return this.getRpcResult(result);
}
async net_version(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(RPCMethod.NetVersion, [], 'net', shardID);
return this.getRpcResult(result);
}
async getProtocolVersion(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.ProtocolVersion,
[],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
address: ['isValidAddress', AssertType.required],
position: ['isHex', AssertType.required],
blockNumber: ['isBlockNumber', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getStorageAt({
address,
position,
blockNumber = DefaultBlockParams.latest,
shardID = this.messenger.currentShard,
}: {
address: string;
position: string;
blockNumber?: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetStorageAt,
[getAddress(address).checksum, position, blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
@assertObject({
address: ['isValidAddress', AssertType.required],
blockNumber: ['isBlockNumber', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async getTransactionCount({
address,
blockNumber = DefaultBlockParams.latest,
shardID = this.messenger.currentShard,
}: {
address: string;
blockNumber?: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.GetTransactionCount,
[getAddress(address).checksum, blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
async getShardingStructure() {
const result = await this.messenger.send(
RPCMethod.GetShardingStructure,
[],
this.messenger.chainPrefix,
);
return this.getRpcResult(result);
}
async sendTransaction(transaction: Transaction) {
if (!transaction.isSigned() || !transaction) {
throw new Error('transaction is not signed or not exist');
}
const result = await this.messenger.send(
RPCMethod.SendRawTransaction,
[transaction.getRawTransaction()],
this.messenger.chainPrefix,
typeof transaction.txParams.shardID === 'string'
? Number.parseInt(transaction.txParams.shardID, 10)
: transaction.txParams.shardID,
);
return this.getRpcResult(result);
}
async sendRawTransaction(transaction: Transaction) {
if (!transaction.isSigned() || !transaction) {
throw new Error('transaction is not signed or not exist');
}
const [txn, result] = await transaction.sendTransaction();
if (txn.isPending()) {
return result;
}
}
createObservedTransaction(transaction: Transaction) {
try {
transaction.sendTransaction().then((response: any) => {
const [txReturned, TranID] = response;
txReturned.confirm(TranID).then((txConfirmed: Transaction) => {
transaction.emitter.resolve(txConfirmed);
});
});
return transaction.emitter;
} catch (err) {
throw err;
}
}
async sendRawStakingTransaction(staking: StakingTransaction) {
if (!staking.isSigned() || !staking) {
throw new Error('staking transaction is not signed or not exist');
}
const [txn, result] = await staking.sendTransaction();
if (txn.isPending()) {
return result;
}
}
createObservedStakingTransaction(staking: StakingTransaction) {
try {
staking.sendTransaction().then((response: any) => {
const [txReturned, TranID] = response;
txReturned.confirm(TranID).then((txConfirmed: StakingTransaction) => {
staking.emitter.resolve(txConfirmed);
});
});
return staking.emitter;
} catch (err) {
throw err;
}
}
@assertObject({
to: ['isValidAddress', AssertType.optional],
data: ['isHex', AssertType.optional],
shardID: ['isNumber', AssertType.optional],
})
async estimateGas({
to,
data,
shardID = this.messenger.currentShard,
}: {
to: string;
data: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.EstimateGas,
[{ to: getAddress(to).checksum, data }],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
async gasPrice(shardID: number = this.messenger.currentShard) {
const result = await this.messenger.send(
RPCMethod.GasPrice,
[],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
async call({
payload,
blockNumber = DefaultBlockParams.latest,
shardID = this.messenger.currentShard,
}: {
payload: any;
blockNumber?: string;
shardID?: number;
}) {
const result = await this.messenger.send(
RPCMethod.Call,
[payload, blockNumber],
this.messenger.chainPrefix,
shardID,
);
return this.getRpcResult(result);
}
newPendingTransactions(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new NewPendingTransactions(this.messenger, shardID);
} else {
throw new Error('HttpProvider does not support this feature');
}
}
newBlockHeaders(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new NewHeaders(this.messenger, shardID);
} else {
throw new Error('HttpProvider does not support this feature');
}
}
syncing(shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new Syncing(this.messenger, shardID);
} else {
throw new Error('HttpProvider does not support this feature');
}
}
logs(options: any, shardID: number = this.messenger.currentShard) {
if (this.messenger.provider instanceof WSProvider) {
return new LogSub(options, this.messenger, shardID);
} else {
throw new Error('HttpProvider does not support this feature');
}
}
}
export { Blockchain };

@ -1,103 +0,0 @@
import * as crypto from '@harmony-js/crypto';
import * as utils from '@harmony-js/utils';
import { Provider, HttpProvider, Messenger, WSProvider, ShardingItem } from '@harmony-js/network';
import { TransactionFactory, Transaction } from '@harmony-js/transaction';
import { StakingTransaction, StakingFactory } from '@harmony-js/staking';
import { ContractFactory, Contract } from '@harmony-js/contract';
import { Wallet, Account } from '@harmony-js/account';
import { Blockchain } from './blockchain';
import { HarmonyConfig } from './util';
export class Harmony extends utils.HarmonyCore {
Modules = {
HttpProvider,
WSProvider,
Messenger,
Blockchain,
TransactionFactory,
StakingFactory,
Wallet,
Transaction,
StakingTransaction,
Account,
Contract,
};
messenger: Messenger;
transactions: TransactionFactory;
stakings: StakingFactory;
wallet: Wallet;
blockchain: Blockchain;
contracts: ContractFactory;
crypto: any;
utils: any;
defaultShardID?: number;
private provider: HttpProvider | WSProvider;
constructor(
url: string,
config: HarmonyConfig = {
chainId: utils.defaultConfig.Default.Chain_ID,
chainType: utils.defaultConfig.Default.Chain_Type,
},
) {
super(config.chainType, config.chainId);
const providerUrl = config.chainUrl || url || utils.defaultConfig.Default.Chain_URL;
this.provider = new Provider(providerUrl).provider;
this.messenger = new Messenger(this.provider, this.chainType, this.chainId);
this.blockchain = new Blockchain(this.messenger);
this.transactions = new TransactionFactory(this.messenger);
this.stakings = new StakingFactory(this.messenger);
this.wallet = new Wallet(this.messenger);
this.contracts = new ContractFactory(this.wallet);
this.crypto = crypto;
this.utils = utils;
this.defaultShardID = config.shardID;
if (this.defaultShardID !== undefined) {
this.setShardID(this.defaultShardID);
}
}
public setProvider(provider: string | HttpProvider | WSProvider): void {
this.provider = new Provider(provider).provider;
this.messenger.setProvider(this.provider);
this.setMessenger(this.messenger);
}
public setChainId(chainId: utils.ChainID) {
this.chainId = chainId;
this.messenger.setChainId(this.chainId);
this.setMessenger(this.messenger);
}
public setShardID(shardID: number) {
this.defaultShardID = shardID;
this.messenger.setDefaultShardID(this.defaultShardID);
this.setMessenger(this.messenger);
}
public setChainType(chainType: utils.ChainType) {
this.chainType = chainType;
this.messenger.setChainType(this.chainType);
this.setMessenger(this.messenger);
}
public shardingStructures(shardingStructures: ShardingItem[]) {
for (const shard of shardingStructures) {
const shardID =
typeof shard.shardID === 'string' ? Number.parseInt(shard.shardID, 10) : shard.shardID;
this.messenger.shardProviders.set(shardID, {
current: shard.current !== undefined ? shard.current : false,
shardID,
http: shard.http,
ws: shard.ws,
});
}
this.setMessenger(this.messenger);
}
private setMessenger(messenger: Messenger) {
this.blockchain.setMessenger(messenger);
this.wallet.setMessenger(messenger);
this.transactions.setMessenger(messenger);
this.stakings.setMessenger(messenger);
}
}

@ -1,5 +0,0 @@
export * from './harmony';
export * from './blockchain';
export * from './truffleProvider';
export * from './harmonyExtension';
export * from './types';

@ -1,25 +0,0 @@
import { HttpProvider, Messenger } from '@harmony-js/network';
import { TransactionFactory, Transaction } from '@harmony-js/transaction';
import { Wallet, Account } from '@harmony-js/account';
import { ChainType, ChainID } from '@harmony-js/utils';
import { Blockchain } from './blockchain';
export interface HarmonyModule {
HttpProvider: HttpProvider;
Messenger: Messenger;
Blockchain: Blockchain;
TransactionFactory: TransactionFactory;
Wallet: Wallet;
Transaction: Transaction;
Account: Account;
}
export const enum UrlType {
http,
ws,
}
export interface HarmonySetting<T extends ChainType, I extends ChainID> {
type: T;
id: I;
}

@ -1,16 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src", "../../typings/**/*.d.ts", "../harmony-utils/src/core.ts"],
"references": [
{"path": "../harmony-account"},
{"path": "../harmony-crypto"},
{"path": "../harmony-utils"},
{"path": "../harmony-network"},
{"path": "../harmony-transaction"},
{"path": "../harmony-contract"}
]
}

@ -1,80 +0,0 @@
import { isAddress, isBech32Address, isBech32TestNetAddress } from '@harmony-js/utils';
import { toChecksumAddress } from './keyTool';
import { fromBech32, toBech32, HRP, tHRP } from './bech32';
export class HarmonyAddress {
// static validator
static isValidBasic(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.basic;
}
// static validator
static isValidChecksum(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.checksum;
}
// static validator
static isValidBech32(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.bech32;
}
// static validator
static isValidBech32TestNet(str: string) {
const toTest = new HarmonyAddress(str);
return toTest.raw === toTest.bech32TestNet;
}
raw: string;
basic: string;
get basicHex() {
return `0x${this.basic}`;
}
get checksum() {
return toChecksumAddress(`0x${this.basic}`);
}
get bech32() {
return toBech32(this.basic, HRP);
}
get bech32TestNet() {
return toBech32(this.basic, tHRP);
}
constructor(raw: string) {
this.raw = raw;
this.basic = this.getBasic(this.raw);
}
private getBasic(addr: string) {
const basicBool = isAddress(addr);
const bech32Bool = isBech32Address(addr);
const bech32TestNetBool = isBech32TestNetAddress(addr);
if (basicBool) {
return addr.replace('0x', '').toLowerCase();
}
if (bech32Bool) {
const fromB32 = fromBech32(addr, HRP);
return fromB32.replace('0x', '').toLowerCase();
}
if (bech32TestNetBool) {
const fromB32TestNet = fromBech32(addr, tHRP);
return fromB32TestNet.replace('0x', '').toLowerCase();
}
throw new Error(`"${addr}" is an invalid address format`);
}
}
export function getAddress(address: string) {
try {
return new HarmonyAddress(address);
} catch (error) {
throw error;
}
}

@ -1,100 +0,0 @@
export const enum RPCMethod {
// 1. hmy_getBlockByHash
GetBlockByHash = 'hmy_getBlockByHash',
// 2. hmy_getBlockByNumber
GetBlockByNumber = 'hmy_getBlockByNumber',
// 3. hmy_getBlockTransactionCountByHash
GetBlockTransactionCountByHash = 'hmy_getBlockTransactionCountByHash',
// 4. hmy_getBlockTransactionCountByNumber
GetBlockTransactionCountByNumber = 'hmy_getBlockTransactionCountByNumber',
// 5. hmy_getCode
GetCode = 'hmy_getCode',
// 6. hmy_getTransactionByBlockHashAndIndex
GetTransactionByBlockHashAndIndex = 'hmy_getTransactionByBlockHashAndIndex',
// 7. hmy_getTransactionByBlockNumberAndIndex
GetTransactionByBlockNumberAndIndex = 'hmy_getTransactionByBlockNumberAndIndex',
// 8. hmy_getTransactionByHash
GetTransactionByHash = 'hmy_getTransactionByHash',
GetTransactionReceipt = 'hmy_getTransactionReceipt',
GetCXReceiptByHash = 'hmy_getCXReceiptByHash',
// 9. hmy_syncing
Syncing = 'hmy_syncing',
// 10. net_peerCount
PeerCount = 'net_peerCount',
// 11. hmy_getBalance
GetBalance = 'hmy_getBalance',
// 12. hmy_getStorageAt
GetStorageAt = 'hmy_getStorageAt',
// 13. hmy_getTransactionCount
GetTransactionCount = 'hmy_getTransactionCount',
// 14. hmy_sendTransaction
SendTransaction = 'hmy_sendTransaction',
// 15. hmy_sendRawTransaction
SendRawTransaction = 'hmy_sendRawTransaction',
// 16. hmy_subscribe
Subscribe = 'hmy_subscribe',
// 17. hmy_getlogs
GetPastLogs = 'hmy_getLogs',
// 18. hmy_getWork
GetWork = 'hmy_getWork',
// 19. hmy_submitWork
// SubmitWork = 'hmy_submitWork',
// 20. hmy_getProof
GetProof = 'hmy_getProof',
// 21, hmy_getFilterChanges
GetFilterChanges = 'hmy_getFilterChanges',
// 22. hmy_newPendingTransactionFilter
NewPendingTransactionFilter = 'hmy_newPendingTransactionFilter',
// 23. hmy_newBlockFilter
NewBlockFilter = 'hmy_newBlockFilter',
// 24. hmy_newFilter
NewFilter = 'hmy_newFilter',
// 25. hmy_call
Call = 'hmy_call',
// 26. hmy_estimateGas
EstimateGas = 'hmy_estimateGas',
// 27. hmy_gasPrice
GasPrice = 'hmy_gasPrice',
// 28. hmy_blockNumber
BlockNumber = 'hmy_blockNumber',
// 29. hmy_unsubscribe
UnSubscribe = 'hmy_unsubscribe',
// 30. net_version
NetVersion = 'net_version',
// 31. hmy_protocolVersion
ProtocolVersion = 'hmy_protocolVersion',
// 32. hmy_getShardingStructure
GetShardingStructure = 'hmy_getShardingStructure',
// 33. hmy_sendRawStakingTransaction
SendRawStakingTransaction = 'hmy_sendRawStakingTransaction',
}
export const enum RPCErrorCode {
// Standard JSON-RPC 2.0 errors
// RPC_INVALID_REQUEST is internally mapped to HTTP_BAD_REQUEST (400).
// It should not be used for application-layer errors.
RPC_INVALID_REQUEST = -32600,
// RPC_METHOD_NOT_FOUND is internally mapped to HTTP_NOT_FOUND (404).
// It should not be used for application-layer errors.
RPC_METHOD_NOT_FOUND = -32601,
RPC_INVALID_PARAMS = -32602,
// RPC_INTERNAL_ERROR should only be used for genuine errors in bitcoind
// (for example datadir corruption).
RPC_INTERNAL_ERROR = -32603,
RPC_PARSE_ERROR = -32700,
// General application defined errors
RPC_MISC_ERROR = -1, // std::exception thrown in command handling
RPC_TYPE_ERROR = -3, // Unexpected type was passed as parameter
RPC_INVALID_ADDRESS_OR_KEY = -5, // Invalid address or key
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
RPC_DATABASE_ERROR = -20, // Database error
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
RPC_VERIFY_ERROR = -25, // General error during transaction or block submission
RPC_VERIFY_REJECTED = -26, // Transaction or block was rejected by network rules
RPC_IN_WARMUP = -28, // Client still warming up
RPC_METHOD_DEPRECATED = -32, // RPC method is deprecated
}

@ -1,2 +0,0 @@
export * from './stakingTransaction';
export * from './factory';

@ -1,39 +0,0 @@
import { getContractAddress, getAddress } from '@harmony-js/crypto';
import { Messenger } from '@harmony-js/network';
import { Transaction } from './transaction';
import { ShardingTransaction } from './shardingTransaction';
import { TxParams, TxStatus } from './types';
export class TransactionFactory {
static getContractAddress(tx: Transaction) {
const { from, nonce } = tx.txParams;
return getAddress(
getContractAddress(getAddress(from).checksum, Number.parseInt(`${nonce}`, 10)),
).checksum;
}
messenger: Messenger;
constructor(messenger: Messenger) {
this.messenger = messenger;
}
setMessenger(messenger: Messenger) {
this.messenger = messenger;
}
newTx(txParams?: TxParams | any, sharding: boolean = false): Transaction {
if (!sharding) {
return new Transaction(txParams, this.messenger, TxStatus.INTIALIZED);
}
return new ShardingTransaction(txParams, this.messenger, TxStatus.INTIALIZED);
}
clone(transaction: Transaction): Transaction {
return new Transaction(transaction.txParams, this.messenger, TxStatus.INTIALIZED);
}
recover(txHash: string): Transaction {
const newTxn = new Transaction({}, this.messenger, TxStatus.INTIALIZED);
newTxn.recover(txHash);
return newTxn;
}
}

@ -1,48 +0,0 @@
import { BN, Signature } from '@harmony-js/crypto';
export 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;
}
export const enum TxStatus {
NONE = 'NONE',
INTIALIZED = 'INITIALIZED',
SIGNED = 'SIGNED',
PENDING = 'PENDING',
CONFIRMED = 'CONFIRMED',
REJECTED = 'REJECTED',
}
export 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`
}

@ -1,73 +0,0 @@
export const enum ChainType {
Harmony = 'hmy',
Ethereum = 'eth',
}
export const enum ChainID {
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,
}
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',
},
};
export abstract class HarmonyCore {
chainType: ChainType;
chainId: ChainID;
constructor(chainType: ChainType, chainId: ChainID = defaultConfig.Default.Chain_ID) {
this.chainType = chainType;
this.chainId = chainId;
}
get chainPrefix(): string {
switch (this.chainType) {
case ChainType.Ethereum: {
return 'eth';
}
case ChainType.Harmony: {
return 'hmy';
}
default: {
return 'hmy';
}
}
}
get getChainId(): ChainID {
return this.chainId;
}
public setChainId(chainId: ChainID) {
this.chainId = chainId;
}
public setChainType(chainType: ChainType) {
this.chainType = chainType;
}
}
export const HDPath = `m/44'/1023'/0'/0/`;
export const AddressSuffix = '-';

@ -0,0 +1,210 @@
# @woop-js/account
This package provides a collection of apis to create accounts and wallets and sign using them. A wallet can hold multiple accounts and account is associated with a unique `one` address. This package also provides facilies to manage account keys.
## Installation
```
npm install @woop-js/account
```
## Usage
Creating new account and display hex and bech32 (one) addresses
```javascript
const account = new Account(); // or const account = Account.new()
console.log(account.checksumAddress);
console.log(account.bech32Address);
```
Creating new account using private key
```javascript
const account = Account.add('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
```
Creating account using private key and custom messenger
```javascript
const account = new Account(
'45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
```
Creating account and setting custom messenger
```javascript
// uses by default http://localhost:9500 as messenger
const account = new Account();
const customMessenger = new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
);
account.setMessenger(customMessenger);
```
Storing the account data to keystore file
```javascript
const passphrase = '';
const account = new Account('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
account.toFile(passphrase).then(keystore => {
console.log(keystore);
});
```
Fetching account from keystore file
```javascript
const passphrase = '';
const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
const account = new Account();
account.fromFile(keystore, passphrase).then(account => {
console.log(account.bech32Address);
});
```
Get the account balance
```javascript
const account = new Account(
'45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
account.getBalance().then(response => {
console.log(response);
});
```
outputs `{ balance: '9126943763247054940484', nonce: 45, shardID: 0 }`
Create a transaction and account, and sign it
```javascript
const account = new Account(
'45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
const { TransactionFactory } = require('@woop-js/transaction');
const { Unit } = require('@woop-js/utils');
const factory = new TransactionFactory();
const txn = factory.newTx({
to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
value: new Unit(1).asOne().toWei(),
// gas limit, you can use string
gasLimit: '21000',
// 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('1').asGwei().toWei(),
});
account.signTransaction(txn).then((signedTxn) => {
console.log(signedTxn);
});
```
Similarily staking transactions can be created and signed using account.
A wallet represents user wallet that can hold one or more user accounts.
Creating an empty wallet
```javascript
const { Wallet } = require('@woop-js/account')
const wallet = new Wallet();
```
Setting a messenger to be used to send wallet transactions
```javascript
wallet.setMessenger(
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
```
Create an empty wallet with messenger
```javascript
const wallet = new Wallet(
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
```
An account could be added to a wallet using different ways. Adding account using mnemonics
```javascript
const mnemonics = 'horse distance dry brother pretty manual chicken mushroom town swim prize clutch';
const account = wallet.addByMnemonic(mnemonics);
```
Adding account using private key
```javascript
const account = wallet.addByPrivateKey('0x676cd9773dd23a4c1d7f22767c61c7b6723cc6be37b078545f6e0e91433a23dd')
```
Adding account using keystore file
```javascript
const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
const passphrase = '';
wallet.addByKeyStore(keystore, passphrase).then(account => {
console.log(account.bech32Address);
});
```
Creating a new account using passphrase
```javascript
const passphrase = 'woop-chain';
wallet.createAccount(passphrase).then(account => {
console.log(account.bech32Address);
});
```
Get all accounts in the wallet
```javascript
wallet.accounts.forEach(addr => {
const account = wallet.getAccount(addr);
console.log(account.bech32Address);
});
```
Set wallet signer when multiple accounts exists in the wallet
```javascript
wallet.setSigner(signerAddr);
```
Sign transaction using wallet, will sign the transaction using the wallet signer
```javascript
const txn = factory.newTx({
to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
value: new Unit(1).asOne().toWei(),
// gas limit, you can use string
gasLimit: '21000',
// 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('1').asGwei().toWei(),
});
wallet.signTransaction(txn).then((signedTxn) => {
console.log(signedTxn);
});
```
Similarily staking transactions can be signed using `signStaking` api.

@ -0,0 +1,218 @@
/**
# @woop-js/account
This package provides a collection of apis to create accounts and wallets and sign using them. A wallet can hold multiple accounts and account is associated with a unique `one` address. This package also provides facilies to manage account keys.
## Installation
```
npm install @woop-js/account
```
## Usage
Creating new account and display hex and bech32 (one) addresses
```javascript
const account = new Account(); // or const account = Account.new()
console.log(account.checksumAddress);
console.log(account.bech32Address);
```
Creating new account using private key
```javascript
const account = Account.add('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
```
Creating account using private key and custom messenger
```javascript
* const account = new Account(
* '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
```
Creating account and setting custom messenger
```javascript
// uses by default http://localhost:9500 as messenger
* const account = new Account();
* const customMessenger = new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* );
account.setMessenger(customMessenger);
```
Storing the account data to keystore file
```javascript
* const passphrase = '';
* const account = new Account('45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e');
* account.toFile(passphrase).then(keystore => {
* console.log(keystore);
* });
```
Fetching account from keystore file
```javascript
* const passphrase = '';
* const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
* const account = new Account();
* account.fromFile(keystore, passphrase).then(account => {
* console.log(account.bech32Address);
* });
```
Get the account balance
```javascript
* const account = new Account(
* '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
* account.getBalance().then(response => {
* console.log(response);
* });
```
outputs `{ balance: '9126943763247054940484', nonce: 45, shardID: 0 }`
Create a transaction and account, and sign it
```javascript
* const account = new Account(
* '45e497bd45a9049bcb649016594489ac67b9f052a6cdf5cb74ee2427a60bf25e',
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
* const { TransactionFactory } = require('@woop-js/transaction');
* const { Unit } = require('@woop-js/utils');
* const factory = new TransactionFactory();
* const txn = factory.newTx({
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* value: new Unit(1).asOne().toWei(),
* // gas limit, you can use string
* gasLimit: '21000',
* // 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('1').asGwei().toWei(),
* });
* account.signTransaction(txn).then((signedTxn) => {
* console.log(signedTxn);
* });
```
Similarily staking transactions can be created and signed using account.
A wallet represents user wallet that can hold one or more user accounts.
Creating an empty wallet
```javascript
* const { Wallet } = require('@woop-js/account')
* const wallet = new Wallet();
```
Setting a messenger to be used to send wallet transactions
```javascript
* wallet.setMessenger(
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
```
Create an empty wallet with messenger
```javascript
* const wallet = new Wallet(
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
```
An account could be added to a wallet using different ways. Adding account using mnemonics
```javascript
const mnemonics = 'horse distance dry brother pretty manual chicken mushroom town swim prize clutch';
const account = wallet.addByMnemonic(mnemonics);
```
Adding account using private key
```javascript
const account = wallet.addByPrivateKey('0x676cd9773dd23a4c1d7f22767c61c7b6723cc6be37b078545f6e0e91433a23dd')
```
Adding account using keystore file
```javascript
* const keystore = '{"version":3,"id":"33363566-3564-4264-a638-363531666335","address":"7c41e0668b551f4f902cfaec05b5bdca68b124ce","crypto":{"ciphertext":"9b09380afb742838b32d9afc0ec1a3df35dbd7a41e3a160d08c07a4d0e79b855","cipherparams":{"iv":"1cd0e0522260eef055b9170f4825f4a0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"salt":"bf35e36c45cccefcef73a4c900f41c682c94c28630d94d2d1f764760d245f30b","n":8192,"r":8,"p":1,"dklen":32},"mac":"25b4442972356bea02af57eba3b87803086d90b5e7657a57b528b89b1aa25f2f"}}';
* const passphrase = '';
* wallet.addByKeyStore(keystore, passphrase).then(account => {
* console.log(account.bech32Address);
* });
```
Creating a new account using passphrase
```javascript
* const passphrase = 'woop-chain';
* wallet.createAccount(passphrase).then(account => {
* console.log(account.bech32Address);
* });
```
Get all accounts in the wallet
```javascript
* wallet.accounts.forEach(addr => {
* const account = wallet.getAccount(addr);
* console.log(account.bech32Address);
* });
```
Set wallet signer when multiple accounts exists in the wallet
```javascript
wallet.setSigner(signerAddr);
```
Sign transaction using wallet, will sign the transaction using the wallet signer
```javascript
* const txn = factory.newTx({
* to: 'one166axnkjmghkf3df7xfvd0hn4dft8kemrza4cd2',
* value: new Unit(1).asOne().toWei(),
* // gas limit, you can use string
* gasLimit: '21000',
* // 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('1').asGwei().toWei(),
* });
* wallet.signTransaction(txn).then((signedTxn) => {
* console.log(signedTxn);
* });
```
Similarily staking transactions can be signed using `signStaking` api.
*
* @packageDocumentation
* @module woop-account
*/
/**@ignore */
export interface README {}

@ -0,0 +1,29 @@
{
"name": "@woop-js/account",
"version": "0.1.58",
"description": "account and wallet for woop",
"main": "dist/index.js",
"node": "dist/index.js",
"browser": "dist/index.js",
"module": "dist/index.esm.js",
"jsnext:main": "dist/index.esm.js",
"typings": "dist/index.d.ts",
"types": "dist/index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"publishConfig": {
"access": "public"
},
"author": "neeboo@firestack.one",
"license": "MIT",
"dependencies": {
"@woop-js/core": "0.1.58",
"@woop-js/crypto": "0.1.58",
"@woop-js/network": "0.1.58",
"@woop-js/staking": "0.1.58",
"@woop-js/transaction": "0.1.58",
"@woop-js/utils": "0.1.58"
},
"gitHead": "56606e9365721729a490c27d6a294e0daf90fbdf"
}

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module woop-account
*
*/
import {
generatePrivateKey,
getAddressFromPrivateKey,
@ -9,7 +15,7 @@ import {
Keystore,
Signature,
getAddress,
} from '@harmony-js/crypto';
} from '@woop-js/crypto';
import {
isPrivateKey,
@ -17,64 +23,151 @@ import {
hexToNumber,
AddressSuffix,
ChainType,
} from '@harmony-js/utils';
import { Transaction, RLPSign } from '@harmony-js/transaction';
import { StakingTransaction } from '@harmony-js/staking';
import { Messenger, RPCMethod } from '@harmony-js/network';
} from '@woop-js/utils';
import { Transaction, RLPSign } from '@woop-js/transaction';
import { StakingTransaction } from '@woop-js/staking';
import { Messenger, RPCMethod } from '@woop-js/network';
import { Shards } from './types';
import { defaultMessenger } from './utils';
export interface Balance {
balance?: string;
nonce?: number;
shardID?: number;
}
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('@woop-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('@woop-js/network');
* const { ChainType, ChainID } = require('@woop-js/utils');
*
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Woop, // if you are connected to Woop's blockchain
* ChainID.WikiLocal, // 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,10 +213,18 @@ 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> {
async getBalance(blockNumber: string = 'latest'): Promise<Balance> {
try {
if (this.messenger) {
const balance = await this.messenger.send(
@ -164,7 +265,6 @@ class Account {
/**
* @function updateShards
* @return {Promise<string>} {description}
*/
async updateBalances(blockNumber: string = 'latest'): Promise<void> {
// this.messenger.setShardingProviders();
@ -183,6 +283,9 @@ class Account {
}
}
/**
* @function signTransaction
*/
async signTransaction(
transaction: Transaction,
updateNonce: boolean = true,
@ -196,30 +299,18 @@ class Account {
if (updateNonce) {
// await this.updateBalances(blockNumber);
const txShardID = transaction.txParams.shardID;
const shardBalanceObject = await this.getShardBalance(
const shardNonce = await this.getShardNonce(
typeof txShardID === 'string' ? Number.parseInt(txShardID, 10) : txShardID,
blockNumber,
);
if (shardBalanceObject !== undefined) {
const shardNonce = shardBalanceObject.nonce;
transaction.setParams({
...transaction.txParams,
from:
this.messenger.chainPrefix === ChainType.Harmony
? this.bech32Address
: this.checksumAddress || '0x',
nonce: shardNonce,
});
} else {
transaction.setParams({
...transaction.txParams,
from:
this.messenger.chainPrefix === ChainType.Harmony
? this.bech32Address
: this.checksumAddress || '0x',
nonce: 0,
});
}
transaction.setParams({
...transaction.txParams,
from:
this.messenger.chainPrefix === ChainType.Woop
? this.bech32Address
: this.checksumAddress || '0x',
nonce: shardNonce,
});
}
if (encodeMode === 'rlp') {
@ -233,7 +324,7 @@ class Account {
signature,
rawTransaction,
from:
this.messenger.chainPrefix === ChainType.Harmony
this.messenger.chainPrefix === ChainType.Woop
? this.bech32Address
: this.checksumAddress || '0x',
};
@ -243,6 +334,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,
@ -257,27 +358,16 @@ class Account {
if (updateNonce) {
// await this.updateBalances(blockNumber);
const txShardID = shardID;
const shardBalanceObject = await this.getShardBalance(
const shardNonce = await this.getShardNonce(
typeof txShardID === 'string' ? Number.parseInt(txShardID, 10) : txShardID,
blockNumber,
);
if (shardBalanceObject !== undefined) {
const shardNonce = shardBalanceObject.nonce;
staking.setFromAddress(
this.messenger.chainPrefix === ChainType.Harmony
? this.bech32Address
: this.checksumAddress || '0x',
);
staking.setNonce(shardNonce);
} else {
staking.setFromAddress(
this.messenger.chainPrefix === ChainType.Harmony
? this.bech32Address
: this.checksumAddress || '0x',
);
staking.setNonce(0);
}
staking.setFromAddress(
this.messenger.chainPrefix === ChainType.Woop
? this.bech32Address
: this.checksumAddress || '0x',
);
staking.setNonce(shardNonce);
}
if (encodeMode === 'rlp') {
@ -285,7 +375,7 @@ class Account {
staking.setRawTransaction(rawTransaction);
staking.setSignature(signature);
staking.setFromAddress(
this.messenger.chainPrefix === ChainType.Harmony
this.messenger.chainPrefix === ChainType.Woop
? this.bech32Address
: this.checksumAddress || '0x',
);
@ -296,10 +386,40 @@ class Account {
return staking;
}
}
/**
* @param messenger
*
* @example
* ```javascript
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Woop, // if you are connected to Woop's blockchain
* ChainID.WikiLocal, // 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 +428,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 +446,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 +486,37 @@ class Account {
nonce: Number.parseInt(hexToNumber(nonce.result), 10),
};
}
/**
* Get the specific shard's nonce
*
* @param shardID `shardID` is binding with the endpoint, IGNORE it!
* @param blockNumber by default, it's `latest`
*
* @example
* ```
* account.getShardNonce().then((value) => {
* console.log(value);
* });
* ```
*/
async getShardNonce(shardID: number, blockNumber: string = 'latest') {
const nonce = await this.messenger.send(
RPCMethod.GetAccountNonce,
[this.address, blockNumber],
this.messenger.chainPrefix,
shardID,
);
if (nonce.isError()) {
throw nonce.error.message;
}
return nonce.result;
}
/**
* @function _new private method create Account
* @return {Account} Account instance
* @ignore
*/
private _new(): Account {
const prv = generatePrivateKey();
@ -360,6 +530,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 +551,7 @@ class Account {
}
}
/**
* This comment _supports_ [Markdown](https://marked.js.org/)
*/
export { Account };

@ -1,4 +1,9 @@
import { bip39, hdkey, getAddress, BN, Signature } from '@harmony-js/crypto';
/**
* @packageDocumentation
* @module woop-account
*/
import { bip39, hdkey, getAddress, BN, Signature } from '@woop-js/crypto';
import {
HDPath,
// defineReadOnly,
@ -9,15 +14,17 @@ import {
Unit,
isHex,
hexToNumber,
} from '@harmony-js/utils';
import { Messenger, HttpProvider, WSProvider } from '@harmony-js/network';
import { Transaction, TxStatus, TransasctionReceipt } from '@harmony-js/transaction';
} from '@woop-js/utils';
import { Messenger, HttpProvider, WSProvider, RPCMethod } from '@woop-js/network';
import { Transaction, TxStatus, TransasctionReceipt } from '@woop-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(
@ -64,7 +81,7 @@ export class HDNode {
index: number = 0,
addressCount: number = 1,
shardID: number = 0,
chainType: ChainType = ChainType.Harmony,
chainType: ChainType = ChainType.Woop,
chainId: ChainID = ChainID.Default,
gasLimit = '1000000',
gasPrice = '2000000000',
@ -76,10 +93,12 @@ export class HDNode {
this.hdwallet = undefined;
this.addresses = [];
this.wallets = {};
this.path = chainType === ChainType.Harmony ? HDPath : `m/44'/60'/0'/0/`;
this.path = chainType === ChainType.Woop ? HDPath : `m/44'/60'/0'/0/`;
this.index = index;
this.addressCount = addressCount;
this.getHdWallet(menmonic || HDNode.generateMnemonic());
if (menmonic !== null && menmonic !== '') {
this.getHdWallet(menmonic || HDNode.generateMnemonic());
}
this.gasLimit = gasLimit;
this.gasPrice = gasPrice;
}
@ -134,6 +153,7 @@ export class HDNode {
}
return this.addresses;
}
// tslint:disable-next-line: ban-types
getPrivateKey(address: string, cb?: Function) {
if (!cb) {
@ -149,13 +169,14 @@ export class HDNode {
cb(null, this.wallets[address].privateKey);
}
}
// tslint:disable-next-line: ban-types
async signTransaction(txParams: any | Web3TxPrams) {
const from: string = txParams.from ? getAddress(txParams.from).checksum : '0x';
const accountNonce = await this.messenger.send(
'hmy_getTransactionCount',
RPCMethod.GetAccountNonce,
[from, 'latest'],
'hmy',
'wiki',
this.shardID,
);
@ -194,7 +215,7 @@ export class HDNode {
const nonce =
txParams.nonce !== undefined && isHex(txParams.nonce)
? Number.parseInt(hexToNumber(txParams.nonce), 10)
: Number.parseInt(hexToNumber(accountNonce.result), 10);
: accountNonce.result;
const data = txParams.data !== undefined && isHex(txParams.data) ? txParams.data : '0x';
const prv = this.wallets[from].privateKey;
@ -221,6 +242,7 @@ export class HDNode {
return signed.getRawTransaction();
}
getAddress(idx?: number) {
if (!idx) {
return this.addresses[0];
@ -228,9 +250,11 @@ export class HDNode {
return this.addresses[idx];
}
}
getAddresses() {
return this.addresses;
}
addByPrivateKey(privateKey: string) {
const account = new Account(privateKey);
const addr = account.checksumAddress;
@ -241,7 +265,7 @@ export class HDNode {
setSigner(address: string) {
const foundIndex = this.addresses.findIndex((value) => value === address);
this.addresses.slice(foundIndex, foundIndex + 1);
this.addresses.splice(foundIndex, 1);
this.addresses.unshift(address);
}
}

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

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

@ -0,0 +1,14 @@
/**
* @packageDocumentation
* @module woop-account
* @hidden
*/
import { HttpProvider, Messenger } from '@woop-js/network';
import { ChainType, ChainID } from '@woop-js/utils';
export const defaultMessenger = new Messenger(
new HttpProvider('http://localhost:9500'),
ChainType.Woop,
ChainID.WikiLocal,
);

@ -1,8 +1,13 @@
import { bip39, hdkey, EncryptOptions, getAddress, generatePrivateKey } from '@harmony-js/crypto';
import { Messenger } from '@harmony-js/network';
import { isPrivateKey, isAddress, ChainType } from '@harmony-js/utils';
import { Transaction } from '@harmony-js/transaction';
import { StakingTransaction } from '@harmony-js/staking';
/**
* @packageDocumentation
* @module woop-account
*/
import { bip39, hdkey, EncryptOptions, getAddress, generatePrivateKey } from '@woop-js/crypto';
import { Messenger } from '@woop-js/network';
import { isPrivateKey, isAddress, ChainType } from '@woop-js/utils';
import { Transaction } from '@woop-js/transaction';
import { StakingTransaction } from '@woop-js/staking';
import { Account } from './account';
import { defaultMessenger } from './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('@woop-js/account');
* const { HttpProvider, Messenger } = require('@woop-js/network');
* const { ChainType, ChainID } = require('@woop-js/utils');
*
* // create a custom messenger
* const customMessenger = new Messenger(
* new HttpProvider('http://localhost:9500'),
* ChainType.Woop, // if you are connected to Woop's blockchain
* ChainID.WikiLocal, // 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)) {
@ -63,18 +116,25 @@ class Wallet {
}
const seed = bip39.mnemonicToSeed(phrase);
const hdKey = hdkey.fromMasterSeed(seed);
// TODO:hdkey should apply to Harmony's settings
const path = this.messenger.chainType === ChainType.Harmony ? '1023' : '60';
// TODO:hdkey should apply to Woop's settings
const path = this.messenger.chainType === ChainType.Woop ? '1023' : '60';
const childKey = hdKey.derive(`m/44'/${path}'/0'/0/${index}`);
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,12 +308,33 @@ class Wallet {
}
}
/**
* Set Customer Messenage
* @param messenger
*
* @example
* ```javascript
* const customMessenger = new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop, // if you are connected to Woop's blockchain
* ChainID.WikiLocal, // 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)) {
if (!isAddress(address) && !this.getAccount(address)) {
throw new Error('could not set signer');
}
this.defaultSigner = address;
@ -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) {

@ -0,0 +1,36 @@
/**
* @packageDocumentation
* @module woop-account
* @ignore
*/
import fetch from 'jest-fetch-mock';
import { Account } from '../src/account';
import { HttpProvider, Messenger } from '@woop-js/network';
import { ChainType, ChainID } from '@woop-js/utils';
const provider = new HttpProvider('http://localhost:9500');
const messenger = new Messenger(provider, ChainType.Woop, ChainID.WikiLocal);
describe('test account', () => {
it('test Account.getBalance returns object that implements Balance interface', () => {
fetch.mockResponses(
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x166c690f33421e"}),
{ status: 200 }
],
[
JSON.stringify({"jsonrpc": "2.0", "id": 1, "result": "0x106"}),
{ status: 200 }
]
);
const acc = Account.new();
acc.setMessenger(messenger);
acc.getBalance().then((res) => {
expect(res).not.toBeNull();
expect(res.balance).not.toBeNull();
expect(res.nonce).not.toBeNull();
expect(res.shardID).not.toBeNull();
});
});
});

@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src", "../../typings/**/*.d.ts", "aaa.ts"],
"references": [
{ "path": "../woop-crypto" },
{ "path": "../woop-utils" },
{ "path": "../woop-transaction" },
{ "path": "../woop-staking" },
{ "path": "../woop-network" }
]
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,147 @@
# @woop-js/contract
This package provides a collection of apis to create, deploy, and interact with smart contracts. In Woop, smart contracts all fully EVM compatible and the formats and terminologies match 1-to-1 with EVM smart contracts.
## Installation
```
npm install @woop-js/contract
```
## Usage
Deploying a contract using `contractConstructor`
```javascript
const { ContractFactory } = require('@woop-js/contract');
const { Wallet } = require('@woop-js/account');
const { Messenger, HttpProvider } = require('@woop-js/network');
const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
const wallet = new Wallet(
new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
),
);
const factory = new ContractFactory(wallet);
const contractJson = require("./Counter.json");
const contract = factory.createContract(contractJson.abi);
const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
const options3 = { data: contractJson.bytecode }; // contractConstructor needs contract bytecode to deploy
contract.wallet.addByPrivateKey('1f054c21a0f57ebc402c00e14bd1707ddf45542d4ed9989933dbefc4ea96ca68');
contract.methods.contractConstructor(options3).estimateGas(options1).then(gas => {
options2 = {...options2, gasLimit: hexToNumber(gas)};
contract.methods.contractConstructor(options3).send(options2).then(response => {
console.log('contract deployed at ' + response.transaction.receipt.contractAddress);
});
});
```
Instead of `contract.methods.contractConstructor`, `contract.deploy` could be used and it will work.
Loading a contract object using the contract json and contract address for interacting with it
```javascript
const { Woop } = require("@woop-js/core");
const { ChainID, ChainType } = require("@woop-js/utils");
const wiki = new Woop("https://api.s0.b.hmny.io", {
chainType: ChainType.Woop,
chainId: ChainID.WikiTestnet,
});
const contractJson = require("./Counter.json");
const contractAddr = "0x19f64050e6b2d376e52AC426E366c49EEb0724B1";
const contract = wiki.contracts.createContract(contractJson.abi, contractAddr);
console.log(contract.methods);
```
Directly loading contract using `ContractFactory`
```javascript
const { ContractFactory } = require('@woop-js/contract');
const { Wallet } = require('@woop-js/account');
const { Messenger, HttpProvider } = require('@woop-js/network');
const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
const wallet = new Wallet(new Messenger(
new HttpProvider('https://api.s0.b.hmny.io'),
ChainType.Woop,
ChainID.WikiTestnet,
));
const factory = new ContractFactory(wallet);
const contract = factory.createContract(contractJson.abi, contractAddr);
```
Estimate gas for contract methods
```javascript
const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
contract.methods.getCount().estimateGas(options1).then(gas => {
console.log('gas required for getCount is ' + hexToNumber(gas));
});
```
Call contract read-only methods. Woop uses 1 Gwei gas price and gas limit of 21000 by default. Use the estimate gas api to correctly set the gas limit.
```javascript
const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
contract.methods.getCount().estimateGas(options1).then(gas => {
options2 = {...options2, gasLimit: hexToNumber(gas)};
contract.methods.getCount().call(options2).then(count => {
console.log('counter value: ' + count);
});
});
```
Invoking contract modification methods using `send` api. Need to add a signing account to the contract wallet, otherwise `send` api will not work.
```javascript
const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
contract.wallet.addByPrivateKey('1f054c21a0f57ebc402c00e14bd1707ddf45542d4ed9989933dbefc4ea96ca68');
contract.methods.incrementCounter().estimateGas(options1).then(gas => {
options2 = {...options2, gasLimit: hexToNumber(gas)};
contract.methods.incrementCounter().send(options2).then(response => {
console.log(response.transaction.receipt);
});
});
```
All the above apis can also be asynchronously executed using `async` and `await`.
Subscribing to the contract events requires web socket based messenger.
```javascript
const { ContractFactory } = require('@woop-js/contract');
const { Wallet } = require('@woop-js/account');
const { Messenger, WSProvider } = require('@woop-js/network');
const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
const ws = new WSProvider('wss://ws.s0.b.hmny.io');
const wallet = new Wallet(
new Messenger(
ws,
ChainType.Woop,
ChainID.WikiTestnet,
),
);
const factory = new ContractFactory(wallet);
const contractJson = require("./Counter.json");
const contractAddr = '0x8ada52172abda19b9838eb00498a40952be6a019';
const contract = factory.createContract(contractJson.abi, contractAddr);
contract.events
.IncrementedBy()
.on('data', (event) => {
console.log(event);
})
.on('error', console.error);
```

@ -1,7 +1,7 @@
{
"name": "@harmony-js/contract",
"version": "0.1.36",
"description": "contract libraries for harmony",
"name": "@woop-js/contract",
"version": "0.1.58",
"description": "contract libraries for woop",
"main": "dist/index.js",
"node": "dist/index.js",
"browser": "dist/index.js",
@ -18,11 +18,11 @@
},
"license": "MIT",
"dependencies": {
"@harmony-js/account": "0.1.36",
"@harmony-js/crypto": "0.1.35",
"@harmony-js/network": "0.1.35",
"@harmony-js/transaction": "0.1.35",
"@harmony-js/utils": "0.1.35"
"@woop-js/account": "0.1.58",
"@woop-js/crypto": "0.1.58",
"@woop-js/network": "0.1.58",
"@woop-js/transaction": "0.1.58",
"@woop-js/utils": "0.1.58"
},
"gitHead": "27bce049c8d99498f464ce2db4fc39e4000a5420"
"gitHead": "56606e9365721729a490c27d6a294e0daf90fbdf"
}

@ -1,3 +1,156 @@
/**
# @woop-js/contract
This package provides a collection of apis to create, deploy, and interact with smart contracts. In Woop, smart contracts all fully EVM compatible and the formats and terminologies match 1-to-1 with EVM smart contracts.
## Installation
```
npm install @woop-js/contract
```
## Usage
Deploying a contract using `contractConstructor`
```javascript
const { ContractFactory } = require('@woop-js/contract');
const { Wallet } = require('@woop-js/account');
const { Messenger, HttpProvider } = require('@woop-js/network');
const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
* const wallet = new Wallet(
* new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
* const factory = new ContractFactory(wallet);
* const contractJson = require("./Counter.json");
* const contract = factory.createContract(contractJson.abi);
* const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
* let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
* const options3 = { data: contractJson.bytecode }; // contractConstructor needs contract bytecode to deploy
* contract.wallet.addByPrivateKey('1f054c21a0f57ebc402c00e14bd1707ddf45542d4ed9989933dbefc4ea96ca68');
* contract.methods.contractConstructor(options3).estimateGas(options1).then(gas => {
* options2 = {...options2, gasLimit: hexToNumber(gas)};
* contract.methods.contractConstructor(options3).send(options2).then(response => {
* console.log('contract deployed at ' + response.transaction.receipt.contractAddress);
* });
* });
```
Instead of `contract.methods.contractConstructor`, `contract.deploy` could be used and it will work.
Loading a contract object using the contract json and contract address for interacting with it
```javascript
* const { Woop } = require("@woop-js/core");
* const { ChainID, ChainType } = require("@woop-js/utils");
* const wiki = new Woop("https://api.s0.b.hmny.io", {
* chainType: ChainType.Woop,
* chainId: ChainID.WikiTestnet,
* });
const contractJson = require("./Counter.json");
const contractAddr = "0x19f64050e6b2d376e52AC426E366c49EEb0724B1";
const contract = wiki.contracts.createContract(contractJson.abi, contractAddr);
console.log(contract.methods);
```
Directly loading contract using `ContractFactory`
```javascript
const { ContractFactory } = require('@woop-js/contract');
const { Wallet } = require('@woop-js/account');
const { Messenger, HttpProvider } = require('@woop-js/network');
const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
* const wallet = new Wallet(new Messenger(
* new HttpProvider('https://api.s0.b.hmny.io'),
* ChainType.Woop,
* ChainID.WikiTestnet,
* ));
const factory = new ContractFactory(wallet);
const contract = factory.createContract(contractJson.abi, contractAddr);
```
Estimate gas for contract methods
```javascript
* const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
* contract.methods.getCount().estimateGas(options1).then(gas => {
* console.log('gas required for getCount is ' + hexToNumber(gas));
* });
```
Call contract read-only methods. Woop uses 1 Gwei gas price and gas limit of 21000 by default. Use the estimate gas api to correctly set the gas limit.
```javascript
* const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
* let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
* contract.methods.getCount().estimateGas(options1).then(gas => {
* options2 = {...options2, gasLimit: hexToNumber(gas)};
* contract.methods.getCount().call(options2).then(count => {
* console.log('counter value: ' + count);
* });
* });
```
Invoking contract modification methods using `send` api. Need to add a signing account to the contract wallet, otherwise `send` api will not work.
```javascript
* const options1 = { gasPrice: '0x3B9ACA00' }; // gas price in hex corresponds to 1 Gwei or 1000000000
* let options2 = { gasPrice: 1000000000, gasLimit: 21000 }; // setting the default gas limit, but changing later based on estimate gas
* contract.wallet.addByPrivateKey('1f054c21a0f57ebc402c00e14bd1707ddf45542d4ed9989933dbefc4ea96ca68');
* contract.methods.incrementCounter().estimateGas(options1).then(gas => {
* options2 = {...options2, gasLimit: hexToNumber(gas)};
* contract.methods.incrementCounter().send(options2).then(response => {
* console.log(response.transaction.receipt);
* });
* });
```
All the above apis can also be asynchronously executed using `async` and `await`.
Subscribing to the contract events requires web socket based messenger.
```javascript
* const { ContractFactory } = require('@woop-js/contract');
* const { Wallet } = require('@woop-js/account');
* const { Messenger, WSProvider } = require('@woop-js/network');
* const { ChainID, ChainType, hexToNumber } = require('@woop-js/utils');
* const ws = new WSProvider('wss://ws.s0.b.hmny.io');
* const wallet = new Wallet(
* new Messenger(
* ws,
* ChainType.Woop,
* ChainID.WikiTestnet,
* ),
* );
* const factory = new ContractFactory(wallet);
* const contractJson = require("./Counter.json");
* const contractAddr = '0x8ada52172abda19b9838eb00498a40952be6a019';
* const contract = factory.createContract(contractJson.abi, contractAddr);
* contract.events
* .IncrementedBy()
* .on('data', (event) => {
* console.log(event);
* })
* .on('error', console.error);
```
*
* @packageDocumentation
* @module woop-contract
*/
// this file is mainly ported from `ethers.js`, but done some fixes
// 1. added bytesPadRight support
// 2. ts-lint
@ -18,22 +171,26 @@ import {
Arrayish,
checkNew,
bytesPadRight,
} from '@harmony-js/crypto';
import { hexToBN, defineReadOnly } from '@harmony-js/utils';
} from '@woop-js/crypto';
import { hexToBN, defineReadOnly } from '@woop-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 +200,7 @@ export interface ParamType {
// @TODO: should this just be a combined Fragment?
/** @hidden */
export interface EventFragment {
type: string;
name: string;
@ -52,6 +210,7 @@ export interface EventFragment {
inputs: ParamType[];
}
/** @hidden */
export interface FunctionFragment {
type: string;
name: string;
@ -68,15 +227,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 +250,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 +267,7 @@ function verifyType(type: string): string {
return type;
}
/** @hidden */
interface ParseState {
allowArray?: boolean;
allowName?: boolean;
@ -113,6 +276,7 @@ interface ParseState {
readArray?: boolean;
}
/** @hidden */
interface ParseNode {
parent?: any;
type?: string;
@ -122,6 +286,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 +320,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 +461,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 +502,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 +582,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 +606,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 +637,13 @@ export function parseSignature(
///////////////////////////////////
// Coders
/** @hidden */
interface DecodedResult {
consumed: number;
value: any;
}
/** @hidden */
abstract class Coder {
readonly coerceFunc: CoerceFunc;
readonly name: string;
@ -508,6 +670,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 +686,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 +709,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);
@ -564,7 +724,12 @@ class CoderNumber extends Coder {
encode(value: BN | number | string): Uint8Array {
let result;
try {
let v = new BN(value);
let v: BN;
if (typeof value == 'string' && value.startsWith('0x')) {
v = new BN(value.slice(2), 'hex');
} else {
v = new BN(value);
}
if (this.signed) {
let bounds = MaxUint256.maskn(this.size * 8 - 1);
if (v.gt(bounds)) {
@ -597,15 +762,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 +785,8 @@ class CoderNumber extends Coder {
};
}
}
/** @hidden */
const uint256Coder = new CoderNumber(
(type: string, value: any) => {
return value;
@ -634,6 +797,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 +829,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 +876,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 +919,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 +927,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 +964,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 +991,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 +1015,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 +1085,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 +1133,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 +1191,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 +1223,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 +1253,7 @@ class CoderTuple extends Coder {
}
}
/** @hidden */
function splitNesting(value: string): any[] {
value = value.trim();
@ -1131,6 +1287,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 +1295,7 @@ const paramTypeSimple: { [key: string]: any } = {
bytes: CoderDynamicBytes,
};
/** @hidden */
function getTupleParamCoder(
coerceFunc: CoerceFunc,
components: any[],
@ -1154,6 +1312,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 +1327,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 +1348,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 +1365,7 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType | any): any {
});
}
/** @hidden */
export enum UnicodeNormalizationForm {
current = '',
NFC = 'NFC',
@ -1228,6 +1374,7 @@ export enum UnicodeNormalizationForm {
NFKD = 'NFKD',
}
/** @hidden */
export function toUtf8Bytes(
str: string,
form: UnicodeNormalizationForm = UnicodeNormalizationForm.current,
@ -1271,6 +1418,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 +1455,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 +1496,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 +1531,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 +1551,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 +1573,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 +1588,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 +1649,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 +1685,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 +1711,5 @@ export class AbiCoder {
}
}
/** @hidden */
export const defaultAbiCoder: AbiCoder = new AbiCoder();

@ -1,6 +1,12 @@
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { AbiCoder as ABICoder, ParamType, toUtf8Bytes } from './abiCoder';
import { isObject, isArray } from '@harmony-js/utils';
import { keccak256, Arrayish } from '@harmony-js/crypto';
import { isObject, isArray } from '@woop-js/utils';
import { keccak256, Arrayish } from '@woop-js/crypto';
import { jsonInterfaceMethodToString, bnToString } from './utils';
export class AbiCoderClass {
@ -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 woop-contract
* @hidden
*/
import { AbiCoderClass } from './api';
import { AbiCoder as EtherCoder } from './abiCoder';

@ -1,5 +1,11 @@
import { isObject, isArray } from '@harmony-js/utils';
import { BN } from '@harmony-js/crypto';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { isObject, isArray } from '@woop-js/utils';
import { BN } from '@woop-js/crypto';
export const jsonInterfaceMethodToString = (json: any): string => {
if (isObject(json) && json.name && json.name.includes('(')) {
@ -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,6 +1,12 @@
import { Wallet } from '@harmony-js/account';
import { Messenger } from '@harmony-js/network';
import { Transaction } from '@harmony-js/transaction';
/**
* @packageDocumentation
* @module woop-contract
*
*/
import { Wallet } from '@woop-js/account';
import { Messenger } from '@woop-js/network';
import { Transaction } from '@woop-js/transaction';
import { AbiCoder } from './abi/index';
import { abiMapper } from './utils/mapper';
import { ContractOptions } from './utils/options';
@ -14,6 +20,9 @@ import { ContractStatus } from './utils/status';
export class Contract {
methods: any;
events: any;
fallback: any = undefined;
receive: any = undefined;
abi: any = [];
abiModel: any | AbiModel;
abiCoder: AbiCoderClass;
options: ContractOptions | any;
@ -21,6 +30,8 @@ export class Contract {
transaction?: Transaction;
status: ContractStatus;
shardID: number;
errorFunc: string = 'Error(string)';
errorFuncSig: string;
constructor(
abi: any = [],
@ -30,6 +41,7 @@ export class Contract {
status: ContractStatus = ContractStatus.INITIALISED,
) {
// super();
this.abi = abi;
this.abiCoder = AbiCoder();
this.abiModel = abiMapper(abi, this.abiCoder);
this.options = options;
@ -41,6 +53,7 @@ export class Contract {
this.runMethodFactory();
this.runEventFactory();
this.status = status;
this.errorFuncSig = this.abiCoder.encodeFunctionSignature(this.errorFunc);
// tslint:disable-next-line: no-unused-expression
}
isInitialised() {
@ -105,7 +118,7 @@ export class Contract {
connect(wallet: Wallet): void {
this.wallet = wallet;
}
setMessegner(messenger: Messenger) {
setMessenger(messenger: Messenger) {
if (this.wallet instanceof Wallet) {
this.wallet.setMessenger(messenger);
} else {

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

@ -1,4 +1,9 @@
import { LogSub } from '@harmony-js/network';
/**
* @packageDocumentation
* @module woop-contract
*/
import { LogSub } from '@woop-js/network';
import { AbiItemModel } from '../models/types';
import { Contract } from '../contract';
import { decode as eventLogDecoder } from '../utils/decoder';

@ -1,4 +1,10 @@
import { isArray } from '@harmony-js/utils';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { isArray } from '@woop-js/utils';
import { AbiCoderClass } from '../abi/api';
import { AbiModel, AbiItemModel } from '../models/types';
import { Contract } from '../contract';
@ -27,7 +33,7 @@ export class EventFactory {
new EventMethod(
key,
// params,
this.map(this.abiModel, this.contract, params),
this.map(this.abiModel.getEvent(key), this.contract, params),
this.abiModel.getEvent(key),
this.contract,
);

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

@ -1,15 +1,18 @@
import { Wallet } from '@harmony-js/account';
import { TransactionFactory, Transaction, TxStatus } from '@harmony-js/transaction';
import { RPCMethod, getResultForData, Emitter } from '@harmony-js/network';
import { hexToNumber, hexToBN } from '@harmony-js/utils';
import { getAddress } from '@harmony-js/crypto';
/**
* @packageDocumentation
* @module woop-contract
*/
import { Wallet } from '@woop-js/account';
import { TransactionFactory, Transaction, TxStatus } from '@woop-js/transaction';
import { RPCMethod, getResultForData, Emitter } from '@woop-js/network';
import { hexToBN, Unit } from '@woop-js/utils';
import { getAddress } from '@woop-js/crypto';
import { AbiItemModel } from '../models/types';
import { Contract } from '../contract';
import { methodEncoder } from '../utils/encoder';
import { ContractStatus } from '../utils/status';
// todo: have to judge if it is contractConstructor
export class ContractMethod {
contract: Contract;
params: any;
@ -31,69 +34,68 @@ export class ContractMethod {
this.callResponse = undefined;
}
send(params: any): Emitter {
if (params && !params.gasLimit) {
params.gasLimit = params.gas;
}
try {
this.transaction = this.transaction.map((tx: any) => {
return { ...tx, ...params };
});
const updateNonce: boolean = params.nonce !== undefined ? false : true;
let gasLimit: any = params.gasLimit; // change by estimateGas
const signTxs = () => {
this.transaction = this.transaction.map((tx: any) => {
return { ...tx, ...params, gasLimit };
});
this.signTransaction(updateNonce).then((signed) => {
this.sendTransaction(signed).then((sent) => {
const [txn, id] = sent;
this.transaction = txn;
this.contract.transaction = this.transaction;
this.confirm(id).then(() => {
this.transaction.emitter.resolve(this.contract);
const waitConfirm: boolean = params && params.waitConfirm === false ? false : true;
const updateNonce: boolean = params && params.nonce !== undefined ? false : true;
this.signTransaction(updateNonce)
.then((signed) => {
this.sendTransaction(signed).then((sent) => {
const [txn, id] = sent;
this.transaction = txn;
this.contract.transaction = this.transaction;
if (this.transaction.isRejected()) {
this.transaction.emitter.reject(id); // in this case, id is error message
} else if (waitConfirm) {
this.confirm(id).then(() => {
this.transaction.emitter.resolve(this.contract);
});
} else {
this.transaction.emitter.resolve(this.contract);
}
});
})
.catch((error) => {
this.transaction.emitter.reject(error);
});
};
if (gasLimit === undefined) {
this.estimateGas(params).then((gas) => {
gasLimit = hexToBN(gas);
signTxs();
});
});
} else {
signTxs();
}
return this.transaction.emitter;
} catch (error) {
throw error;
}
}
async call(options: any, blockNumber: any = 'latest') {
if (options && !options.gasLimit) {
options.gasLimit = options.gas;
}
try {
const shardID =
options !== undefined && options.shardID !== undefined
? options.shardID
: this.contract.shardID;
const nonce =
this.wallet.signer || (options !== undefined && options.from)
? getResultForData(
await this.wallet.messenger.send(
RPCMethod.GetTransactionCount,
[this.wallet.signer ? this.wallet.signer.address : options.from, blockNumber],
shardID,
),
)
: '0x0';
let gasLimit: any;
// tslint:disable-next-line: prefer-conditional-expression
if (options !== undefined) {
gasLimit = options.gas || options.gasLimit;
} else {
gasLimit = hexToBN(await this.estimateGas());
}
let from: string;
// tslint:disable-next-line: prefer-conditional-expression
if (this.wallet.signer) {
from = options && options.from ? options.from : this.wallet.signer.address;
} else {
from =
options && options.from ? options.from : '0x0000000000000000000000000000000000000000';
}
this.transaction = this.transaction.map((tx: any) => {
return {
...tx,
...options,
from: from || tx.from,
gasPrice: options ? options.gasPrice : tx.gasPrice,
gasLimit: gasLimit || tx.gasLimit,
nonce: Number.parseInt(hexToNumber(nonce), 10),
nonce: 0,
};
});
const keys: string[] = Object.keys(this.transaction.txPayload);
@ -155,16 +157,30 @@ export class ContractMethod {
throw error;
}
}
async estimateGas() {
async estimateGas(options: any) {
try {
interface Payload {
[key: string]: any;
}
const estPayload: Payload = {};
const txPayload: Payload = this.transaction.txPayload;
const keys: string[] = ['from', 'to', 'gasPrice', 'value', 'data'];
for (const key of keys) {
if (options && options[key]) {
estPayload[key] = options[key];
} else if (txPayload[key] !== '0x') {
estPayload[key] = txPayload[key];
}
}
if (this.abiItem.isOfType('constructor')) {
delete estPayload.to;
}
const result = getResultForData(
// tslint:disable-line
await (<Wallet>this.wallet).messenger.send(RPCMethod.EstimateGas, [
{
to: this.transaction.txParams.to,
data: this.transaction.txParams.data,
},
]),
await (<Wallet>this.wallet).messenger.send(RPCMethod.EstimateGas, [estPayload]),
);
if (result.responseType === 'error') {
@ -208,7 +224,9 @@ export class ContractMethod {
'rlp',
'latest', // 'pending',
);
this.contract.address = TransactionFactory.getContractAddress(signed);
if (this.abiItem.isOfType('constructor')) {
this.contract.address = TransactionFactory.getContractAddress(signed);
}
this.contract.setStatus(ContractStatus.SIGNED);
return signed;
} catch (error) {
@ -234,7 +252,7 @@ export class ContractMethod {
);
if (result.receipt && result.txStatus === TxStatus.CONFIRMED) {
if (this.methodKey === 'contractConstructor') {
if (this.abiItem.isOfType('constructor')) {
this.contract.setStatus(ContractStatus.DEPLOYED);
} else {
this.contract.setStatus(ContractStatus.CALLED);
@ -249,7 +267,7 @@ export class ContractMethod {
protected createTransaction() {
if (this.wallet.messenger) {
if (this.methodKey === 'contractConstructor') {
if (this.abiItem.isOfType('constructor')) {
// tslint:disable-next-line: no-string-literal
this.contract.data = this.params[0]['data'] || '0x';
@ -259,12 +277,19 @@ export class ContractMethod {
} else {
this.abiItem.contractMethodParameters = this.params || [];
}
const defaultOptions = {
gasLimit: new Unit(21000000).asWei().toWei(),
gasPrice: new Unit(1).asGwei().toWei(),
};
const txObject = {
...defaultOptions,
...this.contract.options,
...this.params[0],
to: this.contract.address === '0x' ? '0x' : getAddress(this.contract.address).checksum,
to: this.abiItem.isOfType('constructor')
? '0x'
: getAddress(this.contract.address).checksum,
data: this.encodeABI(),
};
// tslint:disable-line
const result = new TransactionFactory((<Wallet>this.wallet).messenger).newTx(txObject);
@ -275,11 +300,32 @@ export class ContractMethod {
}
protected afterCall(response: any) {
if (!response || response === '0x') {
return null;
// length of `0x${methodSig}` is 2+4*2=10
if (response.length % 32 === 10 && response.startsWith(this.contract.errorFuncSig)) {
const errmsg = this.contract.abiCoder.decodeParameters(
[{ type: 'string' }],
'0x' + response.slice(10),
);
throw { revert: errmsg[0] };
}
if (
this.abiItem.isOfType('constructor') ||
this.abiItem.isOfType('fallback') ||
this.abiItem.isOfType('receive')
) {
return response;
}
const outputs = this.abiItem.getOutputs();
if (outputs.length === 0) {
// if outputs is empty, we can't know the call is revert or not
return response;
}
if (!response || response === '0x') {
// if outputs isn't empty, treat it as revert
throw { revert: response };
}
if (outputs.length > 1) {
return this.contract.abiCoder.decodeParameters(outputs, response);
}

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { AbiCoderClass } from '../abi/api';
import { AbiModel } from '../models/types';
import { Contract } from '../contract';
@ -21,15 +27,18 @@ 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);
});
if (this.abiModel.hasFallback()) {
this.contract.fallback = (calldata: string) =>
new ContractMethod('fallback', [calldata], this.abiModel.getFallback(), this.contract);
}
if (this.abiModel.hasReceive()) {
this.contract.receive = () =>
new ContractMethod('receive', [], this.abiModel.getReceive(), this.contract);
}
return this.contract;
}
/**

@ -1,4 +1,10 @@
import { isArray } from '@harmony-js/utils';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { isArray } from '@woop-js/utils';
import { AbiItemModel, AbiOutput, AbiInput } from './types';
export class AbiItem {

@ -1,3 +1,9 @@
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { AbiItemModel } from './types';
export class AbiModel {
@ -27,6 +33,20 @@ export class AbiModel {
return false;
}
getFallback(): AbiItemModel | false {
if (this.hasFallback()) {
return this.abi.fallback;
}
return false;
}
getReceive(): AbiItemModel | false {
if (this.hasReceive()) {
return this.abi.receive;
}
return false;
}
getEvents(): AbiItemModel[] {
return this.abi.events;
}
@ -47,6 +67,14 @@ export class AbiModel {
return typeof this.abi.methods[name] !== 'undefined';
}
hasFallback(): boolean {
return typeof this.abi.fallback !== 'undefined';
}
hasReceive(): boolean {
return typeof this.abi.receive !== 'undefined';
}
hasEvent(name: string): boolean {
return typeof this.abi.events[name] !== 'undefined';
}

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

@ -1,11 +1,13 @@
/**
* @packageDocumentation
* @module woop-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,4 +1,10 @@
import { isArray } from '@harmony-js/utils';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { isArray } from '@woop-js/utils';
import { AbiItemModel } from '../models/types';
import { AbiCoderClass } from '../abi/api';
@ -7,6 +13,15 @@ export const methodEncoder = (
abiItemModel: AbiItemModel,
deployData: string,
) => {
if (abiItemModel.isOfType('receive')) {
return undefined;
}
if (abiItemModel.isOfType('fallback')) {
return abiItemModel.contractMethodParameters.length
? abiItemModel.contractMethodParameters[0]
: undefined;
}
let encodedParameters = abiCoder.encodeParameters(
abiItemModel.getInputs(),
abiItemModel.contractMethodParameters,

@ -1,9 +1,10 @@
import {
hexlify,
isHexString,
keccak256,
toChecksumAddress,
} from '@harmony-js/crypto';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { hexlify, isHexString, keccak256, toChecksumAddress } from '@woop-js/crypto';
import {
numberToHex,
isArray,
@ -11,7 +12,7 @@ import {
isString,
isAddress,
hexToBN,
} from '@harmony-js/utils';
} from '@woop-js/utils';
import { toUtf8Bytes } from '../abi/abiCoder';
export const inputLogFormatter = (options: any) => {
@ -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,4 +1,10 @@
import { isArray } from '@harmony-js/utils';
/**
* @packageDocumentation
* @module woop-contract
* @hidden
*/
import { isArray } from '@woop-js/utils';
import { AbiItem } from '../models/AbiItemModel';
import { AbiModel } from '../models/AbiModel';
import { AbiItemModel } from '../models/types';
@ -9,6 +15,8 @@ export const abiMapper = (abi: any[], abiCoder: AbiCoderClass): AbiModel => {
const mappedAbiItems: any = {
methods: {},
events: {},
fallback: undefined,
receive: undefined,
};
let hasConstructor = false;
@ -64,6 +72,11 @@ export const abiMapper = (abi: any[], abiCoder: AbiCoderClass): AbiModel => {
mappedAbiItems.events[abiItem.funcName] = abiItemModel;
}
if (abiItem.type === 'fallback' || abiItem.type === 'receive') {
abiItem.signature = abiItem.type;
mappedAbiItems[abiItem.type] = new AbiItem(abiItem);
}
if (abiItem.type === 'constructor') {
abiItem.signature = abiItem.type;
// tslint:disable-next-line: no-string-literal
@ -86,9 +99,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 woop-contract
* @hidden
*/
export interface ContractOptions {
data?: string;
shardID?: number;

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

@ -1,6 +1,11 @@
/**
* @packageDocumentation
* @ignore
*/
import { AbiCoder } from '../src/abi/abiCoder';
import { BN } from '@harmony-js/crypto';
import { isArray } from '@harmony-js/utils';
import { BN } from '@woop-js/crypto';
import { isArray } from '@woop-js/utils';
import { abis } from './fixtures/abiv2';
function getValues(object: any, format?: any, named?: any): any {

File diff suppressed because one or more lines are too long

@ -6,10 +6,10 @@
},
"include": ["src", "../../typings/**/*.d.ts"],
"references": [
{"path": "../harmony-account"},
{"path": "../harmony-crypto"},
{"path": "../harmony-utils"},
{"path": "../harmony-transaction"},
{"path": "../harmony-network"}
{"path": "../woop-account"},
{"path": "../woop-crypto"},
{"path": "../woop-utils"},
{"path": "../woop-transaction"},
{"path": "../woop-network"}
]
}

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

Loading…
Cancel
Save