Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: docker #29

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
**/node_modules
**/.next
**/.turbo
**/dist
**/.git
**/.env*
**/coverage
60 changes: 60 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Use the official Bun image
FROM --platform=linux/amd64 oven/bun:1.1.38

# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
build-essential \
python3 \
make \
tar \
git

# Install Rust and Nargo dependencies - Updated for ARM compatibility
RUN apt-get update && apt-get install -y curl build-essential && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
. "$HOME/.cargo/env" && \
# Install Nargo v0.39.0 with architecture detection
ARCH=$(uname -m) && \
if [ "$ARCH" = "aarch64" ]; then \
GITHUB_URL="https://github.com/noir-lang/noir/releases/download/v0.39.0/nargo-aarch64-apple-darwin.tar.gz"; \
else \
GITHUB_URL="https://github.com/noir-lang/noir/releases/download/v0.39.0/nargo-x86_64-unknown-linux-gnu.tar.gz"; \
fi && \
curl -L "${GITHUB_URL}" -o nargo.tar.gz && \
tar -xzf nargo.tar.gz && \
mv nargo /usr/local/bin/ && \
chmod +x /usr/local/bin/nargo && \
rm nargo.tar.gz

# Add Rust to PATH
ENV PATH="/root/.cargo/bin:${PATH}"

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json .
COPY bun.lockb .
COPY tsconfig.json .
COPY tsconfig.base.json .

# Copy workspace packages
COPY packages ./packages
COPY apps ./apps

# Clear Bun's cache and install dependencies
RUN mkdir -p ~/.bun/install/cache && \
chmod -R 777 ~/.bun && \
bun install --no-cache

# Set environment variables
ENV NODE_ENV=production
ENV PORT=3001
ENV HOST=0.0.0.0
ENV PATH="/usr/local/bin:${PATH}"

# Expose the port
EXPOSE 3001

CMD bun run zk:build && bun run api:start
25 changes: 25 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# docker-compose.yml
services:
api:
build: .
command: ["bun", "run", "api:start"]
ports:
- "3001:3001"
env_file:
- .env
networks:
- app_network
volumes:
- ./packages/api:/app/packages/api
- /app/packages/api/node_modules
restart: unless-stopped

updates:
build: .
command: ["bun", "run", "updates"]
env_file:
- .env

networks:
app_network:
driver: bridge
8 changes: 4 additions & 4 deletions ecosystem.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ module.exports = {
apps: [
{
name: "rumourcast-api",
script: "/root/.bun/bin/bun",
script: "bun",
args: "run packages/api/src/index.ts",
cwd: "/root/rumourcast",
cwd: "/app",
watch: false,
env: {
NODE_ENV: "production",
Expand All @@ -21,9 +21,9 @@ module.exports = {
},
{
name: "rumourcast-updates",
script: "/root/.bun/bin/bun",
script: "bun",
args: "run packages/api/scripts/updates.ts",
cwd: "/root/rumourcast",
cwd: "/app",
watch: false,
env: {
NODE_ENV: "production",
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/actions/create-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class CreatePostAction {

async execute() {
const { text, embeds, quote, channel, parent, revealHash } = this.data
console.log('api/src/actions/create-post execute:', this.data)

const response = await neynar.createCast({
fid: this.metadata.fid,
Expand All @@ -36,6 +37,7 @@ export class CreatePostAction {
parent,
})

console.log('api/src/actions/create-post execute: neynarResponse', response)
if (!response.success) {
throw new Error('Failed to create cast')
}
Expand All @@ -47,6 +49,7 @@ export class CreatePostAction {
reveal_hash: this.data.revealHash,
})

console.log('api/src/actions/create-post execute: trying createPostCredentials', this.data.roots)
await createPostCredentials(response.cast.hash, this.data.roots)

return {
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export const getAction = async (actionId: string, proofs: ProofData[], data: any
const roots = []
for (const proof of proofs) {
const verified = await merkleMembership.verify(proof)
// if (!verified) {
// throw new Error('Invalid proof')
// }
if (!verified) {
throw new Error('Invalid proof')
}

roots.push(proof.publicInputs[0])
}
Expand Down
11 changes: 8 additions & 3 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { createElysia } from './utils'
import { Elysia } from 'elysia'
import cors from '@elysiajs/cors'
import { actionsRoutes } from './routes/actions'
import { merkleTreeRoutes } from './routes/merkle-tree'
import { postsRoutes } from './routes/posts'
import { feedsRoutes } from './routes/feeds'
import { uploadRoutes } from './routes/upload'
import { farcasterRoutes } from './routes/farcaster'

const app = createElysia()
const app = new Elysia()
.use(cors())
.use(actionsRoutes)
.use(merkleTreeRoutes)
.use(postsRoutes)
.use(feedsRoutes)
.use(uploadRoutes)
.use(farcasterRoutes)

app.listen(3001)
app.listen({
port: process.env.PORT || 3001,
hostname: '0.0.0.0',
})

console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`)
3 changes: 2 additions & 1 deletion packages/api/src/routes/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export const actionsRoutes = createElysia({ prefix: '/actions' }).post(
proof: new Uint8Array(proof.proof),
publicInputs: proof.publicInputs,
}))
const action = await getAction(body.actionId, proofs, body.data)

try {
const action = await getAction(body.actionId, proofs, body.data)

const response = await action.execute()

await logActionExecution({
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/services/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class RedisService {
}

async setMerkleTree(key: string, tree: string) {
await this.client.set(key, tree)
await this.client.setex(key, 600, tree)
}

async getMerkleTreeForCredential(credentialId: string) {
Expand All @@ -49,7 +49,7 @@ export class RedisService {

async setMerkleTreeForCredential(credentialId: string, tree: string) {
const key = `merkle-tree:credential:${credentialId}`
await this.client.set(key, tree)
await this.client.setex(key, 600, tree)
}

async actionOccurred(actionId: string, hash: string) {
Expand Down
13 changes: 12 additions & 1 deletion packages/api/src/services/simplehash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,26 @@ class SimplehashService {
minBalance,
}: { chainId: number; tokenAddress: string; minBalance: bigint }) {
const owners: `0x${string}`[] = []
console.log(`[SimplehashService] Fetching token owners for:`, {
chainId,
tokenAddress,
minBalance: minBalance.toString()
})

let cursor = ''
let totalFetched = 0
while (true) {
const data = await this.getTopWalletsForFungible(chainId, tokenAddress, cursor)
totalFetched += data.owners.length

console.log(`[SimplehashService] Fetched ${data.owners.length} owners (total: ${totalFetched})`)

for (const owner of data.owners) {
if (BigInt(owner.quantity_string) >= minBalance) {
const balance = BigInt(owner.quantity_string)
if (balance >= minBalance) {
owners.push(owner.owner_address.toLowerCase() as `0x${string}`)
} else {
console.log(`[SimplehashService] Stopping at ${owners.length} qualifying holders (min balance: ${minBalance.toString()})`)
return owners
}
}
Expand Down
13 changes: 12 additions & 1 deletion packages/react/src/hooks/use-credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@ export function useCredentials(sdk: AnonWorldSDK) {
if (!address) return

try {
const signature = await signMessageAsync({ message: credentialId })
console.log('Requesting signature for credential:', credentialId)
const signature = await signMessageAsync({
message: credentialId
}).catch(error => {
console.error('Signature request failed:', error)
throw new Error('Failed to get wallet signature')
})
if (!signature) {
throw new Error('No signature received')
}

console.log('Got signature, verifying credential...')
const proof = await sdk.verifyCredential(credentialId, {
address,
signature,
Expand Down