Skip to content

Commit

Permalink
feat: initial daemon implementation (#1)
Browse files Browse the repository at this point in the history
* feat: initial commit

* feat: using generator to download blocks to be able to cancel it when state changes

* chore: updated package.json, lock and tsconfig

* chore: removed .env from git

* feat: resetting blocks on syncing state entry and moving to idle when receiving NEW_BLOCK event'

* feat: checking if our best block is still valid (not voided) before continuing)

* refactor: handling errors better by yielding instead of throwing

* refactor: using bi-directional callbacks on state machine instead of an activity

* feat: using hathorLib Connection class to maintain a connection to the fullnode

* feat: starting the state machine only on START event

* feat: added type to generator and yields

* feat: added tests for utils methods

* refactor: moved state machine methods to a dedicated file

* fix: typo when parsing outputs

* feat: added tests for the state machine

* chore: added baseUrl to prevent warnings

* feat: transition to reorg when a reorg is detected

* docs: added README

* feat: getting NETWORK from env var

* fix: handling lambda call failures

* chore: removed size.yml github action (came from tsdx template)

* docs: added comment explaining the block sync strategy on ws events

* docs: added comment explaining state updates from ws conn

* chore: removed unused and commented import on machine and commented unused sync event type

* docs: added comment on the machine refering to the README

* refactor: getting constant from hathor-lib and removed useless commented block code

* feat: typed prepareTx

* fix: returning success false if a failure has ocurred inside the tx loop

* fix: added missing attributes to PreparedTx type

* docs: added docstring to util methods

* feat: using a LRU cache for transactions

* refactor: removed misleading log

* feat: loading wallet_service_local_url from env variables

* docs: added a TODO to replace the getFullNodeBestBlock API

* fix: added missing type to sendTx parameter

* fix: added missing types and fixed lint on LRU cache

* Added dockerfile to the project (#4)

* chore: added dockerfile

* chore: removed global tsdx from dockerfile

* docs: added a simple explaination on how to run locally, build and run a production service

* chore: updated state machine diagram URL to render automatically

* docs: added missing hathor header

* feat: added winston as a logger and refactored console.logs to use it

* refactor: moved api methods to src/api

* fix: winston import breaking production build

* refactor: using wallet util method to get token index

* refactor: changed reorg message

* refactor: improved blocks download message

* refactor: using a better algorithm to filter unique txs

* docs: added comment explaining Map queue order

* fix: typo

* feat: typed yield result from generator

* feat: added type and docstring to onReceive from syncHandler

* refactor: using strict, refactor types to pass tslint

* fix: token creation tx was not sending token_name and token_symbol

* fix: breaking type on fullnode response

* feat: logging full data instead of data.Response on lambda response

* tests: removed isVoided from tx

* tests: fix typo on tests, clearing all mocks before every test instead of 'beforeAll'

* tests: fix test by using the hathorLib to define whether a tx is a block or not

* feat: typed raw tx response from fullnode

* refactor: typed rawTx and refactored types

* chore: set build output to cjs as the project is node-only

* chore: removed dom from lib

* feat: added spent_by and token to RawOutput and RawInput to handle block_at_height response format

* chore: ignoring some ts errors that can be handled by typing for now.

* chore: using strict: true

* feat: ignoring genesis transactions before sending them to the wallet-service (#5)
  • Loading branch information
andreabadesso authored May 24, 2021
1 parent 42950df commit 72d5d0e
Show file tree
Hide file tree
Showing 20 changed files with 16,693 additions and 0 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist/
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
32 changes: 32 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI
on: [push]
jobs:
build:
name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }}

runs-on: ${{ matrix.os }}
strategy:
matrix:
node: ['10.x', '12.x', '14.x']
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
- name: Checkout repo
uses: actions/checkout@v2

- name: Use Node ${{ matrix.node }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}

- name: Install deps and build (with cache)
uses: bahmutov/npm-install@v1

- name: Lint
run: yarn lint

- name: Test
run: yarn test --ci --coverage --maxWorkers=2

- name: Build
run: yarn build
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.log
.DS_Store
node_modules
dist
.env
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2020 Hathor Labs
# This software is provided ‘as-is’, without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# This software cannot be redistributed unless explicitly agreed in writing with the authors.

FROM node:14 AS builder

COPY package.json /app/

RUN cd /app && npm install --production

COPY . /app/

RUN cd /app && npm run build

FROM node:14-alpine3.13 AS builder

COPY --from=builder /app/dist/ /app/
COPY --from=builder /app/node_modules /app/node_modules

CMD node /app/index.js
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Hathor Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
108 changes: 108 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Hathor Wallet Service -- Sync Daemon

## Running

### Local environment

#### System dependencies

You need nodejs installed on your enviroment, we are using the latest Active LTS version (v14.16.1) on the dev environment. You can read more about installing nodejs on https://nodejs.org/en/download/package-manager/

#### Clone the project and install dependencies

`git clone https://github.com/HathorNetwork/hathor-wallet-service-sync_daemon.git && npm install`

#### Add env variables or an .env file to the repository:

Example:

```
STAGE=local
NETWORK=testnet
MAX_ADDRESS_GAP=20
SERVICE_NAME=hathor-wallet-service
DEFAULT_SERVER=http://fullnode_url/v1a/
```

`STAGE` - Wallet-Service's deployment stage, e.g. `local`, `production`, `staging`
`NETWORK` - The current hathor network we want to connect to
`MAX_ADDRESS_GAP` - The full-node configured GAP between addresses
`SERVICE_NAME` - The Wallet-Service's service name as it was registered on AWS
`DEFAULT_SERVER` - The full-node API url

If the wallet-service is not running locally, you also need to specify the AWS-SDK env variables:

```
AWS_REGION="us-east-1"
AWS_DEFAULT_REGION="us-east-1"
AWS_ACCESS_KEY_ID="..."
AWS_SECRET_ACCESS_KEY="..."
```

#### Run:

`npm start`


### Deploy

The recommended way to deploy this service is to use docker.

#### Building the image:

`docker build -t hathor/sync-daemon .`

#### Running:

```
docker run -d -e STAGE="production" \
-e NODE_ENV="production" \
-e AWS_REGION="us-east-1" \
-e AWS_DEFAULT_REGION="us-east-1" \
-e AWS_ACCESS_KEY_ID="..." \
-e AWS_SECRET_ACCESS_KEY="..." \
-e NETWORK="testnet" \
-e MAX_ADDRESS_GAP=20 \
-e NETWORK="testnet" \
-e SERVICE_NAME="hathor-wallet-service" \
-e DEFAULT_SERVER="http://fullnode:8082/v1a/" \
-ti localhost/hathor/sync-daemon
```

In this example, we are passing the env variables to the container and running as a daemon (`-d`). We are also expecting a fullnode to be running on fullnode:8082.

## State Machine

The state machine diagram can be visualized at https://xstate.js.org/viz/?gist=7299c0ed0ce189bc121a06dce1e11638

## States:

### Idle

The machine starts at the idle state, it will stay there until a `NEW_BLOCK` action is received.

Every time the state of the machine is transitioned to `idle`, the machine will check if `hasMoreBlocks` is set on the state context. If it is, the machine will transition to `syncing`.

#### Actions:
`NEW_BLOCK`: When a `NEW_BLOCK` action is received, the machine will transition to the `syncing` state.

### Syncing

Everytime the state of the machine is transitioned to `syncing`, the machine will invoke the `syncHandler` service that will start syncing new blocks.

#### Actions:
`NEW_BLOCK`: When a `NEW_BLOCK` action is received, the machine will assign `true` to the `hasMoreBlocks` context on the state, so the next time we transition to `IDLE`, the machine will know that there are more blocks to be downloaded.
`DONE`: When a `DONE` action is received, the machine will transition to `idle` to await for new blocks
`ERROR`: When a `ERROR` action is received, the machine will transition to the `failure` state
`REORG`: When a `REORG` action is received, the machine will transition to the `reorg` state
`STOP`: When a `STOP` action is received, the machine will transition to the `idle` state

### Failure

This is a `final` state, meaning that the machine will ignore all actions and wait for a manual restart.

This state can trigger actions to try to automatically solve issues or notify us about it.

### Reorg

This is temporarily a `final` state, this will be changed on a new PR with the reorg code.
Loading

0 comments on commit 72d5d0e

Please sign in to comment.