Skip to content

Commit

Permalink
Merge branch 'staging'
Browse files Browse the repository at this point in the history
  • Loading branch information
KONFeature committed Dec 17, 2024
2 parents 834607d + 5c25255 commit ac10522
Show file tree
Hide file tree
Showing 15 changed files with 488 additions and 600 deletions.
35 changes: 5 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,16 @@
# Frak Indexer
# Infra blockchain

Frak Indexer is an open-source project designed to index events from Frak smart contracts on the Arbitrum network. It combines the power of Ponder for building robust crypto apps with eRPC for efficient RPC caching and load balancing, all deployed using SST (Serverless Stack) on AWS infrastructure.
This repository contain all the blockchain related infra code for the [Frak](https://frak.id) project.

## Architecture Overview

The Frak Indexer consists of two main components:

1. **Ponder Service**: An open-source backend framework for building robust, performant, and maintainable crypto apps. In this project, it's used for indexing blockchain events from Frak smart contracts.
1.**[eRPC](https://github.com/erpc/erpc)**: RPC request caching and load balancing across multiple node providers

2. **eRPC Service**: A fault-tolerant EVM RPC load balancer with reorg-aware permanent caching and auto-discovery of node providers. It provides a layer of caching on top of other RPCs, enhancing performance and reliability.
2.**[Ponder](https://github.com/ponder-sh/ponder)**: Indexing blockchain events from Frak smart contracts.

Both services are deployed as containerized applications on AWS ECS (Elastic Container Service) using Fargate, with an Application Load Balancer (ALB) routing traffic between them.

## Deployment Architecture

- **VPC**: A dedicated VPC is created to house all components.
- **ECS Cluster**: Both Ponder and eRPC services run in the same ECS cluster.
- **Application Load Balancer**:
- Listens on port 80
- Routes traffic based on path patterns:
- `/rpc-main/*` -> eRPC service (for cached RPC requests)
- `/*` (all other paths) -> Ponder service (for indexed data access)
- **CloudFront Distribution**: Sits in front of the ALB to provide additional caching and global content delivery.

## Key Features

- **Efficient Indexing**: Utilizes Ponder to create a robust and maintainable indexing solution for Frak smart contract events.
- **Optimized RPC Access**: eRPC provides caching and load balancing across multiple RPC providers, improving performance and reliability.
- **Scalable**: Utilizes AWS Fargate for serverless container management.
- **High Availability**: Deployed across multiple availability zones.
- **Secure**: Uses AWS security groups and VPC for network isolation.
- **Observable**: Includes CloudWatch logs and metrics for monitoring.
- **Maintainable**: Infrastructure as Code (IaC) using SST for easy updates and version control.

## Contributing

We welcome contributions to the Frak Indexer project!
Both services are deployed as containerized applications on AWS ECS (Elastic Container Service) using Fargate, with a master Application Load Balancer (ALB) routing traffic between them.

## License

Expand Down
Binary file modified bun.lockb
Binary file not shown.
15 changes: 15 additions & 0 deletions infra/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as aws from "@pulumi/aws";
import { Output } from "@pulumi/pulumi";

// Get the VPC
const { id: vpcId } = await aws.ec2.getVpc({
Expand All @@ -10,3 +11,17 @@ export const vpc = sst.aws.Vpc.get("MasterVpc", vpcId);
export const cluster = await aws.ecs.getCluster({
clusterName: `master-cluster-${$app.stage}`,
});

/**
* Build the postgres DB for the current env
*/
export const database =
$app.stage !== "production"
? sst.aws.Postgres.get("blockchain", {
id: "frak-indexer-production-blockchaininstance",
})
: new sst.aws.Postgres("blockchain", {
vpc: Output.create(vpc).apply((v) => ({
subnets: v.privateSubnets,
})),
});
19 changes: 15 additions & 4 deletions infra/erpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as aws from "@pulumi/aws";
import { all } from "@pulumi/pulumi";
import { cluster, vpc } from "./common.ts";
import { cluster, database, vpc } from "./common.ts";
import { ServiceTargets } from "./components/ServiceTargets.ts";
import { SstService } from "./utils.ts";

Expand Down Expand Up @@ -32,6 +32,19 @@ const erpcServiceTargets = new ServiceTargets("ErpcServiceDomain", {
},
});

/**
* Build the erpc database URL
*/
const dbUrl = all([
database.host,
database.port,
database.username,
database.password,
database.database,
]).apply(([host, port, username, password, database]) => {
return `postgres://${username}:${password}@${host}:${port}/${database}`;
});

// Create the erpc service (only on prod stage)
export const erpcService = new SstService("Erpc", {
vpc,
Expand Down Expand Up @@ -60,6 +73,7 @@ export const erpcService = new SstService("Erpc", {
// Env
environment: {
ERPC_LOG_LEVEL: "warn",
ERPC_DATABASE_URL: dbUrl,
},
// SSM secrets
ssm: {
Expand All @@ -79,9 +93,6 @@ export const erpcService = new SstService("Erpc", {
"arn:aws:ssm:eu-west-1:262732185023:parameter/sst/frak-indexer/.fallback/Secret/PONDER_RPC_SECRET/value",
NEXUS_RPC_SECRET:
"arn:aws:ssm:eu-west-1:262732185023:parameter/sst/frak-indexer/.fallback/Secret/NEXUS_RPC_SECRET/value",
// Postgres db
ERPC_DATABASE_URL:
"arn:aws:ssm:eu-west-1:262732185023:parameter/indexer/sst/Secret/ERPC_DATABASE_URL/value",
},
// Tell the service registry to forward requests to the 8080 port
serviceRegistry: {
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@
"engines": {
"node": ">=18.14"
},
"packageManager": "[email protected]",
"workspaces": ["packages/*"]
}
18 changes: 12 additions & 6 deletions packages/erpc/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# Base image is erpc
FROM ghcr.io/erpc/erpc:0.0.24
# Config bundler step
FROM oven/bun:latest AS bundler
RUN mkdir -p /temp/dev

# Copy the config
COPY erpc.yaml /root/erpc.yaml
# Bundle everything in a single erpc.js file
COPY . /temp/dev
RUN cd /temp/dev && bun install --production
RUN cd /temp/dev && bun build --outfile ./erpc.js --minify --target node --external "@erpc-cloud/*" src/index.ts

EXPOSE 8080/tcp
EXPOSE 4001/tcp
# Final image
FROM ghcr.io/erpc/erpc:main AS FINAL

# Copy the bundled config
COPY --from=bundler ./temp/dev/erpc.js /root/erpc.js

# Run the server
CMD ["./erpc-server"]
Loading

0 comments on commit ac10522

Please sign in to comment.