Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add job status update via webhook #203

Merged
merged 5 commits into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 17 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
The Flow Wallet API is a REST HTTP service that allows a developer to integrate wallet functionality into a larger Flow application infrastructure.
This service can be used by an application that needs to manage Flow user accounts and the assets inside them.


## Features

- Create new Flow accounts
Expand All @@ -16,7 +15,6 @@ This service can be used by an application that needs to manage Flow user accoun

View full list of functionality in the [API documentation](https://flow-hydraulics.github.io/flow-wallet-api/).


## Background

Some application developers may wish to manage Flow accounts in a fully-custodial fashion,
Expand All @@ -28,19 +26,16 @@ For security and/or legal reasons,
some developers need to use a custody service running on-premises as part of their existing infrastructure,
rather than a hosted 3rd-party solution.


### Example use cases

- **FLOW/FUSD Hot Wallet** — an application that allows users to convert fiat currency to FLOW or FUSD. A single admin account would be used as a hot wallet for outgoing payments, and additional deposit accounts would be created to accept incoming payments.
- **Exchange** — a cryptocurrency exchange that is listing FLOW and/or FUSD. Similar to the case above, one or more admin accounts may be used as a hot wallet for outgoing payments, and additional deposit accounts would be created to accept incoming payments.
- **Web Wallet** — a user-facing wallet application that is compatible with Flow dapps. Each user account would be created and managed by the wallet service.


## API Specification

View the [Wallet API documentation and OpenAPI (Swagger) specification](https://flow-hydraulics.github.io/flow-wallet-api/).


## Installation

The Wallet API is provided as a Docker image:
Expand All @@ -49,7 +44,6 @@ The Wallet API is provided as a Docker image:
docker pull ghcr.io/flow-hydraulics/flow-wallet-api:latest
```


### Basic example usage

> This setup requires [Docker](https://docs.docker.com/engine/install/) and the [Flow CLI](https://docs.onflow.org/flow-cli/install/).
Expand Down Expand Up @@ -84,9 +78,13 @@ Once you're finished, run this to stop the containers:
docker-compose down
```


## Configuration

### Updates on async requests (webhook)

If you have the possibility to setup a webhook endpoint, you can set `FLOW_WALLET_JOB_STATUS_WEBHOOK` to receive updates on async requests (requests which return a job). The wallet will send a `POST` request to this URL containing the job whenever the status of the job is updated.

**NOTE:** The wallet expects a response with status code **200** and will retry if unsuccessful.

### Enabled fungible tokens

Expand All @@ -100,7 +98,6 @@ Examples:

FLOW_WALLET_ENABLED_TOKENS=FlowToken:0x0ae53cb6e3f42a79:flowToken,FUSD:0xf8d6e0586b0a20c7:fusd


### Database

| Config variable | Environment variable | Description | Default | Examples |
Expand All @@ -122,7 +119,6 @@ For more: https://gorm.io/docs/connecting_to_the_database.html

To learn more about database schema versioning and migrations, read [MIGRATIONS.md](MIGRATIONS.MD).


### Google KMS setup

**Note**: In order to use Google KMS for remote key management you'll need a Google Cloud Platform account.
Expand Down Expand Up @@ -159,7 +155,6 @@ Configure Google KMS as the key storage for `flow-wallet-api` and set the necess
| LocationID | `FLOW_WALLET_GOOGLE_KMS_LOCATION_ID` | GCP Location ID | - | `europe-north1`, `us-west1` |
| KeyRingID | `FLOW_WALLET_GOOGLE_KMS_KEYRING_ID` | GCP Key Ring ID | - | `example-wallet-keyring` |


### Google KMS for admin account

If you want to use a key stored in Google KMS for the admin account, just pass the resource identifier as the private key (`FLOW_WALLET_ADMIN_PRIVATE_KEY`) and set `FLOW_WALLET_ADMIN_KEY_TYPE` to `google_kms`.
Expand All @@ -185,7 +180,6 @@ Example environment:

NOTE: This will mess up the docker-compose setup (emulator won't start) as it uses `FLOW_WALLET_ADMIN_PRIVATE_KEY` as `FLOW_SERVICEPRIVATEKEY`. It will cause an encoding error on the emulator.


### Google KMS key for database encryption

Before configuring a Google KMS key for database encryption please refer to the official guide for setting up a symmetric encryption key;
Expand All @@ -194,18 +188,16 @@ https://cloud.google.com/kms/docs/encrypt-decrypt#before_you_begin

If you want to use an Google KMS symmetric encryption key for encrypting the stored account keys, please refer to the following configuration settings;

| Config variable | Environment variable | Description | Default | Examples value for Google KMS |
| ----------------- | --------------------------------- | ------------------------------------------------------ | ------- | ----------------------------- |
| EncryptionKeyType | `FLOW_WALLET_ENCRYPTION_KEY_TYPE` | Encryption key type | `local` | `google_kms` |
| EncryptionKey | `FLOW_WALLET_ENCRYPTION_KEY` | KMS encryption key resource name | - | `projects/my-project/locations/us-west1/keyRings/my-keyring/cryptoKeys/my-encryption-key` |

| Config variable | Environment variable | Description | Default | Examples value for Google KMS |
| ----------------- | --------------------------------- | -------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
| EncryptionKeyType | `FLOW_WALLET_ENCRYPTION_KEY_TYPE` | Encryption key type | `local` | `google_kms` |
| EncryptionKey | `FLOW_WALLET_ENCRYPTION_KEY` | KMS encryption key resource name | - | `projects/my-project/locations/us-west1/keyRings/my-keyring/cryptoKeys/my-encryption-key` |

### AWS KMS setup

**Note**: In order to use AWS KMS for remote key management you'll need an AWS account.
**Note**: Custom key stores are not supported.


#### Pre-requisites:

1. AWS credentials for an account that has access to KMS
Expand All @@ -223,38 +215,34 @@ Configure AWS KMS as the key storage for `flow-wallet-api` and set the necessary
| --------------- | ------------------------------ | ---------------- | ------- | ----------------- |
| DefaultKeyType | `FLOW_WALLET_DEFAULT_KEY_TYPE` | Default key type | `local` | `aws_kms` |


### AWS KMS for admin account

If you want to use a key stored in AWS KMS for the admin account, please refer to the following configuration settings;

| Config variable | Environment variable | Description | Default | Example value for AWS KMS |
| --------------- | ------------------------------- | --------------------- | ------- | ------------------------- |
| AdminKeyType | `FLOW_WALLET_ADMIN_KEY_TYPE` | Admin key type | `local` | `aws_kms` |
| AdminPrivateKey | `FLOW_WALLET_ADMIN_PRIVATE_KEY` | Admin private key ARN | - | `arn:aws:kms:eu-central-1:012345678910:key/00000000-aaaa-bbbb-cccc-12345678910` |
| Config variable | Environment variable | Description | Default | Example value for AWS KMS |
| --------------- | ------------------------------- | --------------------- | ------- | ------------------------------------------------------------------------------- |
| AdminKeyType | `FLOW_WALLET_ADMIN_KEY_TYPE` | Admin key type | `local` | `aws_kms` |
| AdminPrivateKey | `FLOW_WALLET_ADMIN_PRIVATE_KEY` | Admin private key ARN | - | `arn:aws:kms:eu-central-1:012345678910:key/00000000-aaaa-bbbb-cccc-12345678910` |

When testing make sure to add the key to the admin account. You can convert the AWS public key (e.g. `aws.pem`) you downloaded/copied from AWS with flow-cli;

```
flow keys decode pem --from-file=aws.pem --sig-algo "ECDSA_secp256k1"
```


### AWS KMS for encrypting stored keys

If you want to use an AWS KMS symmetric encryption key for encrypting the stored account keys, please refer to the following configuration settings;

| Config variable | Environment variable | Description | Default | Examples value for AWS KMS |
| ----------------- | --------------------------------- | ------------------------------------------------------ | ------- | -------------------------- |
| EncryptionKeyType | `FLOW_WALLET_ENCRYPTION_KEY_TYPE` | Encryption key type | `local` | `aws_kms` |
| EncryptionKey | `FLOW_WALLET_ENCRYPTION_KEY` | KMS encryption key ARN | - | `arn:aws:kms:eu-central-1:012345678910:key/00000000-aaaa-bbbb-cccc-12345678910` |

| Config variable | Environment variable | Description | Default | Examples value for AWS KMS |
| ----------------- | --------------------------------- | ---------------------- | ------- | ------------------------------------------------------------------------------- |
| EncryptionKeyType | `FLOW_WALLET_ENCRYPTION_KEY_TYPE` | Encryption key type | `local` | `aws_kms` |
| EncryptionKey | `FLOW_WALLET_ENCRYPTION_KEY` | KMS encryption key ARN | - | `arn:aws:kms:eu-central-1:012345678910:key/00000000-aaaa-bbbb-cccc-12345678910` |

### All possible configuration variables

Refer to [configs/configs.go](configs/configs.go) for details and documentation.


## Credit

The Flow Wallet API is developed and maintained by [Equilibrium](https://equilibrium.co/),
Expand Down
2 changes: 2 additions & 0 deletions accounts/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ func (s *Service) executeAccountCreateJob(j *jobs.Job) error {
return jobs.ErrInvalidJobType
}

j.ShouldSendNotification = true

ctx := context.Background()

a, txID, err := s.createAccount(ctx)
Expand Down
2 changes: 2 additions & 0 deletions configs/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type Config struct {
// You can increase the number of workers if you're sending
// too many transactions and find that the queue is often backlogged.
WorkerCount uint `env:"FLOW_WALLET_WORKER_COUNT" envDefault:"100"`
// Webhook endpoint to receive job status updates
JobStatusWebhook string `env:"FLOW_WALLET_JOB_STATUS_WEBHOOK" envDefault:""`

// -- Google KMS --

Expand Down
26 changes: 13 additions & 13 deletions jobs/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ type Result struct {
TransactionID string
}

type Process func(result *Result) error

// State is a type for Job state.
type State string

Expand All @@ -29,22 +27,23 @@ const (

// Job database model
type Job struct {
ID uuid.UUID `gorm:"column:id;primary_key;type:uuid;"`
Type string `gorm:"column:type"`
State State `gorm:"column:state;default:INIT"`
Error string `gorm:"column:error"`
Result string `gorm:"column:result"`
TransactionID string `gorm:"column:transaction_id"`
ExecCount int `gorm:"column:exec_count;default:0"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index"`
Do Process `gorm:"-"`
ID uuid.UUID `gorm:"column:id;primary_key;type:uuid;"`
Type string `gorm:"column:type"`
State State `gorm:"column:state;default:INIT"`
Error string `gorm:"column:error"`
Result string `gorm:"column:result"`
TransactionID string `gorm:"column:transaction_id"`
ExecCount int `gorm:"column:exec_count;default:0"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index"`
ShouldSendNotification bool `gorm:"-"` // Whether or not to notify admin (via webhook for example)
}

// Job HTTP response
type JSONResponse struct {
ID uuid.UUID `json:"jobId"`
Type string `json:"type"`
State State `json:"state"`
Error string `json:"error"`
Result string `json:"result"`
Expand All @@ -56,6 +55,7 @@ type JSONResponse struct {
func (j Job) ToJSONResponse() JSONResponse {
return JSONResponse{
ID: j.ID,
Type: j.Type,
State: j.State,
Error: j.Error,
Result: j.Result,
Expand Down
Loading