diff --git a/.github/scripts/cloud-init.sh b/.github/scripts/cloud-init.sh
new file mode 100755
index 0000000..4c06718
--- /dev/null
+++ b/.github/scripts/cloud-init.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+set -eux
+trap 'poweroff' TERM EXIT INT
+
+Repo=$(curl http://169.254.169.254/latest/meta-data/tags/instance/Repo)
+Branch=$(curl http://169.254.169.254/latest/meta-data/tags/instance/Branch)
+
+Local_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)
+
+# Install pkgs
+apt-get update
+apt-get install -y net-tools
+for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo \
+ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
+ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
+ tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt-get update
+apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
+usermod -aG docker ubuntu
+
+su -P ubuntu -c "git clone -b $Branch --single-branch https://github.com/ntampakas/$Repo.git /home/ubuntu/$Repo"
+su -P ubuntu -c "cp /home/ubuntu/$Repo/apps/api/.env.example /home/ubuntu/$Repo/apps/api/.env"
+su -P ubuntu -c "sed -i 's/\(DB_TYPE=\).*/\1postgres/' /home/ubuntu/$Repo/apps/api/.env"
+su -P ubuntu -c "sed -i 's/\(DB_URL=\).*/\1postgres:\/\/root:helloworld\@postgres:5432\/bandada/' /home/ubuntu/$Repo/apps/api/.env"
+
+su -P ubuntu -c "rm /home/ubuntu/$Repo/apps/{client,dashboard}/.env.production /home/ubuntu/$Repo/apps/{client,dashboard}/.env.staging"
+su -P ubuntu -c "sed -i 's/localhost/$Local_IP/g' /home/ubuntu/$Repo/apps/{client,dashboard}/.env.local"
+
+su -P ubuntu -c "cd /home/ubuntu/$Repo ; docker compose up -d"
+
+sleep 6h
diff --git a/.github/scripts/get_ip.sh b/.github/scripts/get_ip.sh
new file mode 100755
index 0000000..7ca2377
--- /dev/null
+++ b/.github/scripts/get_ip.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -eux
+
+TRIGGER=$1
+ACTOR=$2
+VPC="vpc-07d12b28fd72d152e"
+
+# Stop here in schedule
+[ ! $TRIGGER = "maintenance" ] || exit 0
+
+sleep 10
+
+EC2_IP=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=[running]" "Name=tag:Name,Values='bandada-ephemeral-$ACTOR-*'" "Name=network-interface.vpc-id,Values=[$VPC]" --query "Reservations[*].Instances[*].[NetworkInterfaces[*].[PrivateIpAddress]]" --output text)
+
+echo "URL: http://$EC2_IP:3001"
diff --git a/.github/scripts/run.sh b/.github/scripts/run.sh
new file mode 100755
index 0000000..6e9edae
--- /dev/null
+++ b/.github/scripts/run.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+set -eux
+
+TRIGGER=$1
+BRANCH=$2
+ACTOR=$3
+SHA=$4
+AMI="ami-04e601abe3e1a910f"
+SG="sg-04d8c2eb4beca2de9"
+SUBNET="subnet-066cf21c696ef55c8"
+VPC="vpc-07d12b28fd72d152e"
+
+# Kill old instances
+CURRENT_TIME_EPOCH=$(date -d `date -Is` +"%s")
+EC2=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=[running]" "Name=tag:Name,Values='bandada-ephemeral-*'" "Name=network-interface.vpc-id,Values=[$VPC]" --query "Reservations[*].Instances[*].InstanceId" --output text)
+for i in $EC2; do
+ EC2_LAUNCH_TIME=$(aws ec2 describe-instances --instance-ids $i --query 'Reservations[*].Instances[*].LaunchTime' --output text)
+ LAUNCH_TIME_EPOCH=$(date -d $EC2_LAUNCH_TIME +"%s")
+ diff=$(expr $CURRENT_TIME_EPOCH - $LAUNCH_TIME_EPOCH)
+
+ if [ $diff -gt 21600 ]; then
+ aws ec2 terminate-instances --instance-ids $i
+ fi
+done
+
+# Stop here in schedule
+[ ! $TRIGGER = "maintenance" ] || exit 0
+
+# Check if actor ec2 exists
+ACTOR_EC2=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=[running]" "Name=tag:Name,Values='bandada-ephemeral-$ACTOR-*'" "Name=network-interface.vpc-id,Values=[$VPC]" --query "Reservations[*].Instances[*].InstanceId" --output text)
+
+[ -z $ACTOR_EC2 ] || aws ec2 terminate-instances --instance-ids $ACTOR_EC2
+
+# Launch new instance
+aws ec2 run-instances \
+ --user-data "file://.github/scripts/cloud-init.sh" \
+ --image-id $AMI \
+ --count 1 \
+ --instance-type t3a.large \
+ --key-name bandada \
+ --security-group-ids $SG \
+ --subnet-id $SUBNET \
+ --block-device-mappings "[{\"DeviceName\":\"/dev/sda1\",\"Ebs\":{\"VolumeSize\":32,\"DeleteOnTermination\":true}}]" \
+ --instance-initiated-shutdown-behavior terminate \
+ --tag-specification "ResourceType=instance,Tags=[{Key=Name,Value="bandada-ephemeral-$ACTOR-$SHA"},{Key=Repo,Value="bandada"},{Key=Branch,Value="$BRANCH"}]" \
+ --metadata-options "InstanceMetadataTags=enabled"
diff --git a/.github/workflows/coverall.yml b/.github/workflows/coverall.yml
index bd7b260..f1ce516 100644
--- a/.github/workflows/coverall.yml
+++ b/.github/workflows/coverall.yml
@@ -5,9 +5,6 @@ on:
branches:
- main
-env:
- DEFAULT_NETWORK: localhost
-
jobs:
test:
runs-on: ubuntu-latest
@@ -18,37 +15,22 @@ jobs:
- contracts
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18.x
+ cache: "yarn"
- - name: Get yarn cache directory path
- id: yarn-cache-dir-path
- run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
-
- - name: Restore yarn cache
- uses: actions/cache@v3
- id: yarn-cache
- with:
- path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-yarn-
-
- - name: Install dependencies
+ - name: Build monorepo
run: yarn
- - name: Build libraries
- run: yarn workspaces foreach --no-private run build
-
- name: Test code
run: yarn test:${{ matrix.tests }}:coverage
- name: Coveralls
- uses: coverallsapp/github-action@master
+ uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: run-${{ matrix.tests }}
@@ -60,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
- uses: coverallsapp/github-action@master
+ uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 4690ef0..46909a8 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -60,7 +60,7 @@ jobs:
fi
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
persist-credentials: false
diff --git a/.github/workflows/ephemeral.yml b/.github/workflows/ephemeral.yml
new file mode 100644
index 0000000..9c5c141
--- /dev/null
+++ b/.github/workflows/ephemeral.yml
@@ -0,0 +1,48 @@
+name: Ephemeral
+on:
+ schedule:
+ - cron: "0 */6 * * *"
+ workflow_dispatch:
+ inputs:
+ action:
+ description: "Action"
+ required: true
+ default: "spawn"
+ type: choice
+ options:
+ - spawn
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: false
+
+jobs:
+ deploy:
+ timeout-minutes: 5
+ runs-on: ubuntu-latest
+ env:
+ DATA: ${{ github.event.inputs.action || 'maintenance' }}
+ permissions:
+ id-token: write
+ contents: read
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: arn:aws:iam::490752553772:role/bandada-ephemeral-deploy-slc
+ role-duration-seconds: 900
+ aws-region: eu-central-1
+
+ - name: Launch instance
+ run: |
+ .github/scripts/run.sh ${{ env.DATA }} $GITHUB_REF_NAME $GITHUB_TRIGGERING_ACTOR $GITHUB_SHA
+
+ - name: Instance IP
+ run: |
+ .github/scripts/get_ip.sh ${{ env.DATA }} $GITHUB_TRIGGERING_ACTOR
diff --git a/.github/workflows/postgres.yml b/.github/workflows/postgres.yml
index 7dc5203..3eb9e92 100644
--- a/.github/workflows/postgres.yml
+++ b/.github/workflows/postgres.yml
@@ -35,7 +35,7 @@ jobs:
fi
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
persist-credentials: false
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c332988..85699f9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,29 +13,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
+ - uses: actions/checkout@v4
+
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18.x
+ cache: "yarn"
- - name: Get yarn cache directory path
- id: yarn-cache-dir-path
- run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
-
- - name: Restore yarn cache
- uses: actions/cache@v3
- id: yarn-cache
- with:
- path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-yarn-
-
- - name: Install dependencies
+ - name: Build monorepo
run: yarn
- run: yarn version:release
diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml
index 246934b..4b3f016 100644
--- a/.github/workflows/style.yml
+++ b/.github/workflows/style.yml
@@ -11,32 +11,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18.x
+ cache: "yarn"
- - name: Get yarn cache directory path
- id: yarn-cache-dir-path
- run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
-
- - name: Restore yarn cache
- uses: actions/cache@v3
- id: yarn-cache
- with:
- path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-yarn-
-
- - name: Install dependencies
+ - name: Build monorepo
run: yarn
- - name: Build
- run: yarn build
-
- name: Run Prettier
run: yarn prettier
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 11992ec..d3a0957 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,39 +6,21 @@ on:
branches:
- main
-env:
- DEFAULT_NETWORK: localhost
-
jobs:
test:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Install Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18.x
+ cache: "yarn"
- - name: Get yarn cache directory path
- id: yarn-cache-dir-path
- run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
-
- - name: Restore yarn cache
- uses: actions/cache@v3
- id: yarn-cache
- with:
- path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-yarn-
-
- - name: Install dependencies
+ - name: Build monorepo
run: yarn
- - name: Build libraries
- run: yarn workspaces foreach --no-private run build
-
- name: Test code
run: yarn test
diff --git a/README.md b/README.md
index 598699e..d35d66f 100644
--- a/README.md
+++ b/README.md
@@ -170,7 +170,7 @@ Please see the latest [documentation](https://pse-team.notion.site/Bandada-82d0d
## 🔧 Configuration
-### Prerequisities
+### Prerequisites
- [NodeJS](https://nodejs.org/en) >= v18.17.0
@@ -236,7 +236,7 @@ yarn test
## 🐳 Running in Docker
-### Prerequisities
+### Prerequisites
- [Docker](https://www.docker.com/) >= 4.26.1
- [docker-compose](https://docs.docker.com/compose/) >= 2.24.2
diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts
index cbd02fe..ec94a0a 100644
--- a/apps/api/src/main.ts
+++ b/apps/api/src/main.ts
@@ -57,7 +57,70 @@ async function bootstrap() {
"https://raw.githubusercontent.com/privacy-scaling-explorations/bandada/main/apps/dashboard/src/assets/favicon.ico",
customSiteTitle: "Bandada API Docs",
customCss: `.topbar-wrapper img {content:url('https://raw.githubusercontent.com/privacy-scaling-explorations/bandada/d5268274cbb93f73a1960e131bff0d2bf1eacea9/apps/dashboard/src/assets/icon1.svg'); width:60px; height:auto;}
- .swagger-ui .topbar { background-color: transparent; } small.version-stamp { display: none !important; }`
+ .swagger-ui .topbar { background-color: transparent; } small.version-stamp { display: none !important; }`,
+ customJsStr: `
+ // Add a custom title to the right side of the Swagger UI page
+ document.addEventListener('DOMContentLoaded', function() {
+ const customTitle = document.createElement('div');
+ customTitle.style.position = 'absolute';
+ customTitle.style.top = '27px';
+ customTitle.style.padding = '10px';
+ customTitle.style.color = 'black';
+ customTitle.style.fontSize = '18px';
+ customTitle.style.padding = '0 20px';
+ customTitle.style.maxWidth = '1460px';
+ customTitle.style.display = 'flex';
+ customTitle.style.justifyContent = 'end';
+ customTitle.style.width = '100%';
+
+
+ // Create a hyperlink element
+ const link = document.createElement('a');
+ link.href = 'https://github.com/privacy-scaling-explorations/bandada';
+ link.rel = 'noreferrer noopener nofollow';
+ link.target = '_blank'
+ link.style.color = 'grey';
+ link.style.display = 'flex';
+
+ // Create a text node for the link text
+ const linkText = document.createTextNode('Github');
+
+ // Append the text node to the link
+ link.appendChild(linkText);
+
+ // Create an SVG element for the GitHub icon
+ const githubIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+ githubIcon.setAttribute('width', '24');
+ githubIcon.setAttribute('height', '24');
+ githubIcon.setAttribute('viewBox', '0 0 20 20');
+ githubIcon.setAttribute('fill', 'currentColor');
+
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ path.setAttribute('d', 'M8 .153C3.589.153 0 3.742 0 8.153c0 3.436 2.223 6.358 5.307 7.408.387.071.53-.168.53-.374 0-.185-.007-.674-.01-1.322-2.039.445-2.47-.979-2.47-.979-.334-.849-.815-1.075-.815-1.075-.667-.457.05-.448.05-.448.739.052 1.13.76 1.13.76.656 1.124 1.719.799 2.134.61.067-.478.256-.8.466-.98-1.63-.184-3.34-.815-3.34-3.627 0-.8.287-1.457.754-1.969-.076-.185-.327-.932.072-1.943 0 0 .618-.198 2.03.752a6.74 6.74 0 0 1 1.8-.245c.61.003 1.226.082 1.8.245 1.41-.95 2.027-.752 2.027-.752.4 1.011.148 1.758.073 1.943.47.512.754 1.17.754 1.969 0 2.82-1.712 3.44-3.35 3.623.264.227.497.672.497 1.356 0 .977-.009 1.764-.009 2.004 0 .207.141.449.544.373C13.775 14.511 16 11.59 16 8.154 16 3.743 12.411 .154 8 .154z');
+
+ // Append the path to the GitHub icon
+ githubIcon.appendChild(path);
+
+ // Append the GitHub icon to the link
+ link.insertBefore(githubIcon, link.firstChild);
+
+ // Apply some padding to create space between the icon and the text
+ link.style.paddingLeft = '8px';
+
+ // Append the link to the custom title
+ customTitle.appendChild(link);
+
+ const parentDiv = document.createElement('div');
+ parentDiv.style.display = 'flex';
+ parentDiv.style.justifyContent = 'center';
+ parentDiv.style.width = 'auto';
+
+
+ parentDiv.appendChild(customTitle)
+
+ document.body.appendChild(parentDiv);
+ });
+`
}
SwaggerModule.setup("/", app, document, configUI)
diff --git a/apps/contracts/contracts/README.md b/apps/contracts/contracts/README.md
index d11a573..51c4141 100644
--- a/apps/contracts/contracts/README.md
+++ b/apps/contracts/contracts/README.md
@@ -34,7 +34,7 @@
🔎 Issues
|
-
+
🗣️ Chat & Support
diff --git a/apps/dashboard/src/pages/group.tsx b/apps/dashboard/src/pages/group.tsx
index 0af1602..ac351a6 100644
--- a/apps/dashboard/src/pages/group.tsx
+++ b/apps/dashboard/src/pages/group.tsx
@@ -57,6 +57,13 @@ export default function GroupPage(): JSX.Element {
const [_removeGroupName, setRemoveGroupName] = useState("")
const [_selectedMembers, setSelectedMembers] = useState([])
const { admin } = useContext(AuthContext)
+ const isGroupAdmin = !!(
+ admin &&
+ _group &&
+ (groupType === "off-chain"
+ ? _group.admin === admin.id
+ : _group.admin === admin.address.toLowerCase())
+ )
useEffect(() => {
;(async () => {
@@ -391,82 +398,87 @@ ${memberIds.join("\n")}
/>
)}
- {groupType === "off-chain" && !_group.credentials && (
-
-
- Use API key
+ {groupType === "off-chain" &&
+ !_group.credentials &&
+ isGroupAdmin && (
+
+
+ Use API key
-
- onApiAccessToggle(event.target.checked)
- }
- />
-
+
+ onApiAccessToggle(
+ event.target.checked
+ )
+ }
+ />
+
-
- Connect your app to your group using an API key.
-
+
+ Connect your app to your group using an API
+ key.
+
- {_group.apiEnabled && (
- <>
-
-
+ {_group.apiEnabled && (
+ <>
+
+
-
-
-
- e.preventDefault()
+
+
- }
- />
-
-
-
+ closeOnClick={false}
+ hasArrow
+ >
+
+ e.preventDefault()
+ }
+ icon={
+
+ }
+ />
+
+
+
-
- >
- )}
-
- )}
+
+ >
+ )}
+
+ )}
- {_group.type === "off-chain" && (
+ {_group.type === "off-chain" && isGroupAdmin && (
Add member
@@ -579,18 +585,19 @@ ${memberIds.join("\n")}
>
- {_group.type === "off-chain" && (
-
- toggleMemberSelection(
+ {_group.type === "off-chain" &&
+ isGroupAdmin && (
+
- )}
+ )}
+ onChange={() =>
+ toggleMemberSelection(
+ memberId
+ )
+ }
+ />
+ )}
- {_group.type === "off-chain" && (
-
- )}
+ variant="link"
+ />
+
+
+ }
+ onClick={() =>
+ removeMember(
+ memberId
+ )
+ }
+ >
+ Remove
+
+
+
+ )}
))
)}
- {_group.type === "off-chain" && (
+ {_group.type === "off-chain" && isGroupAdmin && (