Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/devnet-deploys.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ env:
TF_VAR_FORK_MNEMONIC: ${{ secrets.FORK_MNEMONIC }}
TF_VAR_INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }}
TF_VAR_FAUCET_ACCOUNT_INDEX: 5
TF_VAR_BOT_API_KEY: ${{ secrets.BOT_API_KEY }}
TF_VAR_BOT_PRIVATE_KEY: ${{ secrets.BOT_PRIVATE_KEY }}
CONTRACT_S3_BUCKET: s3://aztec-devnet-deployments

jobs:
Expand Down Expand Up @@ -258,3 +260,29 @@ jobs:
run: |
terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-faucet"
terraform apply -input=false -auto-approve

deploy-bot:
runs-on: ubuntu-latest
needs: [terraform_deploy, bootstrap]
steps:
- uses: actions/checkout@v4
with:
ref: "${{ env.GIT_COMMIT }}"
fetch-depth: 0
- uses: ./.github/ci-setup-action
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.5

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2

- name: Deploy transactions bot
working-directory: ./yarn-project/aztec/terraform/bot
run: |
terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/bot"
terraform apply -input=false -auto-approve
7 changes: 5 additions & 2 deletions yarn-project/aztec/src/cli/cmds/start_bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function startBot(
return services;
}

export async function addBot(
export function addBot(
options: any,
services: ServerList,
signalHandlers: (() => Promise<void>)[],
Expand All @@ -37,7 +37,10 @@ export async function addBot(

const botRunner = new BotRunner(config, { pxe: deps.pxe });
const botServer = createBotRunnerRpcServer(botRunner);
await botRunner.start();
if (!config.noStart) {
void botRunner.start(); // Do not block since bot setup takes time
}
services.push({ bot: botServer });
signalHandlers.push(botRunner.stop);
return Promise.resolve();
}
186 changes: 186 additions & 0 deletions yarn-project/aztec/terraform/bot/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
terraform {
backend "s3" {
bucket = "aztec-terraform"
region = "eu-west-2"
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.74.2"
}
}
}

# Define provider and region
provider "aws" {
region = "eu-west-2"
}

data "terraform_remote_state" "aztec2_iac" {
backend = "s3"
config = {
bucket = "aztec-terraform"
key = "aztec2/iac"
region = "eu-west-2"
}
}

data "terraform_remote_state" "setup_iac" {
backend = "s3"
config = {
bucket = "aztec-terraform"
key = "setup/setup-iac"
region = "eu-west-2"
}
}

resource "aws_cloudwatch_log_group" "aztec-bot-log-group" {
name = "/fargate/service/${var.DEPLOY_TAG}/aztec-bot"
retention_in_days = 14
}

resource "aws_service_discovery_service" "aztec-bot" {
name = "${var.DEPLOY_TAG}-aztec-bot"

health_check_custom_config {
failure_threshold = 1
}

dns_config {
namespace_id = data.terraform_remote_state.setup_iac.outputs.local_service_discovery_id

dns_records {
ttl = 60
type = "A"
}

dns_records {
ttl = 60
type = "SRV"
}

routing_policy = "MULTIVALUE"
}

# Terraform just fails if this resource changes and you have registered instances.
provisioner "local-exec" {
when = destroy
command = "${path.module}/../servicediscovery-drain.sh ${self.id}"
}
}

locals {
api_prefix = "/${var.DEPLOY_TAG}/aztec-bot/${var.BOT_API_KEY}"
}

resource "aws_ecs_task_definition" "aztec-bot" {
family = "${var.DEPLOY_TAG}-aztec-bot"
network_mode = "awsvpc"
cpu = 2048
memory = 4096
requires_compatibilities = ["FARGATE"]
execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn
task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn

container_definitions = jsonencode([
{
name = "${var.DEPLOY_TAG}-aztec-bot"
image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}"
command = ["start", "--bot"]
essential = true
portMappings = [
{
containerPort = 80
hostPort = 80
}
]
environment = [
{ name = "BOT_PRIVATE_KEY", value = var.BOT_PRIVATE_KEY },
{ name = "BOT_NO_START", value = "true" },
{ name = "BOT_PXE_URL", value = "http://${var.DEPLOY_TAG}-aztec-pxe-1.local/${var.DEPLOY_TAG}/aztec-pxe-1/${var.API_KEY}" },
{ name = "BOT_TX_INTERVAL_SECONDS", value = 300 },
{ name = "AZTEC_PORT", value = "80" },
{ name = "API_PREFIX", value = local.api_prefix },
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.aztec-bot-log-group.name
"awslogs-region" = "eu-west-2"
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}

resource "aws_ecs_service" "aztec-bot" {
name = "${var.DEPLOY_TAG}-aztec-bot"
cluster = data.terraform_remote_state.setup_iac.outputs.ecs_cluster_id
launch_type = "FARGATE"
desired_count = 1
deployment_maximum_percent = 100
deployment_minimum_healthy_percent = 0
platform_version = "1.4.0"
force_new_deployment = true

network_configuration {
subnets = [
data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id,
data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id
]
security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id]
}

load_balancer {
target_group_arn = aws_alb_target_group.bot_http.arn
container_name = "${var.DEPLOY_TAG}-aztec-bot"
container_port = 80
}

service_registries {
registry_arn = aws_service_discovery_service.aztec-bot.arn
container_name = "${var.DEPLOY_TAG}-aztec-bot"
container_port = 80
}

task_definition = aws_ecs_task_definition.aztec-bot.family
}

resource "aws_alb_target_group" "bot_http" {
name = "${var.DEPLOY_TAG}-bot-http"
port = 80
protocol = "HTTP"
target_type = "ip"
vpc_id = data.terraform_remote_state.setup_iac.outputs.vpc_id
deregistration_delay = 5

health_check {
path = "${local.api_prefix}/status"
matcher = 200
interval = 10
healthy_threshold = 2
unhealthy_threshold = 5
timeout = 5
}

tags = {
name = "${var.DEPLOY_TAG}-bot-http"
}
}

resource "aws_lb_listener_rule" "bot_api" {
listener_arn = data.terraform_remote_state.aztec2_iac.outputs.alb_listener_arn
priority = 700

action {
type = "forward"
target_group_arn = aws_alb_target_group.bot_http.arn
}

condition {
path_pattern {
values = ["${local.api_prefix}*"]
}
}
}
19 changes: 19 additions & 0 deletions yarn-project/aztec/terraform/bot/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
variable "DEPLOY_TAG" {
type = string
}

variable "DOCKERHUB_ACCOUNT" {
type = string
}

variable "API_KEY" {
type = string
}

variable "BOT_API_KEY" {
type = string
}

variable "BOT_PRIVATE_KEY" {
type = string
}
5 changes: 5 additions & 0 deletions yarn-project/bot/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export type BotConfig = {
publicTransfersPerTx: number;
/** How to handle fee payments. */
feePaymentMethod: 'native' | 'none';
/** True to not automatically setup or start the bot on initialization. */
noStart: boolean;
};

export function getBotConfigFromEnv(): BotConfig {
Expand All @@ -29,6 +31,7 @@ export function getBotConfigFromEnv(): BotConfig {
BOT_TX_INTERVAL_SECONDS,
BOT_PRIVATE_TRANSFERS_PER_TX,
BOT_PUBLIC_TRANSFERS_PER_TX,
BOT_NO_START,
} = process.env;
if (BOT_FEE_PAYMENT_METHOD && !['native', 'none'].includes(BOT_FEE_PAYMENT_METHOD)) {
throw new Error(`Invalid bot fee payment method: ${BOT_FEE_PAYMENT_METHOD}`);
Expand All @@ -45,6 +48,7 @@ export function getBotConfigFromEnv(): BotConfig {
privateTransfersPerTx: BOT_PRIVATE_TRANSFERS_PER_TX ? parseInt(BOT_PRIVATE_TRANSFERS_PER_TX) : undefined,
publicTransfersPerTx: BOT_PUBLIC_TRANSFERS_PER_TX ? parseInt(BOT_PUBLIC_TRANSFERS_PER_TX) : undefined,
feePaymentMethod: BOT_FEE_PAYMENT_METHOD ? (BOT_FEE_PAYMENT_METHOD as 'native' | 'none') : undefined,
noStart: BOT_NO_START ? ['1', 'true'].includes(BOT_NO_START) : undefined,
});
}

Expand All @@ -58,6 +62,7 @@ export function getBotDefaultConfig(overrides: Partial<BotConfig> = {}): BotConf
privateTransfersPerTx: 1,
publicTransfersPerTx: 1,
feePaymentMethod: 'none',
noStart: false,
...compact(overrides),
};
}