hubii core is an Ethereum wallet manager and friendly user interface to the Ethereum scaling solution nahmii, by hubii. Send and recieve crypto assets and trustlessly make instant, cheap payments and trades, all within a secure desktop environment
- Highlights
- Install
- Architecture
- Develop
- Build from source
- Development guidelines
- Debugging a production build
- Open source
- Send, receive crypto assets on the Ethereum blockchain
- Manage all wallets & addresses in one application
- Retain full custody and control of private keys
- First class Ledger Nano S support
- First class Trezor support
- Instant payments and trades without compromising on security with nahmii (WIP)
macOS 10.9+, Linux, and Windows 7+ are supported (64bit only)
Download the latest version of hubii core for your system on the official releases page
hubii core is a multiplatform desktop application built with Electron, React, Redux and styled-components. The architecture is heavily influenced by the react-boilerplate project. To understand our design decisions in greater detail, we recommend you checkout the documentaion and reasoning outlined in that repository.
- NodeJS LTS
- Yarn LTS
- Python
- A C++ compiler
-
Send an email with the subject line "API access" to info@hubii.com, we'll get back to you within 24 hours
-
Add the credentials we provide to your PATH
yarn
yarn electron-dev
yarn lint
yarn test
yarn test:dev
There are various faucents providing free Ropsten ETH:
- faucet.ropsten.be
wget https://faucet.ropsten.be/donate/<your ethereum address>
- faucent.metamask.io
- Follow instructions on the website
We recommend the ERC20 BOKKY token on Ropsten. To receive BOKKY, send Ropsten ETH to the BOKKY smart contract for BOKKY tokens in return, 1 for 1.
# compiles and builds the app for your system architecture
# the binary will be created inside the dist folder
yarn && yarn electron-build
During the early development of hubii core, different people with different opinions on testing and best practices touched the code base. As a result, you will notice some of the best practices below are not implemented everywhere you look. The majority of critical code has been refactored and we are confident in the foundations of the application, but we have a long way to go cleaning up less critical components and logic.
Instead of tackling this technical debt all at once, we ask that developers follow the "boy scout rule": leave the code you're working on in a better state than you found it. Over time, we will chip away at these smaller issues.
The architecture of hubii core relies on the library reselect to sit inbetween the Redux store and React components. Reselect allows us to abstract a lot of the complex data processing away from the components, keeping them as simple as possible.
One thing to be careful about when composing a complex selector is that you considered all possible structures input selectors can take, for example a selector could either be 'loaded', 'loading', or 'errored'. Forgetting to check for an uncommmon state like 'errored' can be easy, and cause catastrophic failure for the user.
The best way to lower chances of this kind of failure occuring is to test your selector/component with every variation of its possible inputs. To make this as frictionless as possible, please maintain a mocks/selectors.js
file in a container's tests
folder, that contains samples of every variation of structure a selector could return (see containers/WalletHoc/tests/mocks/selectors.js
for an example).
Then when you or another developer wants to reach for a selector, when they're writing their tests they can be confident that they know exactly which inputs they need to test, and have the ability to effortlessly import the required mocked state.
Please obey by established Gitflow principles. Details can be obtained in post by Vincent Driessen or in Atlassian's Gitflow Workflow tutorial. Driessen's git-flow git extension is indispensable.
During blockchain development, you'll often find yourself working with very small and very large numbers. When dealing with these types of numbers (notably Ether or token amounts), use the BigNumber library to ensure precision isn't lost. If you're interested to read more see this article for a concise explination.
Here is a video about TDD, introducing the motivations behind writing good unit tests.
index.test.js: Test the logics at the container
level. component
tests can be constructed similarly to this.
actions.test.js: Test any actions
reducer.test.js: Test the container reducer
saga.test.js: Test any saga
logic. We recommend and are currently migrating all our saga tests to use redux-saga-test-plan
Some containers contain up to 3 levels of complex components. Combining all the logic of each component into a single container could make the code difficult to maintain and difficult to schedule development.
To isolate the complexities between the sub components, the parent container can use sub routes to wire up the sub components. This enable isolating the logics in the parent page container from their sub pages, as well as isolating the logics between the sub pages.
For example
<Tabs defaultActiveKey={history.location.pathname}>
<TabPane tab="Accounts" key={`${match.url}/accounts`}>
<Route path={`${match.url}/accounts`} component={AccountsContainer} />
</TabPane>
<TabPane tab="Contacts" key={`${match.url}/contacts`}>
Content of Tab Pane 2
</TabPane>
</Tabs>
The containers/Accounts
container is the parent page of a number of sub pages such as payment
, savings
, swap currencies
etc. Although it has quite a number of sub pages, it handles its own container logics and have the sub pages to handle by them own.
In order to let the sub pages know which account and currency is currently chosen, it dispatch the actions CHANGE_CURRENT_CURRENCY
or CHANGE_CURRENT_ACCOUNT
, so the sub pages can react respectively.
Take Swap Currency sub page for example, it connects the currentCurrency
with the state in the store
using reselect. Whenever there is an update to this currentCurrency
state, the swap currency container re-render the view to reflect the newly chosen currency from its parent container containers/Accounts
.
Sample codes from containers/SwapCurrencies
on connecting the props to the defined states from the store
.
import { makeSelectCurrentCurrency } from 'containers/Accounts/selectors';
const mapStateToProps = createStructuredSelector({
currentCurrency: makeSelectCurrentCurrency(),
});
The dev tools can be opened with Cmd+Alt+I
on macOS, or Ctrl+Shift+I
on Linux and Windows.