Skip to content

Job queue #271

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

Merged
merged 9 commits into from
Jun 14, 2025
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
190 changes: 90 additions & 100 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,133 +3,123 @@
# =============================================================================
# Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
LOG_LEVEL=INFO

# Backend type (supabase, cloudflare)
AIBTC_BACKEND="supabase"

# Network configuration (mainnet, testnet)
NETWORK="testnet"

# WebSocket settings
WEBSOCKETS_MAX_LINE_LENGTH=31928
# Network Configuration
NETWORK=testnet

# =============================================================================
# Database Configuration (Supabase)
# =============================================================================
AIBTC_SUPABASE_URL="https://hellowowld.supabase.co"
AIBTC_SUPABASE_SERVICE_KEY="your-service-key"
AIBTC_SUPABASE_BUCKET_NAME="your-bucket-name"
# Database connection details
AIBTC_SUPABASE_USER="user"
AIBTC_SUPABASE_PASSWORD="user"
AIBTC_SUPABASE_HOST="localhost"
AIBTC_SUPABASE_PORT="5432"
AIBTC_SUPABASE_DBNAME="postgres"
AIBTC_BACKEND=supabase
AIBTC_SUPABASE_USER=your_supabase_user
AIBTC_SUPABASE_PASSWORD=your_supabase_password
AIBTC_SUPABASE_HOST=your_supabase_host
AIBTC_SUPABASE_PORT=5432
AIBTC_SUPABASE_DBNAME=your_database_name
AIBTC_SUPABASE_URL=https://your-project.supabase.co
AIBTC_SUPABASE_SERVICE_KEY=your_supabase_service_key
AIBTC_SUPABASE_BUCKET_NAME=your_bucket_name

# =============================================================================
# External API Endpoints & Keys
# Backend Wallet Configuration
# =============================================================================
# Webhook Configuration
AIBTC_WEBHOOK_URL="https://core-staging.aibtc.dev/webhooks/chainhook"
AIBTC_WEBHOOK_AUTH_TOKEN="Bearer your-webhook-auth-token"
AIBTC_BACKEND_WALLET_SEED_PHRASE=your_wallet_seed_phrase
AIBTC_BACKEND_WALLET_PRIVATE_KEY=your_wallet_private_key
AIBTC_BACKEND_WALLET_PUBLIC_KEY=your_wallet_public_key
AIBTC_BACKEND_WALLET_ADDRESS=your_wallet_address

# Platform APIs
AIBTC_PLATFORM_API_URL="https://api.platform.hiro.so"
AIBTC_HIRO_API_URL=https://api.hiro.so
HIRO_API_KEY="your-hiro-api-key"
AIBTC_ALEX_BASE_URL=https://api.alexgo.io/
AIBTC_VELAR_BASE_URL="https://gateway.velar.network/"
# =============================================================================
# Twitter Configuration
# =============================================================================
AIBTC_TWITTER_ENABLED=false
AIBTC_TWITTER_INTERVAL_SECONDS=120
AIBTC_TWITTER_CONSUMER_KEY=your_twitter_consumer_key
AIBTC_TWITTER_CONSUMER_SECRET=your_twitter_consumer_secret
AIBTC_TWITTER_CLIENT_ID=your_twitter_client_id
AIBTC_TWITTER_CLIENT_SECRET=your_twitter_client_secret
AIBTC_TWITTER_ACCESS_TOKEN=your_twitter_access_token
AIBTC_TWITTER_ACCESS_SECRET=your_twitter_access_secret
AIBTC_TWITTER_USERNAME=your_twitter_username
AIBTC_TWITTER_AUTOMATED_USER_ID=your_automated_user_id
AIBTC_TWITTER_WHITELISTED=user1,user2,user3

# AI Services
OPENAI_MODEL_NAME="gpt-4.1"
OPENAI_API_KEY="sk-proj-your-api-key-here"
# For local model deployment
# OPENAI_API_BASE="http://localhost:5000"
# =============================================================================
# Telegram Configuration
# =============================================================================
AIBTC_TELEGRAM_BOT_TOKEN=your_telegram_bot_token
AIBTC_TELEGRAM_BOT_ENABLED=false

# Market Data APIs
SERPER_API_KEY="your-serper-api-key"
AIBTC_CMC_API_KEY='cmc-api-key'
AIBTC_LUNARCRUSH_API_KEY="lunarcrush-api-key"
AIBTC_LUNARCRUSH_BASE_URL="https://lunarcrush.com/api/v2"
# =============================================================================
# Discord Configuration
# =============================================================================
AIBTC_DISCORD_WEBHOOK_URL_PASSED=https://discord.com/api/webhooks/your_passed_webhook
AIBTC_DISCORD_WEBHOOK_URL_FAILED=https://discord.com/api/webhooks/your_failed_webhook

# =============================================================================
# Task Scheduling Configuration
# Job Scheduler Configuration (NEW NAMING - matches job types exactly)
# =============================================================================
# Schedule Sync

# General Scheduler Settings
AIBTC_SCHEDULE_SYNC_ENABLED=false
AIBTC_SCHEDULE_SYNC_INTERVAL_SECONDS=60

# DAO Processing Pipeline
# Step 1: Process DAO deployments
AIBTC_DAO_RUNNER_ENABLED=false
AIBTC_DAO_RUNNER_INTERVAL_SECONDS=30
# Agent Account Deployer Job
AIBTC_AGENT_ACCOUNT_DEPLOYER_ENABLED=false
AIBTC_AGENT_ACCOUNT_DEPLOYER_INTERVAL_SECONDS=60

# Step 2: Generate tweets for completed DAOs
AIBTC_DAO_TWEET_RUNNER_ENABLED=false
AIBTC_DAO_TWEET_RUNNER_INTERVAL_SECONDS=30
# Chain State Monitor Job
AIBTC_CHAIN_STATE_MONITOR_ENABLED=true
AIBTC_CHAIN_STATE_MONITOR_INTERVAL_SECONDS=300

# Step 3: Post generated tweets
AIBTC_TWEET_RUNNER_ENABLED=false
AIBTC_TWEET_RUNNER_INTERVAL_SECONDS=30
# DAO Deployment Job
AIBTC_DAO_DEPLOYMENT_ENABLED=false
AIBTC_DAO_DEPLOYMENT_INTERVAL_SECONDS=60

# Step 4: Process DAO proposal votes
AIBTC_DAO_PROPOSAL_VOTE_RUNNER_ENABLED=false
AIBTC_DAO_PROPOSAL_VOTE_RUNNER_INTERVAL_SECONDS=60
# DAO Deployment Tweet Job
AIBTC_DAO_DEPLOYMENT_TWEET_ENABLED=false
AIBTC_DAO_DEPLOYMENT_TWEET_INTERVAL_SECONDS=60

# Step 5: Process DAO proposal conclusions
AIBTC_DAO_PROPOSAL_CONCLUDE_RUNNER_ENABLED=false
AIBTC_DAO_PROPOSAL_CONCLUDE_RUNNER_INTERVAL_SECONDS=60
AIBTC_DAO_PROPOSAL_CONCLUDE_RUNNER_WALLET_ID="your-wallet-id"
# DAO Proposal Conclude Job
AIBTC_DAO_PROPOSAL_CONCLUDE_ENABLED=false
AIBTC_DAO_PROPOSAL_CONCLUDE_INTERVAL_SECONDS=60

# Step 6:
AIBTC_DAO_PROPOSAL_EVALUATION_RUNNER_ENABLED=false
AIBTC_DAO_PROPOSAL_EVALUATION_RUNNER_INTERVAL_SECONDS=60
# DAO Proposal Embedder Job
AIBTC_DAO_PROPOSAL_EMBEDDER_ENABLED=false
AIBTC_DAO_PROPOSAL_EMBEDDER_INTERVAL_SECONDS=300

# Step 6: Process agent account deployments
AIBTC_AGENT_ACCOUNT_DEPLOY_RUNNER_ENABLED=false
AIBTC_AGENT_ACCOUNT_DEPLOY_RUNNER_INTERVAL_SECONDS=60
AIBTC_AGENT_ACCOUNT_DEPLOY_RUNNER_WALLET_ID="your-wallet-id"
# DAO Proposal Evaluation Job
AIBTC_DAO_PROPOSAL_EVALUATION_ENABLED=false
AIBTC_DAO_PROPOSAL_EVALUATION_INTERVAL_SECONDS=60

# =============================================================================
# Social Media Integration
# =============================================================================
# Twitter Configuration
AIBTC_TWITTER_ENABLED=false
AIBTC_TWITTER_INTERVAL_SECONDS=120
# DAO Proposal Vote Job
AIBTC_DAO_PROPOSAL_VOTE_ENABLED=false
AIBTC_DAO_PROPOSAL_VOTE_INTERVAL_SECONDS=60

# Twitter API Credentials
AIBTC_TWITTER_CONSUMER_KEY="your-twitter-consumer-key"
AIBTC_TWITTER_CONSUMER_SECRET="your-twitter-consumer-secret"
AIBTC_TWITTER_ACCESS_TOKEN="your-twitter-access-token"
AIBTC_TWITTER_ACCESS_SECRET="your-twitter-access-secret"
AIBTC_TWITTER_CLIENT_ID="your-twitter-client-id"
AIBTC_TWITTER_CLIENT_SECRET="your-twitter-client-secret"

# Twitter User Configuration
AIBTC_TWITTER_AUTOMATED_USER_ID="your-twitter-automated-user-id"
AIBTC_TWITTER_PROFILE_ID="your-twitter-profile-id"
AIBTC_TWITTER_AGENT_ID="your-twitter-agent-id"
# Comma-separated list of whitelisted Twitter user IDs
AIBTC_TWITTER_WHITELISTED="your-twitter-whitelisted"
AIBTC_TWITTER_WHITELIST_ENABLED=false
# Discord Job
AIBTC_DISCORD_ENABLED=false
AIBTC_DISCORD_INTERVAL_SECONDS=30

# Tweet Job
AIBTC_TWEET_ENABLED=false
AIBTC_TWEET_INTERVAL_SECONDS=30

# Telegram Configuration
AIBTC_TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
AIBTC_TELEGRAM_BOT_ENABLED=false

#Discrod
# For successful proposals (celebrations, announcements)
AIBTC_DISCORD_WEBHOOK_URL_PASSED="https://discord.com/api/webhooks/YOUR_SUCCESS_WEBHOOK"
# For failed proposals (notifications, discussions)
AIBTC_DISCORD_WEBHOOK_URL_FAILED="https://discord.com/api/webhooks/YOUR_FAILURE_WEBHOOK"

# =============================================================================
# Additional Tools & Services
# API Configuration
# =============================================================================
AIBTC_FAKTORY_API_KEY="your-faktory-api-key"
AIBTC_BASEURL=https://app-staging.aibtc.dev
AIBTC_ALEX_BASE_URL=https://api.alexgo.io/
AIBTC_HIRO_API_URL=https://api.hiro.so
AIBTC_PLATFORM_API_URL=https://api.platform.hiro.so
AIBTC_VELAR_BASE_URL=https://gateway.velar.network/
AIBTC_LUNARCRUSH_BASE_URL=https://lunarcrush.com/api/v2

# API Keys
HIRO_API_KEY=your_hiro_api_key
AIBTC_LUNARCRUSH_API_KEY=your_lunarcrush_api_key
AIBTC_CMC_API_KEY=your_coinmarketcap_api_key
OPENAI_API_KEY=your_openai_api_key

# Bitflow Configuration
BITFLOW_API_HOST=https://bitflowapihost.hiro.so
BITFLOW_API_KEY="your-bitflow-api-key"
BITFLOW_STACKS_API_HOST=https://api.hiro.so/
BITFLOW_READONLY_CALL_API_HOST=https://readonly-call-api.hiro.so
# Webhook Configuration
AIBTC_WEBHOOK_URL=https://your-webhook-url.com
AIBTC_WEBHOOK_AUTH_TOKEN=Bearer your_webhook_auth_token
113 changes: 81 additions & 32 deletions backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

class CustomBaseModel(BaseModel):
model_config = ConfigDict(
json_encoders={UUID: str, datetime: lambda v: v.isoformat()}
json_encoders={UUID: str, datetime: lambda v: v.isoformat()},
arbitrary_types_allowed=True,
)


Expand Down Expand Up @@ -63,44 +64,69 @@ def __str__(self):
return self.value


class QueueMessageType(str, Enum):
TWEET = "tweet"
DAO = "dao"
DAO_TWEET = "dao_tweet"
DAO_PROPOSAL_VOTE = "dao_proposal_vote"
DAO_PROPOSAL_CONCLUDE = "dao_proposal_conclude"
DAO_PROPOSAL_EVALUATION = (
"dao_proposal_evaluation" # New type for proposal evaluation
)
AGENT_ACCOUNT_DEPLOY = (
"agent_account_deploy" # New type for agent account deployment
)
DISCORD = "discord" # New type for Discord queue messages
class QueueMessageType:
"""Dynamic queue message types that are registered at runtime.

def __str__(self):
return self.value
This system is compatible with the runner's dynamic JobType system.
Queue message types are registered dynamically as job tasks are discovered.
"""

_message_types: Dict[str, "QueueMessageType"] = {}

#
# SECRETS
#
class SecretBase(CustomBaseModel):
name: Optional[str] = None
description: Optional[str] = None
secret: Optional[str] = None
decrypted_secret: Optional[str] = None
key_id: Optional[str] = None
nonce: Optional[str] = None
def __init__(self, value: str):
self._value = value.lower()
self._name = value.upper()

@property
def value(self) -> str:
return self._value

class SecretCreate(SecretBase):
pass
@property
def name(self) -> str:
return self._name

def __str__(self) -> str:
return self._value

class Secret(SecretBase):
id: UUID
created_at: datetime
updated_at: datetime
def __repr__(self) -> str:
return f"QueueMessageType({self._value})"

def __eq__(self, other) -> bool:
if isinstance(other, QueueMessageType):
return self._value == other._value
if isinstance(other, str):
return self._value == other.lower()
return False

def __hash__(self) -> int:
return hash(self._value)

@classmethod
def get_or_create(cls, message_type: str) -> "QueueMessageType":
"""Get existing message type or create new one."""
normalized = message_type.lower()
if normalized not in cls._message_types:
cls._message_types[normalized] = cls(normalized)
return cls._message_types[normalized]

@classmethod
def register(cls, message_type: str) -> "QueueMessageType":
"""Register a new message type and return the instance."""
return cls.get_or_create(message_type)

@classmethod
def get_all_message_types(cls) -> Dict[str, str]:
"""Get all registered message types."""
return {mt._value: mt._value for mt in cls._message_types.values()}

@classmethod
def list_all(cls) -> List["QueueMessageType"]:
"""Get all registered message type instances."""
return list(cls._message_types.values())


# Types are registered dynamically by the runner system
# No need to pre-register common types


#
Expand All @@ -114,6 +140,7 @@ class QueueMessageBase(CustomBaseModel):
conversation_id: Optional[str] = None
dao_id: Optional[UUID] = None
wallet_id: Optional[UUID] = None
result: Optional[dict] = None


class QueueMessageCreate(QueueMessageBase):
Expand All @@ -125,6 +152,28 @@ class QueueMessage(QueueMessageBase):
created_at: datetime


#
# SECRETS
#
class SecretBase(CustomBaseModel):
name: Optional[str] = None
description: Optional[str] = None
secret: Optional[str] = None
decrypted_secret: Optional[str] = None
key_id: Optional[str] = None
nonce: Optional[str] = None


class SecretCreate(SecretBase):
pass


class Secret(SecretBase):
id: UUID
created_at: datetime
updated_at: datetime


#
# WALLETS
#
Expand Down
Loading