feat: refactored to codex factory

This commit is contained in:
Adam Uhlíř 2025-04-14 16:54:35 +02:00
parent 92b43baed1
commit 8769818ad8
No known key found for this signature in database
GPG Key ID: 1D17A9E81F76155B
73 changed files with 579 additions and 19384 deletions

View File

@ -1,135 +0,0 @@
on:
repository_dispatch:
types: [ build-images ]
workflow_dispatch:
inputs:
buildImage:
description: 'Build and push Docker Image according to the environment'
default: 'false'
commitVersionTag:
description: 'The image tag will be retrieved from the bee version command'
default: 'false'
beeVersion:
description: 'The official bee image tag that the image will be built on. Default: last supported version'
default: 'latest'
beeVersionAsCommitHash:
description: 'The beeVersion parameter will be interpreted as a source code commit hash that the bee base image will be built on'
default: 'false'
stateCommit:
description: 'The images will have cheques by the traffic generation'
default: 'false'
branch:
description: 'Branch of this repo to build (default "master")'
default: master
required: false
push:
branches:
- 'master'
pull_request:
branches:
- '**'
env:
BEE_IMAGE_PREFIX: 'ethersphere'
BUILD_IMAGE: 'false'
COMMIT_VERSION_TAG: 'false'
STATE_COMMIT: 'true'
BEE_VERSION: '${{ github.event.client_payload.tag }}'
BEE_PLATFORM: 'linux/amd64,linux/arm64,linux/arm/v7'
jobs:
bee-images:
name: Build and publish images
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.branch }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
with:
install: true
- name: Override inputs from `workflow_dispatch`
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "BEE_VERSION=${{ github.event.inputs.beeVersion }}" >> $GITHUB_ENV
echo "BUILD_IMAGE=${{ github.event.inputs.beeVersionAsCommitHash }}" >> $GITHUB_ENV
echo "COMMIT_VERSION_TAG=${{ github.event.inputs.commitVersionTag }}" >> $GITHUB_ENV
echo "STATE_COMMIT=${{ github.event.inputs.stateCommit }}" >> $GITHUB_ENV
else
echo "BEE_VERSION=${BEE_VERSION/v}" >> $GITHUB_ENV
fi
- name: Auth to Docker Hub
if: ${{ github.event_name == 'repository_dispatch' || (github.event.inputs.buildImage == 'true' && success()) }}
run: |
echo "PUSH_IMAGES=1" >> $GITHUB_ENV
echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u ${{secrets.DOCKERHUB_USERNAME}} --password-stdin
- uses: actions/cache@v3
id: cache-npm
with:
path: generator/node_modules
key: ${{ runner.os }}-${{ hashFiles('generator/package-lock.json') }}
- name: Install npm deps
if: steps.cache-npm.outputs.cache-hit != 'true'
run: cd ./generator && npm ci
- name: Build images
id: build
run: |
cd ./generator
BUILD_PARAMS=""
if [ $BUILD_IMAGE == 'true' ] ; then
BUILD_PARAMS+=" --build-base-bee --base-bee-commit-hash=$BEE_VERSION"
fi
if [ $STATE_COMMIT == 'true' ] ; then
BUILD_PARAMS+=" --gen-traffic"
fi
npm run build:env -- $BUILD_PARAMS
- name: Update bee version in package.json
uses: jossef/action-set-json-field@v2
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.tag != 'latest' }}
with:
file: package.json
field: engines.bee
value: ${{ env.BEE_VERSION }}
- name: Add trailing new-line to package.json
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.tag != 'latest' }}
run: printf "\n" >> package.json
- name: Create/update PR
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.tag != 'latest' }}
uses: gr2m/create-or-update-pull-request-action@v1
env:
GITHUB_TOKEN: ${{ secrets.REPO_GHA_PAT }}
with:
title: "chore: update to bee ${{ env.BEE_VERSION }}"
body: "Updated Bee version ${{ env.BEE_VERSION }}"
branch: "bee-${{ env.BEE_VERSION }}"
commit-message: "chore: update to new bee"
author: "bee-worker <bee-worker@ethswarm.org>"
- name: Trigger Bee-js PR creation
if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.tag != 'latest' }}
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ secrets.REPO_GHA_PAT }}
repository: ethersphere/bee-js
event-type: update-bee
client-payload: '{"beeVersion": "${{ steps.build.outputs.full-version }}", "apiVersion": "${{ steps.build.outputs.api-version }}", "debugApiVersion": "${{ steps.build.outputs.debug-api-version }}"}'

View File

@ -1,25 +0,0 @@
# After new release is published on github, publish it to npmjs
name: Publish on npmjs
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
- uses: apexskier/github-release-commenter@v1
with:
GITHUB_TOKEN: ${{ secrets.REPO_GHA_PAT }}
comment-template: |
Release {release_link} addresses this.

View File

@ -1,20 +0,0 @@
# On each new commit to master, create/update a PR with release
# automatically bumps version and creates changelog as per conventional commits
name: Release Github
on:
push:
branches:
- master
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: GoogleCloudPlatform/release-please-action@v3
id: release
with:
token: ${{ secrets.REPO_GHA_PAT }}
release-type: node
package-name: bee-factory
bump-minor-pre-major: true

37
.github/workflows/release_please.yaml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Release Please
on:
push:
branches:
- master
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
release-type: node
- uses: actions/checkout@v4
if: ${{ steps.release.outputs.release_created }}
- uses: actions/setup-node@v4
if: ${{ steps.release.outputs.release_created }}
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
- run: npm ci
if: ${{ steps.release.outputs.release_created }}
- run: npm publish --provenance --access public
if: ${{ steps.release.outputs.release_created }}
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

View File

@ -1,133 +0,0 @@
# Changelog
## [0.5.2](https://github.com/ethersphere/bee-factory/compare/v0.5.1...v0.5.2) (2022-12-19)
### Bug Fixes
* add postage contract start block ([#235](https://github.com/ethersphere/bee-factory/issues/235)) ([0fa8acf](https://github.com/ethersphere/bee-factory/commit/0fa8acfd1bb74a655fcb7a03e5a8605f6b7c0b75))
## [0.5.1](https://github.com/ethersphere/bee-factory/compare/v0.5.0...v0.5.1) (2022-12-14)
### Bug Fixes
* allow multiple digits versions ([#233](https://github.com/ethersphere/bee-factory/issues/233)) ([4058525](https://github.com/ethersphere/bee-factory/commit/4058525ab6ca0168d036691676302dc0bc3f0702))
## [0.5.0](https://github.com/ethersphere/bee-factory/compare/v0.4.1...v0.5.0) (2022-11-08)
This is a bigger breaking release that brings support for the Bee 1.9. It is not compatible with the earlier Bee's version.
### Features
* increased nodes funding ([#221](https://github.com/ethersphere/bee-factory/issues/221)) ([86e8649](https://github.com/ethersphere/bee-factory/commit/86e86491d460536015425be5f5a91d06e19db694))
* latest builds ([#150](https://github.com/ethersphere/bee-factory/issues/150)) ([2ef924d](https://github.com/ethersphere/bee-factory/commit/2ef924d615cfc1a612cb9167a28037918114597e))
* queen image has postage stamp bought ([#220](https://github.com/ethersphere/bee-factory/issues/220)) ([ffbfaa2](https://github.com/ethersphere/bee-factory/commit/ffbfaa2cfa4dc57dd7bc4d1c09debabf450a0d86))
* supported bee version check ([#223](https://github.com/ethersphere/bee-factory/issues/223)) ([4b02910](https://github.com/ethersphere/bee-factory/commit/4b029108efa70314656e05b10220adf7f0b3958b))
* update blockchain image and contracts addresses are in labels ([#214](https://github.com/ethersphere/bee-factory/issues/214)) ([a7eb6c6](https://github.com/ethersphere/bee-factory/commit/a7eb6c6d05d35dd44f08e7c3641cf3721a5d9d28))
### Bug Fixes
* invalid mode and gas block limit ([#217](https://github.com/ethersphere/bee-factory/issues/217)) ([b8f3039](https://github.com/ethersphere/bee-factory/commit/b8f30398a425be75113056830ff6f4fb787c996b))
* state generation of docker images ([#216](https://github.com/ethersphere/bee-factory/issues/216)) ([7dc8992](https://github.com/ethersphere/bee-factory/commit/7dc8992df7c92320b7c20c9001b02bd05918d846))
### [0.4.1](https://www.github.com/ethersphere/bee-factory/compare/v0.4.0...v0.4.1) (2022-05-24)
### Bug Fixes
* node 18 fetch support ([#117](https://www.github.com/ethersphere/bee-factory/issues/117)) ([4fa6467](https://www.github.com/ethersphere/bee-factory/commit/4fa64673507831e73e949cf4ad8fc3c93ed09f82))
## [0.4.0](https://www.github.com/ethersphere/bee-factory/compare/v0.3.0...v0.4.0) (2022-05-16)
### Features
* specify workers count ([#111](https://www.github.com/ethersphere/bee-factory/issues/111)) ([81ed316](https://www.github.com/ethersphere/bee-factory/commit/81ed316b38f3fb44a1ba5f02b11c01c1f8c2f078))
### Bug Fixes
* bee 1.6.0 requires mainnet false ([#110](https://www.github.com/ethersphere/bee-factory/issues/110)) ([00a6f38](https://www.github.com/ethersphere/bee-factory/commit/00a6f38585a387a96c116a1a9bd9d2aae0f2ffb9))
* proper error handling when conf does not exists ([#106](https://www.github.com/ethersphere/bee-factory/issues/106)) ([c1a1d3a](https://www.github.com/ethersphere/bee-factory/commit/c1a1d3a885aa14adf89405d8b737272678e4e814))
## [0.3.0](https://www.github.com/ethersphere/bee-factory/compare/v0.2.0...v0.3.0) (2022-05-10)
### Features
* multiarch builds ([#99](https://www.github.com/ethersphere/bee-factory/issues/99)) ([927405b](https://www.github.com/ethersphere/bee-factory/commit/927405bab3cafd79b5b8f53039c49478a0aad01f))
### Bug Fixes
* add full bee version with commit for bee-js update ([#104](https://www.github.com/ethersphere/bee-factory/issues/104)) ([b11aab3](https://www.github.com/ethersphere/bee-factory/commit/b11aab3d3cf954b78405d64b8b5d929780948995))
* commit removing regex honors rc suffix ([#98](https://www.github.com/ethersphere/bee-factory/issues/98)) ([e146b84](https://www.github.com/ethersphere/bee-factory/commit/e146b8406b4b4f1fb25cd6b5c4320fb60785585b))
* dont use promise fs namespace for node12 support ([#97](https://www.github.com/ethersphere/bee-factory/issues/97)) ([bef03ca](https://www.github.com/ethersphere/bee-factory/commit/bef03cabc86716917c4b7d0047e7a96c47324058))
## [0.2.0](https://www.github.com/ethersphere/bee-factory/compare/v0.1.2...v0.2.0) (2022-05-05)
### Features
* allow version with commit hash ([9c99180](https://www.github.com/ethersphere/bee-factory/commit/9c99180aacc94a7e9fa0116812686766a29c0096))
### Bug Fixes
* regex ([1ac6d89](https://www.github.com/ethersphere/bee-factory/commit/1ac6d89815a29f0b319a7d2c16dbc31dbb554cfd))
* shebang and bee-js in deps ([b7659fc](https://www.github.com/ethersphere/bee-factory/commit/b7659fc8b4ebd5967470e7517ab2990086c72a54))
### [0.1.2](https://www.github.com/ethersphere/bee-factory/compare/v0.1.1...v0.1.2) (2022-05-05)
### Bug Fixes
* correct bin endpoint ([9520830](https://www.github.com/ethersphere/bee-factory/commit/952083001d3b1f858fd5102ba06a7121661bb15e))
### [0.1.1](https://www.github.com/ethersphere/bee-factory/compare/v0.1.0...v0.1.1) (2022-05-05)
### Bug Fixes
* release ([bc63108](https://www.github.com/ethersphere/bee-factory/commit/bc631084522abee182c1adb62022ed5adabebfc8))
## 0.1.0 (2022-05-05)
### Features
* 0.6.0 Bee ([#4](https://www.github.com/ethersphere/bee-factory/issues/4)) ([9e36613](https://www.github.com/ethersphere/bee-factory/commit/9e366130b81cb41fd3fcd2d7d3e09759777c15ec))
* adding docker meta label for required blockchain image ([#88](https://www.github.com/ethersphere/bee-factory/issues/88)) ([51f37f4](https://www.github.com/ethersphere/bee-factory/commit/51f37f402f692c977530698ead8046d977ae4649))
* api versions support ([#72](https://www.github.com/ethersphere/bee-factory/issues/72)) ([9ac5b11](https://www.github.com/ethersphere/bee-factory/commit/9ac5b11421982474e1fe0c23751f296b0f7113ee))
* bee 1.0.0 ([#41](https://www.github.com/ethersphere/bee-factory/issues/41)) ([b8e451e](https://www.github.com/ethersphere/bee-factory/commit/b8e451e57e7b095059aec0e51fca56ce377a4249))
* bee 1.1.0 ([#52](https://www.github.com/ethersphere/bee-factory/issues/52)) ([84e7925](https://www.github.com/ethersphere/bee-factory/commit/84e7925165fa3befa215151752696a93b59a0700))
* change BEE_VERSION to 1.2.0 ([#55](https://www.github.com/ethersphere/bee-factory/issues/55)) ([568f174](https://www.github.com/ethersphere/bee-factory/commit/568f17465ca64ff850a0a6a7de7d7ba7f5405b1f))
* configurable hostname to which blockchain and bee nodes are bound ([#53](https://www.github.com/ethersphere/bee-factory/issues/53)) ([8151b55](https://www.github.com/ethersphere/bee-factory/commit/8151b5597eaf79f3013d1f3bda841d4e7a7daf4b))
* create docker network on environment.sh run ([9a34ba2](https://www.github.com/ethersphere/bee-factory/commit/9a34ba2ff9056b964580fd63fcb00e0b043f9b80))
* docker image builds ([#2](https://www.github.com/ethersphere/bee-factory/issues/2)) ([0bce2ed](https://www.github.com/ethersphere/bee-factory/commit/0bce2ed4859468bd7e9180e9eb80488245bfa92f))
* external configuration ([#89](https://www.github.com/ethersphere/bee-factory/issues/89)) ([ddd764e](https://www.github.com/ethersphere/bee-factory/commit/ddd764e668f5f34b3aab02611e2a98e6f9e2f701))
* image generation improvements ([#87](https://www.github.com/ethersphere/bee-factory/issues/87)) ([365f77c](https://www.github.com/ethersphere/bee-factory/commit/365f77c1abfe15e9465574955652b02438e5641c))
* init ([#1](https://www.github.com/ethersphere/bee-factory/issues/1)) ([d38a255](https://www.github.com/ethersphere/bee-factory/commit/d38a2551a84cae433eb73a674c8f3e2c05989977))
* let's roll ([8bf781f](https://www.github.com/ethersphere/bee-factory/commit/8bf781f84af9eca0790fb60d9bd81f1d4e6fa89e))
* parametric traffic gen ([#35](https://www.github.com/ethersphere/bee-factory/issues/35)) ([e163745](https://www.github.com/ethersphere/bee-factory/commit/e16374583991930937bfd025678e1ca2e6c657b7))
* queen waits for worker connections ([#12](https://www.github.com/ethersphere/bee-factory/issues/12)) ([2feb3b3](https://www.github.com/ethersphere/bee-factory/commit/2feb3b35a7b3122715556752c46cddde410f89a1))
* restricted api support ([#69](https://www.github.com/ethersphere/bee-factory/issues/69)) ([03e8694](https://www.github.com/ethersphere/bee-factory/commit/03e8694d4c3b33b0da8c1486318154fec8b89de4))
* separate blockchain versioning ([#3](https://www.github.com/ethersphere/bee-factory/issues/3)) ([9d9afbf](https://www.github.com/ethersphere/bee-factory/commit/9d9afbfe25ff4765373114a73dd5081d5105bad4))
* tag with commit hash ([#10](https://www.github.com/ethersphere/bee-factory/issues/10)) ([73595f8](https://www.github.com/ethersphere/bee-factory/commit/73595f86d0cd105967cd8daa38593670778f41c1))
* timeout on infinite loops ([#18](https://www.github.com/ethersphere/bee-factory/issues/18)) ([fcb873e](https://www.github.com/ethersphere/bee-factory/commit/fcb873ee5cfdd26c9463badb2b1d256dadaf8989))
* traffic gen ([#21](https://www.github.com/ethersphere/bee-factory/issues/21)) ([e61f2cb](https://www.github.com/ethersphere/bee-factory/commit/e61f2cb8a1fd3668b8f8e543b3c1052209e997da))
* ts cli orchestrator ([#81](https://www.github.com/ethersphere/bee-factory/issues/81)) ([360f3e0](https://www.github.com/ethersphere/bee-factory/commit/360f3e07c275cf187a85f351396900847195c63f))
### Bug Fixes
* add blockchain image push to the publish script ([6aa40f0](https://www.github.com/ethersphere/bee-factory/commit/6aa40f09f000be53d4ee3ef35349fd18316bf5db))
* add tag to the docker image ls in docker push script ([e15c7ea](https://www.github.com/ethersphere/bee-factory/commit/e15c7eabcac49f324c1332a7d6c53dfe61644942))
* ci double quotes at if statement ([ba9ab71](https://www.github.com/ethersphere/bee-factory/commit/ba9ab717ed2e8f803c45e4c51956e7fef71a9d42))
* handling comman in underlay address array ([#13](https://www.github.com/ethersphere/bee-factory/issues/13)) ([1719ebd](https://www.github.com/ethersphere/bee-factory/commit/1719ebda946e645c6da517d6448107ea41d97522))
* pull bee image on tagged version image build ([0c35926](https://www.github.com/ethersphere/bee-factory/commit/0c359264c686e12bdcd2331b14f2b63f0e4c16ac))
* pull env variables from .env file in publish-environment.sh ([b3fe994](https://www.github.com/ethersphere/bee-factory/commit/b3fe994fe07ed92297cc5371be2337f516d57661))
* push docker images by their name instead of the ids ([ccc3b5e](https://www.github.com/ethersphere/bee-factory/commit/ccc3b5eca6e388964b56ab570ed4b5535cafbed4))
* traffic generation ([#71](https://www.github.com/ethersphere/bee-factory/issues/71)) ([d22a727](https://www.github.com/ethersphere/bee-factory/commit/d22a727d2d0d68c511b8f34de2c153b87e6677d9))

View File

@ -1 +1 @@
* @Cafe137 * @AuHau

View File

@ -1,4 +1,5 @@
Copyright (c) 2022 The Swarm Authors. All rights reserved. Copyright (c) 2025 Status Research & Development GmbH.
Copyright (c) 2022-2025 The Swarm Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are

106
README.md
View File

@ -1,16 +1,13 @@
**This project is superseded by [fdp-play](https://github.com/fairDataSociety/fdp-play) and is no longer maintained.** # Codex Factory
# Bee Factory [![Tests](https://github.com/codex-storage/codex-factory/actions/workflows/test.yaml/badge.svg)](https://github.com/codex-storage/codex-factory/actions/workflows/test.yaml)
[![Tests](https://github.com/ethersphere/bee-factory/actions/workflows/test.yaml/badge.svg)](https://github.com/ethersphere/bee-factory/actions/workflows/test.yaml)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fethersphere%2Fbee-factory.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fethersphere%2Fbee-factory?ref=badge_shield)
[![](https://img.shields.io/badge/made%20by-Swarm-blue.svg?style=flat-square)](https://swarm.ethereum.org/) [![](https://img.shields.io/badge/made%20by-Swarm-blue.svg?style=flat-square)](https://swarm.ethereum.org/)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) [![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
![](https://img.shields.io/badge/npm-%3E%3D6.9.0-orange.svg?style=flat-square) ![](https://img.shields.io/badge/npm-%3E%3D10.0.0-orange.svg?style=flat-square)
![](https://img.shields.io/badge/Node.js-%3E%3D12.0.0-orange.svg?style=flat-square) ![](https://img.shields.io/badge/Node.js-%3E%3D18.0.0-orange.svg?style=flat-square)
> CLI tool to spin up Docker cluster of Bee nodes for advanced testing and/or development > CLI tool to spin up Docker cluster of Codex nodes for advanced testing and/or development
**Warning: This project is in beta state. There might (and most probably will) be changes in the future to its API and working. Also, no guarantees can be made about its stability, efficiency, and security at this stage.** **Warning: This project is in beta state. There might (and most probably will) be changes in the future to its API and working. Also, no guarantees can be made about its stability, efficiency, and security at this stage.**
@ -26,104 +23,77 @@
**Requirements:** Docker **Requirements:** Docker
```shell ```shell
$ npm install -g @ethersphere/bee-factory $ npm install -g @codex-storage/codex-factory
``` ```
## Usage ## Usage
**Starting with Bee Factory's version `0.5.0` it is compatible only with Bee version `1.9.0` and higher!**
```shell ```shell
# This spins up the cluster for specific Bee version and exits # This spins up the cluster for specific Codex version and exits
$ bee-factory start --detach 1.9.0 $ codex-factory start --detach 0.2.0
# The spins up the cluster using Bee version configured in external places. See below for options where to place it. # The spins up the cluster using Codex version configured in external places. See below for options where to place it.
$ bee-factory start --detach $ codex-factory start --detach
# This attaches to the Queen container and displays its logs # This attaches to the client container and displays its logs
$ bee-factory logs queen --follow $ codex-factory logs client --follow
# This stops the cluster and keeping the containers so next time they are spinned up the data are kept # This stops the cluster and keeping the containers so next time they are spinned up the data are kept
# but data are not persisted across version's bump! # but data are not persisted across version's bump!
$ bee-factory stop $ codex-factory stop
# You can also spin up the cluster without the --detach which then directly # You can also spin up the cluster without the --detach which then directly
# attaches to the Queen logs and the cluster is terminated upon SIGINT (Ctrl+C) # attaches to the client logs and the cluster is terminated upon SIGINT (Ctrl+C)
$ bee-factory start 1.9.0 $ codex-factory start 0.2.0
# You can spin cluster with the last nim-codex's master build - this might not work!
$ codex-factory start latest
# You can spin cluster with the specific Git commit nim-codex's master build - this might not work!
$ codex-factory start ce2db15
``` ```
For more details see the `--help` page of the CLI and its commands. For more details see the `--help` page of the CLI and its commands.
### External Bee version configuration ### External Codex version configuration
You can omit the Bee version argument when running `bee-factory start` command if you specify it in one of the expected places: You can omit the Codex version argument when running `codex-factory start` command if you specify it in one of the expected places:
- `package.json` placed in current working directory (cwd) under the `engines.bee` property. - `package.json` placed in current working directory (cwd) under the `engines.codex` property.
- `.beefactory.json` placed in current working directory (cwd) with property `version`. - `.codexfactory.json` placed in current working directory (cwd) with property `version`.
### Docker Images #### Build versions
Bee Factory as the NPM package that you can install, like mentioned above, works in a way that it orchestrates launching Bee Factory Docker images Docker images are built upon every push to `nim-codex`'s `master` branch, so if you need to test some specific commit
in correct order and awaits for certain initializations to happen in correct form. These Docker images are automatically built with our CI you can then use its short Git commit hash in order to spin Codex's factory cluster. But be aware that this might not
upon every new Bee release, so you can just specify which version you want to run (starting with `1.9.0` version) as part of the `start` command. work as Codex factory is maintained based on the released versions and hence if there were some changes in configuration
parameters in the build you want to use, Codex factory might not yet support it.
If for some reason you want built your own images, that is possible but discouraged and not supported (**here be dragons**) using the scripts in the `generator` subfolder.
Upon building and publishing these images you can consume them using with Bee Factory with the `--repo` flag.
#### Latest versions #### Latest versions
There is special Bee Factory image tag `latest` that has the latest Bee's master build. There is special Codex Factory image tag `latest` that has the latest Codex's master build.
It is not recommended using this tag unless you need to test some upcoming feature and know what are you doing. It is not recommended using this tag unless you need to test some upcoming feature and know what are you doing.
There is high chance that there might be some change in Bee that is not compatible with current Bee Factory and so it might not even work. There is high chance that there might be some change in Codex that is not compatible with current Codex Factory and so it might not even work.
## Contribute ## Contribute
There are some ways you can make this module better: There are some ways you can make this module better:
- Consult our [open issues](https://github.com/ethersphere/bee-factory/issues) and take on one of them - Consult our [open issues](https://github.com/codex-storage/codex-factory/issues) and take on one of them
- Help our tests reach 100% coverage! - Something not working - create issue!
- Join us in our [Discord chat](https://discord.gg/wdghaQsGq5) in the #develop-on-swarm channel if you have questions or want to give feedback - See something to tweak - create PR!
- Join us in our [Discord chat](https://discord.gg/codex-storage) if you have questions or want to give feedback
### Developing ### Developing
You can run the CLI while developing using `npm start -- <command> ...`. You can run the CLI while developing using `npm start -- <command> ...`.
### Local images
If you want to locally build the Bee Factory images, then edit the `./generator/scripts/.env` file with appropriate configuration
and then run the `./generator/scripts/build-environment.sh` script. This will build the images with the `ethersphere/bee-factory-*` tags.
Then simply run the `npm start -- <command>` with the appropriate version of Bee you have build.
The CLI should pickup local images prior trying to pull it from Docker Hub, so it will use your build ones.
### Updating Blockchain images
If Bee updated its smart contracts suite, then smart contracts needs to be updated in Bee Factory as well otherwise the spawned Bees might
have unpredictable behavior.
First of all you have to preprocess the smart contract's bytecodes. In Solidity the constructor parameters are passed to the contract by appending the parameters
ABI-encoded to the end of the bytecode (for more see for example [here](https://ethereum.stackexchange.com/questions/58866/how-does-a-contracts-constructor-work-and-load-input-values)).
So you have to make sure that the bytecodes that you update are stripped of these constructor parameters.
This is because these parameters are then later on appended during smart contract deployment.
If only internal smart contract's logic has changed and there is no change to the smart contract's constructor, then you have to only
update the bytecodes. You do it by pasting the bytecodes to appropriate files in `./generator/contracts/` folder.
If there are new smart contracts or their constructor's have changed then you have to also modify the deploy script which is present in
`./generator/migrations/1_initial.js` file. **Don't remove the logging that starts with `::CONTRACT:`!** This serves to extract the deployed
contracts addresses and apply them to the Docker image's label.
If you are adding new smart contract than also add new `::CONTRACT:` log line that has format of `::CONTRACT:<bee-option-name>:<smart-contract-address>`,
where the `bee-option-name` stands for the option name that customize the contract's address in Bee.
Last step is to bump the `BLOCKCHAIN_VERSION` version in `./generator/scripts/.env` file.
## Maintainers ## Maintainers
- [Cafe137](https://github.com/cafe137) - [AuHau](https://github.com/auhau)
## License ## License
[BSD-3-Clause](./LICENSE) [BSD-3-Clause](./LICENSE)
Originally written for Swarm's Bee client: https://github.com/ethersphere/bee-factory
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fethersphere%2Fbee-factory.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fethersphere%2Fbee-factory?ref=badge_large)

View File

@ -1,136 +0,0 @@
# Bee Factory Generator
This project builds up a test environment with Bee clients and with a test blockchain.
The created environment is runnable on local machine as well.
All services run in `Docker` containers only.
Currently, the repository supports running Bee nodes up to 5 by default.
## Maintainers
- [nugaon](https://github.com/nugaon)
- [Cafe137](https://github.com/Cafe137)
See what "Maintainer" means [here](https://github.com/ethersphere/repo-maintainer).
## Usage
The whole Bee environment (with blockchain) can be started by [running one script](###Run-Environment),
but for that you need to have the necessary Docker images, which is possible to build yourself by [running some scripts](###Setup-the-environment)
First you may want to set all global variables that the scripts will use.
For that, there is a [.env](scripts/.env) file which contains all necessary variables that you need.
```sh
set -a && source ./scripts/.env && set +a
```
If you do not set these global variables, the scripts will use those which are available in the [.env](scripts/.env) file.
## Setup the environment
Create the common Docker network for the environment with
```sh
./scripts/network.sh
```
To start the blockchain, run the following command in the root directory of the project:
```sh
./scripts/blockchain.sh
```
After that, it's possible to deploy Swarm smart contracts
```sh
npm run migrate:contracts
```
Before you start the Bee nodes with the deployed Swap Factory, you have to fund your overlay addresses of your Bee nodes for the successful start.
The [supply.js](src/supply.js) script can fund the addresses which are defined in [bee-overlay-addresses.json](bee-overlay-addresses.json) file.
To run this script just execute
```sh
npm run supply
```
and the configured accounts will get 1 ether and 100 BZZ Token.
After all above went successfully you can start the Bee nodes
```sh
./scripts/bee.sh start --workers=4
```
OR it is possible to build docker images on a desired state, so that a fresh environment can be started on each run.
### Build Docker Images
Basically, a full-featured Bee environment has 2 types of Docker image:
- Bee images: Bee clients with pre-defined keys (and optionally including the state which you nodes have in its [data-dirs](scripts/bee-data-dirs))
```sh
./scripts/bee-docker-build.sh
```
- Blockchain image: Ganache blockchain which you may want to take a snapshot of after the contracts are deployed and the pre-defined Bee client keys are funded already.
```sh
./scripts/blockchain-docker-build.sh
```
## Index Environment
If you have all Docker images that your [environment file](scripts/.env) requires,
start the Bee cluster
```sh
./scripts/environment.sh start
```
### Restricted API
If you want to enable permission check feature of Bee on the API endpoints you can use `--restrict` flag. This will
use default password `SwarmToTheMoon` or if you want you can pass your own password as `--restrict=someOtherPassword`.
This feature requires to have `htpasswd` command available which is part of the `apache2-utils` package.
### Pull images
Bee Factory can build images for CIs, but it is also possible to pull image to your computer as well.
For that you have to login to the Github docker registry with
```sh
docker login docker.pkg.github.com
```
it will ask for your _GitHub_ username and for the password. For the latter you can generate a [Personal Access Token](https://github.com/settings/tokens).
The suggested permissions for the token are `read:org` and `read:packages`.
## Utilities
It is possible to generate random traffic in your cluster:
```sh
$ npm run gen:traffic
```
The script is in an infinite loop, so if you want to stop the generation you have to terminate it manually in your terminal by pressing `Ctrl^C`.
If you don't specify any parameters it will produce 400 chunks/0.5 sec that the script tries to upload on the `http://localhost:1633` - that is the binded port of the queen node if you orchestrated the environment with the `envrionment.sh`.
The following way you can pass parameter
1. MIN_CHEQUE_NUMBER - Minimum required cheques for Bee under the given BEE_DEBUG_API_URL. If -1 then it does not check for cheques [Number,Default:-1]
2. BEE_API_URL;BEE_DEBUG_API_URL - Bee API and Debug API URL separated by semicolon. The random data will sent to the Bee API URL, and the generated cheques will be checked on the Bee Debug URL. The two URLs should belong to different Bee clients as the generated data will propagate from that client to the network. [string,Default:'http://localhost:1633;http://localhost:11635']
```sh
$ npm run gen:traffic -- <MIN_CHEQUE_NUMBER> <BEE_API_URL;BEE_DEBUG_API_URL> <BEE_API_URL;BEE_DEBUG_API_URL> (...)
```
e.g.
```sh
$ npm run gen:traffic -- 2 http://localhost:1633;http://localhost:11635
```
With the example above, random data will be generated until _minimum_ two cheques will generated on Bee client that serves debug endpoint `http://localhost:11635`

View File

@ -1,7 +0,0 @@
[
"0x26234a2ad3ba8b398a762f279b792cfacd536a3f",
"0x8e3cb0148c5f39577fb815dc8c37795e30f5dcfa",
"0xed52b8ac9b1bc1e7f3fe46ea3a094fbaa8f6ccb4",
"0x119331b8074bd779fc5b96fe4d50947d31addfe4",
"0x102aaa556337d86e270010588d9fbd5ecaeebff8"
]

View File

@ -1,3 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity =0.6.12;
import "@openzeppelin/contracts/presets/ERC20PresetMinterPauser.sol";

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
608060405234801561001057600080fd5b506040516104b83803806104b883398101604081905261002f9161007e565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001919091556002556100a1565b60008060408385031215610090578182fd5b505080516020909101519092909150565b610408806100b06000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806398d5fdca1161005b57806398d5fdca146100dd578063a035b1fe146100f8578063dd4899321461010f578063f2fde38b1461011857600080fd5b8063710f2dd11461008d578063715018a6146100a25780638d6cc56d146100aa5780638da5cb5b146100bd575b600080fd5b6100a061009b366004610385565b61012b565b005b6100a061019a565b6100a06100b8366004610385565b61020e565b6000546040516001600160a01b0390911681526020015b60405180910390f35b600154600254604080519283526020830191909152016100d4565b61010160015481565b6040519081526020016100d4565b61010160025481565b6100a0610126366004610357565b61026d565b6000546001600160a01b0316331461015e5760405162461bcd60e51b81526004016101559061039d565b60405180910390fd5b60028190556040518181527f0f45948e42a1e34f851df8452200e744563dae2029a99b8178ff6530458bd3df906020015b60405180910390a150565b6000546001600160a01b031633146101c45760405162461bcd60e51b81526004016101559061039d565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146102385760405162461bcd60e51b81526004016101559061039d565b60018190556040518181527fae46785019700e30375a5d7b4f91e32f8060ef085111f896ebf889450aa2ab5a9060200161018f565b6000546001600160a01b031633146102975760405162461bcd60e51b81526004016101559061039d565b6001600160a01b0381166102fc5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610155565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600060208284031215610368578081fd5b81356001600160a01b038116811461037e578182fd5b9392505050565b600060208284031215610396578081fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea264697066735822122069737c178b79be7973d71a433150ff2571d211a983a7f5a5ba0f7dba3d57fd7664736f6c63430008040033

View File

@ -1,133 +0,0 @@
const ERC20PresetMinterPauser = artifacts.require('ERC20PresetMinterPauser')
const FS = require('fs')
const Path = require('path')
const NETWORK_ID = 4020
function prefixedAddressParamToByteCode(address) {
// the first 2 chars removal removes 0x prefix
return address.substring(2).toLowerCase().padStart(64, '0')
}
function intToByteCode(intParam) {
return Number(intParam).toString(16).padStart(64, '0')
}
function getSimpleSwapFactoryBin(tokenAddress) {
const binPath = Path.join(__dirname, '..', 'contracts', 'SimpleSwapFactory.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
tokenAddress = prefixedAddressParamToByteCode(tokenAddress)
//add tokenaddress for param to the end of the bytecode
return bin + tokenAddress
}
function getPostageStampBin(tokenAddress) {
const binPath = Path.join(__dirname, '..', 'contracts', 'PostageStamp.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
tokenAddress = prefixedAddressParamToByteCode(tokenAddress)
//add tokenaddress for param to the end of the bytecode
return bin + tokenAddress
}
function getPostagePriceOracleBin(tokenAddress) {
const binPath = Path.join(__dirname, '..', 'contracts', 'PostagePriceOracle.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
tokenAddress = prefixedAddressParamToByteCode(tokenAddress)
//add tokenaddress for param to the end of the bytecode
return bin + tokenAddress
}
function getSwapPriceOracleBin(price, chequeValueDeduction) {
const binPath = Path.join(__dirname, '..', 'contracts', 'SwapPriceOracle.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
const priceAbi = intToByteCode(price)
const chequeValueAbi = intToByteCode(chequeValueDeduction)
//add tokenaddress for param to the end of the bytecode
return bin + priceAbi + chequeValueAbi
}
function getStakeRegistryBin(tokenAddress) {
const binPath = Path.join(__dirname, '..', 'contracts', 'StakeRegistry.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
tokenAddress = prefixedAddressParamToByteCode(tokenAddress)
const networkIdAbi = intToByteCode(NETWORK_ID)
//add tokenaddress and encoded network ID for param to the end of the bytecode
return bin + tokenAddress + networkIdAbi
}
function getRedistributionBin(stakingAddress, postageContractAddress, oracleContractAddress) {
const binPath = Path.join(__dirname, '..', 'contracts', 'Redistribution.bytecode')
const bin = FS.readFileSync(binPath, 'utf8').toString().trim()
stakingAddress = prefixedAddressParamToByteCode(stakingAddress)
postageContractAddress = prefixedAddressParamToByteCode(postageContractAddress)
oracleContractAddress = prefixedAddressParamToByteCode(oracleContractAddress)
//add staking address, postage address and oracle contract address for param to the end of the bytecode
return bin + stakingAddress + postageContractAddress + oracleContractAddress
}
/** Returns back contract hash */
async function createContract(contractName, data, creatorAccount, configName) {
const transaction = await web3.eth.sendTransaction({
data: data,
gasLimit: 6721975,
gasPrice: web3.utils.toWei('10', 'gwei'),
from: creatorAccount,
})
if (!transaction.status) {
console.error(`${contractName} contract creation Error`, error)
throw new Error(`Error happened at creating ${contractName} contract creation`)
}
console.log(
`${contractName} contract creation was successful!\n` +
`\tTransaction ID: ${transaction.transactionHash}\n` +
`\tContract ID: ${transaction.contractAddress}`,
)
if (configName) {
console.log(`::CONTRACT:${configName}:${transaction.contractAddress}\n`)
}
return transaction.contractAddress
}
module.exports = function (deployer, network, accounts) {
const creatorAccount = accounts[0]
deployer.deploy(ERC20PresetMinterPauser, 'Swarm Token', 'BZZ').then(async () => {
await createContract('SwapPriceOracle', getSwapPriceOracleBin(100000, 100), creatorAccount, 'price-oracle-address')
await createContract(
'SimpleSwapFactory',
getSimpleSwapFactoryBin(ERC20PresetMinterPauser.address),
creatorAccount,
'swap-factory-address',
)
const postageStampAddress = await createContract(
'PostageStamp',
getPostageStampBin(ERC20PresetMinterPauser.address),
creatorAccount,
'postage-stamp-address',
)
const postagePriceOracleAddress = await createContract(
'PostagePriceOracle',
getPostagePriceOracleBin(ERC20PresetMinterPauser.address),
creatorAccount,
)
const stakeRegistryAddress = await createContract(
'StakeRegistry',
getStakeRegistryBin(ERC20PresetMinterPauser.address),
creatorAccount,
'staking-address',
)
await createContract(
'Redistribution',
getRedistributionBin(stakeRegistryAddress, postageStampAddress, postagePriceOracleAddress),
creatorAccount,
'redistribution-address',
)
})
}

16675
generator/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
{
"name": "bee-factory",
"version": "0.0.1",
"description": "Setup Swarm Test Blockchain and arbitrary numbered Bee nodes",
"scripts": {
"compile:contracts": "truffle compile",
"migrate:contracts": "truffle migrate",
"supply": "truffle exec src/supply.js",
"build:env": "./scripts/build-environment.sh",
"publish:env": "./scripts/publish-environment.sh",
"run:env": "./scripts/environment.sh",
"setApiVersions": "node ./src/setApiVersions.js",
"gen:traffic": "node ./scripts/gen-traffic.js"
},
"dependencies": {
"@ethersphere/bee-js": "^5.1.0",
"@ethersphere/swarm-cli": "^1.12.0",
"@openzeppelin/contracts": "^3.1.0",
"truffle": "^5.6.3"
},
"keywords": [
"swarm",
"ethereum-swarm",
"bee-factory"
],
"license": "BSD-3-Clause"
}

View File

@ -1,6 +0,0 @@
BEE_VERSION="1.10.0-rc17"
BLOCKCHAIN_VERSION="1.3.1"
BEE_ENV_PREFIX="bee-factory"
BEE_IMAGE_PREFIX="ethersphere"
COMMIT_VERSION_TAG="false"
STATE_COMMIT="true"

View File

@ -1,38 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
echo "Removing 'localstore' and 'statestore' folders from Bee datadirs..."
echo "You may need to pass your password for sudo permission to remove the bee-data folders"
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
BEE_DIRS=$(ls -d $MY_PATH/bee-data-dirs/*/)
for BEE_DIR in $BEE_DIRS
do
echo "$BEE_DIR"
rm -rf "$BEE_DIR/localstore"
rm -rf "$BEE_DIR/statestore"
done
echo "Removing stopped Bee Docker containers..."
docker container prune -f
echo "Removing built Bee Docker images..."
BEE_VERSION=$("$MY_PATH/utils/build-image-tag.sh" get)
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
DOCKER_IMAGES=$(docker image ls -qaf reference="$BEE_IMAGE_PREFIX/$BEE_ENV_PREFIX*:$BEE_VERSION")
for DOCKER_IMAGE in $DOCKER_IMAGES
do
echo "$DOCKER_IMAGE"
docker image rm "$DOCKER_IMAGE"
done
echo "Removing built Blockchain Docker image..."
BLOCKCHAIN_DOCKER_IMAGE=$(docker image ls -qaf reference="$BEE_IMAGE_PREFIX/$BEE_ENV_PREFIX-blockchain:$BLOCKCHAIN_VERSION")
if [ -n "$BLOCKCHAIN_DOCKER_IMAGE" ] ; then
docker image rm "$BLOCKCHAIN_DOCKER_IMAGE"
fi

View File

@ -1 +0,0 @@
Dockerfile

View File

@ -1,2 +0,0 @@
statestore
localstore

View File

@ -1 +0,0 @@
{"address":"33d0fff43ab18b6066d5a7c1a74852f0e5f1d549","crypto":{"cipher":"aes-128-ctr","ciphertext":"d0c9f5ba4d26f4c3a5ff75054a452ae06c4e7137456964286fb71ee4c39001c9","cipherparams":{"iv":"d53f8d37effe8eaf9215b614194c6336"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"676530f1559492f872a030a68044434c62b4e4ccc45834cfdd93ac7ae5bf3eaf"},"mac":"b4f0c223f23a028d0070a0657ac2f394c17d7501b23d17ffc9da0e0eb4a468f7"},"version":3}

View File

@ -1 +0,0 @@
{"address":"4f86d2a325b5484114c746f4f62567c3307c4609","crypto":{"cipher":"aes-128-ctr","ciphertext":"a965f1be20058860f1c463de2f7fd14b168f0eacf015dcfa009c5e8fff6f943f","cipherparams":{"iv":"51379174047cfdf82a4267e4f33de608"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"18779e1a157feb172aee97c53f8c2302b74127289b10466372cd3971a66ab28e"},"mac":"6d052ca5750d5f35b7d3798484c414bcc8ad8f8b3ed5309e78a80974a55d1a9e"},"version":3}

View File

@ -1 +0,0 @@
{"address":"26234a2ad3ba8b398a762f279b792cfacd536a3f","crypto":{"cipher":"aes-128-ctr","ciphertext":"fffb7140c654126abb77a8c2f876d6be0e15213a823b1bb69b061bc015b4dbb1","cipherparams":{"iv":"ee1fd715ab558a569ca47707c5cc0dda"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"4d959d634ced780cd51217d654b2b4c776118a4bdfa91c6899ab08348ce2d6b0"},"mac":"b3ebd4561b62ced24a4b059fcbc4106690fb25bb3774bff323dcdfdf61661c6c"},"version":3}

View File

@ -1,2 +0,0 @@
statestore
localstore

View File

@ -1 +0,0 @@
{"address":"a073d821229ab0ec33a4ca823a48328171f30dfc","crypto":{"cipher":"aes-128-ctr","ciphertext":"e73ed3fabee776bd9151f7f7594479f969b58941a2bbdeb7534c4897211b0e51","cipherparams":{"iv":"2d376deaad1c949dc7eb49af4521a6e1"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"bbd2a1f20411edd89c7ca4eabad6fc4deb23edadfdbba94067ec6b30f68bd313"},"mac":"20c5d9d0ec69877d8087f91056cce750a624eae094d05a18428b36ce36549603"},"version":3}

View File

@ -1 +0,0 @@
{"address":"172c9699e88d18b9c4bb91bd76cfba83c021d341","crypto":{"cipher":"aes-128-ctr","ciphertext":"81de20a914b615f102e660283402f8481fb37db55916351fa7ec4d73be167f20","cipherparams":{"iv":"054a833aced209f8435cb7ed6153832d"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"2395d56b6397fbe4c76bd74f5b312b4b1e7e4cddc5b86986eee411cb98b1789c"},"mac":"0342ec20f4d1ac86734527fc28015cd84a1bcfbf621c0e4fcefecf8f98ccc206"},"version":3}

View File

@ -1 +0,0 @@
{"address":"8e3cb0148c5f39577fb815dc8c37795e30f5dcfa","crypto":{"cipher":"aes-128-ctr","ciphertext":"c3c64c5b4371a59d87a4883b499a5622774511d4421298c0e8849acb64d1111e","cipherparams":{"iv":"e31330130d3045f1b2614e819a4c06f6"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"25be64863839d78f078ff7c874412c682dc2fc290138ce749ac3bdc7ed267b5a"},"mac":"c8ecf497e8afec977de05b2c514194aa329eca701ca559520a0d4545591e3d2f"},"version":3}

View File

@ -1,2 +0,0 @@
statestore
localstore

View File

@ -1 +0,0 @@
{"address":"d31ef99de0a34356f3bd356617f332fddc948232","crypto":{"cipher":"aes-128-ctr","ciphertext":"022c6805e9b8e7e499046d26cba90e90fd37c46cf9ee21c1aff15f50a2a8d3c6","cipherparams":{"iv":"d4d96fb0ee5a1df7534fdf702c7733ca"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"a0f1e03f9f73c5e7607c4b8c68242e0a7c705e40e9193952a209d4ed9b204a7f"},"mac":"ecea407aa1c76be3fb0254aecf92cba256dfd8f9f1eca904415f7c8877be8452"},"version":3}

View File

@ -1 +0,0 @@
{"address":"7618b0084b6b274d5140049df8b3ae423626fcac","crypto":{"cipher":"aes-128-ctr","ciphertext":"19a117a9c17ef72f2b2fb3642f6a07bafda0487d58428fab05dc175976dbd0b3","cipherparams":{"iv":"10d2d1bcf0281b0cac32b2e2a84ea701"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"e504f0e661803766a6e0841345987ec112edbda80569d9f912a3618d8c9fc904"},"mac":"682392951017ce45ea64a2e225dcd5cae129b78d6f34602123f3746bd0db5168"},"version":3}

View File

@ -1 +0,0 @@
{"address":"ed52b8ac9b1bc1e7f3fe46ea3a094fbaa8f6ccb4","crypto":{"cipher":"aes-128-ctr","ciphertext":"439cd5a2ebe1b37417708dff4f494eccef49ca8bf90caf28fb941fe964e3826d","cipherparams":{"iv":"0ea3e06704e1842ab7a9756a18ac4c27"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"54774845914adc48df887864a1935e97de333045021c27eb0561cacfd65eed78"},"mac":"40de101683baa8acd76a3577211a6827e330a81d7a7e28af9c5872e2ea855b6a"},"version":3}

View File

@ -1,2 +0,0 @@
statestore
localstore

View File

@ -1 +0,0 @@
{"address":"906ab9aede7032f8e1049d057355904f8b9e15bc","crypto":{"cipher":"aes-128-ctr","ciphertext":"32bf4178f95c3554ff1b99c0f8a00458e0b6e1b017cd18dbac8e08d620687c33","cipherparams":{"iv":"66e35d850dfc6ff0bbfb67e8ce7d11c7"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"dd0a67dd5feb9f4c538fcfdcdfa04b48d229a9d0222513a14ddd6b92083d07f1"},"mac":"7bc40b0ea294d77bdcff48dab0d83f02302ae1d73154be132f017cf84c30ac6f"},"version":3}

View File

@ -1 +0,0 @@
{"address":"b531efea3a09881d97e6526ff5ac2647fb8d8fb7","crypto":{"cipher":"aes-128-ctr","ciphertext":"a6e3791bf08c4c49531ebe24156201b2654c1b27c4fdf022c8281197736e3b4d","cipherparams":{"iv":"e6a73c1b91f81dff9031f64edce1b611"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"31acaa07698ca075e9da7fc039087d58991cf719d69d547e9b87a8ae9f8da193"},"mac":"9d04640df0f569275f99c70e20d1221b6dda50f387824409ff40c68efc98289c"},"version":3}

View File

@ -1 +0,0 @@
{"address":"119331b8074bd779fc5b96fe4d50947d31addfe4","crypto":{"cipher":"aes-128-ctr","ciphertext":"8ad055c629e5ec8731a879a72c994a4813c1fcc512ed2630c287dfd13e00aa1e","cipherparams":{"iv":"602457307b87eb967542f89d90ab6116"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"fcb50fe029550bce3c8d33db67bd8a48bd51d74b32b13e8e771bb158a9083bf3"},"mac":"e3e590561691f13c12d78c5eadb7adb106cb32e32af6f07f44a8d0188bda0043"},"version":3}

View File

@ -1,2 +0,0 @@
statestore
localstore

View File

@ -1 +0,0 @@
{"address":"554b4e35700ba8118b74b0c3d006b46b4322d37c","crypto":{"cipher":"aes-128-ctr","ciphertext":"b8b2431700b19fffaab5b5a3afae2f26610617c30db4d85a10eeebc6c2c1e2ed","cipherparams":{"iv":"2e5228d8b2cebf36989f3e8738034ce4"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"cde5530d1e339e03087f6bcc17e4380c685df529307caeb66e2437bc455d7f09"},"mac":"80ae4166ded63aa4c8f77227e6c200c11621ee6ee2a0f2370e17fefd61776160"},"version":3}

View File

@ -1 +0,0 @@
{"address":"e629ba730a0ac0d6efc6a90957af96ca12be257d","crypto":{"cipher":"aes-128-ctr","ciphertext":"5878029af23f16cb63d4a4d9d90a40fb53921aa8a7639c0e35f4ad835ae7299c","cipherparams":{"iv":"b3d8e4e9d0366ee572e8ead3b5c7d05b"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"78b7beef4f18d6cc4cfb751e7a34f4bdd837e25f0fa2ad0c0f0f437368eb0566"},"mac":"4ea8a7787dc1a055af8ecfaded2d2d3fd45cd45d626fbcb3f5dadbda3bd5588e"},"version":3}

View File

@ -1 +0,0 @@
{"address":"102aaa556337d86e270010588d9fbd5ecaeebff8","crypto":{"cipher":"aes-128-ctr","ciphertext":"0794b7bfb7f68df0abb0a729c1774fa5821fb1811cd04c48e8644d6743b20307","cipherparams":{"iv":"533434567172fb0c3cf6c1c5a94621cd"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"70fa8ec6fce2fc2adcb14ecef2945dd49592c27605baa45f7e051845b2f04813"},"mac":"4f5ef03dcf39e7b6e2c3d3ffaca260a576968f64a2026b1b8749f430b25217a0"},"version":3}

View File

@ -1,87 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
dockerfile() {
cat << DOCKERFILE > "$1"
FROM ethersphere/bee:$2
# Sample docker file
COPY --chown=bee:bee . /home/bee/.bee
DOCKERFILE
}
dockerbuild() {
BLOCKCHAIN_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BLOCKCHAIN_VERSION)
PLATFORM_FLAG=""
if [ -n "$BEE_PLATFORM" ]; then
PLATFORM_FLAG="--platform=$BEE_PLATFORM"
fi
if [ -n "$PUSH_IMAGES" ]; then
# Multiplatform build needs to push the images right away as docker buildx does not output images loaded into
# docker itself, or it can do that but only for one platform.
PLATFORM_FLAG+=" --push"
fi
IMAGE_NAME=$(basename "$1")
IMAGE_NAME="$4/$IMAGE_NAME"
docker build "$1" --no-cache -f "$2" -t "$IMAGE_NAME:$3" $PLATFORM_FLAG --label "org.ethswarm.beefactory.blockchain-version=$BLOCKCHAIN_VERSION" $5
}
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
BEE_DIRS=$(ls -d "$MY_PATH"/bee-data-dirs/*/)
BEE_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BEE_VERSION)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
STATE_COMMIT=$("$MY_PATH/utils/env-variable-value.sh" STATE_COMMIT)
OFFICIAL_BEE_IMAGE="ethersphere/bee:$BEE_VERSION"
CONTRACT_ADDRESSES="$1"
# Make sure we the user has permission all the files
echo "Build Bee Docker images..."
echo "Update common dockerfile"
dockerfile "$MY_PATH/bee-data-dirs/Dockerfile" "$BEE_VERSION"
### BEE_VERSION ALTERNATIONS START
# If the user has been set the COMMIT_VERSION_TAG env variable
# The image will be built with the tag that is the bee version string
COMMIT_VERSION_TAG="$("$MY_PATH/utils/env-variable-value.sh" COMMIT_VERSION_TAG)"
if [ "$COMMIT_VERSION_TAG" == "true" ] ; then
echo "Image version tag will be extracted from the bee version command from image $OFFICIAL_BEE_IMAGE"
docker pull $OFFICIAL_BEE_IMAGE
# somehow the version command's output goes to the stderr
BEE_VERSION=$(docker run --rm $OFFICIAL_BEE_IMAGE version 2>&1)
echo "Extracted Bee version: $BEE_VERSION"
"$MY_PATH/utils/build-image-tag.sh" set "$BEE_VERSION"
fi
if [ "$STATE_COMMIT" == 'false' ] ; then
echo "The bee image will be built without their state"
BEE_VERSION+="-stateless"
"$MY_PATH/utils/build-image-tag.sh" set "$BEE_VERSION"
echo "Stateless Bee version: $BEE_VERSION"
fi
### BEE_VERSION ALERNATIONS END
CONTRACT_ADDRESSES_LABELS=""
OLD_IFS=$IFS
IFS=';' array=($CONTRACT_ADDRESSES)
for element in "${array[@]}";
do
CONTRACT_ADDRESSES_LABELS+=" --label org.ethswarm.beefactory.contracts.${element}"
done
IFS=$OLD_IFS
echo "Build Dockerfiles"
for BEE_DIR in $BEE_DIRS
do
echo "Build Bee version $BEE_VERSION on $BEE_DIR"
dockerbuild "$BEE_DIR" "$MY_PATH/bee-data-dirs/Dockerfile" "$BEE_VERSION" "$BEE_IMAGE_PREFIX" "$CONTRACT_ADDRESSES_LABELS"
done
echo "Docker image builds were successful!"

View File

@ -1,337 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
echoerr() { if [[ $QUIET -ne 1 ]] ; then echo "$@" 1>&2; fi }
usage() {
cat << USAGE >&2
USAGE:
$ bee.sh [COMMAND] [PARAMETERS]
COMMANDS:
start create Bee cluster with the given parameters
stop stop Bee cluster
PARAMETERS:
--restrict=string turns on Restricted API support with given string as password
--ephemeral create ephemeral container for bee-client. Data won't be persisted.
--workers=number all Bee nodes in the test environment. Default is 4.
--port-maps=number map ports of the cluster nodes to the hosting machine in the following manner:
1. 1633:1635
2. 11633:11635
3. 21633:21635 (...)
number represents the nodes number to map from. Default is 2.
--password=string password for Bee client(s).
--own-image If passed, the used Docker image names will be identical as the name of the workers.
--version=x.y.z used version of Bee client.
--detach It will not log the output of Queen node at the end of the process.
USAGE
exit 1
}
stop_containers() {
echo "Stop Bee following containers:"
docker container stop "$QUEEN_CONTAINER_NAME";
WORKER_NAMES=$(docker container ls -f name="$WORKER_CONTAINER_NAME*" --format "{{.Names}}")
for WORKER_NAME in $WORKER_NAMES; do
docker container stop "$WORKER_NAME"
done
}
stop() {
stop_containers
trap - SIGINT
exit 0;
}
queen_failure() {
docker logs "$QUEEN_CONTAINER_NAME"
stop_containers
echo "Timeout limit has been reached, exit from the process.."
exit 1
}
check_queen_is_running() {
QUEEN_RUNNING=$(docker container inspect -f "{{.State.Running}}" $QUEEN_CONTAINER_NAME)
if [ "$QUEEN_RUNNING" == 'false' ] ; then
echo "Queen container has been stopped... stop environment start process..."
queen_failure
fi
}
get_token() {
echo "$(curl -X POST -s "http://$HOSTNAME:1633/auth" -u "_:$1" -d '{"role":"maintainer","expiry":400}' | python -c 'import json,sys; obj=json.load(sys.stdin); print(obj["key"]);')"
}
fetch_queen_underlay_addr() {
set +e
if [[ -n "$QUEEN_UNDERLAY_ADDRESS" ]] ; then return; fi
ELAPSED_TIME=0
WAITING_TIME=5
# Wait 2 mins for queen start
TIMEOUT=$((2*12*WAITING_TIME))
while (( TIMEOUT > ELAPSED_TIME )) ; do
check_queen_is_running
QUEEN_UNDERLAY_ADDRESS=$(curl -s "$HOSTNAME:1635/addresses" | python -mjson.tool | grep "/ip4/" | awk "!/127.0.0.1/" | sed 's/,$//' | xargs)
if [[ -z "$QUEEN_UNDERLAY_ADDRESS" ]] ; then
echo "Waiting for the Queen initialization..."
ELAPSED_TIME=$((ELAPSED_TIME+WAITING_TIME))
sleep $WAITING_TIME
else
echo "Queen underlay address: $QUEEN_UNDERLAY_ADDRESS"
break;
fi
done
set -e
if (( TIMEOUT == ELAPSED_TIME )) ; then
queen_failure
fi
}
log_queen() {
trap stop SIGINT
docker logs --tail 25 -f "$QUEEN_CONTAINER_NAME"
}
count_connected_peers() {
COUNT=$( (curl -s "http://$HOSTNAME:1635/peers" -H "Authorization: Bearer $1" | python -c 'import json,sys; obj=json.load(sys.stdin); print (len(obj["peers"]));') || echo 0 )
echo "$COUNT"
}
MY_PATH=$(dirname "$0") # relative
MY_PATH=$( cd "$MY_PATH" && pwd ) # absolutized and normalized
# Check used system variable set
BEE_VERSION=$("$MY_PATH/utils/build-image-tag.sh" get)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
# Init variables
EPHEMERAL=false
WORKERS=4
LOG=true
RESTRICTED=false
RESTRICTED_PASSWORD=""
RESTRICTED_PASSWORD_HASH=""
QUEEN_CONTAINER_NAME="$BEE_ENV_PREFIX-queen"
WORKER_CONTAINER_NAME="$BEE_ENV_PREFIX-worker"
SWARM_BLOCKCHAIN_NAME="$BEE_ENV_PREFIX-blockchain"
NETWORK="$BEE_ENV_PREFIX-network"
QUEEN_CONTAINER_IN_DOCKER=$(docker container ls -qaf name="$QUEEN_CONTAINER_NAME")
BEE_BASE_IMAGE="ethersphere/bee"
OWN_IMAGE=false
BEE_PASSWORD="password"
QUEEN_BOOTNODE=""
PORT_MAPS=2
SWAP=true
INIT_ROOT_DATA_DIR="$MY_PATH/bee-data-dirs"
HOSTNAME="127.0.0.1"
CONTRACT_ADDRESSES=""
# Decide script action
case "$1" in
start)
shift 1
;;
stop)
stop
;;
*)
echoerr "Unknown command: $1"
usage
;;
esac
# Alter variables from flags
while [ $# -gt 0 ]
do
case "$1" in
--ephemeral)
EPHEMERAL=true
shift 1
;;
--workers=*)
WORKERS=${1#*=}
shift 1
;;
--password=*)
BEE_PASSWORD="${1#*=}"
shift 1
;;
--restrict=*)
RESTRICTED="true"
RESTRICTED_PASSWORD="${1#*=}"
RESTRICTED_PASSWORD_HASH=$(htpasswd -bnBC 10 "" $RESTRICTED_PASSWORD | tr -d ':\n')
shift 1
;;
--version=*)
BEE_VERSION="${1#*=}"
shift 1
;;
--port-maps=*)
PORT_MAPS="${1#*=}"
shift 1
;;
--contract-addrs=*)
CONTRACT_ADDRESSES="${1#*=}"
shift 1
;;
--own-image)
OWN_IMAGE=true
shift 1
;;
--detach)
LOG=false
shift 1
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
BEE_IMAGE="$BEE_BASE_IMAGE:$BEE_VERSION"
if $EPHEMERAL ; then
EXTRA_DOCKER_PARAMS="--rm"
fi
CONTRACT_ADDRESSES_ARGS=""
OLD_IFS=$IFS
IFS=';' array=($CONTRACT_ADDRESSES)
for element in "${array[@]}";
do
CONTRACT_ADDRESSES_ARGS+=" --${element}"
done
IFS=$OLD_IFS
# Start Bee Queen
if [ -z "$QUEEN_CONTAINER_IN_DOCKER" ] || $EPHEMERAL ; then
DOCKER_IMAGE="$BEE_IMAGE"
if $OWN_IMAGE ; then
DOCKER_IMAGE="$BEE_IMAGE_PREFIX/$QUEEN_CONTAINER_NAME:$BEE_VERSION"
else
EXTRA_QUEEN_PARAMS="-v $INIT_ROOT_DATA_DIR/$QUEEN_CONTAINER_NAME:/home/bee/.bee"
fi
if [ "$PORT_MAPS" -ge 1 ] ; then
EXTRA_QUEEN_PARAMS="$EXTRA_QUEEN_PARAMS -p 1633-1635:1633-1635"
fi
echo "start Bee Queen process"
if [ $RESTRICTED == "true" ]; then
echo "Enabled Restricted API with password: $RESTRICTED_PASSWORD"
fi
docker run \
-d \
--network="$NETWORK" \
--name="$QUEEN_CONTAINER_NAME" \
$EXTRA_DOCKER_PARAMS \
$EXTRA_QUEEN_PARAMS \
$DOCKER_IMAGE \
start \
--admin-password="$RESTRICTED_PASSWORD_HASH" \
--restricted="$RESTRICTED" \
--warmup-time=0 \
--password "$BEE_PASSWORD" \
--bootnode="$QUEEN_BOOTNODE" \
--debug-api-enable \
--verbosity=4 \
--mainnet=false \
--block-time=1 \
--swap-enable=$SWAP \
--swap-endpoint="http://$SWARM_BLOCKCHAIN_NAME:9545" \
--network-id 4020 \
--full-node=true \
--welcome-message="You have found the queen of the beehive..." \
--cors-allowed-origins="*" \
--postage-stamp-start-block=1 \
$CONTRACT_ADDRESSES_ARGS
else
docker start "$QUEEN_CONTAINER_IN_DOCKER"
fi
# Start Bee workers
for i in $(seq 1 1 "$WORKERS"); do
WORKER_NAME="$WORKER_CONTAINER_NAME-$i"
WORKER_CONTAINER_IN_DOCKER=$(docker container ls -qaf name="$WORKER_NAME")
if [ -z "$WORKER_CONTAINER_IN_DOCKER" ] || $EPHEMERAL ; then
# fetch queen underlay address
fetch_queen_underlay_addr
# construct additional params
EXTRA_WORKER_PARAMS=""
DOCKER_IMAGE="$BEE_IMAGE"
if $OWN_IMAGE ; then
DOCKER_IMAGE="$BEE_IMAGE_PREFIX/$WORKER_NAME:$BEE_VERSION"
else
EXTRA_WORKER_PARAMS="$EXTRA_WORKER_PARAMS -v $INIT_ROOT_DATA_DIR/$WORKER_NAME:/home/bee/.bee"
fi
if [ $PORT_MAPS -gt $i ] ; then
PORT_START=$((1633+(10000*i)))
PORT_END=$((PORT_START + 2))
EXTRA_WORKER_PARAMS="$EXTRA_WORKER_PARAMS -p $PORT_START-$PORT_END:1633-1635"
fi
# run docker container
echo "start Bee worker $i process"
docker run \
-d \
--network="$NETWORK" \
--name="$WORKER_NAME" \
$EXTRA_DOCKER_PARAMS \
$EXTRA_WORKER_PARAMS \
$DOCKER_IMAGE \
start \
--warmup-time=0 \
--password "$BEE_PASSWORD" \
--bootnode="$QUEEN_UNDERLAY_ADDRESS" \
--debug-api-enable \
--verbosity=4 \
--mainnet=false \
--block-time=1 \
--swap-enable=$SWAP \
--swap-endpoint="http://$SWARM_BLOCKCHAIN_NAME:9545" \
--network-id 4020 \
--full-node=true \
--welcome-message="I'm just Bee worker ${i} in the beehive." \
--cors-allowed-origins="*" \
--postage-stamp-start-block=1 \
$CONTRACT_ADDRESSES_ARGS
else
docker start "$WORKER_CONTAINER_IN_DOCKER"
fi
done
echo "Check whether the queen node has been connected to every worker..."
ELAPSED_TIME=0
WAITING_TIME=2
TIMEOUT=$((6*30*WAITING_TIME))
RESTRICTED_TOKEN=""
while (( TIMEOUT > ELAPSED_TIME )) ; do
check_queen_is_running
if [ $RESTRICTED == "true" ] && [ -z "$RESTRICTED_TOKEN" ]; then
RESTRICTED_TOKEN=$(get_token "$RESTRICTED_PASSWORD")
echo "Fetched Bearer token: $RESTRICTED_TOKEN"
fi;
COUNT=$(count_connected_peers "$RESTRICTED_TOKEN")
[[ $COUNT < $WORKERS ]] || break
echo "Only $COUNT peers have been connected to the Queen Bee node yet. Waiting until $WORKERS"
ELAPSED_TIME=$((ELAPSED_TIME+WAITING_TIME))
sleep $WAITING_TIME
done
if (( ELAPSED_TIME >= TIMEOUT )) ; then
queen_failure
fi
# log Bee Queen
if $LOG ; then
log_queen
fi

View File

@ -1,25 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
# Check used system variable set
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
BLOCKCHAIN_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BLOCKCHAIN_VERSION)
echo "Blockchain will have image version: $BLOCKCHAIN_VERSION"
NAME="$BEE_ENV_PREFIX-blockchain"
echo "Make a snapshot from the blockchain..."
docker commit $NAME $BEE_IMAGE_PREFIX/$NAME:$BLOCKCHAIN_VERSION
if [ -n "$PUSH_IMAGES" ]; then
docker push $BEE_IMAGE_PREFIX/$NAME:$BLOCKCHAIN_VERSION
fi
echo "Stop and remove running blockchain node that the image built on..."
docker container stop $NAME
docker container rm $NAME

View File

@ -1,27 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
# Check used system variable set
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
NETWORK="$BEE_ENV_PREFIX-network"
NAME="$BEE_ENV_PREFIX-blockchain"
CONTAINER_IN_DOCKER=$(docker container ls -qaf name=$NAME)
if [ -z "$CONTAINER_IN_DOCKER" ]; then
# necessary "-b 1" because anyway the Bee throws Error: waiting backend sync: Post "http://swarm-test-blockchain:9545": EOF
docker run \
-p 9545:9545 \
--network $NETWORK \
--name $NAME -d \
trufflesuite/ganache \
--wallet.deterministic --chain.networkId 4020 -h 0.0.0.0 -p 9545 \
--miner.blockTime 2 \
--chain.chainId 4020 \
--database.dbPath swarm-testchain --miner.blockGasLimit 16721975
else
docker start $NAME
fi

View File

@ -1,156 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
usage() {
cat << USAGE >&2
USAGE:
$ build-environment.sh [PARAMETERS]
PARAMETERS:
--build-base-bee The base bee image will be built from source code
--base-bee-commit-hash=string the source code commit hash of the base bee; Default: HEAD; Dependency: --build-base-bee
--gen-traffic Generate traffic before bee image commit.
--gen-traffic-upload-node=string The traffic will be generated on the node under the given API URL. Default: http://locahost:1635; Dependency: --gen-traffic
--gen-traffic-upload-node-debug=string The traffic will be generated on the node under the given API URL. Default: http://locahost:1635; Dependency: --gen-traffic
--gen-traffic-checker-node-debug=string The incoming cheques will be checked on the node under the given Debug API URL. Default: http://localhost:11635; Dependency: --gen-traffic
--cheques-count=number This amount of cheques is intended to be generated by the traffic gen. Default: 1; Dependency: --gen-traffic
USAGE
exit 1
}
echoerr() {
>&2 echo "$@"
}
build_bee() {
# Clone source code
BEE_SOURCE_PATH=$MY_PATH/../bee
if [ -d "$BEE_SOURCE_PATH" ] ; then
rm -rf "$BEE_SOURCE_PATH"
fi
mkdir "$BEE_SOURCE_PATH" && cd "$BEE_SOURCE_PATH" || exit 1
git init
git remote add origin https://github.com/ethersphere/bee.git
git fetch origin --depth=1 "$COMMIT_HASH"
git reset --hard FETCH_HEAD
# Build bee and make docker image
export BEE_VERSION=${COMMIT_HASH::7}-commit
make binary
echo "Bee image will be built with version: $BEE_VERSION"
docker build . -t ethersphere/bee:$BEE_VERSION
cd "$MY_PATH" || exit 1
# Set build image tag so that other terminal session can retrieve
"$MY_PATH/utils/build-image-tag.sh" set "$BEE_VERSION"
}
deploy_contracts_and_return_addresses() {
CONTRACT_ADDRESSES=""
while IFS=$'\n' read -r contract; do
CONTRACT_ADDRESSES+="$(echo $contract | cut -d ":" -f 4)=$(echo $contract | cut -d ":" -f 5);"
done < <(npm run migrate:contracts | grep ^::CONTRACT)
echo "$CONTRACT_ADDRESSES"
}
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
COMMIT_HASH=HEAD
BUILD_BASE_BEE=false
GEN_TRAFFIC=false
GEN_TRAFFIC_CHECKER_NODE_DEBUG="http://localhost:1635"
GEN_TRAFFIC_UPLOAD_NODE="http://localhost:11633"
GEN_TRAFFIC_UPLOAD_NODE_DEBUG="http://localhost:11635"
CHEQUES_COUNT=1
# Bee version here means the base bee version on which the images will be built
BEE_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BEE_VERSION)
BLOCKCHAIN_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BLOCKCHAIN_VERSION)
SUPPORTED_WORKER_N=4
# handle passed options
while [ $# -gt 0 ]
do
case "$1" in
--build-base-bee)
BUILD_BASE_BEE=true
shift 1
;;
--base-bee-commit-hash=*)
COMMIT_HASH="${1#*=}"
shift 1
;;
--gen-traffic)
GEN_TRAFFIC=true
shift 1
;;
--cheques-count=*)
CHEQUES_COUNT=${1#*=}
shift 1
;;
--gen-traffic-upload-node=*)
GEN_TRAFFIC_UPLOAD_NODE="${1#*=}"
shift 1
;;
--gen-traffic-upload-node-debug=*)
GEN_TRAFFIC_UPLOAD_NODE_DEBUG="${1#*=}"
shift 1
;;
--gen-traffic-checker-node-debug=*)
GEN_TRAFFIC_CHECKER_NODE_DEBUG="${1#*=}"
shift 1
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
# cleanup for start from an empty state
"$MY_PATH/bee-cleanup.sh"
if $BUILD_BASE_BEE ; then
build_bee
fi
"$MY_PATH/network.sh"
"$MY_PATH/blockchain.sh"
CONTRACT_ADDRESSES=$(deploy_contracts_and_return_addresses)
npm run supply
chmod -R 777 "$MY_PATH/bee-data-dirs/"
if $GEN_TRAFFIC ; then
export STATE_COMMIT='true'
echo "Bee image with special state will be commited... traffic generation is on."
# give the permission to the bee user
echo "Start Bee nodes so that traffic can be generated and commited to the images"
"$MY_PATH/bee.sh" start --version="$BEE_VERSION" --workers=$SUPPORTED_WORKER_N --contract-addrs=$CONTRACT_ADDRESSES --detach
echo "Generating traffic on Bee node $GEN_TRAFFIC_UPLOAD_NODE"
echo "Run traffic generation until $CHEQUES_COUNT incoming cheques will arrive to node under Debug API $GEN_TRAFFIC_CHECKER_NODE_DEBUG"
npm run gen:traffic -- "$CHEQUES_COUNT" "$GEN_TRAFFIC_CHECKER_NODE_DEBUG;$GEN_TRAFFIC_UPLOAD_NODE;$GEN_TRAFFIC_UPLOAD_NODE_DEBUG"
echo "traffic has been generated"
echo "Adding postage stamp to Queen"
npx swarm-cli stamp buy --yes --quiet --depth 22 --amount 1_000_000 --label "==testingStamp=="
echo "Stamp bought"
# This sets output parameter in Github Actions that
# is then used to trigger Bee-js PR creation
if [ "$CI" == 'true' ]; then
echo "Image version tag will be extracted from the bee version command..."
docker pull "ethersphere/bee:$BEE_VERSION"
FULL_BEE_VERSION=$(docker run --rm "ethersphere/bee:$BEE_VERSION" version 2>&1)
echo "Extracted Bee version: $FULL_BEE_VERSION"
echo "::set-output name=full-version::$FULL_BEE_VERSION"
npm run setApiVersions "$GEN_TRAFFIC_CHECKER_NODE_DEBUG"
fi
"$MY_PATH/bee.sh" stop
docker container prune -f
export BLOCKCHAIN_VERSION+="-for-$BEE_VERSION"
fi
"$MY_PATH/bee-docker-build.sh" "$CONTRACT_ADDRESSES"
"$MY_PATH/blockchain-docker-build.sh"

View File

@ -1,157 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
usage() {
cat << USAGE >&2
USAGE:
$ environment.sh [COMMAND] [PARAMETERS]
COMMANDS:
start create Bee cluster with the given parameters
stop stop Bee cluster
PARAMETERS:
--ephemeral create ephemeral container for bee-client. Data won't be persisted.
--restrict(=string) turns on Restricted API support. If string is given then it uses it as the main password otherwise 'SwarmToTheMoon' is used
--workers=number all Bee nodes in the test environment. Default is 4.
--detach It will not log the output of Queen node at the end of the process.
--port-maps=number map ports of the cluster nodes to the hosting machine in the following manner:
1. 1633:1635
2. 11633:11635
3. 21633:21635 (...)
number represents the nodes number to map from. Default is 2.
--hostname=string Interface to which should the nodes be bound (default 127.0.0.0).
USAGE
exit 1
}
stop() {
#Stop Bee nodes
docker stop "$SWARM_BLOCKCHAIN_NAME"
#Stop blockchain nodes
"$MY_PATH/bee.sh" stop
trap - SIGINT
exit 0;
}
MY_PATH=$(dirname "$0") # relative
MY_PATH=$( cd "$MY_PATH" && pwd ) # absolutized and normalized
# Check used system variable set
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
BLOCKCHAIN_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BLOCKCHAIN_VERSION)
# Init variables
EPHEMERAL=false
RESTRICTED=false
RESTRICTED_PASSWORD="SwarmToTheMoon"
WORKERS=4
LOG=true
SWARM_BLOCKCHAIN_NAME="$BEE_ENV_PREFIX-blockchain"
SWARM_NETWORK="$BEE_ENV_PREFIX-network"
PORT_MAPS=2
HOSTNAME="127.0.0.1"
# Decide script action
case "$1" in
start)
shift 1
;;
stop)
stop
;;
*)
echoerr "Unknown command: $1"
usage
;;
esac
# Alter variables from flags
while [ $# -gt 0 ]
do
case "$1" in
--ephemeral)
EPHEMERAL=true
shift 1
;;
--workers=*)
WORKERS=${1#*=}
shift 1
;;
--port-maps=*)
PORT_MAPS="${1#*=}"
shift 1
;;
--detach)
LOG=false
shift 1
;;
--hostname=*)
HOSTNAME="${1#*=}"
shift 1
;;
--restrict*)
RESTRICTED=true
if [ "${1#*=}" != "--restrict" ] ; then
RESTRICTED_PASSWORD="${1#*=}"
fi
shift 1
;;
--help)
usage
;;
*)
echoerr "Unknown argument: $1"
usage
;;
esac
done
echo "Create Docker network..."
"$MY_PATH/network.sh"
# Start blockchain node
echo "Start Blockchain node..."
BLOCKCHAIN_CONTAINER=$(docker container ls -qaf name=$SWARM_BLOCKCHAIN_NAME)
if [ -z "$BLOCKCHAIN_CONTAINER" ] ; then
BLOCKCHAIN_ARGUMENTS="--name $SWARM_BLOCKCHAIN_NAME --network $SWARM_NETWORK -p $HOSTNAME:9545:9545 -d"
if $EPHEMERAL ; then
BLOCKCHAIN_ARGUMENTS="$BLOCKCHAIN_ARGUMENTS --rm"
fi
docker run $BLOCKCHAIN_ARGUMENTS $BEE_IMAGE_PREFIX/$SWARM_BLOCKCHAIN_NAME:$BLOCKCHAIN_VERSION
else
docker start $BLOCKCHAIN_CONTAINER
fi
# Wait for blockchain service initializes
while : ; do
CHAINID=$(curl -s -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"eth_chainId","id":1}' http://localhost:9545 | grep "0xfb4")
[[ "$CHAINID" != '{"id":1,"jsonrpc":"2.0","result":"0xfb4"}' ]] || break
echo "waiting for blockchain service is up..."
sleep 3
done
# Build up bee.sh parameters
BEE_SH_ARGUMENTS="--workers=$WORKERS --own-image --port-maps=$PORT_MAPS --hostname=$HOSTNAME"
if $EPHEMERAL ; then
BEE_SH_ARGUMENTS="$BEE_SH_ARGUMENTS --ephemeral"
fi
if $RESTRICTED ; then
BEE_SH_ARGUMENTS="$BEE_SH_ARGUMENTS --restrict=$RESTRICTED_PASSWORD"
fi
if ! $LOG ; then
BEE_SH_ARGUMENTS="$BEE_SH_ARGUMENTS --detach"
fi
# Call bee.sh with the passed arguments
echo "Start Bee nodes..."
"$MY_PATH/bee.sh" start $BEE_SH_ARGUMENTS
# If the code run reach this point without detach flag,
# then the user interrupted the log process in the bee.sh
if $LOG ; then
docker stop $SWARM_BLOCKCHAIN_NAME
fi

View File

@ -1,151 +0,0 @@
const { Bee, BeeDebug } = require('@ethersphere/bee-js')
class BeePair {
/**
* @param {BeeDebug} chequeReceiverBeeDebug
* @param {Bee} uploaderBee
* @param {BeeDebug} uploaderBeeDebug
* @param {string} uploaderStamp
*/
constructor(chequeReceiverBeeDebug, uploaderBee, uploaderBeeDebug, uploaderStamp) {
this.chequeReceiverBeeDebug = chequeReceiverBeeDebug
this.uploaderBee = uploaderBee
this.uploaderBeeDebug = uploaderBeeDebug
this.uploaderStamp = uploaderStamp
}
}
const SLEEP_BETWEEN_UPLOADS_MS = 1000
const POSTAGE_STAMPS_AMOUNT = '10000'
const POSTAGE_STAMPS_DEPTH = 22
/**
* Lehmer random number generator with seed (minstd_rand in C++11)
* !!! Very fast but not well distributed pseudo-random function !!!
*
* @param seed Seed for the pseudo-random generator
*/
function lrng(seed) {
return () => ((2 ** 31 - 1) & (seed = Math.imul(48271, seed))) / 2 ** 31
}
/**
* Utility function for generating random Buffer
* !!! IT IS NOT CRYPTO SAFE !!!
* For that use `crypto.randomBytes()`
*
* @param length Number of bytes to generate
* @param seed Seed for the pseudo-random generator
*/
function randomByteArray(length, seed = 500) {
const rand = lrng(seed)
const buf = new Uint8Array(length)
for (let i = 0; i < length; ++i) {
buf[i] = (rand() * 0xff) << 0
}
return buf
}
/**
* @param {BeePair} beePair
*/
async function uploadRandomBytes(beePair, seed = 500, bytes = 1024 * 4 * 400) {
const randomBytes = randomByteArray(bytes, seed)
const reference = await beePair.uploaderBee.uploadData(beePair.uploaderStamp, randomBytes)
console.log(`${beePair.uploaderBee.url} uploaded ${bytes} bytes to ${reference}`)
}
/**
* Generate traffic on Bee node(s)
*
* @param {BeePair[]} beePairs
*/
async function genTrafficOnOpenPorts(beePairs) {
const promises = beePairs.map(beePair => {
return uploadRandomBytes(beePair, Date.now())
})
await Promise.all(promises)
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
/**
*
* Generates cheques on the given Bee API EP
*
* The hosts parameter has to be assimetric in the API;DEBUG_API paired string
* because on the API EP the data will be generated, so the cheques should be
*
* @param {string[]} hosts API;DEBUG_API URL strings of the target Bee (e.g. http://localhost:1635;http://localhost:11633;http://localhost:11635)
* @param {number} minCheques
*/
async function genTrafficLoop(hosts, minCheques) {
const promises = hosts.map(async host => {
const [chequeReceiverBeeDebugUrl, uploaderBeeUrl, uploaderBeeDebugUrl] = host.split(';')
const chequeReceiverBeeDebug = new BeeDebug(chequeReceiverBeeDebugUrl)
const uploaderBee = new Bee(uploaderBeeUrl)
const uploaderBeeDebug = new BeeDebug(uploaderBeeDebugUrl)
console.log(`Depositing 10 BZZ to Chequebook on ${uploaderBeeDebugUrl}...`)
await uploaderBeeDebug.depositTokens('1000000000000000000')
console.log(`Creating postage stamp on ${uploaderBeeDebugUrl}...`)
const postageBatchId = await uploaderBeeDebug.createPostageBatch(POSTAGE_STAMPS_AMOUNT, POSTAGE_STAMPS_DEPTH, {
waitForUsable: true,
})
console.log(`Generated ${postageBatchId} postage stamp on ${uploaderBeeDebugUrl}.`)
return new BeePair(chequeReceiverBeeDebug, uploaderBee, uploaderBeeDebug, postageBatchId)
})
const bees = await Promise.all(promises)
while (true) {
await genTrafficOnOpenPorts(bees)
if (!isNaN(minCheques)) {
const beesUncashedCheques = []
for (const beePair of bees) {
const { chequeReceiverBeeDebug } = beePair
const { lastcheques } = await chequeReceiverBeeDebug.getLastCheques()
const incomingCheques = lastcheques.filter(cheque => !!cheque.lastreceived)
const uncashedCheques = []
const lastCashOutPromises = incomingCheques.map(({ peer }) => chequeReceiverBeeDebug.getLastCashoutAction(peer))
const lastCashOuts = await Promise.all(lastCashOutPromises)
for (const [index, lastCashOut] of lastCashOuts.entries()) {
if (BigInt(lastCashOut.uncashedAmount) > 0) {
uncashedCheques.push(incomingCheques[index])
}
}
beesUncashedCheques.push(uncashedCheques)
}
if (beesUncashedCheques.every(uncashedCheques => uncashedCheques.length >= minCheques)) {
console.log(`Generated at least ${minCheques} for every node on the given Debug API endpoints`)
process.exit()
} else {
console.log(
`There is not enough uncashed cheques on Bee node(s)`,
beesUncashedCheques.map(beeCheques => beeCheques.length),
)
}
}
await sleep(SLEEP_BETWEEN_UPLOADS_MS)
}
}
let inputArray = process.argv.slice(2)
// if there is no related input to the minimum required cheques count,
// then the traffic generation will go infinitely
let minCheques = parseInt(inputArray[0])
let hosts = inputArray.slice(1)
if (hosts.length === 0) {
hosts = ['http://localhost:1635;http://localhost:11633;http://localhost:11635']
}
genTrafficLoop(hosts, minCheques)

View File

@ -1,15 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
# Check used system variable set
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
NETWORK="$BEE_ENV_PREFIX-network"
if ! eval "docker network inspect $NETWORK > /dev/null" ; then
echo "Creating $NETWORK..."
docker network create $NETWORK
fi

View File

@ -1,39 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
STATE_COMMIT=$("$MY_PATH/utils/env-variable-value.sh" STATE_COMMIT)
BUILD_IMAGE=$("$MY_PATH/utils/env-variable-value.sh" BUILD_IMAGE)
BLOCKCHAIN_VERSION=$("$MY_PATH/utils/env-variable-value.sh" BLOCKCHAIN_VERSION)
if [ $BUILD_IMAGE == 'true' ] ; then
# Necessary for fetch BEE_VERSION from .commit-version-tag
export COMMIT_VERSION_TAG='true'
fi
BEE_VERSION=$("$MY_PATH/utils/build-image-tag.sh" get)
if [ $STATE_COMMIT == 'true' ] ; then
BLOCKCHAIN_VERSION+="-for-$BEE_VERSION"
fi
BEE_ENV_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_ENV_PREFIX)
BEE_IMAGE_PREFIX=$("$MY_PATH/utils/env-variable-value.sh" BEE_IMAGE_PREFIX)
BLOCKCHAIN_NAME="$BEE_ENV_PREFIX-blockchain"
BLOCKCHAIN_IMAGE_NAME="$BEE_IMAGE_PREFIX/$BLOCKCHAIN_NAME:$BLOCKCHAIN_VERSION"
echo "Search Docker built images with the following parameters: $BEE_IMAGE_PREFIX/$BEE_ENV_PREFIX*:$BEE_VERSION"
DOCKER_IMAGES=$(docker image ls --format "{{.Repository}}:{{.Tag}}" -af reference="$BEE_IMAGE_PREFIX/$BEE_ENV_PREFIX*:$BEE_VERSION")
echo "Push Bee docker images: $DOCKER_IMAGES"
for DOCKER_IMAGE in $DOCKER_IMAGES
do
echo "$DOCKER_IMAGE"
docker push "$DOCKER_IMAGE"
done
echo "Push Blockchain docker image: $BLOCKCHAIN_IMAGE_NAME"
docker push "$BLOCKCHAIN_IMAGE_NAME"

View File

@ -1,2 +0,0 @@
# ignore tmp file for custom image tag
.commit-version-tag

View File

@ -1,28 +0,0 @@
#!/bin/bash
# Store/get the tag of the Docker image that will be built
store_custom_tag() {
echo "$1" > "$MY_PATH/$COMMIT_VERSION_TAG_FILENAME"
}
# Echos the image tag which is defined by the environment or has been extracted from the Bee version command
get_tag() {
COMMIT_VERSION_TAG=$("$MY_PATH/env-variable-value.sh" COMMIT_VERSION_TAG)
if [ "$COMMIT_VERSION_TAG" == 'true' ] ; then
# retrieve from the output of previous store action
cat "$MY_PATH/$COMMIT_VERSION_TAG_FILENAME"
else
BEE_VERSION=$("$MY_PATH/env-variable-value.sh" BEE_VERSION)
echo "$BEE_VERSION"
fi
}
MY_PATH=$(dirname "$0")
MY_PATH=$( cd "$MY_PATH" && pwd )
COMMIT_VERSION_TAG_FILENAME=".commit-version-tag"
if [ "$1" == "set" ] ; then
store_custom_tag "$2"
elif [ "$1" == "get" ] ; then
get_tag
fi

View File

@ -1,19 +0,0 @@
#!/bin/bash
echo_env_variable_value() {
REF=$(printenv $1)
# There were no global set
if [ -z "$REF" ] ; then
MY_PATH=$(dirname "$0")
ENV_PATH=$( cd "$MY_PATH/.." && pwd )
VALUE=$(grep "^$1=" "$ENV_PATH/.env" | cut -d= -f2)
VALUE=${VALUE//\"/}
VALUE=${VALUE//\'/}
echo "$VALUE"
else
echo "$REF"
fi
}
echo_env_variable_value $1

View File

@ -1,22 +0,0 @@
const { BeeDebug } = require('@ethersphere/bee-js')
// This is a small utility that connects to given node and retrieve its API versions
// It outputs them to STDOUT in Github Actions format
async function setApiVersions (node) {
console.log('Getting API versions from node ', node)
const debug = new BeeDebug(node)
const versions = await debug.getHealth()
console.log('API version: ', versions.apiVersion)
console.log('Debug API version: ', versions.debugApiVersion)
console.log('::set-output name=api-version::', versions.apiVersion)
console.log('::set-output name=debug-api-version::', versions.debugApiVersion)
}
setApiVersions(process.argv[2]).catch(err => {
console.error('There was an error: ', err)
process.exit(1)
})

View File

@ -1,84 +0,0 @@
const ERC20PresetMinterPauser = artifacts.require('ERC20PresetMinterPauser')
const beeAddresses = require('../bee-overlay-addresses.json')
function getRawTokenAmount(amount, decimals = 18) {
amount = web3.utils.toBN(amount)
const rawAmount = amount.mul(web3.utils.toBN(10).pow(web3.utils.toBN(decimals)))
return rawAmount
}
/** Supply given address with Ether */
async function supplyEther(recepientAddress, supplierAddress, etherAmount = '10') {
const transaction = await web3.eth.sendTransaction({
gasLimit: 6721975,
gasPrice: web3.utils.toWei('10', 'gwei'),
value: web3.utils.toWei(etherAmount),
from: supplierAddress,
to: recepientAddress,
})
if (!transaction.status) {
console.error('Supply Ether Error', transaction)
throw new Error(`Error happened at supplying address ${recepientAddress} from account ${supplierAddress}`)
}
console.log(
`Supplying address ${recepientAddress} with Ether from account ${supplierAddress} was successful! \n` +
`\tGiven Ether Amount: ${etherAmount}\n` +
`\tTransaction ID: ${transaction.transactionHash}`,
)
console.log('-'.repeat(process.stdout.columns))
}
/** Supply given address with the given Token amount */
async function mintToken(recepientAddress, supplierAddress, tokenAddress, tokenAmount = '1000000') {
const instance = await ERC20PresetMinterPauser.at(tokenAddress)
const rawTokenAmount = getRawTokenAmount(tokenAmount)
const transaction = await instance.mint(recepientAddress, rawTokenAmount, {
from: supplierAddress,
gasLimit: 6721975,
})
if (!transaction.receipt.status) {
console.error('Supply Token Error', transaction)
throw new Error(`Error happened at supplying address ${recepientAddress} from account ${supplierAddress}`)
}
console.log(
`Supplying address ${recepientAddress} with Token from account ${supplierAddress} was successful! \n` +
`\tGiven Token Amount: ${tokenAmount}\n` +
`\tTransaction ID: ${transaction.tx}`,
)
console.log('-'.repeat(process.stdout.columns))
}
/** Supply ERC20 tokens to all configured Bee client overlay addresses */
async function supplyTokenForBees(supplierAddress, erc20ContractAddress) {
const txPromises = []
console.log(`Supply ERC20 tokens (${erc20ContractAddress}) to the configured Bee addresses`)
console.log('='.repeat(process.stdout.columns))
for (const beeAddress of beeAddresses) {
txPromises.push(mintToken(beeAddress, supplierAddress, erc20ContractAddress))
}
return Promise.all(txPromises)
}
/** Supply ether to all configured Bee client overlay addresses */
async function supplyEtherForBees(supplierAddress) {
const txPromises = []
console.log('Supply Ether to the configured Bee addresses')
console.log('='.repeat(process.stdout.columns))
for (const beeAddress of beeAddresses) {
txPromises.push(supplyEther(beeAddress, supplierAddress))
}
return Promise.all(txPromises)
}
module.exports = async function (callback) {
const accounts = await web3.eth.getAccounts()
await supplyTokenForBees(accounts[0], ERC20PresetMinterPauser.address)
await supplyEtherForBees(accounts[0])
callback()
}

View File

@ -1,28 +0,0 @@
module.exports = {
networks: {
development: {
host: '127.0.0.1',
port: 9545,
network_id: '4020',
gasPrice: '10000000000', //10 gwei
},
},
compilers: {
solc: {
version: '0.6.12', // Fetch exact version from solc-bin (default: truffle's version)
docker: true,
settings: {
optimizer: {
enabled: true,
runs: 200, // Optimize for how many times you intend to run the code
},
evmVersion: 'istanbul',
},
},
},
db: {
enabled: true,
},
}

View File

@ -26,7 +26,7 @@ export default async (): Promise<Config.InitialOptions> => {
// The root directory that Jest should scan for tests and modules within // The root directory that Jest should scan for tests and modules within
rootDir: 'test', rootDir: 'test',
// Increase timeout since we are spinning Bee containers // Increase timeout since we are spinning Codex containers
testTimeout: 4 * 60 * 1000, testTimeout: 4 * 60 * 1000,
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped

539
package-lock.json generated
View File

@ -1,15 +1,15 @@
{ {
"name": "@ethersphere/bee-factory", "name": "@codex-storage/codex-factory",
"version": "0.5.2", "version": "0.1.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@ethersphere/bee-factory", "name": "@codex-storage/codex-factory",
"version": "0.5.2", "version": "0.1.0",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@ethersphere/bee-js": "^5.0.0", "@codex-storage/sdk-js": "^0.1.2",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"dockerode": "^3.3.4", "dockerode": "^3.3.4",
"furious-commander": "^1.7.1", "furious-commander": "^1.7.1",
@ -18,7 +18,7 @@
"semver": "^7.3.8" "semver": "^7.3.8"
}, },
"bin": { "bin": {
"bee-factory": "dist/src/index.js" "codex-factory": "dist/src/index.js"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.1.2", "@commitlint/cli": "^17.1.2",
@ -46,10 +46,10 @@
"typescript": "^4.8.4" "typescript": "^4.8.4"
}, },
"engines": { "engines": {
"bee": "1.9.0", "codex": "0.2.0",
"node": ">=12.0.0", "node": ">=12.0.0",
"npm": ">=6.0.0", "npm": ">=6.0.0",
"supportedBee": ">=1.9.0" "supportedCodex": ">=0.2.0"
} }
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
@ -652,6 +652,50 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true "dev": true
}, },
"node_modules/@codex-storage/sdk-js": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@codex-storage/sdk-js/-/sdk-js-0.1.2.tgz",
"integrity": "sha512-QOi2gONLA9G1LVtFJLl9WjjZbAAvf4j1VVEAm//BUjUJi0xay309fb1z0kuW771ybNA+KHnVaYQu+RJS1K518Q==",
"license": "MIT",
"dependencies": {
"valibot": "^1.0.0"
},
"engines": {
"node": ">=20.18.1"
},
"peerDependencies": {
"undici": "^7.7.0"
}
},
"node_modules/@codex-storage/sdk-js/node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"license": "Apache-2.0",
"optional": true,
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/@codex-storage/sdk-js/node_modules/valibot": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz",
"integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==",
"license": "MIT",
"peerDependencies": {
"typescript": ">=5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@commitlint/cli": { "node_modules/@commitlint/cli": {
"version": "17.1.2", "version": "17.1.2",
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz",
@ -1025,42 +1069,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/@ethersphere/bee-js": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-5.0.0.tgz",
"integrity": "sha512-Dr5Xon0UZvi37fvbyGj46kw3/0D8fydwfDtVtFHKi2p7mNEizG0uok2mXvwLZrMvUMOS8uXkFhbQjTFBjB+pWA==",
"dependencies": {
"@ethersphere/swarm-cid": "^0.1.0",
"@types/readable-stream": "^2.3.13",
"bufferutil": "^4.0.6",
"elliptic": "^6.5.4",
"fetch-blob": "2.1.2",
"isomorphic-ws": "^4.0.1",
"js-sha3": "^0.8.0",
"ky": "^0.25.1",
"ky-universal": "^0.8.2",
"semver": "^7.3.5",
"tar-js": "^0.3.0",
"utf-8-validate": "^5.0.9",
"web-streams-polyfill": "^4.0.0-beta.1",
"ws": "^8.7.0"
},
"engines": {
"bee": "1.7.0-bbf13011",
"beeApiVersion": "3.0.2",
"beeDebugApiVersion": "3.0.2",
"node": ">=14.0.0",
"npm": ">=6.0.0"
}
},
"node_modules/@ethersphere/bee-js/node_modules/web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
"engines": {
"node": ">= 14"
}
},
"node_modules/@ethersphere/jest-serial-runner": { "node_modules/@ethersphere/jest-serial-runner": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@ethersphere/jest-serial-runner/-/jest-serial-runner-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@ethersphere/jest-serial-runner/-/jest-serial-runner-1.0.0.tgz",
@ -1070,18 +1078,6 @@
"jest-runner": ">=27.x" "jest-runner": ">=27.x"
} }
}, },
"node_modules/@ethersphere/swarm-cid": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@ethersphere/swarm-cid/-/swarm-cid-0.1.0.tgz",
"integrity": "sha512-n+n+w5RJBPm7CiPf8TIgNFIRMo4bLh5bYpZxHObgCaxFW8WNZ4UGfqg+qjS/jEr+A3Mmp0lugKDvd8GnfFy7JQ==",
"dependencies": {
"multiformats": "^9.5.4"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
}
},
"node_modules/@fluffy-spoon/substitute": { "node_modules/@fluffy-spoon/substitute": {
"version": "1.208.0", "version": "1.208.0",
"resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz", "resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz",
@ -1754,7 +1750,8 @@
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.3", "version": "18.11.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
"integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==" "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==",
"dev": true
}, },
"node_modules/@types/normalize-package-data": { "node_modules/@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -1774,15 +1771,6 @@
"integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
"dev": true "dev": true
}, },
"node_modules/@types/readable-stream": {
"version": "2.3.14",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.14.tgz",
"integrity": "sha512-8jQ5Mp7bsDJEnW/69i6nAaQMoLwAVJVc7ZRAVTrdh/o6XueQsX38TEvKuYyoQj76/mg7WdlRfMrtl9pDLCJWsg==",
"dependencies": {
"@types/node": "*",
"safe-buffer": "*"
}
},
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "7.3.12", "version": "7.3.12",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz",
@ -2074,17 +2062,6 @@
"integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==", "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==",
"dev": true "dev": true
}, },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
@ -2369,11 +2346,6 @@
"readable-stream": "^3.4.0" "readable-stream": "^3.4.0"
} }
}, },
"node_modules/bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2396,11 +2368,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
},
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.21.4", "version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
@ -2479,18 +2446,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true "dev": true
}, },
"node_modules/bufferutil": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz",
"integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==",
"hasInstallScript": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/buildcheck": { "node_modules/buildcheck": {
"version": "0.0.3", "version": "0.0.3",
"resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz", "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz",
@ -3147,20 +3102,6 @@
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
"dev": true "dev": true
}, },
"node_modules/elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.1",
"inherits": "^2.0.4",
"minimalistic-assert": "^1.0.1",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/emittery": { "node_modules/emittery": {
"version": "0.13.1", "version": "0.13.1",
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
@ -3603,14 +3544,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/execa": { "node_modules/execa": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@ -4031,25 +3964,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
"dependencies": {
"inherits": "^2.0.3",
"minimalistic-assert": "^1.0.1"
}
},
"node_modules/hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
"dependencies": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"node_modules/hosted-git-info": { "node_modules/hosted-git-info": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@ -4357,14 +4271,6 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true "dev": true
}, },
"node_modules/isomorphic-ws": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
"peerDependencies": {
"ws": "*"
}
},
"node_modules/istanbul-lib-coverage": { "node_modules/istanbul-lib-coverage": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@ -4992,11 +4898,6 @@
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==",
"dev": true "dev": true
}, },
"node_modules/js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -5113,41 +5014,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/ky": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/ky/-/ky-0.25.1.tgz",
"integrity": "sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/ky?sponsor=1"
}
},
"node_modules/ky-universal": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.8.2.tgz",
"integrity": "sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ==",
"dependencies": {
"abort-controller": "^3.0.0",
"node-fetch": "3.0.0-beta.9"
},
"engines": {
"node": ">=10.17"
},
"funding": {
"url": "https://github.com/sindresorhus/ky-universal?sponsor=1"
},
"peerDependencies": {
"ky": ">=0.17.0",
"web-streams-polyfill": ">=2.0.0"
},
"peerDependenciesMeta": {
"web-streams-polyfill": {
"optional": true
}
}
},
"node_modules/leven": { "node_modules/leven": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@ -5394,16 +5260,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"node_modules/minimalistic-crypto-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -5449,11 +5305,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/multiformats": {
"version": "9.9.0",
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="
},
"node_modules/multimatch": { "node_modules/multimatch": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
@ -5522,16 +5373,6 @@
"url": "https://opencollective.com/node-fetch" "url": "https://opencollective.com/node-fetch"
} }
}, },
"node_modules/node-gyp-build": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/node-int64": { "node_modules/node-int64": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@ -6710,14 +6551,6 @@
"tar-stream": "^2.0.0" "tar-stream": "^2.0.0"
} }
}, },
"node_modules/tar-js": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/tar-js/-/tar-js-0.3.0.tgz",
"integrity": "sha512-9uqP2hJUZNKRkwPDe5nXxXdzo6w+BFBPq9x/tyi5/U/DneuSesO/HMb0y5TeWpfcv49YDJTs7SrrZeeu8ZHWDA==",
"engines": {
"node": "*"
}
},
"node_modules/tar-stream": { "node_modules/tar-stream": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
@ -6989,6 +6822,16 @@
"node": ">=4.2.0" "node": ">=4.2.0"
} }
}, },
"node_modules/undici": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.7.0.tgz",
"integrity": "sha512-tZ6+5NBq4KH35rr46XJ2JPFKxfcBlYNaqLF/wyWIO9RMHqqU/gx/CLB1Y2qMcgB8lWw/bKHa7qzspqCN7mUHvA==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/universalify": { "node_modules/universalify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@ -7033,18 +6876,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/utf-8-validate": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
"hasInstallScript": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -7097,16 +6928,6 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"node_modules/web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"optional": true,
"peer": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -7199,26 +7020,6 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
} }
}, },
"node_modules/ws": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@ -7747,6 +7548,29 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true "dev": true
}, },
"@codex-storage/sdk-js": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@codex-storage/sdk-js/-/sdk-js-0.1.2.tgz",
"integrity": "sha512-QOi2gONLA9G1LVtFJLl9WjjZbAAvf4j1VVEAm//BUjUJi0xay309fb1z0kuW771ybNA+KHnVaYQu+RJS1K518Q==",
"requires": {
"valibot": "^1.0.0"
},
"dependencies": {
"typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"optional": true,
"peer": true
},
"valibot": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-1.0.0.tgz",
"integrity": "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw==",
"requires": {}
}
}
},
"@commitlint/cli": { "@commitlint/cli": {
"version": "17.1.2", "version": "17.1.2",
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.1.2.tgz",
@ -8040,34 +7864,6 @@
} }
} }
}, },
"@ethersphere/bee-js": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-5.0.0.tgz",
"integrity": "sha512-Dr5Xon0UZvi37fvbyGj46kw3/0D8fydwfDtVtFHKi2p7mNEizG0uok2mXvwLZrMvUMOS8uXkFhbQjTFBjB+pWA==",
"requires": {
"@ethersphere/swarm-cid": "^0.1.0",
"@types/readable-stream": "^2.3.13",
"bufferutil": "^4.0.6",
"elliptic": "^6.5.4",
"fetch-blob": "2.1.2",
"isomorphic-ws": "^4.0.1",
"js-sha3": "^0.8.0",
"ky": "^0.25.1",
"ky-universal": "^0.8.2",
"semver": "^7.3.5",
"tar-js": "^0.3.0",
"utf-8-validate": "^5.0.9",
"web-streams-polyfill": "^4.0.0-beta.1",
"ws": "^8.7.0"
},
"dependencies": {
"web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="
}
}
},
"@ethersphere/jest-serial-runner": { "@ethersphere/jest-serial-runner": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/@ethersphere/jest-serial-runner/-/jest-serial-runner-1.0.0.tgz", "resolved": "https://registry.npmjs.org/@ethersphere/jest-serial-runner/-/jest-serial-runner-1.0.0.tgz",
@ -8075,14 +7871,6 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"@ethersphere/swarm-cid": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@ethersphere/swarm-cid/-/swarm-cid-0.1.0.tgz",
"integrity": "sha512-n+n+w5RJBPm7CiPf8TIgNFIRMo4bLh5bYpZxHObgCaxFW8WNZ4UGfqg+qjS/jEr+A3Mmp0lugKDvd8GnfFy7JQ==",
"requires": {
"multiformats": "^9.5.4"
}
},
"@fluffy-spoon/substitute": { "@fluffy-spoon/substitute": {
"version": "1.208.0", "version": "1.208.0",
"resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz", "resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz",
@ -8642,7 +8430,8 @@
"@types/node": { "@types/node": {
"version": "18.11.3", "version": "18.11.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz",
"integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==" "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==",
"dev": true
}, },
"@types/normalize-package-data": { "@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -8662,15 +8451,6 @@
"integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
"dev": true "dev": true
}, },
"@types/readable-stream": {
"version": "2.3.14",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.14.tgz",
"integrity": "sha512-8jQ5Mp7bsDJEnW/69i6nAaQMoLwAVJVc7ZRAVTrdh/o6XueQsX38TEvKuYyoQj76/mg7WdlRfMrtl9pDLCJWsg==",
"requires": {
"@types/node": "*",
"safe-buffer": "*"
}
},
"@types/semver": { "@types/semver": {
"version": "7.3.12", "version": "7.3.12",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz",
@ -8873,14 +8653,6 @@
"integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==", "integrity": "sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==",
"dev": true "dev": true
}, },
"abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"requires": {
"event-target-shim": "^5.0.0"
}
},
"acorn": { "acorn": {
"version": "8.8.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
@ -9091,11 +8863,6 @@
"readable-stream": "^3.4.0" "readable-stream": "^3.4.0"
} }
}, },
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -9115,11 +8882,6 @@
"fill-range": "^7.0.1" "fill-range": "^7.0.1"
} }
}, },
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
},
"browserslist": { "browserslist": {
"version": "4.21.4", "version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
@ -9165,14 +8927,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true "dev": true
}, },
"bufferutil": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz",
"integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"buildcheck": { "buildcheck": {
"version": "0.0.3", "version": "0.0.3",
"resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz", "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz",
@ -9664,20 +9418,6 @@
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
"dev": true "dev": true
}, },
"elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"requires": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.1",
"inherits": "^2.0.4",
"minimalistic-assert": "^1.0.1",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"emittery": { "emittery": {
"version": "0.13.1", "version": "0.13.1",
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
@ -9980,11 +9720,6 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true "dev": true
}, },
"event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
},
"execa": { "execa": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@ -10301,25 +10036,6 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
"requires": {
"inherits": "^2.0.3",
"minimalistic-assert": "^1.0.1"
}
},
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
"requires": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"hosted-git-info": { "hosted-git-info": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@ -10534,12 +10250,6 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true "dev": true
}, },
"isomorphic-ws": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
"integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
"requires": {}
},
"istanbul-lib-coverage": { "istanbul-lib-coverage": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@ -11026,11 +10736,6 @@
"integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==",
"dev": true "dev": true
}, },
"js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -11115,20 +10820,6 @@
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true "dev": true
}, },
"ky": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/ky/-/ky-0.25.1.tgz",
"integrity": "sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA=="
},
"ky-universal": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.8.2.tgz",
"integrity": "sha512-xe0JaOH9QeYxdyGLnzUOVGK4Z6FGvDVzcXFTdrYA1f33MZdEa45sUDaMBy98xQMcsd2XIBrTXRrRYnegcSdgVQ==",
"requires": {
"abort-controller": "^3.0.0",
"node-fetch": "3.0.0-beta.9"
}
},
"leven": { "leven": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@ -11316,16 +11007,6 @@
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"dev": true "dev": true
}, },
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
},
"minimalistic-crypto-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="
},
"minimatch": { "minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -11362,11 +11043,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"multiformats": {
"version": "9.9.0",
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="
},
"multimatch": { "multimatch": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz",
@ -11415,11 +11091,6 @@
"fetch-blob": "^2.1.1" "fetch-blob": "^2.1.1"
} }
}, },
"node-gyp-build": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg=="
},
"node-int64": { "node-int64": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@ -12269,11 +11940,6 @@
"tar-stream": "^2.0.0" "tar-stream": "^2.0.0"
} }
}, },
"tar-js": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/tar-js/-/tar-js-0.3.0.tgz",
"integrity": "sha512-9uqP2hJUZNKRkwPDe5nXxXdzo6w+BFBPq9x/tyi5/U/DneuSesO/HMb0y5TeWpfcv49YDJTs7SrrZeeu8ZHWDA=="
},
"tar-stream": { "tar-stream": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
@ -12451,6 +12117,12 @@
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true "dev": true
}, },
"undici": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.7.0.tgz",
"integrity": "sha512-tZ6+5NBq4KH35rr46XJ2JPFKxfcBlYNaqLF/wyWIO9RMHqqU/gx/CLB1Y2qMcgB8lWw/bKHa7qzspqCN7mUHvA==",
"peer": true
},
"universalify": { "universalify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@ -12476,14 +12148,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"utf-8-validate": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -12533,13 +12197,6 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"optional": true,
"peer": true
},
"which": { "which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -12607,12 +12264,6 @@
"signal-exit": "^3.0.7" "signal-exit": "^3.0.7"
} }
}, },
"ws": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
"requires": {}
},
"y18n": { "y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

View File

@ -1,28 +1,27 @@
{ {
"name": "@ethersphere/bee-factory", "name": "@codex-storage/codex-factory",
"version": "0.5.2", "version": "0.1.0",
"description": "Orchestration CLI for spinning up local development Bee cluster with Docker", "description": "Orchestration CLI for spinning up local development Codex cluster with Docker",
"keywords": [ "keywords": [
"bee", "codex",
"swarm", "codex-storage",
"decentralised", "decentralised",
"storage", "storage",
"ethereum",
"typescript", "typescript",
"p2p", "p2p",
"docker" "docker"
], ],
"homepage": "https://github.com/ethersphere/bee-factory", "homepage": "https://github.com/codex-storage/codex-factory",
"bugs": { "bugs": {
"url": "https://github.com/ethersphere/bee-factory/issues/" "url": "https://github.com/codex-storage/codex-factory/issues/"
}, },
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/ethersphere/bee-factory.git" "url": "https://github.com/codex-storage/codex-factory.git"
}, },
"bin": { "bin": {
"bee-factory": "./dist/src/index.js" "codex-factory": "./dist/src/index.js"
}, },
"main": "dist/src/index.js", "main": "dist/src/index.js",
"files": [ "files": [
@ -39,7 +38,7 @@
"depcheck": "depcheck ." "depcheck": "depcheck ."
}, },
"dependencies": { "dependencies": {
"@ethersphere/bee-js": "^5.0.0", "@codex-storage/sdk-js": "^0.1.2",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"dockerode": "^3.3.4", "dockerode": "^3.3.4",
"furious-commander": "^1.7.1", "furious-commander": "^1.7.1",
@ -73,9 +72,9 @@
"typescript": "^4.8.4" "typescript": "^4.8.4"
}, },
"engines": { "engines": {
"node": ">=12.0.0", "node": ">=18.0.0",
"npm": ">=6.0.0", "npm": ">=6.0.0",
"bee": "1.9.0", "codex": "4ace774",
"supportedBee": ">=1.9.0" "supportedCodex": ">=0.2.0"
} }
} }

View File

@ -2,9 +2,9 @@ import { Application } from 'furious-commander/dist/application'
import PackageJson from '../package.json' import PackageJson from '../package.json'
export const application: Application = { export const application: Application = {
name: 'Bee Factory', name: 'Codex Factory',
command: 'bee-factory', command: 'codex-factory',
description: 'Orchestration CLI for spinning up local development Bee cluster with Docker', description: 'Orchestration CLI for spinning up local development Codex cluster with Docker',
version: PackageJson.version, version: PackageJson.version,
autocompletion: 'fromOption', autocompletion: 'fromOption',
} }

68
src/command/client.ts Normal file
View File

@ -0,0 +1,68 @@
import { Argument, GroupCommand, LeafCommand, Option } from 'furious-commander'
import { RootCommand } from './root-command'
import { ContainerType, DEFAULT_ENV_PREFIX, DEFAULT_IMAGE_PREFIX, Docker } from '../utils/docker'
class ClientRequestCommand extends RootCommand implements LeafCommand {
public readonly name = 'request'
public readonly description = `Prints logs for given container. Valid container's names are: ${Object.values(
ContainerType,
).join(', ')}`
@Option({
key: 'image-prefix',
type: 'string',
description: 'Docker image name prefix',
envKey: 'FACTORY_IMAGE_PREFIX',
default: DEFAULT_IMAGE_PREFIX,
})
public imagePrefix!: string
@Option({
key: 'env-prefix',
type: 'string',
description: "Docker container's names prefix",
envKey: 'FACTORY_ENV_PREFIX',
default: DEFAULT_ENV_PREFIX,
})
public envPrefix!: string
@Option({
key: 'follow',
alias: 'f',
type: 'boolean',
description: 'Stays attached to the container and output any new logs.',
default: false,
})
public follow!: boolean
@Option({
key: 'tail',
alias: 't',
type: 'number',
description: 'Prints specified number of last log lines.',
})
public tail!: number
@Argument({ key: 'container', description: 'Container name as described above', required: true })
public container!: ContainerType
public async run(): Promise<void> {
await super.init()
if (!Object.values(ContainerType).includes(this.container)) {
throw new Error(`Passed container name is not valid! Valid values: ${Object.values(ContainerType).join(', ')}`)
}
const docker = new Docker(this.console, this.envPrefix, this.imagePrefix)
await docker.logs(this.container, process.stdout, this.follow, this.tail)
}
}
export class ClientGroupCommand implements GroupCommand {
public readonly name = 'client'
public subCommandClasses = [ClientRequestCommand]
public readonly description = 'Group of commands to operate client node'
}

View File

@ -11,7 +11,7 @@ export class RootCommand {
public verbosity!: VerbosityLevel public verbosity!: VerbosityLevel
public console!: Logging public console!: Logging
public readonly appName = 'bee-factory' public readonly appName = 'codex-factory'
protected async init(): Promise<void> { protected async init(): Promise<void> {
this.verbosity = VerbosityLevel.Normal this.verbosity = VerbosityLevel.Normal

View File

@ -6,28 +6,26 @@ import {
DEFAULT_IMAGE_PREFIX, DEFAULT_IMAGE_PREFIX,
Docker, Docker,
RunOptions, RunOptions,
WORKER_COUNT, HOST_COUNT,
} from '../utils/docker' } from '../utils/docker'
import { waitForBlockchain, waitForQueen, waitForWorkers } from '../utils/wait' import { waitForBlockchain, waitForClient, waitForHosts } from '../utils/wait'
import ora from 'ora' import ora from 'ora'
import { VerbosityLevel } from './root-command/logging' import { VerbosityLevel } from './root-command/logging'
import { findBeeVersion, stripCommit } from '../utils/config-sources' import { findCodexVersion, validateVersion } from '../utils/config-sources'
import PackageJson from '../../package.json'
import semver from 'semver'
const DEFAULT_REPO = 'ethersphere' const DEFAULT_REPO = 'codexstorage'
export const ENV_ENV_PREFIX_KEY = 'FACTORY_ENV_PREFIX' export const ENV_ENV_PREFIX_KEY = 'FACTORY_ENV_PREFIX'
const ENV_IMAGE_PREFIX_KEY = 'FACTORY_IMAGE_PREFIX' const ENV_IMAGE_PREFIX_KEY = 'FACTORY_IMAGE_PREFIX'
const ENV_REPO_KEY = 'FACTORY_DOCKER_REPO' const ENV_REPO_KEY = 'FACTORY_DOCKER_REPO'
const ENV_DETACH_KEY = 'FACTORY_DETACH' const ENV_DETACH_KEY = 'FACTORY_DETACH'
const ENV_WORKERS_KEY = 'FACTORY_WORKERS' const ENV_HOSTS_KEY = 'FACTORY_HOSTS'
const ENV_FRESH_KEY = 'FACTORY_FRESH' const ENV_FRESH_KEY = 'FACTORY_FRESH'
export class Start extends RootCommand implements LeafCommand { export class Start extends RootCommand implements LeafCommand {
public readonly name = 'start' public readonly name = 'start'
public readonly description = 'Spin up the Bee Factory cluster' public readonly description = 'Spin up the Codex Factory cluster'
@Option({ @Option({
key: 'fresh', key: 'fresh',
@ -50,14 +48,14 @@ export class Start extends RootCommand implements LeafCommand {
public detach!: boolean public detach!: boolean
@Option({ @Option({
key: 'workers', key: 'hosts',
alias: 'w', alias: 'h',
type: 'number', type: 'number',
description: `Number of workers to spin. Value between 0 and ${WORKER_COUNT} including.`, description: `Number of hosts to spin. Value between 0 and ${HOST_COUNT} including.`,
envKey: ENV_WORKERS_KEY, envKey: ENV_HOSTS_KEY,
default: WORKER_COUNT, default: HOST_COUNT,
}) })
public workers!: number public hosts!: number
@Option({ @Option({
key: 'repo', key: 'repo',
@ -86,30 +84,23 @@ export class Start extends RootCommand implements LeafCommand {
}) })
public envPrefix!: string public envPrefix!: string
@Argument({ key: 'bee-version', description: 'Bee image version', required: false }) @Argument({ key: 'codex-version', description: 'Codex image version', required: false })
public beeVersion!: string public codexVersion!: string
public async run(): Promise<void> { public async run(): Promise<void> {
await super.init() await super.init()
if (this.workers < 0 || this.workers > WORKER_COUNT) { if (this.hosts < 0 || this.hosts > HOST_COUNT) {
throw new Error(`Worker count has to be between 0 and ${WORKER_COUNT} including.`) throw new Error(`Worker count has to be between 0 and ${HOST_COUNT} including.`)
} }
if (!this.beeVersion) { if (!this.codexVersion) {
this.beeVersion = await findBeeVersion() this.codexVersion = await findCodexVersion()
this.console.log('Bee version not specified. Found it configured externally.') this.console.log('Codex version not specified. Found it configured externally.')
this.console.log(`Spinning up cluster with Bee version ${this.beeVersion}.`) this.console.log(`Spinning up cluster with Codex version ${this.codexVersion}.`)
} }
this.beeVersion = stripCommit(this.beeVersion) this.codexVersion = validateVersion(this.codexVersion)
const supportedBeeVersion = PackageJson.engines.supportedBee
if (!semver.satisfies(this.beeVersion, supportedBeeVersion, { includePrerelease: true })) {
throw new Error(
`Unsupported Bee version!\nThis version of Bee Factory supports versions: ${supportedBeeVersion}, but you have requested start of ${this.beeVersion}`,
)
}
const dockerOptions = await this.buildDockerOptions() const dockerOptions = await this.buildDockerOptions()
const docker = new Docker(this.console, this.envPrefix, this.imagePrefix, this.repo) const docker = new Docker(this.console, this.envPrefix, this.imagePrefix, this.repo)
@ -122,10 +113,10 @@ export class Start extends RootCommand implements LeafCommand {
return return
} }
await docker.logs(ContainerType.QUEEN, process.stdout) await docker.logs(ContainerType.CLIENT, process.stdout)
} }
let queenAddress: string let clientDockerIpAddress: string
process.on('SIGINT', async () => { process.on('SIGINT', async () => {
try { try {
@ -160,10 +151,10 @@ export class Start extends RootCommand implements LeafCommand {
}).start() }).start()
try { try {
const blockchainVersion = await docker.getBlockchainVersionFromQueenMetadata(this.beeVersion) const blockchainImage = await docker.getBlockchainImage(this.codexVersion)
blockchainSpinner.text = 'Starting blockchain node...' blockchainSpinner.text = 'Starting blockchain node...'
await docker.startBlockchainNode(blockchainVersion, dockerOptions) await docker.startBlockchainNode(blockchainImage, dockerOptions)
blockchainSpinner.text = 'Waiting until blockchain is ready...' blockchainSpinner.text = 'Waiting until blockchain is ready...'
await waitForBlockchain() await waitForBlockchain()
blockchainSpinner.succeed('Blockchain node is up and listening') blockchainSpinner.succeed('Blockchain node is up and listening')
@ -173,51 +164,53 @@ export class Start extends RootCommand implements LeafCommand {
throw e throw e
} }
const queenSpinner = ora({ const clientSpinner = ora({
text: 'Starting queen Bee node...', text: 'Starting Codex client node...',
spinner: 'point', spinner: 'point',
color: 'yellow', color: 'yellow',
isSilent: this.verbosity === VerbosityLevel.Quiet, isSilent: this.verbosity === VerbosityLevel.Quiet,
}).start() }).start()
async function clientStatus(): Promise<boolean> {
return (await docker.getStatusForContainer(ContainerType.CLIENT)) === 'running'
}
try { try {
await docker.startQueenNode(this.beeVersion, dockerOptions) await docker.startClientNode(this.codexVersion, dockerOptions)
queenSpinner.text = 'Waiting until queen node is ready...' clientSpinner.text = 'Waiting until client node is ready...'
queenAddress = await waitForQueen( clientDockerIpAddress = await waitForClient(clientStatus)
async () => (await docker.getStatusForContainer(ContainerType.QUEEN)) === 'running', clientSpinner.succeed('Client boot node is up and listening')
)
queenSpinner.succeed('Queen node is up and listening')
} catch (e) { } catch (e) {
queenSpinner.fail(`It was not possible to start queen node!`) clientSpinner.fail(`It was not possible to start client node!`)
await this.stopDocker(docker) await this.stopDocker(docker)
throw e throw e
} }
if (this.workers > 0) { if (this.hosts > 0) {
const workerSpinner = ora({ const hostSpinner = ora({
text: 'Starting worker Bee nodes...', text: 'Starting Codex host nodes...',
spinner: 'point', spinner: 'point',
color: 'yellow', color: 'yellow',
isSilent: this.verbosity === VerbosityLevel.Quiet, isSilent: this.verbosity === VerbosityLevel.Quiet,
}).start() }).start()
try { try {
for (let i = 1; i <= this.workers; i++) { for (let i = 1; i <= this.hosts; i++) {
await docker.startWorkerNode(this.beeVersion, i, queenAddress, dockerOptions) await docker.startHostNode(this.codexVersion, i, clientDockerIpAddress, dockerOptions)
} }
workerSpinner.text = 'Waiting until all workers connect to queen...' hostSpinner.text = 'Waiting until all host nodes connect to client...'
await waitForWorkers(this.workers, docker.getAllStatus.bind(docker)) await waitForHosts(this.hosts, docker.getAllStatus.bind(docker))
workerSpinner.succeed('Worker nodes are up and listening') hostSpinner.succeed('Host nodes are up and listening')
} catch (e) { } catch (e) {
workerSpinner.fail(`It was not possible to start worker nodes!`) hostSpinner.fail(`It was not possible to start host nodes!`)
await this.stopDocker(docker) await this.stopDocker(docker)
throw e throw e
} }
} }
if (!this.detach) { if (!this.detach) {
await docker.logs(ContainerType.QUEEN, process.stdout, true) await docker.logs(ContainerType.CLIENT, process.stdout, true)
} }
} }

View File

@ -7,7 +7,7 @@ import { VerbosityLevel } from './root-command/logging'
export class Stop extends RootCommand implements LeafCommand { export class Stop extends RootCommand implements LeafCommand {
public readonly name = 'stop' public readonly name = 'stop'
public readonly description = 'Stops the Bee Factory cluster' public readonly description = 'Stops the Codex Factory cluster'
@Option({ @Option({
key: 'env-prefix', key: 'env-prefix',

View File

@ -1,21 +1,33 @@
import { readFile as readFileCb } from 'fs' import { readFile as readFileCb } from 'fs'
import * as path from 'path' import * as path from 'path'
import { promisify } from 'util' import { promisify } from 'util'
import PackageJson from '../../package.json'
import semver from 'semver'
const readFile = promisify(readFileCb) const readFile = promisify(readFileCb)
const VERSION_REGEX = /^\d+\.\d+\.\d+(-\w+)*$/ const VERSION_REGEX = /^\d+\.\d+\.\d+$/
const COMMIT_HASH_REGEX = /^([a-f0-9]{7,10})$/i
export function stripCommit(version: string): string { export function validateVersion(version: string): string {
if (version === 'latest') { if (version === 'latest') {
return version return version
} }
if (!VERSION_REGEX.test(version)) { if (VERSION_REGEX.test(version)) {
const supportedCodexVersion = PackageJson.engines.supportedCodex
if (!semver.satisfies(version, supportedCodexVersion, { includePrerelease: true })) {
throw new Error(
`Unsupported Codex version!\nThis version of Codex Factory supports versions: ${supportedCodexVersion}, but you have requested start of ${version}`,
)
}
return version
} else if (COMMIT_HASH_REGEX.test(version)) {
return `sha-${version}`
} else {
throw new Error('The version does not have expected format!') throw new Error('The version does not have expected format!')
} }
// If the version contains commit ==> hash remove it
return version.replace('-stateful', '').replace(/-[0-9a-fA-F]{8}$/, '')
} }
async function searchPackageJson(): Promise<string | undefined> { async function searchPackageJson(): Promise<string | undefined> {
@ -24,14 +36,14 @@ async function searchPackageJson(): Promise<string | undefined> {
try { try {
const pkgJson = JSON.parse(await readFile(expectedPath, { encoding: 'utf8' })) const pkgJson = JSON.parse(await readFile(expectedPath, { encoding: 'utf8' }))
return pkgJson?.engines?.bee return pkgJson?.engines?.codex
} catch (e) { } catch (e) {
return undefined return undefined
} }
} }
async function searchBeeFactory(): Promise<string | undefined> { async function searchCodexFactory(): Promise<string | undefined> {
const expectedPath = path.join(process.cwd(), '.beefactory.json') const expectedPath = path.join(process.cwd(), '.codexfactory.json')
try { try {
const pkgJson = JSON.parse(await readFile(expectedPath, { encoding: 'utf8' })) const pkgJson = JSON.parse(await readFile(expectedPath, { encoding: 'utf8' }))
@ -42,18 +54,18 @@ async function searchBeeFactory(): Promise<string | undefined> {
} }
} }
export async function findBeeVersion(): Promise<string> { export async function findCodexVersion(): Promise<string> {
const packageJson = await searchPackageJson() const packageJson = await searchPackageJson()
if (packageJson) { if (packageJson) {
return packageJson return packageJson
} }
const beeFactory = await searchBeeFactory() const codexFactory = await searchCodexFactory()
if (beeFactory) { if (codexFactory) {
return beeFactory return codexFactory
} }
throw new Error('Bee Version was not specified nor it is present in expected external places!') throw new Error('Codex Version was not specified nor it is present in expected external places!')
} }

View File

@ -2,29 +2,50 @@ import Dockerode, { Container, ContainerCreateOptions } from 'dockerode'
import { Logging } from '../command/root-command/logging' import { Logging } from '../command/root-command/logging'
import { ContainerImageConflictError } from './error' import { ContainerImageConflictError } from './error'
export const DEFAULT_ENV_PREFIX = 'bee-factory' export const DEFAULT_ENV_PREFIX = 'codex-factory'
export const DEFAULT_IMAGE_PREFIX = 'bee-factory' export const DEFAULT_IMAGE_PREFIX = 'nim-codex'
export const HOST_COUNT = 4
const BLOCKCHAIN_IMAGE_NAME_SUFFIX = '-blockchain' const BLOCKCHAIN_IMAGE_NAME_SUFFIX = '-blockchain'
const QUEEN_IMAGE_NAME_SUFFIX = '-queen' const CLIENT_IMAGE_NAME_SUFFIX = '-client'
const WORKER_IMAGE_NAME_SUFFIX = '-worker' const HOST_IMAGE_NAME_SUFFIX = '-host'
const NETWORK_NAME_SUFFIX = '-network' const NETWORK_NAME_SUFFIX = '-network'
const HARDHAT_ACCOUNTS = [
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', // Deployer account
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // Client account
'0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC', // Host 1 account
'0x90F79bf6EB2c4f870365E785982E1f101E93b906', // Host 2 account
'0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', // .
'0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc', // .
'0x976EA74026E726554dB657fA54763abd0C3a0aa9', // .
'0x14dC79964da2C08b23698B3D3cc7Ca32193d9955',
'0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f',
'0xa0Ee7A142d267C1f36714E4a8F75612F20a79720',
'0xBcd4042DE499D14e55001CcbB24a551F3b954096',
'0x71bE63f3384f5fb98995898A86B02Fb2426c5788',
'0xFABB0ac9d68B0B445fB7357272Ff202C5651694a',
'0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec',
'0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097',
'0xcd3B766CCDd6AE721141F452C550Ca635964ce71',
'0x2546BcD3c84621e976D8185a91A922aE77ECEc30',
'0xbDA5747bFD65F08deb54cb465eB87D40e51B197E',
'0xdD2FD4581271e230360230F9337D5c0430Bf44C0',
'0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199',
]
export const WORKER_COUNT = 4 export const BLOCKCHAIN_IMAGE_LABEL_KEY = 'storage.codex.nim-codex.blockchain-image'
export const BLOCKCHAIN_VERSION_LABEL_KEY = 'org.ethswarm.beefactory.blockchain-version'
export const CONTRACT_LABEL_KEY_PREFIX = 'org.ethswarm.beefactory.contracts.'
export interface RunOptions { export interface RunOptions {
fresh: boolean fresh: boolean
} }
export enum ContainerType { export enum ContainerType {
QUEEN = 'queen', CLIENT = 'client',
BLOCKCHAIN = 'blockchain', BLOCKCHAIN = 'blockchain',
WORKER_1 = 'worker1', HOST = 'host',
WORKER_2 = 'worker2', HOST_2 = 'host2',
WORKER_3 = 'worker3', HOST_3 = 'host3',
WORKER_4 = 'worker4', HOST_4 = 'host4',
} }
export type Status = 'running' | 'exists' | 'not-found' export type Status = 'running' | 'exists' | 'not-found'
@ -32,11 +53,11 @@ type FindResult = { container?: Container; image?: string }
export interface AllStatus { export interface AllStatus {
blockchain: Status blockchain: Status
queen: Status client: Status
worker1: Status host: Status
worker2: Status host_2: Status
worker3: Status host_3: Status
worker4: Status host_4: Status
} }
export interface DockerError extends Error { export interface DockerError extends Error {
@ -59,30 +80,19 @@ export class Docker {
private get blockchainName() { private get blockchainName() {
return `${this.envPrefix}${BLOCKCHAIN_IMAGE_NAME_SUFFIX}` return `${this.envPrefix}${BLOCKCHAIN_IMAGE_NAME_SUFFIX}`
} }
private blockchainImage(blockchainVersion: string) {
private hostName(index: number) {
return `${this.envPrefix}${HOST_IMAGE_NAME_SUFFIX}-${index}`
}
private get clientName() {
return `${this.envPrefix}${CLIENT_IMAGE_NAME_SUFFIX}`
}
private codexImage(codexVersion: string) {
if (!this.repo) throw new TypeError('Repo has to be defined!') if (!this.repo) throw new TypeError('Repo has to be defined!')
return `${this.repo}/${this.imagePrefix}${BLOCKCHAIN_IMAGE_NAME_SUFFIX}:${blockchainVersion}` return `${this.repo}/${this.imagePrefix}:${codexVersion}`
}
private get queenName() {
return `${this.envPrefix}${QUEEN_IMAGE_NAME_SUFFIX}`
}
private queenImage(beeVersion: string) {
if (!this.repo) throw new TypeError('Repo has to be defined!')
return `${this.repo}/${this.imagePrefix}${QUEEN_IMAGE_NAME_SUFFIX}:${beeVersion}`
}
private workerName(index: number) {
return `${this.envPrefix}${WORKER_IMAGE_NAME_SUFFIX}-${index}`
}
private workerImage(beeVersion: string, workerNumber: number) {
if (!this.repo) throw new TypeError('Repo has to be defined!')
return `${this.repo}/${this.imagePrefix}${WORKER_IMAGE_NAME_SUFFIX}-${workerNumber}:${beeVersion}`
} }
constructor(console: Logging, envPrefix: string, imagePrefix: string, repo?: string) { constructor(console: Logging, envPrefix: string, imagePrefix: string, repo?: string) {
@ -102,20 +112,20 @@ export class Docker {
} }
} }
public async startBlockchainNode(blockchainVersion: string, options: RunOptions): Promise<void> { public async startBlockchainNode(blockchainImage: string, options: RunOptions): Promise<void> {
if (options.fresh) await this.removeContainer(this.blockchainName) if (options.fresh) await this.removeContainer(this.blockchainName)
await this.pullImageIfNotFound(this.blockchainImage(blockchainVersion)) await this.pullImageIfNotFound(blockchainImage)
const container = await this.findOrCreateContainer(this.blockchainName, { const container = await this.findOrCreateContainer(this.blockchainName, {
Image: this.blockchainImage(blockchainVersion), Image: blockchainImage,
name: this.blockchainName, name: this.blockchainName,
ExposedPorts: { ExposedPorts: {
'9545/tcp': {}, '8545/tcp': {},
}, },
AttachStderr: false, AttachStderr: false,
AttachStdout: false, AttachStdout: false,
HostConfig: { HostConfig: {
PortBindings: { '9545/tcp': [{ HostPort: '9545' }] }, PortBindings: { '8545/tcp': [{ HostPort: '8545' }] },
NetworkMode: this.networkName, NetworkMode: this.networkName,
}, },
}) })
@ -131,30 +141,29 @@ export class Docker {
} }
} }
public async startQueenNode(beeVersion: string, options: RunOptions): Promise<void> { public async startClientNode(codexVersion: string, options: RunOptions): Promise<void> {
if (options.fresh) await this.removeContainer(this.queenName) if (options.fresh) await this.removeContainer(this.clientName)
await this.pullImageIfNotFound(this.queenImage(beeVersion)) await this.pullImageIfNotFound(this.codexImage(codexVersion))
const contractAddresses = await this.getContractAddresses(this.queenImage(beeVersion)) const container = await this.findOrCreateContainer(this.clientName, {
const container = await this.findOrCreateContainer(this.queenName, { Image: this.codexImage(codexVersion),
Image: this.queenImage(beeVersion), name: this.clientName,
name: this.queenName,
ExposedPorts: { ExposedPorts: {
'1633/tcp': {}, '8070/tcp': {},
'1634/tcp': {}, '8080/tcp': {},
'1635/tcp': {}, '8090/udp': {},
}, },
Tty: true, Tty: true,
Cmd: ['start'], Cmd: ['codex', 'persistence'],
Env: this.createBeeEnvParameters(contractAddresses), Env: this.createCodexEnvParameters(HARDHAT_ACCOUNTS[1], 0),
AttachStderr: false, AttachStderr: false,
AttachStdout: false, AttachStdout: false,
HostConfig: { HostConfig: {
NetworkMode: this.networkName, NetworkMode: this.networkName,
PortBindings: { PortBindings: {
'1633/tcp': [{ HostPort: '1633' }], '8070/tcp': [{ HostPort: '8070' }],
'1634/tcp': [{ HostPort: '1634' }], '8080/tcp': [{ HostPort: '8080' }],
'1635/tcp': [{ HostPort: '1635' }], '8090/udp': [{ HostPort: '8090' }],
}, },
}, },
}) })
@ -167,38 +176,37 @@ export class Docker {
if (!state.State.Running) { if (!state.State.Running) {
await container.start() await container.start()
} else { } else {
this.console.info('The Queen node container was already running, so not starting it again.') this.console.info('The Client node container was already running, so not starting it again.')
} }
} }
public async startWorkerNode( public async startHostNode(
beeVersion: string, codexVersion: string,
workerNumber: number, hostNumber: number,
queenAddress: string, bootstrapAddress: string,
options: RunOptions, options: RunOptions,
): Promise<void> { ): Promise<void> {
if (options.fresh) await this.removeContainer(this.workerName(workerNumber)) if (options.fresh) await this.removeContainer(this.hostName(hostNumber))
await this.pullImageIfNotFound(this.workerImage(beeVersion, workerNumber)) await this.pullImageIfNotFound(this.codexImage(codexVersion))
const contractAddresses = await this.getContractAddresses(this.workerImage(beeVersion, workerNumber)) const container = await this.findOrCreateContainer(this.hostName(hostNumber), {
const container = await this.findOrCreateContainer(this.workerName(workerNumber), { Image: this.codexImage(codexVersion),
Image: this.workerImage(beeVersion, workerNumber), name: this.hostName(hostNumber),
name: this.workerName(workerNumber),
ExposedPorts: { ExposedPorts: {
'1633/tcp': {}, [`${8070 + hostNumber}/tcp`]: {},
'1634/tcp': {}, [`${8080 + hostNumber}/tcp`]: {},
'1635/tcp': {}, [`${8090 + hostNumber}/udp`]: {},
}, },
Cmd: ['start'], Env: this.createCodexEnvParameters(HARDHAT_ACCOUNTS[hostNumber + 1], hostNumber, bootstrapAddress),
Env: this.createBeeEnvParameters(contractAddresses, queenAddress), Cmd: ['codex', 'persistence', 'prover'],
AttachStderr: false, AttachStderr: false,
AttachStdout: false, AttachStdout: false,
HostConfig: { HostConfig: {
NetworkMode: this.networkName, NetworkMode: this.networkName,
PortBindings: { PortBindings: {
'1633/tcp': [{ HostPort: (1633 + workerNumber * 10000).toString() }], [`${8070 + hostNumber}/tcp`]: [{ HostPort: (8070 + hostNumber).toString() }],
'1634/tcp': [{ HostPort: (1634 + workerNumber * 10000).toString() }], [`${8080 + hostNumber}/tcp`]: [{ HostPort: (8080 + hostNumber).toString() }],
'1635/tcp': [{ HostPort: (1635 + workerNumber * 10000).toString() }], [`${8090 + hostNumber}/udp`]: [{ HostPort: (8090 + hostNumber).toString() }],
}, },
}, },
}) })
@ -210,7 +218,7 @@ export class Docker {
if (!state.State.Running) { if (!state.State.Running) {
await container.start() await container.start()
} else { } else {
this.console.info('The Queen node container was already running, so not starting it again.') this.console.info('The client node container was already running, so not starting it again.')
} }
} }
@ -223,7 +231,7 @@ export class Docker {
const { container } = await this.findContainer(this.getContainerName(target)) const { container } = await this.findContainer(this.getContainerName(target))
if (!container) { if (!container) {
throw new Error('Queen container does not exists, even though it should have had!') throw new Error('Client container does not exists, even though it should have had!')
} }
const logs = await container.logs({ stdout: true, stderr: true, follow, tail }) const logs = await container.logs({ stdout: true, stderr: true, follow, tail })
@ -265,29 +273,28 @@ export class Docker {
} }
} }
public async getBlockchainVersionFromQueenMetadata(beeVersion: string): Promise<string> { public async getBlockchainImage(codexVersion: string): Promise<string> {
// Lets pull the Queen's image if it is not present // Lets pull the Codex's image if it is not present
await this.pullImageIfNotFound(this.queenImage(beeVersion)) await this.pullImageIfNotFound(this.codexImage(codexVersion))
const queenMetadata = await this.docker.getImage(this.queenImage(beeVersion)).inspect() const codexImageMeta = await this.docker.getImage(this.codexImage(codexVersion)).inspect()
const blockchainImage = codexImageMeta.Config.Labels[BLOCKCHAIN_IMAGE_LABEL_KEY]
const version = queenMetadata.Config.Labels[BLOCKCHAIN_VERSION_LABEL_KEY] if (!blockchainImage) {
throw new Error('Blockchain image version was not found in given Codex image labels!')
if (!version) {
throw new Error('Blockchain image version was not found in Queen image labels!')
} }
return version return blockchainImage
} }
public async getAllStatus(): Promise<AllStatus> { public async getAllStatus(): Promise<AllStatus> {
return { return {
queen: await this.getStatusForContainer(ContainerType.QUEEN), client: await this.getStatusForContainer(ContainerType.CLIENT),
blockchain: await this.getStatusForContainer(ContainerType.BLOCKCHAIN), blockchain: await this.getStatusForContainer(ContainerType.BLOCKCHAIN),
worker1: await this.getStatusForContainer(ContainerType.WORKER_1), host: await this.getStatusForContainer(ContainerType.HOST),
worker2: await this.getStatusForContainer(ContainerType.WORKER_2), host_2: await this.getStatusForContainer(ContainerType.HOST_2),
worker3: await this.getStatusForContainer(ContainerType.WORKER_3), host_3: await this.getStatusForContainer(ContainerType.HOST_3),
worker4: await this.getStatusForContainer(ContainerType.WORKER_4), host_4: await this.getStatusForContainer(ContainerType.HOST_4),
} }
} }
@ -371,49 +378,51 @@ export class Docker {
switch (name) { switch (name) {
case ContainerType.BLOCKCHAIN: case ContainerType.BLOCKCHAIN:
return this.blockchainName return this.blockchainName
case ContainerType.QUEEN: case ContainerType.CLIENT:
return this.queenName return this.clientName
case ContainerType.WORKER_1: case ContainerType.HOST:
return this.workerName(1) return this.hostName(1)
case ContainerType.WORKER_2: case ContainerType.HOST_2:
return this.workerName(2) return this.hostName(2)
case ContainerType.WORKER_3: case ContainerType.HOST_3:
return this.workerName(3) return this.hostName(3)
case ContainerType.WORKER_4: case ContainerType.HOST_4:
return this.workerName(4) return this.hostName(4)
default: default:
throw new Error('Unknown container!') throw new Error('Unknown container!')
} }
} }
private createBeeEnvParameters(contractAddresses: Record<string, string>, bootnode?: string): string[] { private createCodexEnvParameters(ethAccount: string, portIndex: number, bootnode?: string): string[] {
const options: Record<string, string> = { const options: Record<string, string> = {
'warmup-time': '0', 'eth-provider': `http://${this.blockchainName}:8545`,
'debug-api-enable': 'true', 'eth-account': ethAccount,
verbosity: '4', 'disc-port': `${8090 + portIndex}`,
'swap-enable': 'true', 'listen-addrs': `/ip4/0.0.0.0/tcp/${8070 + portIndex}`,
mainnet: 'false', 'api-port': `${8080 + portIndex}`,
'swap-endpoint': `http://${this.blockchainName}:9545`, 'api-bindaddr': '0.0.0.0',
password: 'password', 'api-cors-origin': '*',
'network-id': '4020', validator: 'true',
'full-node': 'true', 'validator-max-slots': '1000',
'welcome-message': 'You have found the queen of the beehive...', 'marketplace-address': '0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44',
'cors-allowed-origins': '*', 'log-level': 'NOTICE; TRACE: marketplace,sales,node,restapi',
'postage-stamp-start-block': '1',
...contractAddresses,
} }
if (bootnode) { // Env variables for Codex has form of `CODEX_LOG_LEVEL`, so we need to transform it.
options.bootnode = bootnode const envVariables = Object.entries(options).reduce<string[]>((previous, current) => {
} const keyName = `CODEX_${current[0].toUpperCase().replace(/-/g, '_')}`
// Env variables for Bee has form of `BEE_WARMUP_TIME`, so we need to transform it.
return Object.entries(options).reduce<string[]>((previous, current) => {
const keyName = `BEE_${current[0].toUpperCase().replace(/-/g, '_')}`
previous.push(`${keyName}=${current[1]}`) previous.push(`${keyName}=${current[1]}`)
return previous return previous
}, []) }, [])
if (bootnode) {
envVariables.push(`BOOTSTRAP_NODE_URL=${bootnode}:8080`)
}
envVariables.push('NAT_IP_AUTO=true')
return envVariables
} }
private async pullImageIfNotFound(name: string): Promise<void> { private async pullImageIfNotFound(name: string): Promise<void> {
@ -426,19 +435,4 @@ export class Docker {
await new Promise(res => this.docker.modem.followProgress(pullStream, res)) await new Promise(res => this.docker.modem.followProgress(pullStream, res))
} }
} }
private async getContractAddresses(imageName: string): Promise<Record<string, string>> {
const imageMetadata = await this.docker.getImage(imageName).inspect()
const contractAddresses: Record<string, string> = {}
// @ts-ignore: Dockerode typings does not have iterator even though it is a simple object
for (const [labelKey, labelValue] of Object.entries(imageMetadata.Config.Labels)) {
if (labelKey.startsWith(CONTRACT_LABEL_KEY_PREFIX)) {
contractAddresses[labelKey.replace(CONTRACT_LABEL_KEY_PREFIX, '')] = labelValue
}
}
return contractAddresses
}
} }

View File

@ -1,5 +1,5 @@
/** /**
* Thrown when the error is not related to Bee/network * Thrown when the error is not related to Codex/network
*/ */
export class TimeoutError extends Error {} export class TimeoutError extends Error {}

View File

@ -1,13 +1,13 @@
import fetch, { FetchError } from 'node-fetch' import fetch, { FetchError } from 'node-fetch'
import { sleep } from './index' import { sleep } from './index'
import { TimeoutError } from './error' import { TimeoutError } from './error'
import { BeeDebug } from '@ethersphere/bee-js'
import { AllStatus } from './docker' import { AllStatus } from './docker'
import { Codex } from '@codex-storage/sdk-js'
const AWAIT_SLEEP = 3_000 const AWAIT_SLEEP = 3_000
const BLOCKCHAIN_BODY_REQUEST = JSON.stringify({ jsonrpc: '2.0', method: 'eth_chainId', id: 1 }) const BLOCKCHAIN_BODY_REQUEST = JSON.stringify({ jsonrpc: '2.0', method: 'eth_chainId', id: 1 })
const EXPECTED_CHAIN_ID = '0xfb4' const EXPECTED_CHAIN_ID = '0x7a69'
const ALLOWED_ERRORS = ['ECONNREFUSED', 'ECONNRESET', 'UND_ERR_SOCKET'] const ALLOWED_ERRORS = ['ECONNREFUSED', 'ECONNRESET', 'UND_ERR_SOCKET']
function isAllowedError(e: FetchError): boolean { function isAllowedError(e: FetchError): boolean {
@ -30,10 +30,20 @@ function isAllowedError(e: FetchError): boolean {
return ALLOWED_ERRORS.some(substring => e.message.includes(substring)) return ALLOWED_ERRORS.some(substring => e.message.includes(substring))
} }
function extractIpFromMultiaddr(multiaddr: string): string {
const match = multiaddr.match(/\/ip4\/([\d.]+)\/tcp\/(\d+)/)
if (match) {
return match[1]
} else {
throw new Error('Unsupported multiaddr')
}
}
export async function waitForBlockchain(waitingIterations = 30): Promise<void> { export async function waitForBlockchain(waitingIterations = 30): Promise<void> {
for (let i = 0; i < waitingIterations; i++) { for (let i = 0; i < waitingIterations; i++) {
try { try {
const request = await fetch('http://127.0.0.1:9545', { const request = await fetch('http://127.0.0.1:8545', {
method: 'POST', method: 'POST',
body: BLOCKCHAIN_BODY_REQUEST, body: BLOCKCHAIN_BODY_REQUEST,
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@ -55,22 +65,29 @@ export async function waitForBlockchain(waitingIterations = 30): Promise<void> {
throw new TimeoutError('Waiting for blockchain container timed-out') throw new TimeoutError('Waiting for blockchain container timed-out')
} }
export async function waitForQueen(verifyQueenIsUp: () => Promise<boolean>, waitingIterations = 120): Promise<string> { export async function waitForClient(
const beeDebug = new BeeDebug('http://127.0.0.1:1635') verifyClientIsUp: () => Promise<boolean>,
waitingIterations = 120,
): Promise<string> {
const codex = new Codex('http://127.0.0.1:8080')
for (let i = 0; i < waitingIterations; i++) { for (let i = 0; i < waitingIterations; i++) {
try { try {
if (!(await verifyQueenIsUp())) { if (!(await verifyClientIsUp())) {
throw new Error('Queen node is not running!') throw new Error('Client node is not running!')
} }
const addresses = await beeDebug.getNodeAddresses() const info = await codex.debug.info()
if (addresses.underlay.length > 0) { if (info.error) {
const addr = addresses.underlay.find(addr => !addr.includes('127.0.0.1')) throw info.data
}
if (info.data.addrs.length > 0) {
const addr = info.data.addrs.find(addr => !addr.includes('127.0.0.1'))
if (addr) { if (addr) {
return addr return extractIpFromMultiaddr(addr)
} }
} }
} catch (e) { } catch (e) {
@ -82,28 +99,36 @@ export async function waitForQueen(verifyQueenIsUp: () => Promise<boolean>, wait
await sleep(AWAIT_SLEEP) await sleep(AWAIT_SLEEP)
} }
throw new TimeoutError('Waiting for queen container timed-out') throw new TimeoutError('Waiting for client container timed-out')
} }
export async function waitForWorkers( export async function waitForHosts(
workerCount: number, hostCount: number,
getStatus: () => Promise<AllStatus>, getStatus: () => Promise<AllStatus>,
waitingIterations = 120, waitingIterations = 120,
): Promise<void> { ): Promise<void> {
const beeDebug = new BeeDebug('http://127.0.0.1:1635') const codex = new Codex('http://127.0.0.1:8080')
const status = await getStatus() const status = await getStatus()
for (let i = 1; i <= workerCount; i++) {
if (status[`worker${i}` as keyof AllStatus] !== 'running') { if (status[`host` as keyof AllStatus] !== 'running') {
throw new Error('Some of the workers node is not running!') throw new Error('Some of the hosts node is not running!')
}
for (let i = 2; i <= hostCount; i++) {
if (status[`host_${i}` as keyof AllStatus] !== 'running') {
throw new Error('Some of the hosts node is not running!')
} }
} }
for (let i = 0; i < waitingIterations; i++) { for (let i = 0; i < waitingIterations; i++) {
try { try {
const peers = await beeDebug.getPeers() const info = await codex.debug.info()
if (peers.length >= workerCount) { if (info.error) {
throw info.data
}
if (info.data.table.nodes.length >= hostCount) {
return return
} }
} catch (e) { } catch (e) {
@ -115,5 +140,5 @@ export async function waitForWorkers(
await sleep(AWAIT_SLEEP) await sleep(AWAIT_SLEEP)
} }
throw new TimeoutError('Waiting for worker nodes timed-out') throw new TimeoutError('Waiting for host nodes timed-out')
} }

View File

@ -1,12 +1,13 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import Dockerode from 'dockerode' import Dockerode from 'dockerode'
import crypto from 'crypto' import crypto from 'crypto'
import { Codex } from '@codex-storage/sdk-js'
import { run } from '../utils/run' import { run } from '../utils/run'
import { ENV_ENV_PREFIX_KEY } from '../../src/command/start' import { ENV_ENV_PREFIX_KEY } from '../../src/command/start'
import { Bee, BeeDebug, Reference } from '@ethersphere/bee-js'
import { DockerError } from '../../src/utils/docker' import { DockerError } from '../../src/utils/docker'
import { findContainer, waitForUsablePostageStamp } from '../utils/docker' import { findContainer } from '../utils/docker'
let testFailed = false let testFailed = false
@ -26,15 +27,15 @@ function wrapper(fn: () => Promise<unknown>): () => Promise<unknown> {
describe('start command', () => { describe('start command', () => {
let docker: Dockerode let docker: Dockerode
let bee: Bee, beeDebug: BeeDebug let codexClient: Codex, codexHost: Codex
const envPrefix = `bee-factory-test-${crypto.randomBytes(4).toString('hex')}` const envPrefix = `codex-factory-test-${crypto.randomBytes(4).toString('hex')}`
beforeAll(() => { beforeAll(() => {
docker = new Dockerode() docker = new Dockerode()
bee = new Bee('http://127.0.0.1:1633') codexClient = new Codex('http://127.0.0.1:8080')
beeDebug = new BeeDebug('http://127.0.0.1:1635') codexHost = new Codex('http://127.0.0.1:8081')
// This will force Bee Factory to create // This will force Codex Factory to create
process.env[ENV_ENV_PREFIX_KEY] = envPrefix process.env[ENV_ENV_PREFIX_KEY] = envPrefix
}) })
@ -44,7 +45,7 @@ describe('start command', () => {
const containers = await docker.listContainers() const containers = await docker.listContainers()
containers.forEach(c => console.log(` - ${c.Names.join(', ')}`)) containers.forEach(c => console.log(` - ${c.Names.join(', ')}`))
await run(['logs', 'queen']) await run(['logs', 'client'])
} }
await run(['stop']) await run(['stop'])
@ -60,18 +61,18 @@ describe('start command', () => {
// As spinning the cluster with --detach the command will exit once the cluster is up and running // As spinning the cluster with --detach the command will exit once the cluster is up and running
await run(['start', '--detach']) await run(['start', '--detach'])
await expect(findContainer(docker, 'queen')).resolves.toBeDefined() await expect(findContainer(docker, 'client')).resolves.toBeDefined()
await expect(findContainer(docker, 'blockchain')).resolves.toBeDefined() await expect(findContainer(docker, 'blockchain')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-1')).resolves.toBeDefined() await expect(findContainer(docker, 'host-1')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-2')).resolves.toBeDefined() await expect(findContainer(docker, 'host-2')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-3')).resolves.toBeDefined() await expect(findContainer(docker, 'host-3')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-4')).resolves.toBeDefined() await expect(findContainer(docker, 'host-4')).resolves.toBeDefined()
await expect(beeDebug.getHealth()).resolves.toHaveProperty('status') expect((await codexClient.debug.info()).data).toHaveProperty('id')
}), }),
) )
describe('should start cluster with just few workers', () => { describe('should start cluster with just few hosts', () => {
beforeAll(async () => { beforeAll(async () => {
await run(['stop', '--rm']) // Cleanup the testing containers await run(['stop', '--rm']) // Cleanup the testing containers
}) })
@ -80,16 +81,16 @@ describe('start command', () => {
'', '',
wrapper(async () => { wrapper(async () => {
// As spinning the cluster with --detach the command will exit once the cluster is up and running // As spinning the cluster with --detach the command will exit once the cluster is up and running
await run(['start', '--workers', '2']) await run(['start', '--hosts', '2'])
await expect(findContainer(docker, 'queen')).resolves.toBeDefined() await expect(findContainer(docker, 'client')).resolves.toBeDefined()
await expect(findContainer(docker, 'blockchain')).resolves.toBeDefined() await expect(findContainer(docker, 'blockchain')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-1')).resolves.toBeDefined() await expect(findContainer(docker, 'host-1')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-2')).resolves.toBeDefined() await expect(findContainer(docker, 'host-2')).resolves.toBeDefined()
await expect(findContainer(docker, 'worker-3')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-3')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'worker-4')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-4')).rejects.toHaveProperty('statusCode', 404)
await expect(beeDebug.getHealth()).resolves.toHaveProperty('status') expect((await codexClient.debug.info()).data).toHaveProperty('id')
}), }),
) )
}) })
@ -119,35 +120,42 @@ describe('start command', () => {
}) })
describe('should remove containers with --fresh option', () => { describe('should remove containers with --fresh option', () => {
let reference: Reference, data: string let availabilityId: string
beforeAll(async () => { beforeAll(async () => {
console.log('(before) Starting up Bee Factory') console.log('(before) Starting up Codex Factory')
await run(['start', '--detach']) await run(['start', '--detach'])
const result = await codexClient.marketplace.createAvailability({
totalCollateral: 1,
totalSize: 3000,
minPricePerBytePerSecond: 100,
duration: 100,
})
console.log('(before) Creating postage stamp ') if (result.error) {
const postage = await beeDebug.createPostageBatch('10', 18) throw result.data
}
console.log('(before) Waiting for the postage stamp to be usable') availabilityId = result.data.id
await waitForUsablePostageStamp(beeDebug, postage)
data = `hello from ${Date.now()}`
reference = (await bee.uploadData(postage, data)).reference
// Lets just verify that it the current container has the data console.log('(before) Stopping the Codex Factory')
expect((await bee.downloadData(reference)).text()).toEqual(data)
console.log('(before) Stopping the Bee Factory')
await run(['stop']) await run(['stop'])
}) })
it( it(
'', '',
wrapper(async () => { wrapper(async () => {
console.log('(test) Starting the Bee Factory') console.log('(test) Starting the Codex Factory')
await run(['start', '--fresh', '--detach']) await run(['start', '--fresh', '--detach'])
console.log('(test) Trying to fetch the data') console.log('(test) Trying to fetch the data')
await expect(bee.downloadData(reference)).rejects.toHaveProperty('status', 404) expect((await codexClient.marketplace.availabilities()).data).not.toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.stringContaining(availabilityId),
}),
]),
)
}), }),
) )
}) })

View File

@ -8,12 +8,12 @@ import { findContainer } from '../utils/docker'
describe('stop command', () => { describe('stop command', () => {
let docker: Dockerode let docker: Dockerode
const envPrefix = `bee-factory-test-${crypto.randomBytes(4).toString('hex')}` const envPrefix = `codex-factory-test-${crypto.randomBytes(4).toString('hex')}`
beforeAll(() => { beforeAll(() => {
docker = new Dockerode() docker = new Dockerode()
// This will force Bee Factory to create // This will force Codex Factory to create
process.env[ENV_ENV_PREFIX_KEY] = envPrefix process.env[ENV_ENV_PREFIX_KEY] = envPrefix
}) })
@ -28,21 +28,21 @@ describe('stop command', () => {
}) })
it('', async () => { it('', async () => {
await expect(findContainer(docker, 'queen')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'client')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-1')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-1')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-2')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-2')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-3')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-3')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-4')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-4')).resolves.toHaveProperty('State.Status', 'running')
await run(['stop']) await run(['stop'])
await expect(findContainer(docker, 'queen')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'client')).resolves.toHaveProperty('State.Status', 'exited')
await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'exited')
await expect(findContainer(docker, 'worker-1')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'host-1')).resolves.toHaveProperty('State.Status', 'exited')
await expect(findContainer(docker, 'worker-2')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'host-2')).resolves.toHaveProperty('State.Status', 'exited')
await expect(findContainer(docker, 'worker-3')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'host-3')).resolves.toHaveProperty('State.Status', 'exited')
await expect(findContainer(docker, 'worker-4')).resolves.toHaveProperty('State.Status', 'exited') await expect(findContainer(docker, 'host-4')).resolves.toHaveProperty('State.Status', 'exited')
}) })
}) })
@ -53,21 +53,21 @@ describe('stop command', () => {
}) })
it('', async () => { it('', async () => {
await expect(findContainer(docker, 'queen')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'client')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'blockchain')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-1')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-1')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-2')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-2')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-3')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-3')).resolves.toHaveProperty('State.Status', 'running')
await expect(findContainer(docker, 'worker-4')).resolves.toHaveProperty('State.Status', 'running') await expect(findContainer(docker, 'host-4')).resolves.toHaveProperty('State.Status', 'running')
await run(['stop', '--rm']) await run(['stop', '--rm'])
await expect(findContainer(docker, 'queen')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'client')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'blockchain')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'blockchain')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'worker-1')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-1')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'worker-2')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-2')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'worker-3')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-3')).rejects.toHaveProperty('statusCode', 404)
await expect(findContainer(docker, 'worker-4')).rejects.toHaveProperty('statusCode', 404) await expect(findContainer(docker, 'host-4')).rejects.toHaveProperty('statusCode', 404)
}) })
}) })
}) })

View File

@ -1,6 +1,5 @@
import Dockerode from 'dockerode' import Dockerode from 'dockerode'
import { ENV_ENV_PREFIX_KEY } from '../../src/command/start' import { ENV_ENV_PREFIX_KEY } from '../../src/command/start'
import { BatchId, BeeDebug } from '@ethersphere/bee-js'
export async function findContainer(docker: Dockerode, name: string): Promise<Dockerode.ContainerInspectInfo> { export async function findContainer(docker: Dockerode, name: string): Promise<Dockerode.ContainerInspectInfo> {
return docker.getContainer(`${process.env[ENV_ENV_PREFIX_KEY]}-${name}`).inspect() return docker.getContainer(`${process.env[ENV_ENV_PREFIX_KEY]}-${name}`).inspect()
@ -9,18 +8,3 @@ export async function findContainer(docker: Dockerode, name: string): Promise<Do
export async function sleep(ms: number): Promise<void> { export async function sleep(ms: number): Promise<void> {
return new Promise<void>(resolve => setTimeout(() => resolve(), ms)) return new Promise<void>(resolve => setTimeout(() => resolve(), ms))
} }
export async function waitForUsablePostageStamp(beeDebug: BeeDebug, id: BatchId, timeout = 120_000): Promise<void> {
const TIME_STEP = 1500
for (let time = 0; time < timeout; time += TIME_STEP) {
const stamp = await beeDebug.getPostageBatch(id)
if (stamp.usable) {
return
}
await sleep(TIME_STEP)
}
throw new Error('Timeout on waiting for postage stamp to become usable')
}