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

Upgrade demo environment #162

Merged
merged 23 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
abbc764
Change the error message in updateVoucherDelivered
levalleux-ludo Jul 1, 2021
991d40a
Upgrade the keepers and triggers services so that it's possible to ru…
levalleux-ludo Jul 8, 2021
25e6d22
Change the default value for IMAGE_UPLOAD_STORAGE_ENGINE to be "AWS" …
levalleux-ludo Jul 8, 2021
358c17c
Merge remote-tracking branch 'origin/develop' into local-triggers
levalleux-ludo Jul 8, 2021
8ffe796
fix test for default image_upload_storage_engine
Jul 9, 2021
213d86c
update alchemy url
moh-abk Jul 9, 2021
fd0d897
prod pipeline
moh-abk Jul 12, 2021
7fb7be7
Merge pull request #156 from bosonprotocol/chore/update-alchemy-demo
moh-abk Jul 13, 2021
06b7844
Merge branch 'develop' into tag-pipeline
moh-abk Jul 13, 2021
8447e10
Merge pull request #157 from bosonprotocol/tag-pipeline
moh-abk Jul 13, 2021
03c5090
Remove app:run command from README
dennisfurrer Jul 13, 2021
3e007b7
prod bootstrap
moh-abk Jul 13, 2021
886c98b
Merge branch 'develop' into local-triggers
dennisfurrer Jul 13, 2021
f8d9d22
Merge pull request #155 from bosonprotocol/local-triggers
dennisfurrer Jul 13, 2021
468ca36
Merge branch 'develop' into tag-bootstrap
moh-abk Jul 13, 2021
59fdb85
Merge pull request #158 from bosonprotocol/tag-bootstrap
moh-abk Jul 13, 2021
3df4f34
Merge branch 'develop' into change-error-message-2
HristiyanG Jul 13, 2021
ad99644
Fix formatting and linting
dennisfurrer Jul 13, 2021
f8dec59
Merge pull request #147 from bosonprotocol/change-error-message-2
dennisfurrer Jul 13, 2021
31dbe39
Configure production environment contract addresses
dennisfurrer Jul 13, 2021
e523525
Merge pull request #159 from bosonprotocol/prod-contracts-config
dennisfurrer Jul 13, 2021
6c716df
Remove configuration section from README
dennisfurrer Jul 13, 2021
1bdd942
Merge pull request #161 from bosonprotocol/readme-remove-config
dennisfurrer Jul 13, 2021
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ node_modules

# Secrets
.secret
.env
**/.env
.env.prod

# OS
Expand Down
95 changes: 77 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ This reference app may be used as a template for building your own marketplace p
- [Design & Architecture](#design--architecture)
- [Local Development](#local-development)
- [Prerequisites](#prerequisites)
- [Configuration](#configuration)
- [Build](#build)
- [Run](#run)
- [Test](#test)
- [Unit Tests](#unit-tests)
- [Component Tests](#component-tests)
- [Persistence Tests](#persistence-tests)
- [Code Linting & Formatting](#code-linting--formatting)
- [Contributing](#contributing)
- [License](#license)
Expand Down Expand Up @@ -58,12 +60,6 @@ For instructions on how to get set up with these specific versions:
* See the [OS X guide](docs/setup/osx.md) if you are on a Mac.
* See the [Linux guide](docs/setup/linux.md) if you use a Linux distribution.

---
### Configuration
Prior to running the application, you must set up a `.env` file in the project's root directory with the following environment variables:
- `TOKEN_SECRET` - The token used to authenticate the user. Based on the verification with the secret, we derive the user's address.
- `GCLOUD_SECRET` - The token used to authenticate requests from the Event Listeners and Keepers.

---
### Build
We have a fully automated local build process to check that your changes are
Expand All @@ -85,17 +81,80 @@ To fetch dependencies:

---
### Run
A task has been created which will:
- Install any necessary dependencies
- Provision a local database
- Run the server locally
- Run a local keepers service (dependent on local contracts deployment as described in the [`contracts`](https://github.com/bosonprotocol/contracts) repository - see "Run" section).
- Run local event listeners (dependent on local contracts deployment as described in the [`contracts`](https://github.com/bosonprotocol/contracts) repository - see "Run" section).

This can be executed by running the following from the project root directory:
```shell
./go app:run
```
You will need to:
- Run a MongoDB database instance (can be local or cloud hosted, like MongoDb Atlas). Be sure the deployed instance is secured with authentication enforced (https://docs.mongodb.com/guides/server/auth/)

* Create a file './.env' on the basis of './.env.example' with the following information:
```
DB_CONNECTION_STRING=mongodb://localhost:27017
DB_NAME=api
DB_USERNAME=admin
DB_PASSWORD=secret

TOKEN_SECRET=1fdd5ab2823e118ee997219330c7abc37a56a5093b753b545ab40e5f216491eec5d400f121e678d6c5b03b01f2e56e1fd14b79afd5c0fdd61477ce469472a8a6
GCLOUD_SECRET=1f123ce56aeec5d400b2823e7abc121e6756e1f4b118ee

VOUCHERS_BUCKET="vouchers-upload-images-bucket"
```
Where:
* DB_CONNECTION_STRING: the connection string to the DB
* DB_NAME: the name of the DB (will be created)
* DB_USERNAME/DB_PASSWORD: login/password to access the database
* TOKEN_SECRET: see §Configuration above
* GCLOUD_SECRET: see §Configuration above
* Run the API server:
```shell
npm install
set PORT=3333
npm run start
```
* Create a file './external/keepers/src/.env' on the basis of './external/keepers/src/.env.example' with the following information:
```
TOKENS_CONTRACT_ADDRESS="0x..."
BOSON_ROUTER_CONTRACT_ADDRESS="0x..."
VOUCHER_KERNEL_ADDRESS="0x..."
API_URL="http://localhost:3333"
GCLOUD_SECRET="GENERATED_TOKEN"
ALCHEMY_URL="https://eth-desired-network.alchemyapi.io/v2/your-api-key"
```
Where:
* TOKENS_CONTRACT_ADDRESS: the address of the ERC1155721 contract
* BOSON_ROUTER_CONTRACT_ADDRESS: the address of the BosonRouter contract
* VOUCHER_KERNEL_ADDRESS: the address of the VoucherKernel contract
* API_URL: the URL of the backend API server (started above)
* GCLOUD_SECRET: generated on http://jwtbuilder.jamiekurtz.com with payload = {token: <GCLOUD_SECRET>} and key=<TOKEN_SECRET>, where GCLOUD_SECRET and TOKEN_SECRET values are defined in the env var of the API server
* ALCHEMY_URL: URL of the blockchain entry node (Alchemy, Infura, ...). If omitted will fallback to local rpc at port 8545 (default)
* Run the Keepers service:
```shell
npm run start:local:keepers
```
* Create a file './external/lambdas/.env' on the basis of './external/lambdas/.env.example' with the following information:
```
TOKENS_CONTRACT_ADDRESS="0x..."
BOSON_ROUTER_CONTRACT_ADDRESS="0x..."
CASHIER_ADDRESS="0x..."
VOUCHER_KERNEL_ADDRESS="0x..."
EXECUTOR_PRIVATE_KEY="0x..."
API_URL="http://localhost:3333"
GCLOUD_SECRET="GENERATED_TOKEN"
PROVIDER_URL="https://eth-desired-network.alchemyapi.io/v2/your-api-key"
#If the provider requires a secret authorization field in the request header (like Infura)
PROVIDER_SECRET=
```
Where:
* TOKENS_CONTRACT_ADDRESS: the address of the ERC1155721 contract
* BOSON_ROUTER_CONTRACT_ADDRESS: the address of the BosonRouter contract
* CASHIER_ADDRESS: the address of the Cashier contract
* VOUCHER_KERNEL_ADDRESS: the address of the VoucherKernel contract
* EXECUTOR_PRIVATE_KEY: the private key of the wallet to be used to interact with the contracts
* API_URL: the URL of the backend API server (started above)
* GCLOUD_SECRET: generated on http://jwtbuilder.jamiekurtz.com with payload = {token: <GCLOUD_SECRET>} and key=<TOKEN_SECRET>, where GCLOUD_SECRET and TOKEN_SECRET values are defined in the env var of the API server
* PROVIDER_URL: URL of the blockchain entry node (Alchemy, Infura, ...). If omitted will fallback to local rpc at port 8545 (default)
* PROVIDER_SECRET: (optional) if the provider requires a secret authorization field in the request header (like Infura)
* Run the Triggers service:
```shell
npm run start:local:triggers
```

---
### Test
Expand Down
27 changes: 27 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,33 @@ namespace :ci do
t.home_directory = 'build/fly'
end

RakeFly.define_pipeline_tasks(
namespace: :production,
argument_names: [
:ci_deployment_type,
:ci_deployment_label
]
) do |t, args|
configuration = configuration
.for_scope(args.to_h.merge(role: 'tag-pipeline'))
ci_deployment_type = configuration.ci_deployment_identifier

t.target = configuration.concourse_team
t.team = configuration.concourse_team
t.pipeline = "reference-backend-production"

t.config = 'pipelines/tag/pipeline.yaml'

t.vars = configuration.vars
t.var_files = [
'config/secrets/pipeline/constants.yaml',
"config/secrets/pipeline/#{ci_deployment_type}.yaml"
]

t.non_interactive = true
t.home_directory = 'build/fly'
end

RakeFly.define_pipeline_tasks(
namespace: :builder,
argument_names: [
Expand Down
5 changes: 5 additions & 0 deletions config/deployments/bsn-production-oganesson.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ database_type: "deployed"

image_upload_storage_engine: "AWS"

voucher_kernel_address: "0x72ed3a45303D5102B92b6F837162684673c40477"
token_contact_address: "0x94588Ba858c7F67B60a0a079FE2131c4C0351fB9"
boson_router_contact_address: "0x6D7f06CC2F2583A44226A9077Bea8C5f646B5095"
cashier_address: "0x5aF8E92541Ce126d2BfF69A03F301a7E16943A9c"

# State
domain_state_bucket_name: "bsn-aws-application-account-bsn-production-lutetium"
domain_state_key: "common/deployment-state/default.tfstate"
Expand Down
29 changes: 29 additions & 0 deletions config/roles/tag-pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
vars:
source_repository_url: "%{hiera('source_repository_url')}"
source_repository_branch: "%{hiera('source_repository_branch')}"

app_image_repository_url: "%{hiera('app_image_repository_url')}"
keepers_image_repository_url: "%{hiera('keepers_image_repository_url')}"
node_builder_image_repository_url: "%{hiera('node_builder_image_repository_url')}"

storage_bucket_name: "%{hiera('ci_storage_bucket_name')}"
storage_bucket_region: "%{hiera('ci_storage_bucket_region')}"
storage_bucket_encryption: "%{hiera('ci_storage_bucket_encryption')}"

ci_provisioning_role_arn: "%{hiera('ci_provisioning_role_arn')}"
ci_deployment_type: "%{hiera('ci_deployment_type')}"
ci_deployment_label: "%{hiera('ci_deployment_label')}"

production_oganesson_provisioning_role_arn: "%{hiera('production_oganesson_provisioning_role_arn')}"
production_oganesson_deployment_type: "%{hiera('production_oganesson_deployment_type')}"
production_oganesson_deployment_label: "%{hiera('production_oganesson_deployment_label')}"

slack_success_channel: "#builds"
slack_success_message: "<%{hiera('concourse_url')}/builds/$BUILD_ID|$BUILD_TEAM_NAME:$BUILD_PIPELINE_NAME:$BUILD_JOB_NAME [$BUILD_NAME]> _successful_! :clap:."
slack_error_channel: "#engineering"
slack_error_message: "<%{hiera('concourse_url')}/builds/$BUILD_ID|$BUILD_TEAM_NAME:$BUILD_PIPELINE_NAME:$BUILD_JOB_NAME [$BUILD_NAME]> *errored*! :cry:."
slack_failure_channel: "#engineering"
slack_failure_message: "<%{hiera('concourse_url')}/builds/$BUILD_ID|$BUILD_TEAM_NAME:$BUILD_PIPELINE_NAME:$BUILD_JOB_NAME [$BUILD_NAME]> *failed*! :cry:."
slack_abort_channel: "#engineering"
slack_abort_message: "<%{hiera('concourse_url')}/builds/$BUILD_ID|$BUILD_TEAM_NAME:$BUILD_PIPELINE_NAME:$BUILD_JOB_NAME [$BUILD_NAME]> *aborted*! :warning:."
Binary file modified config/secrets/app/bsn-demo-mendelevium.yaml
Binary file not shown.
Binary file modified config/secrets/app/bsn-production-oganesson.yaml
Binary file not shown.
5 changes: 3 additions & 2 deletions external/keepers/src/.env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

TOKENS_CONTRACT_ADDRESS="0x..."
BOSON_ROUTER_CONTRACT_ADDRESS="0x..."
VOUCHER_KERNEL_ADDRESS="0x..."
API_URL="http://localhost:3000"
GCLOUD_SECRET="TOKEN_SECRET"
# generated on http://jwtbuilder.jamiekurtz.com with payload = {token: <GCOULD_SECRET>} and key=<TOKEN_SECRET>,
# where GCLOUD_SECRET and TOKEN_SECRET values are defined in the env var of the API server
GCLOUD_SECRET="GENERATED_TOKEN"

#Serves as a RPC provider if you want to connect to a certain network. If omitted will fallback to local rpc at port 8545 (default)
ALCHEMY_URL="https://eth-desired-network.alchemyapi.io/v2/your-api-key"
Expand Down
13 changes: 13 additions & 0 deletions external/lambdas/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
BOSON_ROUTER_CONTRACT_ADDRESS="0x..."
CASHIER_ADDRESS="0x..."
VOUCHER_KERNEL_ADDRESS="0x..."
EXECUTOR_PRIVATE_KEY="0x..."
API_URL="http://localhost:3000"
# generated on http://jwtbuilder.jamiekurtz.com with payload = {token: <GCOULD_SECRET>} and key=<TOKEN_SECRET>,
# where GCLOUD_SECRET and TOKEN_SECRET values are defined in the env var of the API server
GCLOUD_SECRET="GENERATED_TOKEN"

#Serves as a RPC provider if you want to connect to a certain network. If omitted will fallback to local rpc at port 8545 (default)
PROVIDER_URL="https://eth-desired-network.alchemyapi.io/v2/your-api-key"
#If the provider requires a secret authorization field in the request header (like Infura)
PROVIDER_SECRET=
39 changes: 39 additions & 0 deletions external/lambdas/localConfigs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const ethers = require("ethers");
const resolve = require('path').resolve;
require('dotenv').config({path: resolve(__dirname, './.env')})

const getLocalConfigs = () => {
const apiUrl = process.env.API_URL;

let connectionHeaders = {};
if (process.env.PROVIDER_SECRET) {
const data = `:${process.env.PROVIDER_SECRET}`;
const buff = Buffer.from(data);
const b64ProviderSecret = buff.toString('base64');
connectionHeaders = {
'Authorization': `Basic ${b64ProviderSecret}`
};
}

return {
VOUCHER_KERNEL_ADDRESS: process.env.VOUCHER_KERNEL_ADDRESS,
CASHIER_ADDRESS: process.env.CASHIER_ADDRESS,
EXECUTOR_PRIVATE_KEY: process.env.EXECUTOR_PRIVATE_KEY,
API_URL: apiUrl,
ALL_VOUCHERS_URL: `${apiUrl}/vouchers/all`,
UPDATE_STATUS_URL: `${apiUrl}/vouchers/update-status-from-keepers`,
WITHDRAW_VOUCHER_URL: `${apiUrl}/payments/create-payment`,
GCLOUD_SECRET: process.env.GCLOUD_SECRET,
GAS_LIMIT: "6000000",
PROVIDER: new ethers.providers.JsonRpcProvider(
{
url: process.env.PROVIDER_URL,
headers: {
connectionHeaders
}
}
),
}
};

module.exports = getLocalConfigs;
15 changes: 12 additions & 3 deletions external/lambdas/localTriggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ const triggerInterval = 600000; //10 minutes in millis
const finalizationTrigger = require('./triggerFinalizations/src/index').handler;
const withdrawalsTrigger = require('./triggerWithdrawals/src/index').handler;
const expiryTrigger = require('./triggerExpirations/src/index').handler;
const getLocalConfigs = require('./localConfigs')

const config = getLocalConfigs();

// Run first before running the loop
finalizationTrigger(config);
withdrawalsTrigger(config);
expiryTrigger(config);


setInterval(() => {
finalizationTrigger();
withdrawalsTrigger();
expiryTrigger();
finalizationTrigger(config);
withdrawalsTrigger(config);
expiryTrigger(config);
}, triggerInterval);
15 changes: 1 addition & 14 deletions external/lambdas/triggerExpirations/src/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,7 @@ const getSecrets = async (SecretId) => {

const configs = {
local: () => {
const apiUrl = "http://localhost:3000";

return {
VOUCHER_KERNEL_ADDRESS: '0x...',
CASHIER_ADDRESS: '0x...',
EXECUTOR_PRIVATE_KEY: '0x...',
API_URL: apiUrl,
ALL_VOUCHERS_URL: `${apiUrl}/vouchers/all`,
UPDATE_STATUS_URL: `${apiUrl}/vouchers/update-status-from-keepers`,
WITHDRAW_VOUCHER_URL: `${apiUrl}/payments/create-payment`,
GCLOUD_SECRET: "tokensecret",
GAS_LIMIT: "6000000",
PROVIDER: new ethers.providers.JsonRpcProvider(),
}
throw new Error('Local run is expected to use config defined in a specific module')
},
cloud: secrets => {
const apiUrl = secrets.apiurl;
Expand Down
6 changes: 4 additions & 2 deletions external/lambdas/triggerExpirations/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const BN = ethers.BigNumber.from;
const VoucherKernel = require("./abis/VoucherKernel.json");
const utils = require("./utils");

exports.handler = async (event) => {
const config = await getConfigParams(process.env.SSM_SECRET, "cloud");
exports.handler = async (config) => {
if (!config) {
config = await getConfigParams(process.env.SSM_SECRET, "cloud");
}
const executor = new ethers.Wallet(config.EXECUTOR_PRIVATE_KEY, config.PROVIDER);

axios.defaults.headers.common = {
Expand Down
14 changes: 1 addition & 13 deletions external/lambdas/triggerFinalizations/src/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,7 @@ const getSecrets = async (SecretId) => {

const configs = {
local: () => {
const apiUrl = "http://localhost:3000";
return {
VOUCHER_KERNEL_ADDRESS: '0x...',
CASHIER_ADDRESS: '0x...',
EXECUTOR_PRIVATE_KEY: '0x...',
API_URL: apiUrl,
ALL_VOUCHERS_URL: `${apiUrl}/vouchers/all`,
UPDATE_STATUS_URL: `${apiUrl}/vouchers/update-status-from-keepers`,
WITHDRAW_VOUCHER_URL: `${apiUrl}/payments/create-payment`,
GCLOUD_SECRET: "tokensecret",
GAS_LIMIT: "6000000",
PROVIDER: new ethers.providers.JsonRpcProvider(),
}
throw new Error('Local run is expected to use config defined in a specific module')
},
cloud: secrets => {
const apiUrl = secrets.apiurl;
Expand Down
6 changes: 4 additions & 2 deletions external/lambdas/triggerFinalizations/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ const BN = ethers.BigNumber.from;
const VoucherKernel = require("./abis/VoucherKernel.json");
const utils = require("./utils");

exports.handler = async (event) => {
const config = await getConfigParams(process.env.SSM_SECRET, "cloud");
exports.handler = async (config) => {
if (!config) {
config = await getConfigParams(process.env.SSM_SECRET, "cloud");
}
const executor = new ethers.Wallet(config.EXECUTOR_PRIVATE_KEY, config.PROVIDER);

axios.defaults.headers.common = {
Expand Down
15 changes: 1 addition & 14 deletions external/lambdas/triggerWithdrawals/src/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,7 @@ const getSecrets = async (SecretId) => {

const configs = {
local: () => {
const apiUrl = "http://localhost:3000";

return {
VOUCHER_KERNEL_ADDRESS: '0x...',
CASHIER_ADDRESS: '0x...',
EXECUTOR_PRIVATE_KEY: '0x...',
API_URL: apiUrl,
ALL_VOUCHERS_URL: `${apiUrl}/vouchers/all`,
UPDATE_STATUS_URL: `${apiUrl}/vouchers/update-status-from-keepers`,
WITHDRAW_VOUCHER_URL: `${apiUrl}/payments/create-payment`,
GCLOUD_SECRET: "tokensecret",
GAS_LIMIT: "6000000",
PROVIDER: new ethers.providers.JsonRpcProvider(),
}
throw new Error('Local run is expected to use config defined in a specific module')
},
cloud: secrets => {
const apiUrl = secrets.apiurl;
Expand Down
6 changes: 4 additions & 2 deletions external/lambdas/triggerWithdrawals/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ const Cashier = require("./abis/Cashier.json");

const utils = require("./utils");

exports.handler = async (event) => {
const config = await getConfigParams(process.env.SSM_SECRET, "cloud");
exports.handler = async (config) => {
if (!config) {
config = await getConfigParams(process.env.SSM_SECRET, "cloud");
}
const executor = new ethers.Wallet(config.EXECUTOR_PRIVATE_KEY, config.PROVIDER);

axios.defaults.headers.common = {
Expand Down
Loading