refactor: remove browser wallet extensions from repository
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Successful in 3s
Deploy to Testnet / deploy-testnet (push) Successful in 1m18s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Documentation Validation / validate-docs (push) Failing after 12s
Documentation Validation / validate-policies-strict (push) Successful in 5s
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Successful in 3s
Deploy to Testnet / deploy-testnet (push) Successful in 1m18s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Documentation Validation / validate-docs (push) Failing after 12s
Documentation Validation / validate-policies-strict (push) Successful in 5s
- Deleted extensions/ directory containing Chrome and Firefox wallet implementations - Removed aitbc-wallet and aitbc-wallet-firefox subdirectories with all source files - Removed Firefox .xpi package (v1.0.5) - Deleted extension documentation (README.md files, API reference, architecture diagrams) - Removed manifest files, background scripts, content scripts, injected scripts, and popup UI code - Cleaned up wallet API implementation (connect
This commit is contained in:
448
docs/blockchain/ENVIRONMENT_CONFIGURATION.md
Normal file
448
docs/blockchain/ENVIRONMENT_CONFIGURATION.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# AITBC Blockchain Node Environment Configuration Guide
|
||||
|
||||
Complete reference for configuring `node.env` and `blockchain.env` files for AITBC blockchain nodes.
|
||||
|
||||
## Overview
|
||||
|
||||
AITBC uses two environment configuration files:
|
||||
|
||||
- **`/etc/aitbc/node.env`** - Node-specific settings (unique per node)
|
||||
- **`/etc/aitbc/blockchain.env`** - Shared blockchain settings (can be identical across nodes)
|
||||
|
||||
## node.env Reference
|
||||
|
||||
**Location:** `/etc/aitbc/node.env`
|
||||
**Purpose:** Contains variables unique to each node. Must be customized for every node in the network.
|
||||
|
||||
### Node Identity
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `NODE_ID` | Yes | - | Unique identifier for this node (e.g., `aitbc`, `aitbc1`, `aitbc2`) |
|
||||
| `p2p_node_id` | Yes | - | Unique P2P network identity. Format: `node-<uuid>` |
|
||||
| `proposer_id` | Yes* | - | PoA proposer address. Format: `ait1<public-key>` |
|
||||
| `enable_block_production` | No | `true` | Set `false` on follower nodes to prevent forks |
|
||||
| `block_production_chains` | No | - | Comma-separated list of chains to produce blocks for |
|
||||
|
||||
*Required if `enable_block_production=true`
|
||||
|
||||
### P2P Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `p2p_bind_host` | Yes | `0.0.0.0` | Interface to bind P2P service |
|
||||
| `p2p_bind_port` | Yes | `7070` | P2P service port |
|
||||
| `p2p_peers` | No | - | Comma-separated list of peer nodes (e.g., `aitbc1:7070,aitbc2:7070`) |
|
||||
| `trusted_proposers` | No | - | For follower nodes - trusted proposer addresses |
|
||||
|
||||
### Node-Specific Overrides
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `NODE_HOST` | No | `0.0.0.0` | Override default host binding |
|
||||
| `NODE_PORT` | No | `7070` | Override default port |
|
||||
|
||||
### Example node.env (Hub Node)
|
||||
|
||||
```bash
|
||||
# AITBC Node-Specific Environment Configuration
|
||||
# This file contains variables unique to this node
|
||||
|
||||
# Node Identity
|
||||
NODE_ID=aitbc
|
||||
|
||||
# P2P Configuration
|
||||
p2p_node_id=node-ad4e9170aea04a349469d17758de7b27
|
||||
p2p_bind_host=0.0.0.0
|
||||
p2p_bind_port=7070
|
||||
proposer_id=ait1ytkh0cn8v2a4zjwzyav6854832myf9j7unsse8yntmuwzst4qhtqe9hqdw
|
||||
|
||||
# P2P Peers (empty for hub node)
|
||||
p2p_peers=
|
||||
|
||||
# Trusted Propers (for follower nodes)
|
||||
trusted_proposers=
|
||||
|
||||
# Block Production Configuration
|
||||
block_production_chains=ait-mainnet
|
||||
enable_block_production=true
|
||||
```
|
||||
|
||||
### Example node.env (Follower Node)
|
||||
|
||||
```bash
|
||||
# AITBC Node-Specific Environment Configuration
|
||||
# This file contains variables unique to this node
|
||||
|
||||
# Node Identity
|
||||
NODE_ID=aitbc2
|
||||
|
||||
# P2P Configuration
|
||||
p2p_node_id=node-7af14c549bab473d9deb4ca8ab4bdcde
|
||||
p2p_bind_host=0.0.0.0
|
||||
p2p_bind_port=7070
|
||||
proposer_id=ait1ytkh0cn8v2a4zjwzyav6854832myf9j7unsse8yntmuwzst4qhtqe9hqdw
|
||||
|
||||
# P2P Peers (connect to hub and other nodes)
|
||||
p2p_peers=aitbc:7070,aitbc1:7070
|
||||
|
||||
# Trusted Propers (for follower nodes)
|
||||
trusted_proposers=
|
||||
|
||||
# Block Production Configuration
|
||||
block_production_chains=
|
||||
enable_block_production=false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## blockchain.env Reference
|
||||
|
||||
**Location:** `/etc/aitbc/blockchain.env`
|
||||
**Purpose:** Contains shared blockchain settings. Can be identical across all nodes or customized per node.
|
||||
|
||||
### Environment & Logging
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `NODE_ENV` | No | `production` | Environment mode (`development`, `production`) |
|
||||
| `DEBUG` | No | `false` | Enable debug logging |
|
||||
| `LOG_LEVEL` | No | `INFO` | Logging level (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
|
||||
|
||||
### Security
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `API_KEY_HASH_SECRET` | Yes | - | Secret for API key hashing |
|
||||
| `SECRET_KEY` | Yes | - | Application secret key |
|
||||
| `BLOCKCHAIN_API_KEY` | Yes | - | API key for blockchain access |
|
||||
| `COORDINATOR_API_KEY` | Yes | - | API key for coordinator access |
|
||||
| `JWT_SECRET` | Yes | - | JWT signing secret |
|
||||
|
||||
### Database Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `DATABASE_URL` | No | - | PostgreSQL URL (if using PostgreSQL) |
|
||||
| `db_encryption_enabled` | No | `false` | Enable SQLCipher encryption (ait-mainnet only) |
|
||||
| `MEMPOOL_DB_URL` | No | - | PostgreSQL URL for mempool backend |
|
||||
|
||||
### Redis & Gossip
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `REDIS_URL` | Yes | - | Redis connection URL |
|
||||
| `gossip_backend` | Yes | `broadcast` | Gossip backend type |
|
||||
| `gossip_broadcast_url` | Yes | - | Redis URL for gossip broadcast |
|
||||
| `SYNC_REDIS_URL` | Yes | - | Redis URL for chain sync |
|
||||
|
||||
### Sync Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `SYNC_SOURCE_HOST` | No | - | Host to sync from |
|
||||
| `SYNC_SOURCE_PORT` | No | `8006` | Port to sync from |
|
||||
| `SYNC_LEADER_HOST` | No | - | Leader node host |
|
||||
| `SYNC_IMPORT_HOST` | No | `localhost` | Import service host |
|
||||
| `SYNC_IMPORT_PORT` | No | `8006` | Import service port |
|
||||
| `SYNC_CHAIN_ID` | No | - | Chain ID to sync |
|
||||
| `auto_sync_enabled` | No | `false` | Enable automatic sync on gap detection |
|
||||
|
||||
### Blockchain Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `CHAIN_ID` | Yes | `ait-mainnet` | Primary chain ID |
|
||||
| `supported_chains` | Yes | `ait-mainnet` | Comma-separated list of supported chains |
|
||||
| `island_id` | Yes | - | Island identifier for this node |
|
||||
| `BLOCK_TIME` | No | `5` | Target block time in seconds |
|
||||
| `NETWORK_ID` | No | `1337` | Network identifier |
|
||||
| `CONSENSUS` | No | `proof_of_authority` | Consensus mechanism |
|
||||
|
||||
### RPC Configuration
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `rpc_bind_host` | No | `0.0.0.0` | RPC service bind host |
|
||||
| `rpc_bind_port` | No | `8006` | RPC service port |
|
||||
| `default_peer_rpc_url` | No | - | Default peer RPC URL for sync |
|
||||
|
||||
### Service Ports
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `api_host` | No | `0.0.0.0` | API service host |
|
||||
| `api_port` | No | `8000` | API service port |
|
||||
| `wallet_host` | No | `0.0.0.0` | Wallet service host |
|
||||
| `wallet_port` | No | `8003` | Wallet service port |
|
||||
| `exchange_host` | No | `0.0.0.0` | Exchange service host |
|
||||
| `exchange_port` | No | `8001` | Exchange service port |
|
||||
|
||||
### Feature Flags
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `ENFORCE_STATE_ROOT_VALIDATION` | No | `false` | Enable state root validation |
|
||||
| `WORKERS` | No | `1` | Number of worker processes |
|
||||
|
||||
### Monitoring
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `MONITORING_PORT` | No | `9000` | Monitoring service port |
|
||||
| `PROMETHEUS_PORT` | No | `9090` | Prometheus port |
|
||||
| `GRAFANA_PORT` | No | `3000` | Grafana port |
|
||||
|
||||
### Example blockchain.env (Hub Node - ait-mainnet)
|
||||
|
||||
```bash
|
||||
# AITBC Environment Configuration
|
||||
# This file contains shared environment variables
|
||||
|
||||
# Environment
|
||||
NODE_ENV=production
|
||||
DEBUG=false
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# API Key Security
|
||||
API_KEY_HASH_SECRET=f55e8a64e2cc3b44c50a43f25c7f985a6251ad4d0ceb469852d297721def28d2
|
||||
SECRET_KEY=production-secret-key-change-me-in-production
|
||||
BLOCKCHAIN_API_KEY=production-api-key-change-me
|
||||
COORDINATOR_API_KEY=admin_prod_key_use_real_value
|
||||
JWT_SECRET=production-jwt-secret-32-chars-long-change-me
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
gossip_backend=broadcast
|
||||
gossip_broadcast_url=redis://10.1.223.93:6379
|
||||
SYNC_REDIS_URL=redis://10.1.223.93:6379
|
||||
|
||||
# Sync Configuration (for ait-testnet following)
|
||||
SYNC_SOURCE_HOST=aitbc1
|
||||
SYNC_SOURCE_PORT=8006
|
||||
SYNC_LEADER_HOST=aitbc1
|
||||
SYNC_IMPORT_HOST=localhost
|
||||
SYNC_IMPORT_PORT=8006
|
||||
SYNC_CHAIN_ID=ait-testnet
|
||||
|
||||
# Blockchain Configuration
|
||||
CHAIN_ID=ait-mainnet
|
||||
BLOCK_TIME=5
|
||||
NETWORK_ID=1337
|
||||
CONSENSUS=proof_of_authority
|
||||
|
||||
# RPC Configuration
|
||||
rpc_bind_host=0.0.0.0
|
||||
rpc_bind_port=8006
|
||||
|
||||
# API Configuration
|
||||
api_host=0.0.0.0
|
||||
api_port=8000
|
||||
|
||||
# Wallet Configuration
|
||||
wallet_host=0.0.0.0
|
||||
wallet_port=8003
|
||||
|
||||
# Exchange Configuration
|
||||
exchange_host=0.0.0.0
|
||||
exchange_port=8001
|
||||
|
||||
# Services Configuration
|
||||
auto_sync_enabled=true
|
||||
island_id=ait-mainnet-island
|
||||
supported_chains=ait-mainnet,ait-testnet
|
||||
db_encryption_enabled=false
|
||||
default_peer_rpc_url=http://aitbc1:8006
|
||||
MEMPOOL_DB_URL=postgresql+psycopg://aitbc_mempool:password@localhost:5432/aitbc_mempool
|
||||
ENFORCE_STATE_ROOT_VALIDATION=true
|
||||
WORKERS=1
|
||||
|
||||
# Monitoring Configuration
|
||||
MONITORING_PORT=9000
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3000
|
||||
```
|
||||
|
||||
### Example blockchain.env (Hub Node - ait-testnet)
|
||||
|
||||
```bash
|
||||
# AITBC Environment Configuration
|
||||
|
||||
# Environment
|
||||
NODE_ENV=production
|
||||
DEBUG=false
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# API Key Security
|
||||
API_KEY_HASH_SECRET=f55e8a64e2cc3b44c50a43f25c7f985a6251ad4d0ceb469852d297721def28d2
|
||||
SECRET_KEY=production-secret-key-change-me-in-production
|
||||
BLOCKCHAIN_API_KEY=production-api-key-change-me
|
||||
COORDINATOR_API_KEY=admin_prod_key_use_real_value
|
||||
JWT_SECRET=production-jwt-secret-32-chars-long-change-me
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
gossip_backend=broadcast
|
||||
gossip_broadcast_url=redis://10.1.223.93:6379
|
||||
SYNC_REDIS_URL=redis://10.1.223.93:6379
|
||||
|
||||
# Sync Configuration (following ait-mainnet)
|
||||
SYNC_SOURCE_HOST=aitbc
|
||||
SYNC_SOURCE_PORT=8006
|
||||
SYNC_LEADER_HOST=aitbc
|
||||
SYNC_IMPORT_HOST=localhost
|
||||
SYNC_IMPORT_PORT=8006
|
||||
SYNC_CHAIN_ID=ait-testnet
|
||||
|
||||
# Blockchain Configuration
|
||||
CHAIN_ID=ait-testnet
|
||||
BLOCK_TIME=5
|
||||
NETWORK_ID=1337
|
||||
CONSENSUS=proof_of_authority
|
||||
|
||||
# RPC Configuration
|
||||
rpc_bind_host=0.0.0.0
|
||||
rpc_bind_port=8006
|
||||
|
||||
# API Configuration
|
||||
api_host=0.0.0.0
|
||||
api_port=8000
|
||||
|
||||
# Wallet Configuration
|
||||
wallet_host=0.0.0.0
|
||||
wallet_port=8003
|
||||
|
||||
# Exchange Configuration
|
||||
exchange_host=0.0.0.0
|
||||
exchange_port=8001
|
||||
|
||||
# Services Configuration
|
||||
auto_sync_enabled=true
|
||||
island_id=ait-testnet-island
|
||||
supported_chains=ait-testnet
|
||||
db_encryption_enabled=false
|
||||
default_peer_rpc_url=http://aitbc:8006
|
||||
MEMPOOL_DB_URL=postgresql+psycopg://aitbc_mempool:password@localhost:5432/aitbc_mempool
|
||||
ENFORCE_STATE_ROOT_VALIDATION=true
|
||||
WORKERS=1
|
||||
|
||||
# Monitoring Configuration
|
||||
MONITORING_PORT=9000
|
||||
PROMETHEUS_PORT=9090
|
||||
GRAFANA_PORT=3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Node Role Patterns
|
||||
|
||||
### Hub Node (Block Producer)
|
||||
|
||||
**Characteristics:**
|
||||
- `enable_block_production=true`
|
||||
- `block_production_chains=<chain-id>`
|
||||
- `p2p_peers=` (empty or minimal)
|
||||
- `auto_sync_enabled=false` (for its own chain)
|
||||
- Creates genesis block locally
|
||||
|
||||
**Example:** aitbc for ait-mainnet, aitbc1 for ait-testnet
|
||||
|
||||
### Follower Node
|
||||
|
||||
**Characteristics:**
|
||||
- `enable_block_production=false`
|
||||
- `block_production_chains=` (empty)
|
||||
- `p2p_peers=hub:7070,other:7070`
|
||||
- `auto_sync_enabled=true`
|
||||
- `default_peer_rpc_url=http://hub:8006`
|
||||
- Syncs genesis from hub
|
||||
|
||||
**Example:** gitea-runner following both chains
|
||||
|
||||
---
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Issue: "Gap detected" errors
|
||||
|
||||
**Cause:** Node is receiving blocks but missing intermediate blocks
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Enable auto-sync
|
||||
auto_sync_enabled=true
|
||||
default_peer_rpc_url=http://hub-node:8006
|
||||
```
|
||||
|
||||
### Issue: Fork detection errors
|
||||
|
||||
**Cause:** Multiple nodes with same `proposer_id` producing blocks simultaneously
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# On follower nodes
|
||||
enable_block_production=false
|
||||
```
|
||||
|
||||
### Issue: P2P service fails to start
|
||||
|
||||
**Cause:** Missing `p2p_bind_host` or `p2p_bind_port`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Add to node.env
|
||||
p2p_bind_host=0.0.0.0
|
||||
p2p_bind_port=7070
|
||||
```
|
||||
|
||||
### Issue: Chain ID mismatch
|
||||
|
||||
**Cause:** `supported_chains` not set explicitly
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Always set explicitly in blockchain.env
|
||||
supported_chains=ait-mainnet,ait-testnet
|
||||
```
|
||||
|
||||
### Issue: Database location mismatch
|
||||
|
||||
**Cause:** `DATABASE_URL` doesn't match actual database path
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Use correct path (default is /var/lib/aitbc/data/<chain-id>/chain.db)
|
||||
# Don't override DATABASE_URL unless using PostgreSQL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
Before starting services, verify:
|
||||
|
||||
- [ ] `NODE_ID` is unique across all nodes
|
||||
- [ ] `p2p_node_id` is unique across all nodes
|
||||
- [ ] `proposer_id` is unique for each proposer node
|
||||
- [ ] `p2p_bind_host` and `p2p_bind_port` are set
|
||||
- [ ] `supported_chains` matches the network chain ID
|
||||
- [ ] `island_id` is set correctly
|
||||
- [ ] `auto_sync_enabled` is `true` for follower nodes
|
||||
- [ ] `enable_block_production` is `false` for follower nodes
|
||||
- [ ] `default_peer_rpc_url` points to hub node for followers
|
||||
- [ ] Redis URLs are correct and accessible
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Adding Third Node Guide](./adding_gitea_runner_as_third_node.md) - Real-world setup example
|
||||
- [Node Deployment Guide](../infrastructure/NODE_AITBC.md) - Infrastructure setup
|
||||
- [Blockchain Node Schema](./node/SCHEMA.md) - Database schema reference
|
||||
- [Multi-Node Setup Core](../../.windsurf/workflows/multi-node-blockchain-setup-core.md) - Workflow guide
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.0
|
||||
**Last Updated:** 2026-05-19
|
||||
**Status:** Complete
|
||||
@@ -1,77 +0,0 @@
|
||||
# AITBC Browser Wallet Extensions
|
||||
|
||||
This directory contains browser wallet extensions for AITBC, supporting both Chrome and Firefox browsers.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### For Chrome/Brave/Edge Users
|
||||
|
||||
1. Navigate to `aitbc-wallet/` folder
|
||||
2. Follow the installation instructions in `aitbc-wallet/README.md`
|
||||
|
||||
### For Firefox Users
|
||||
|
||||
1. Navigate to `aitbc-wallet-firefox/` folder
|
||||
2. Follow the installation instructions in `aitbc-wallet-firefox/README.md`
|
||||
|
||||
## Using the Extensions
|
||||
|
||||
1. Install the appropriate extension for your browser
|
||||
2. Navigate to the AITBC Trade Exchange: https://aitbc.bubuit.net/Exchange
|
||||
3. Toggle from "Demo Mode" to "Real Mode"
|
||||
4. Click "Connect AITBC Wallet"
|
||||
5. Create a new account or import an existing one
|
||||
6. Approve the connection request
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Cross-browser support (Chrome, Firefox, Edge, Brave)
|
||||
- ✅ Secure local key storage
|
||||
- ✅ dApp connection management
|
||||
- ✅ Transaction signing
|
||||
- ✅ Message signing
|
||||
- ✅ Balance tracking
|
||||
- ✅ Account management (create/import)
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never share your private key** - It's the key to your funds
|
||||
2. **Keep backups** - Save your private key in a secure location
|
||||
3. **Verify URLs** - Always check you're on aitbc.bubuit.net
|
||||
4. **Use strong passwords** - Protect your browser with a strong password
|
||||
5. **Keep updated** - Keep your browser and extension updated
|
||||
|
||||
## Development
|
||||
|
||||
Both extensions share most of their code:
|
||||
|
||||
- `injected.js` - Provides the wallet API to dApps
|
||||
- `popup.html/js` - Wallet user interface
|
||||
- `content.js` - Communicates between the extension and dApps
|
||||
|
||||
The main differences are:
|
||||
- Chrome uses Manifest V3
|
||||
- Firefox uses Manifest V2 (required for full functionality)
|
||||
- Different background script architectures
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│ dApp Page │────▶│ Content Script │────▶│ Background Script│
|
||||
│ (Exchange UI) │ │ (bridge) │ │ (wallet logic) │
|
||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
||||
▲ │
|
||||
│ ▼
|
||||
┌──────────────────┐ ┌─────────────────┐
|
||||
│ Injected Script │ │ Extension UI │
|
||||
│ (window.aitbcWallet)│ │ (popup.html) │
|
||||
└──────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
1. Check the individual README files for your browser
|
||||
2. Create an issue in the repository
|
||||
3. Join our community discussions
|
||||
Binary file not shown.
@@ -1,133 +0,0 @@
|
||||
# AITBC Wallet Extension for Firefox
|
||||
|
||||
A Firefox browser extension that provides AITBC wallet functionality for interacting with the AITBC Trade Exchange and other dApps.
|
||||
|
||||
## Differences from Chrome Version
|
||||
|
||||
This version is specifically built for Firefox with the following differences:
|
||||
|
||||
- Uses Manifest V2 (Firefox still requires V2 for full functionality)
|
||||
- Uses `browser_action` instead of `action` (V2 syntax)
|
||||
- Uses `chrome.runtime.connect()` for background script communication
|
||||
- Background script uses persistent connections via ports
|
||||
|
||||
## Installation
|
||||
|
||||
### Development Installation
|
||||
|
||||
1. Clone this repository
|
||||
2. Open Firefox and navigate to `about:debugging`
|
||||
3. Click "This Firefox" in the left sidebar
|
||||
4. Click "Load Temporary Add-on..."
|
||||
5. Select the `manifest.json` file from the `aitbc-wallet-firefox` folder
|
||||
|
||||
### Production Installation
|
||||
|
||||
The extension will be published to the Firefox Add-on Store (AMO). Installation instructions will be available once published.
|
||||
|
||||
## Usage
|
||||
|
||||
The usage is identical to the Chrome version:
|
||||
|
||||
1. Install the AITBC Wallet extension
|
||||
2. Navigate to https://aitbc.bubuit.net/Exchange
|
||||
3. Toggle the switch from "Demo Mode" to "Real Mode"
|
||||
4. Click "Connect AITBC Wallet"
|
||||
5. Approve the connection request in the popup
|
||||
|
||||
## Features
|
||||
|
||||
- **Wallet Management**: Create new accounts or import existing private keys
|
||||
- **Secure Storage**: Private keys are stored locally in Firefox's storage
|
||||
- **dApp Integration**: Connect to AITBC Trade Exchange and other supported dApps
|
||||
- **Transaction Signing**: Sign transactions and messages securely
|
||||
- **Balance Tracking**: View your AITBC token balance
|
||||
|
||||
## API Reference
|
||||
|
||||
The extension injects a `window.aitbcWallet` object into supported dApps with the following methods:
|
||||
|
||||
### `aitbcWallet.connect()`
|
||||
Connect the dApp to the wallet.
|
||||
```javascript
|
||||
const response = await aitbcWallet.connect();
|
||||
console.log(response.address); // User's AITBC address
|
||||
```
|
||||
|
||||
### `aitbcWallet.getAccount()`
|
||||
Get the current account address.
|
||||
```javascript
|
||||
const address = await aitbcWallet.getAccount();
|
||||
```
|
||||
|
||||
### `aitbcWallet.getBalance(address)`
|
||||
Get the AITBC balance for an address.
|
||||
```javascript
|
||||
const balance = await aitbcWallet.getBalance('aitbc1...');
|
||||
console.log(balance.amount); // Balance in AITBC
|
||||
```
|
||||
|
||||
### `aitbcWallet.sendTransaction(to, amount, data)`
|
||||
Send AITBC tokens to another address.
|
||||
```javascript
|
||||
const tx = await aitbcWallet.sendTransaction('aitbc1...', 100);
|
||||
console.log(tx.hash); // Transaction hash
|
||||
```
|
||||
|
||||
### `aitbcWallet.signMessage(message)`
|
||||
Sign a message with the private key.
|
||||
```javascript
|
||||
const signature = await aitbcWallet.signMessage('Hello AITBC!');
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Private keys are stored locally in Firefox's storage
|
||||
- Always verify you're on the correct domain before connecting
|
||||
- Never share your private key with anyone
|
||||
- Keep your browser and extension updated
|
||||
|
||||
## Development
|
||||
|
||||
To modify the extension:
|
||||
|
||||
1. Make changes to the source files
|
||||
2. Go to `about:debugging` in Firefox
|
||||
3. Find "AITBC Wallet" and click "Reload"
|
||||
4. Test your changes
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
aitbc-wallet-firefox/
|
||||
├── manifest.json # Extension configuration (Manifest V2)
|
||||
├── background.js # Background script for wallet operations
|
||||
├── content.js # Content script for dApp communication
|
||||
├── injected.js # Script injected into dApps
|
||||
├── popup.html # Extension popup UI
|
||||
├── popup.js # Popup logic
|
||||
├── icons/ # Extension icons
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Firefox-Specific Notes
|
||||
|
||||
- Firefox requires Manifest V2 for extensions that use content scripts in this manner
|
||||
- The `browser_action` API is used instead of the newer `action` API
|
||||
- Background scripts use port-based communication for better performance
|
||||
- Storage APIs use `chrome.storage` which is compatible with Firefox
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Extension not loading
|
||||
- Ensure you're loading the `manifest.json` file, not the folder
|
||||
- Check the Browser Console for error messages (`Ctrl+Shift+J`)
|
||||
|
||||
### dApp connection not working
|
||||
- Refresh the dApp page after installing/updating the extension
|
||||
- Check that the site is in the `matches` pattern in manifest.json
|
||||
- Look for errors in the Browser Console
|
||||
|
||||
### Permission errors
|
||||
- Firefox may show additional permission prompts
|
||||
- Make sure to allow all requested permissions when installing
|
||||
@@ -1,153 +0,0 @@
|
||||
// Background script for Firefox extension
|
||||
// Handles messages from content scripts and manages wallet state
|
||||
|
||||
let currentPort = null;
|
||||
|
||||
// Listen for connection from content script
|
||||
chrome.runtime.onConnect.addListener(function(port) {
|
||||
if (port.name === "aitbc-wallet") {
|
||||
currentPort = port;
|
||||
|
||||
port.onMessage.addListener(function(request) {
|
||||
handleWalletRequest(request, port);
|
||||
});
|
||||
|
||||
port.onDisconnect.addListener(function() {
|
||||
currentPort = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle wallet requests from dApps
|
||||
async function handleWalletRequest(request, port) {
|
||||
const { method, params, id } = request;
|
||||
|
||||
try {
|
||||
switch (method) {
|
||||
case 'connect':
|
||||
const response = await handleConnect();
|
||||
port.postMessage({ id, result: response });
|
||||
break;
|
||||
|
||||
case 'accounts':
|
||||
const accounts = await getAccounts();
|
||||
port.postMessage({ id, result: accounts });
|
||||
break;
|
||||
|
||||
case 'getBalance':
|
||||
const balance = await getBalance(params.address);
|
||||
port.postMessage({ id, result: balance });
|
||||
break;
|
||||
|
||||
case 'sendTransaction':
|
||||
const txResult = await sendTransaction(params);
|
||||
port.postMessage({ id, result: txResult });
|
||||
break;
|
||||
|
||||
case 'signMessage':
|
||||
const signature = await signMessage(params.message);
|
||||
port.postMessage({ id, result: signature });
|
||||
break;
|
||||
|
||||
default:
|
||||
port.postMessage({ id, error: 'Unknown method: ' + method });
|
||||
}
|
||||
} catch (error) {
|
||||
port.postMessage({ id, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
// Handle connection request from dApp
|
||||
async function handleConnect() {
|
||||
// Get current account
|
||||
const result = await chrome.storage.local.get(['currentAccount']);
|
||||
|
||||
if (!result.currentAccount) {
|
||||
throw new Error('No account found. Please create or import an account first.');
|
||||
}
|
||||
|
||||
// Show connection prompt (in a real implementation, this would show a proper UI)
|
||||
const connected = confirm(`Allow this site to connect to your AITBC Wallet?\n\nAddress: ${result.currentAccount.address}`);
|
||||
|
||||
if (!connected) {
|
||||
throw new Error('User rejected connection');
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
address: result.currentAccount.address
|
||||
};
|
||||
}
|
||||
|
||||
// Get all accounts
|
||||
async function getAccounts() {
|
||||
const result = await chrome.storage.local.get(['accounts']);
|
||||
const accounts = result.accounts || [];
|
||||
return accounts.map(acc => acc.address);
|
||||
}
|
||||
|
||||
// Get balance for an address
|
||||
async function getBalance(address) {
|
||||
// In a real implementation, this would query the blockchain
|
||||
// For demo, return stored balance
|
||||
const result = await chrome.storage.local.get(['accounts']);
|
||||
const accounts = result.accounts || [];
|
||||
const account = accounts.find(acc => acc.address === address);
|
||||
|
||||
return {
|
||||
address: address,
|
||||
balance: account ? account.balance || 0 : 0,
|
||||
symbol: 'AITBC'
|
||||
};
|
||||
}
|
||||
|
||||
// Send transaction
|
||||
async function sendTransaction(params) {
|
||||
// In a real implementation, this would create, sign, and broadcast a transaction
|
||||
const { to, amount, data } = params;
|
||||
|
||||
// Get current account
|
||||
const result = await chrome.storage.local.get(['currentAccount']);
|
||||
const account = result.currentAccount;
|
||||
|
||||
if (!account) {
|
||||
throw new Error('No account connected');
|
||||
}
|
||||
|
||||
// Confirm transaction
|
||||
const confirmed = confirm(`Send ${amount} AITBC to ${to}?\n\nFrom: ${account.address}`);
|
||||
if (!confirmed) {
|
||||
throw new Error('Transaction rejected');
|
||||
}
|
||||
|
||||
// Return mock transaction hash
|
||||
return {
|
||||
hash: '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)), b => b.toString(16).padStart(2, '0')).join(''),
|
||||
status: 'pending'
|
||||
};
|
||||
}
|
||||
|
||||
// Sign message
|
||||
async function signMessage(message) {
|
||||
// Get current account
|
||||
const result = await chrome.storage.local.get(['currentAccount']);
|
||||
const account = result.currentAccount;
|
||||
|
||||
if (!account) {
|
||||
throw new Error('No account connected');
|
||||
}
|
||||
|
||||
// Confirm signing
|
||||
const confirmed = confirm(`Sign the following message?\n\n"${message}"\n\nAccount: ${account.address}`);
|
||||
if (!confirmed) {
|
||||
throw new Error('Message signing rejected');
|
||||
}
|
||||
|
||||
// In a real implementation, this would sign with the private key
|
||||
// For demo, return a mock signature
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(message + account.privateKey);
|
||||
const hash = await crypto.subtle.digest('SHA-256', data);
|
||||
|
||||
return Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// Content script for AITBC Wallet Firefox extension
|
||||
(function() {
|
||||
// Inject the wallet API into the page
|
||||
const script = document.createElement('script');
|
||||
script.src = chrome.runtime.getURL('injected.js');
|
||||
script.onload = function() {
|
||||
this.remove();
|
||||
};
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
|
||||
// Create a port to background script
|
||||
const port = chrome.runtime.connect({ name: "aitbc-wallet" });
|
||||
|
||||
// Listen for messages from the injected script
|
||||
window.addEventListener('message', function(event) {
|
||||
// Only accept messages from our own window
|
||||
if (event.source !== window) return;
|
||||
|
||||
if (event.data.type && event.data.type === 'AITBC_WALLET_REQUEST') {
|
||||
// Forward the request to the background script
|
||||
port.postMessage(event.data);
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for responses from background script
|
||||
port.onMessage.addListener(function(response) {
|
||||
// Send the response back to the page
|
||||
window.postMessage({
|
||||
type: 'AITBC_WALLET_RESPONSE',
|
||||
id: response.id,
|
||||
result: response.result,
|
||||
error: response.error
|
||||
}, '*');
|
||||
});
|
||||
})();
|
||||
@@ -1,106 +0,0 @@
|
||||
// Injected script that provides the AITBC wallet API to the dApp
|
||||
(function() {
|
||||
// Create the wallet API object
|
||||
const aitbcWallet = {
|
||||
// Check if wallet is available
|
||||
isAvailable: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
// Connect to wallet
|
||||
connect: async function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestId = Date.now().toString();
|
||||
|
||||
// Send request to content script
|
||||
window.postMessage({
|
||||
type: 'AITBC_WALLET_REQUEST',
|
||||
id: requestId,
|
||||
method: 'connect'
|
||||
}, '*');
|
||||
|
||||
// Listen for response
|
||||
const messageHandler = function(event) {
|
||||
if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
if (event.data.response.error) {
|
||||
reject(new Error(event.data.response.error));
|
||||
} else {
|
||||
resolve(event.data.response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', messageHandler);
|
||||
|
||||
// Timeout after 30 seconds
|
||||
setTimeout(() => {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
reject(new Error('Connection timeout'));
|
||||
}, 30000);
|
||||
});
|
||||
},
|
||||
|
||||
// Get account address
|
||||
getAccount: async function() {
|
||||
const accounts = await this.request({ method: 'accounts' });
|
||||
return accounts[0];
|
||||
},
|
||||
|
||||
// Get balance
|
||||
getBalance: async function(address) {
|
||||
return this.request({ method: 'getBalance', params: { address } });
|
||||
},
|
||||
|
||||
// Send transaction
|
||||
sendTransaction: async function(to, amount, data = null) {
|
||||
return this.request({
|
||||
method: 'sendTransaction',
|
||||
params: { to, amount, data }
|
||||
});
|
||||
},
|
||||
|
||||
// Sign message
|
||||
signMessage: async function(message) {
|
||||
return this.request({ method: 'signMessage', params: { message } });
|
||||
},
|
||||
|
||||
// Generic request method
|
||||
request: async function(payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestId = Date.now().toString();
|
||||
|
||||
window.postMessage({
|
||||
type: 'AITBC_WALLET_REQUEST',
|
||||
id: requestId,
|
||||
method: payload.method,
|
||||
params: payload.params || {}
|
||||
}, '*');
|
||||
|
||||
const messageHandler = function(event) {
|
||||
if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
if (event.data.response.error) {
|
||||
reject(new Error(event.data.response.error));
|
||||
} else {
|
||||
resolve(event.data.response);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', messageHandler);
|
||||
|
||||
setTimeout(() => {
|
||||
window.removeEventListener('message', messageHandler);
|
||||
reject(new Error('Request timeout'));
|
||||
}, 30000);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Inject the wallet API into the window object
|
||||
window.aitbcWallet = aitbcWallet;
|
||||
|
||||
// Fire an event to notify the dApp that the wallet is ready
|
||||
window.dispatchEvent(new Event('aitbcWalletReady'));
|
||||
})();
|
||||
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "AITBC Wallet",
|
||||
"version": "1.0.0",
|
||||
"description": "AITBC Browser Wallet for trading and managing AITBC tokens",
|
||||
|
||||
"permissions": [
|
||||
"storage",
|
||||
"activeTab"
|
||||
],
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"],
|
||||
"js": ["content.js"],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_title": "AITBC Wallet",
|
||||
"default_icon": {
|
||||
"16": "icons/icon-16.png",
|
||||
"32": "icons/icon-32.png",
|
||||
"48": "icons/icon-48.png",
|
||||
"128": "icons/icon-128.png"
|
||||
}
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
["injected.js"]
|
||||
],
|
||||
|
||||
"icons": {
|
||||
"16": "icons/icon-16.png",
|
||||
"32": "icons/icon-32.png",
|
||||
"48": "icons/icon-48.png",
|
||||
"128": "icons/icon-128.png"
|
||||
},
|
||||
|
||||
"background": {
|
||||
"scripts": ["background.js"],
|
||||
"persistent": false
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body {
|
||||
width: 350px;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
|
||||
color: white;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.logo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
color: #f97316;
|
||||
}
|
||||
.wallet-info {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.address {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.balance {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
button {
|
||||
background: white;
|
||||
color: #f97316;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
button:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.transactions {
|
||||
margin-top: 20px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tx-item {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="logo">AITBC</div>
|
||||
<h1>Wallet</h1>
|
||||
</div>
|
||||
|
||||
<div class="wallet-info">
|
||||
<div>Account Address:</div>
|
||||
<div class="address" id="accountAddress">Not connected</div>
|
||||
<div class="balance" id="balance">0 AITBC</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button onclick="createAccount()">Create New Account</button>
|
||||
<button onclick="importAccount()">Import Private Key</button>
|
||||
<button onclick="sendTokens()">Send Tokens</button>
|
||||
<button onclick="receiveTokens()">Receive Tokens</button>
|
||||
<button onclick="viewOnExplorer()">View on Explorer</button>
|
||||
</div>
|
||||
|
||||
<div class="transactions">
|
||||
<h3>Recent Transactions</h3>
|
||||
<div id="transactionList">
|
||||
<div class="tx-item">No transactions yet</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,162 +0,0 @@
|
||||
// Popup script for AITBC Wallet extension
|
||||
let currentAccount = null;
|
||||
let accounts = [];
|
||||
|
||||
// Load wallet data on popup open
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
await loadWalletData();
|
||||
updateUI();
|
||||
});
|
||||
|
||||
// Load wallet data from storage
|
||||
async function loadWalletData() {
|
||||
const result = await chrome.storage.local.get(['accounts', 'currentAccount']);
|
||||
accounts = result.accounts || [];
|
||||
currentAccount = result.currentAccount || null;
|
||||
}
|
||||
|
||||
// Save wallet data to storage
|
||||
async function saveWalletData() {
|
||||
await chrome.storage.local.set({
|
||||
accounts: accounts,
|
||||
currentAccount: currentAccount
|
||||
});
|
||||
}
|
||||
|
||||
// Update UI with current wallet state
|
||||
function updateUI() {
|
||||
const addressEl = document.getElementById('accountAddress');
|
||||
const balanceEl = document.getElementById('balance');
|
||||
|
||||
if (currentAccount) {
|
||||
addressEl.textContent = currentAccount.address;
|
||||
balanceEl.textContent = `${currentAccount.balance || 0} AITBC`;
|
||||
} else {
|
||||
addressEl.textContent = 'Not connected';
|
||||
balanceEl.textContent = '0 AITBC';
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new account
|
||||
async function createAccount() {
|
||||
// Generate a new private key and address
|
||||
const privateKey = generatePrivateKey();
|
||||
const address = await generateAddress(privateKey);
|
||||
|
||||
const newAccount = {
|
||||
address: address,
|
||||
privateKey: privateKey,
|
||||
balance: 0,
|
||||
created: new Date().toISOString()
|
||||
};
|
||||
|
||||
accounts.push(newAccount);
|
||||
currentAccount = newAccount;
|
||||
await saveWalletData();
|
||||
updateUI();
|
||||
|
||||
alert('New account created! Please save your private key securely.');
|
||||
}
|
||||
|
||||
// Import account from private key
|
||||
async function importAccount() {
|
||||
const privateKey = prompt('Enter your private key:');
|
||||
if (!privateKey) return;
|
||||
|
||||
try {
|
||||
const address = await generateAddress(privateKey);
|
||||
|
||||
// Check if account already exists
|
||||
const existing = accounts.find(a => a.address === address);
|
||||
if (existing) {
|
||||
currentAccount = existing;
|
||||
} else {
|
||||
currentAccount = {
|
||||
address: address,
|
||||
privateKey: privateKey,
|
||||
balance: 0,
|
||||
created: new Date().toISOString()
|
||||
};
|
||||
accounts.push(currentAccount);
|
||||
}
|
||||
|
||||
await saveWalletData();
|
||||
updateUI();
|
||||
alert('Account imported successfully!');
|
||||
} catch (error) {
|
||||
alert('Invalid private key!');
|
||||
}
|
||||
}
|
||||
|
||||
// Send tokens
|
||||
async function sendTokens() {
|
||||
if (!currentAccount) {
|
||||
alert('Please create or import an account first!');
|
||||
return;
|
||||
}
|
||||
|
||||
const to = prompt('Send to address:');
|
||||
const amount = prompt('Amount:');
|
||||
|
||||
if (!to || !amount) return;
|
||||
|
||||
// In a real implementation, this would create and sign a transaction
|
||||
alert(`Would send ${amount} AITBC to ${to}`);
|
||||
}
|
||||
|
||||
// Receive tokens
|
||||
function receiveTokens() {
|
||||
if (!currentAccount) {
|
||||
alert('Please create or import an account first!');
|
||||
return;
|
||||
}
|
||||
|
||||
alert(`Your receiving address:\n${currentAccount.address}`);
|
||||
}
|
||||
|
||||
// View on explorer
|
||||
function viewOnExplorer() {
|
||||
if (!currentAccount) {
|
||||
alert('Please create or import an account first!');
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.tabs.create({ url: `https://aitbc.bubuit.net/explorer/address/${currentAccount.address}` });
|
||||
}
|
||||
|
||||
// Generate a random private key (demo only)
|
||||
function generatePrivateKey() {
|
||||
const array = new Uint8Array(32);
|
||||
crypto.getRandomValues(array);
|
||||
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
// Generate address from private key (demo only)
|
||||
async function generateAddress(privateKey) {
|
||||
// In a real implementation, this would derive the address from the private key
|
||||
// using the appropriate cryptographic algorithm
|
||||
const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(privateKey));
|
||||
return 'aitbc1' + Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('').substring(0, 40);
|
||||
}
|
||||
|
||||
// Listen for connection requests from dApps
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
if (request.method === 'connect') {
|
||||
// Show connection dialog
|
||||
const connected = confirm(`Allow this site to connect to your AITBC Wallet?`);
|
||||
|
||||
if (connected && currentAccount) {
|
||||
sendResponse({
|
||||
success: true,
|
||||
address: currentAccount.address
|
||||
});
|
||||
} else {
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: 'User rejected connection'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Keep the message channel open for async response
|
||||
});
|
||||
44
website/agent/.htaccess
Normal file
44
website/agent/.htaccess
Normal file
@@ -0,0 +1,44 @@
|
||||
# Apache configuration for agent endpoints
|
||||
# Enable CORS for agent access
|
||||
Header always set Access-Control-Allow-Origin "*"
|
||||
Header always set Access-Control-Allow-Methods "GET, OPTIONS"
|
||||
Header always set Access-Control-Allow-Headers "Content-Type, Accept"
|
||||
|
||||
# Set JSON content type for .json files
|
||||
<FilesMatch "\.json$">
|
||||
ForceType application/json
|
||||
Header always set Content-Type "application/json"
|
||||
</FilesMatch>
|
||||
|
||||
# Cache control - short cache for dynamic content
|
||||
<FilesMatch "discovery\.json$">
|
||||
Header always set Cache-Control "max-age=60, must-revalidate"
|
||||
</FilesMatch>
|
||||
|
||||
<FilesMatch "islands\.json$">
|
||||
Header always set Cache-Control "max-age=30, must-revalidate"
|
||||
</FilesMatch>
|
||||
|
||||
<FilesMatch "chains\.json$">
|
||||
Header always set Cache-Control "max-age=60, must-revalidate"
|
||||
</FilesMatch>
|
||||
|
||||
# Longer cache for static content
|
||||
<FilesMatch "openapi\.json$">
|
||||
Header always set Cache-Control "max-age=3600"
|
||||
</FilesMatch>
|
||||
|
||||
<FilesMatch "join/.*\.json$">
|
||||
Header always set Cache-Control "max-age=3600"
|
||||
</FilesMatch>
|
||||
|
||||
# Disable caching for health endpoint
|
||||
<FilesMatch "health$">
|
||||
Header always set Cache-Control "no-cache, no-store, must-revalidate"
|
||||
</FilesMatch>
|
||||
|
||||
# Enable rewrite engine for clean URLs
|
||||
RewriteEngine On
|
||||
|
||||
# Redirect /agent to /agent/ (add trailing slash)
|
||||
RewriteRule ^/agent$ /agent/ [R=301,L]
|
||||
105
website/agent/README.md
Normal file
105
website/agent/README.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# AITBC Agent API
|
||||
|
||||
Machine-readable API endpoints for autonomous agents to discover and interact with the AITBC network.
|
||||
|
||||
## Overview
|
||||
|
||||
This directory provides agent-first access to the AITBC blockchain network. All endpoints return structured JSON for programmatic consumption.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# 1. Discover the network
|
||||
curl -s http://aitbc:8006/agent/discovery.json | jq .
|
||||
|
||||
# 2. Get island information
|
||||
curl -s http://aitbc:8006/agent/islands.json | jq '.islands[]'
|
||||
|
||||
# 3. Get chain information
|
||||
curl -s http://aitbc:8006/agent/chains.json | jq '.chains[]'
|
||||
|
||||
# 4. Get join instructions
|
||||
curl -s http://aitbc:8006/agent/join/ait-mainnet.json | jq '.how_to_join'
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Discovery
|
||||
|
||||
| Endpoint | Description | Cache |
|
||||
|----------|-------------|-------|
|
||||
| `/agent/discovery.json` | Complete network information | 60s |
|
||||
| `/agent/islands.json` | All islands with status | 30s |
|
||||
| `/agent/chains.json` | Chain configurations | 60s |
|
||||
|
||||
### Join Network
|
||||
|
||||
| Endpoint | Description | Cache |
|
||||
|----------|-------------|-------|
|
||||
| `/agent/join/ait-mainnet.json` | Join instructions for mainnet | 1h |
|
||||
| `/agent/join/ait-testnet.json` | Join instructions for testnet | 1h |
|
||||
|
||||
### API Documentation
|
||||
|
||||
| Endpoint | Description | Cache |
|
||||
|----------|-------------|-------|
|
||||
| `/agent/openapi.json` | OpenAPI 3.0 specification | 1h |
|
||||
| `/agent/health` | Health check endpoint | No cache |
|
||||
|
||||
### RPC Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
|----------|-------------|
|
||||
| `/rpc/head` | Current head block |
|
||||
| `/rpc/info` | Chain information |
|
||||
| `/rpc/islands` | Island memberships |
|
||||
| `/rpc/islands/{id}` | Island details |
|
||||
|
||||
## CORS Support
|
||||
|
||||
All `/agent/` and `/rpc/` endpoints include CORS headers for cross-origin access:
|
||||
|
||||
```
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type, Accept
|
||||
```
|
||||
|
||||
## Agent Landing Page
|
||||
|
||||
Human-readable documentation is available at:
|
||||
- http://aitbc:8006/agent/
|
||||
|
||||
## Network Architecture
|
||||
|
||||
### Islands
|
||||
|
||||
- **ait-mainnet-island**: Production chain (hub: aitbc)
|
||||
- **ait-testnet-island**: Test chain (hub: aitbc1)
|
||||
|
||||
### Nodes
|
||||
|
||||
| Node | Role | Chains | Island |
|
||||
|------|------|--------|--------|
|
||||
| aitbc | Hub | ait-mainnet | ait-mainnet-island |
|
||||
| aitbc | Follower | ait-testnet | ait-testnet-island |
|
||||
| aitbc1 | Hub | ait-testnet | ait-testnet-island |
|
||||
| aitbc1 | Follower | ait-mainnet | ait-mainnet-island |
|
||||
|
||||
## Configuration Templates
|
||||
|
||||
See `/agent/join/*.json` files for complete configuration templates including:
|
||||
- Environment variables
|
||||
- P2P peer lists
|
||||
- RPC endpoints
|
||||
- Step-by-step join instructions
|
||||
|
||||
## Version
|
||||
|
||||
- API Version: 1.0.0
|
||||
- Format Version: 1.0
|
||||
- Last Updated: 2026-05-19
|
||||
|
||||
## For Humans
|
||||
|
||||
The main website is available at the root: http://aitbc:8006/
|
||||
72
website/agent/chains.json
Normal file
72
website/agent/chains.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"chains": [
|
||||
{
|
||||
"chain_id": "ait-mainnet",
|
||||
"name": "AIT Mainnet",
|
||||
"island_id": "ait-mainnet-island",
|
||||
"type": "production",
|
||||
"status": "active",
|
||||
"config": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337,
|
||||
"enable_empty_blocks": true,
|
||||
"max_empty_block_interval": 60
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": ["http://aitbc:8006/rpc", "http://aitbc1:8006/rpc"],
|
||||
"head": "/rpc/head",
|
||||
"info": "/rpc/info",
|
||||
"supply": "/rpc/supply"
|
||||
},
|
||||
"join": {
|
||||
"p2p": {
|
||||
"port": 7070,
|
||||
"peers": ["aitbc:7070", "aitbc1:7070"]
|
||||
},
|
||||
"sync": {
|
||||
"source": "http://aitbc1:8006",
|
||||
"chain_id": "ait-mainnet"
|
||||
},
|
||||
"guide": "/agent/join/ait-mainnet.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"chain_id": "ait-testnet",
|
||||
"name": "AIT Testnet",
|
||||
"island_id": "ait-testnet-island",
|
||||
"type": "test",
|
||||
"status": "active",
|
||||
"config": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337,
|
||||
"enable_empty_blocks": true,
|
||||
"max_empty_block_interval": 60
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": ["http://aitbc:8006/rpc", "http://aitbc1:8006/rpc"],
|
||||
"head": "/rpc/head",
|
||||
"info": "/rpc/info",
|
||||
"supply": "/rpc/supply"
|
||||
},
|
||||
"join": {
|
||||
"p2p": {
|
||||
"port": 7070,
|
||||
"peers": ["aitbc:7070", "aitbc1:7070"]
|
||||
},
|
||||
"sync": {
|
||||
"source": "http://aitbc1:8006",
|
||||
"chain_id": "ait-testnet"
|
||||
},
|
||||
"guide": "/agent/join/ait-testnet.json"
|
||||
}
|
||||
}
|
||||
],
|
||||
"_meta": {
|
||||
"generated_at": "2026-05-19T15:50:00Z",
|
||||
"format_version": "1.0",
|
||||
"total_chains": 2,
|
||||
"active_chains": 2
|
||||
}
|
||||
}
|
||||
70
website/agent/discovery.json
Normal file
70
website/agent/discovery.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"network": {
|
||||
"name": "AITBC",
|
||||
"version": "1.0.0",
|
||||
"description": "AI-powered blockchain platform with multi-island architecture",
|
||||
"apis": {
|
||||
"rpc": {
|
||||
"url": "http://localhost:8006/rpc",
|
||||
"documentation": "/agent/openapi.json",
|
||||
"version": "1.0"
|
||||
},
|
||||
"agent": {
|
||||
"discovery": "/agent/discovery.json",
|
||||
"islands": "/agent/islands.json",
|
||||
"chains": "/agent/chains.json",
|
||||
"health": "/agent/health",
|
||||
"join": "/agent/join/"
|
||||
}
|
||||
},
|
||||
"islands": [
|
||||
{
|
||||
"island_id": "ait-mainnet-island",
|
||||
"name": "AIT Mainnet",
|
||||
"chain_id": "ait-mainnet",
|
||||
"status": "active",
|
||||
"description": "Primary production chain for AITBC",
|
||||
"endpoints": {
|
||||
"rpc": ["http://aitbc:8006", "http://aitbc1:8006"],
|
||||
"p2p": ["aitbc:7070", "aitbc1:7070"]
|
||||
},
|
||||
"chain_info": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337
|
||||
},
|
||||
"join_guide": "/agent/join/ait-mainnet.json"
|
||||
},
|
||||
{
|
||||
"island_id": "ait-testnet-island",
|
||||
"name": "AIT Testnet",
|
||||
"chain_id": "ait-testnet",
|
||||
"status": "active",
|
||||
"description": "Test network for development and experimentation",
|
||||
"endpoints": {
|
||||
"rpc": ["http://aitbc:8006", "http://aitbc1:8006"],
|
||||
"p2p": ["aitbc:7070", "aitbc1:7070"]
|
||||
},
|
||||
"chain_info": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337
|
||||
},
|
||||
"join_guide": "/agent/join/ait-testnet.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"this_node": {
|
||||
"node_id": "aitbc",
|
||||
"role": "hub",
|
||||
"is_hub": true,
|
||||
"block_production": true,
|
||||
"chains": ["ait-mainnet"],
|
||||
"island_memberships": ["ait-mainnet-island"],
|
||||
"discovery_url": "http://aitbc:8006/agent/discovery.json"
|
||||
},
|
||||
"_meta": {
|
||||
"generated_at": "2026-05-19T15:50:00Z",
|
||||
"format_version": "1.0"
|
||||
}
|
||||
}
|
||||
23
website/agent/health
Normal file
23
website/agent/health
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2026-05-19T15:50:00Z",
|
||||
"node_id": "aitbc",
|
||||
"services": {
|
||||
"blockchain_node": "running",
|
||||
"blockchain_rpc": "running",
|
||||
"p2p": "running"
|
||||
},
|
||||
"chains": [
|
||||
{
|
||||
"chain_id": "ait-mainnet",
|
||||
"status": "active",
|
||||
"sync_status": "hub"
|
||||
},
|
||||
{
|
||||
"chain_id": "ait-testnet",
|
||||
"status": "active",
|
||||
"sync_status": "syncing"
|
||||
}
|
||||
],
|
||||
"discovery": "http://aitbc:8006/agent/discovery.json"
|
||||
}
|
||||
356
website/agent/index.html
Normal file
356
website/agent/index.html
Normal file
@@ -0,0 +1,356 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AITBC Agent API - Machine-Readable Network Interface</title>
|
||||
<meta name="description" content="Agent-first API for AITBC blockchain network discovery and island management">
|
||||
<meta name="robots" content="noindex, follow">
|
||||
<link rel="alternate" type="application/json" href="/agent/discovery.json" title="AITBC Network Discovery">
|
||||
<style>
|
||||
:root {
|
||||
--primary: #2563eb;
|
||||
--secondary: #7c3aed;
|
||||
--bg: #0f172a;
|
||||
--surface: #1e293b;
|
||||
--text: #f8fafc;
|
||||
--text-muted: #94a3b8;
|
||||
--border: #334155;
|
||||
--success: #10b981;
|
||||
--warning: #f59e0b;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, monospace;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
padding: 2rem;
|
||||
}
|
||||
.container { max-width: 900px; margin: 0 auto; }
|
||||
header { margin-bottom: 2rem; padding-bottom: 1rem; border-bottom: 1px solid var(--border); }
|
||||
h1 { font-size: 1.5rem; color: var(--primary); margin-bottom: 0.5rem; }
|
||||
.subtitle { color: var(--text-muted); font-size: 0.9rem; }
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--success);
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.section { margin: 2rem 0; }
|
||||
h2 {
|
||||
font-size: 1.1rem;
|
||||
color: var(--secondary);
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.endpoint-grid {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
}
|
||||
.endpoint {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
}
|
||||
.endpoint-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.method {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.path {
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text);
|
||||
}
|
||||
.description {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.code-block {
|
||||
background: #000;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
padding: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
code {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.85rem;
|
||||
color: #a5b4fc;
|
||||
}
|
||||
.copy-btn {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.75rem;
|
||||
float: right;
|
||||
}
|
||||
.copy-btn:hover { background: var(--border); }
|
||||
.island-status {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
.island-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 1rem;
|
||||
}
|
||||
.island-card h3 {
|
||||
font-size: 1rem;
|
||||
color: var(--primary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.status-indicator {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--success);
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 3rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--border);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
a {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover { text-decoration: underline; }
|
||||
.json-link {
|
||||
display: inline-block;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.note {
|
||||
background: rgba(37, 99, 235, 0.1);
|
||||
border-left: 3px solid var(--primary);
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>AITBC Agent API <span class="badge">v1.0</span></h1>
|
||||
<p class="subtitle">Machine-readable network interface for autonomous agents</p>
|
||||
</header>
|
||||
|
||||
<div class="note">
|
||||
<strong>Agent-First Design:</strong> This page provides human-readable documentation, but all endpoints return structured JSON for programmatic consumption. Start with <a href="/agent/discovery.json">/agent/discovery.json</a> for complete network information.
|
||||
</div>
|
||||
|
||||
<section class="section">
|
||||
<h2>Network Status</h2>
|
||||
<div class="island-status">
|
||||
<div class="island-card">
|
||||
<h3>AIT Mainnet</h3>
|
||||
<p><span class="status-indicator"></span>active</p>
|
||||
<p class="description">Island: ait-mainnet-island</p>
|
||||
<p class="description">Role: Hub (Block Production)</p>
|
||||
</div>
|
||||
<div class="island-card">
|
||||
<h3>AIT Testnet</h3>
|
||||
<p><span class="status-indicator"></span>active</p>
|
||||
<p class="description">Island: ait-testnet-island</p>
|
||||
<p class="description">Role: Follower (Syncing)</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Agent Discovery</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/discovery.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Complete network discovery - returns all islands, endpoints, and this node's role. <strong>Start here.</strong></p>
|
||||
<a href="/agent/discovery.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Island Management</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/islands.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">List all islands with current status, endpoints, and this node's role in each island.</p>
|
||||
<a href="/agent/islands.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/rpc/islands</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Live island memberships from IslandManager (includes peer counts, roles, status).</p>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/rpc/islands/{island_id}</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Detailed information about a specific island.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Chain Information</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/chains.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">All chains with configuration, endpoints, and join information.</p>
|
||||
<a href="/agent/chains.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/rpc/head</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Current head block (height, hash, timestamp).</p>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/rpc/info</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Chain information (chain_id, network_id, consensus).</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Join Network</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/join/ait-mainnet.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Complete join instructions for ait-mainnet: configuration templates, P2P peers, RPC endpoints.</p>
|
||||
<a href="/agent/join/ait-mainnet.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/join/ait-testnet.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Complete join instructions for ait-testnet.</p>
|
||||
<a href="/agent/join/ait-testnet.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>API Documentation</h2>
|
||||
<div class="endpoint-grid">
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/openapi.json</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">OpenAPI 3.0 specification for all RPC and agent endpoints.</p>
|
||||
<a href="/agent/openapi.json" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
<div class="endpoint">
|
||||
<div class="endpoint-header">
|
||||
<span class="path">/agent/health</span>
|
||||
<span class="method">GET</span>
|
||||
</div>
|
||||
<p class="description">Health check endpoint for monitoring.</p>
|
||||
<a href="/agent/health" class="json-link">View JSON →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Quick Start for Agents</h2>
|
||||
<div class="code-block">
|
||||
<button class="copy-btn" onclick="navigator.clipboard.writeText(this.nextElementSibling.innerText)">Copy</button>
|
||||
<code># 1. Discover network
|
||||
curl -s http://aitbc:8006/agent/discovery.json | jq .
|
||||
|
||||
# 2. Get island information
|
||||
curl -s http://aitbc:8006/agent/islands.json | jq '.islands[]'
|
||||
|
||||
# 3. Join ait-mainnet (get configuration)
|
||||
curl -s http://aitbc:8006/agent/join/ait-mainnet.json | jq '.how_to_join'
|
||||
|
||||
# 4. Check chain head
|
||||
curl -s http://aitbc:8006/rpc/head | jq .</code>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Key Configuration Values</h2>
|
||||
<div class="code-block">
|
||||
<button class="copy-btn" onclick="navigator.clipboard.writeText(this.nextElementSibling.innerText)">Copy</button>
|
||||
<code>{
|
||||
"p2p": {
|
||||
"port": 7070,
|
||||
"peers": ["aitbc:7070", "aitbc1:7070"]
|
||||
},
|
||||
"rpc": {
|
||||
"aitbc": "http://aitbc:8006",
|
||||
"aitbc1": "http://aitbc1:8006"
|
||||
},
|
||||
"islands": [
|
||||
{
|
||||
"id": "ait-mainnet-island",
|
||||
"chain": "ait-mainnet",
|
||||
"hub": "aitbc"
|
||||
},
|
||||
{
|
||||
"id": "ait-testnet-island",
|
||||
"chain": "ait-testnet",
|
||||
"hub": "aitbc1"
|
||||
}
|
||||
]
|
||||
}</code>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<p>AITBC Network • Agent-First Architecture</p>
|
||||
<p>Node ID: aitbc | Role: Hub | <a href="/">Human Interface →</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
103
website/agent/islands.json
Normal file
103
website/agent/islands.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"islands": [
|
||||
{
|
||||
"island_id": "ait-mainnet-island",
|
||||
"island_name": "AIT Mainnet",
|
||||
"chain_id": "ait-mainnet",
|
||||
"status": "active",
|
||||
"role": "hub",
|
||||
"chain_info": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337,
|
||||
"genesis_timestamp": "2026-05-19T14:44:44.174290"
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": [
|
||||
{
|
||||
"url": "http://aitbc:8006",
|
||||
"node_id": "aitbc",
|
||||
"role": "hub"
|
||||
},
|
||||
{
|
||||
"url": "http://aitbc1:8006",
|
||||
"node_id": "aitbc1",
|
||||
"role": "follower"
|
||||
}
|
||||
],
|
||||
"p2p": [
|
||||
{
|
||||
"address": "aitbc:7070",
|
||||
"node_id": "aitbc"
|
||||
},
|
||||
{
|
||||
"address": "aitbc1:7070",
|
||||
"node_id": "aitbc1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"this_node": {
|
||||
"node_id": "aitbc",
|
||||
"role": "hub",
|
||||
"is_hub": true,
|
||||
"block_production_chains": ["ait-mainnet"],
|
||||
"enable_block_production": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"island_id": "ait-testnet-island",
|
||||
"island_name": "AIT Testnet",
|
||||
"chain_id": "ait-testnet",
|
||||
"status": "active",
|
||||
"role": "follower",
|
||||
"chain_info": {
|
||||
"block_time": 5,
|
||||
"consensus": "proof_of_authority",
|
||||
"network_id": 1337,
|
||||
"genesis_timestamp": "2025-01-01T00:00:00"
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": [
|
||||
{
|
||||
"url": "http://aitbc:8006",
|
||||
"node_id": "aitbc",
|
||||
"role": "follower"
|
||||
},
|
||||
{
|
||||
"url": "http://aitbc1:8006",
|
||||
"node_id": "aitbc1",
|
||||
"role": "hub"
|
||||
}
|
||||
],
|
||||
"p2p": [
|
||||
{
|
||||
"address": "aitbc:7070",
|
||||
"node_id": "aitbc"
|
||||
},
|
||||
{
|
||||
"address": "aitbc1:7070",
|
||||
"node_id": "aitbc1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sync_source": {
|
||||
"host": "aitbc1",
|
||||
"port": 8006,
|
||||
"rpc_url": "http://aitbc1:8006"
|
||||
},
|
||||
"this_node": {
|
||||
"node_id": "aitbc",
|
||||
"role": "follower",
|
||||
"is_hub": false,
|
||||
"block_production_chains": [],
|
||||
"enable_block_production": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"_meta": {
|
||||
"generated_at": "2026-05-19T15:50:00Z",
|
||||
"format_version": "1.0",
|
||||
"total_islands": 2,
|
||||
"active_islands": 2
|
||||
}
|
||||
}
|
||||
121
website/agent/join/ait-mainnet.json
Normal file
121
website/agent/join/ait-mainnet.json
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"chain_id": "ait-mainnet",
|
||||
"island_id": "ait-mainnet-island",
|
||||
"name": "AIT Mainnet",
|
||||
"description": "Primary production chain for AITBC platform",
|
||||
"type": "production",
|
||||
"status": "active",
|
||||
"requirements": {
|
||||
"minimum_version": "1.0.0",
|
||||
"required_services": ["aitbc-blockchain-node", "aitbc-blockchain-rpc"],
|
||||
"ports": {
|
||||
"p2p": 7070,
|
||||
"rpc": 8006
|
||||
}
|
||||
},
|
||||
"how_to_join": {
|
||||
"step_1_environment": {
|
||||
"description": "Configure node.env for this node",
|
||||
"file": "/etc/aitbc/node.env",
|
||||
"variables": {
|
||||
"NODE_ID": "your-node-id",
|
||||
"p2p_node_id": "node-$(uuidgen | tr -d '-')",
|
||||
"p2p_bind_host": "0.0.0.0",
|
||||
"p2p_bind_port": "7070",
|
||||
"proposer_id": "your-proposer-id",
|
||||
"p2p_peers": "aitbc:7070,aitbc1:7070",
|
||||
"enable_block_production": "false",
|
||||
"block_production_chains": ""
|
||||
},
|
||||
"note": "Set enable_block_production=false for follower nodes"
|
||||
},
|
||||
"step_2_blockchain_env": {
|
||||
"description": "Configure blockchain.env",
|
||||
"file": "/etc/aitbc/blockchain.env",
|
||||
"variables": {
|
||||
"island_id": "ait-mainnet-island",
|
||||
"supported_chains": "ait-mainnet",
|
||||
"CHAIN_ID": "ait-mainnet",
|
||||
"auto_sync_enabled": "true",
|
||||
"default_peer_rpc_url": "http://aitbc1:8006",
|
||||
"SYNC_SOURCE_HOST": "aitbc1",
|
||||
"SYNC_SOURCE_PORT": "8006",
|
||||
"SYNC_CHAIN_ID": "ait-mainnet"
|
||||
}
|
||||
},
|
||||
"step_3_networking": {
|
||||
"description": "Ensure network connectivity",
|
||||
"requirements": [
|
||||
"Port 7070 open for P2P communication",
|
||||
"Port 8006 open for RPC access",
|
||||
"Connectivity to aitbc (10.1.223.93) and aitbc1 (10.1.223.40)"
|
||||
]
|
||||
},
|
||||
"step_4_start_services": {
|
||||
"description": "Start blockchain services",
|
||||
"commands": [
|
||||
"systemctl start aitbc-blockchain-node.service",
|
||||
"systemctl start aitbc-blockchain-rpc.service"
|
||||
]
|
||||
},
|
||||
"step_5_verify": {
|
||||
"description": "Verify successful join",
|
||||
"commands": [
|
||||
"curl -s http://localhost:8006/rpc/head",
|
||||
"sqlite3 /var/lib/aitbc/data/ait-mainnet/chain.db 'SELECT MAX(height) FROM block'"
|
||||
],
|
||||
"expected_result": "Block height should be increasing as blocks are synced"
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": {
|
||||
"hub": "http://aitbc:8006",
|
||||
"backup": "http://aitbc1:8006"
|
||||
},
|
||||
"p2p": {
|
||||
"peers": ["aitbc:7070", "aitbc1:7070"]
|
||||
}
|
||||
},
|
||||
"configuration_templates": {
|
||||
"follower_node": {
|
||||
"node.env": {
|
||||
"NODE_ID": "your-node-id",
|
||||
"p2p_node_id": "node-unique-uuid",
|
||||
"p2p_bind_host": "0.0.0.0",
|
||||
"p2p_bind_port": "7070",
|
||||
"proposer_id": "ait1your-proposer-id",
|
||||
"p2p_peers": "aitbc:7070,aitbc1:7070",
|
||||
"trusted_proposers": "",
|
||||
"block_production_chains": "",
|
||||
"enable_block_production": "false"
|
||||
},
|
||||
"blockchain.env": {
|
||||
"auto_sync_enabled": "true",
|
||||
"island_id": "ait-mainnet-island",
|
||||
"supported_chains": "ait-mainnet",
|
||||
"default_peer_rpc_url": "http://aitbc1:8006",
|
||||
"SYNC_SOURCE_HOST": "aitbc1",
|
||||
"SYNC_SOURCE_PORT": "8006",
|
||||
"SYNC_CHAIN_ID": "ait-mainnet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"troubleshooting": {
|
||||
"gap_detected_errors": {
|
||||
"cause": "Node is receiving blocks but missing intermediate blocks",
|
||||
"solution": "Ensure auto_sync_enabled=true and default_peer_rpc_url points to active hub"
|
||||
},
|
||||
"fork_detection": {
|
||||
"cause": "Multiple nodes with same proposer_id producing blocks",
|
||||
"solution": "Ensure enable_block_production=false on follower nodes"
|
||||
},
|
||||
"p2p_connection_failed": {
|
||||
"cause": "Cannot connect to P2P peers",
|
||||
"solution": "Verify p2p_bind_host and p2p_bind_port are set correctly, check firewall rules"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"format_version": "1.0",
|
||||
"updated_at": "2026-05-19T15:50:00Z"
|
||||
}
|
||||
}
|
||||
122
website/agent/join/ait-testnet.json
Normal file
122
website/agent/join/ait-testnet.json
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"chain_id": "ait-testnet",
|
||||
"island_id": "ait-testnet-island",
|
||||
"name": "AIT Testnet",
|
||||
"description": "Test network for AITBC platform development and experimentation",
|
||||
"type": "test",
|
||||
"status": "active",
|
||||
"requirements": {
|
||||
"minimum_version": "1.0.0",
|
||||
"required_services": ["aitbc-blockchain-node", "aitbc-blockchain-rpc"],
|
||||
"ports": {
|
||||
"p2p": 7070,
|
||||
"rpc": 8006
|
||||
}
|
||||
},
|
||||
"how_to_join": {
|
||||
"step_1_environment": {
|
||||
"description": "Configure node.env for this node",
|
||||
"file": "/etc/aitbc/node.env",
|
||||
"variables": {
|
||||
"NODE_ID": "your-node-id",
|
||||
"p2p_node_id": "node-$(uuidgen | tr -d '-')",
|
||||
"p2p_bind_host": "0.0.0.0",
|
||||
"p2p_bind_port": "7070",
|
||||
"proposer_id": "your-proposer-id",
|
||||
"p2p_peers": "aitbc:7070,aitbc1:7070",
|
||||
"enable_block_production": "false",
|
||||
"block_production_chains": ""
|
||||
},
|
||||
"note": "Set enable_block_production=false for follower nodes (hub is aitbc1)"
|
||||
},
|
||||
"step_2_blockchain_env": {
|
||||
"description": "Configure blockchain.env",
|
||||
"file": "/etc/aitbc/blockchain.env",
|
||||
"variables": {
|
||||
"island_id": "ait-testnet-island",
|
||||
"supported_chains": "ait-testnet",
|
||||
"CHAIN_ID": "ait-testnet",
|
||||
"auto_sync_enabled": "true",
|
||||
"default_peer_rpc_url": "http://aitbc:8006",
|
||||
"SYNC_SOURCE_HOST": "aitbc",
|
||||
"SYNC_SOURCE_PORT": "8006",
|
||||
"SYNC_CHAIN_ID": "ait-testnet"
|
||||
}
|
||||
},
|
||||
"step_3_networking": {
|
||||
"description": "Ensure network connectivity",
|
||||
"requirements": [
|
||||
"Port 7070 open for P2P communication",
|
||||
"Port 8006 open for RPC access",
|
||||
"Connectivity to aitbc (10.1.223.93) and aitbc1 (10.1.223.40)"
|
||||
]
|
||||
},
|
||||
"step_4_start_services": {
|
||||
"description": "Start blockchain services",
|
||||
"commands": [
|
||||
"systemctl start aitbc-blockchain-node.service",
|
||||
"systemctl start aitbc-blockchain-rpc.service"
|
||||
]
|
||||
},
|
||||
"step_5_verify": {
|
||||
"description": "Verify successful join",
|
||||
"commands": [
|
||||
"curl -s http://localhost:8006/rpc/head",
|
||||
"sqlite3 /var/lib/aitbc/data/ait-testnet/chain.db 'SELECT MAX(height) FROM block'"
|
||||
],
|
||||
"expected_result": "Block height should be increasing as blocks are synced from hub (aitbc1)"
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
"rpc": {
|
||||
"hub": "http://aitbc1:8006",
|
||||
"backup": "http://aitbc:8006"
|
||||
},
|
||||
"p2p": {
|
||||
"peers": ["aitbc:7070", "aitbc1:7070"]
|
||||
}
|
||||
},
|
||||
"configuration_templates": {
|
||||
"follower_node": {
|
||||
"node.env": {
|
||||
"NODE_ID": "your-node-id",
|
||||
"p2p_node_id": "node-unique-uuid",
|
||||
"p2p_bind_host": "0.0.0.0",
|
||||
"p2p_bind_port": "7070",
|
||||
"proposer_id": "ait1your-proposer-id",
|
||||
"p2p_peers": "aitbc:7070,aitbc1:7070",
|
||||
"trusted_proposers": "",
|
||||
"block_production_chains": "",
|
||||
"enable_block_production": "false"
|
||||
},
|
||||
"blockchain.env": {
|
||||
"auto_sync_enabled": "true",
|
||||
"island_id": "ait-testnet-island",
|
||||
"supported_chains": "ait-testnet",
|
||||
"default_peer_rpc_url": "http://aitbc:8006",
|
||||
"SYNC_SOURCE_HOST": "aitbc",
|
||||
"SYNC_SOURCE_PORT": "8006",
|
||||
"SYNC_CHAIN_ID": "ait-testnet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"troubleshooting": {
|
||||
"gap_detected_errors": {
|
||||
"cause": "Node is receiving blocks but missing intermediate blocks",
|
||||
"solution": "Ensure auto_sync_enabled=true and default_peer_rpc_url points to active hub (aitbc1 for testnet)"
|
||||
},
|
||||
"fork_detection": {
|
||||
"cause": "Multiple nodes with same proposer_id producing blocks",
|
||||
"solution": "Ensure enable_block_production=false on follower nodes (only aitbc1 should produce on testnet)"
|
||||
},
|
||||
"p2p_connection_failed": {
|
||||
"cause": "Cannot connect to P2P peers",
|
||||
"solution": "Verify p2p_bind_host and p2p_bind_port are set correctly, check firewall rules"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"format_version": "1.0",
|
||||
"updated_at": "2026-05-19T15:50:00Z",
|
||||
"note": "Testnet hub is aitbc1, not aitbc. Ensure sync source points to correct hub."
|
||||
}
|
||||
}
|
||||
418
website/agent/openapi.json
Normal file
418
website/agent/openapi.json
Normal file
@@ -0,0 +1,418 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "AITBC Agent API",
|
||||
"description": "Machine-readable API for AITBC blockchain agents. Provides endpoints for discovery, island management, and chain operations.",
|
||||
"version": "1.0.0",
|
||||
"contact": {
|
||||
"name": "AITBC Network",
|
||||
"url": "https://aitbc.bubuit.net"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://localhost:8006",
|
||||
"description": "Local node RPC"
|
||||
},
|
||||
{
|
||||
"url": "http://aitbc:8006",
|
||||
"description": "AITBC hub node"
|
||||
},
|
||||
{
|
||||
"url": "http://aitbc1:8006",
|
||||
"description": "AITBC1 node"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/agent/discovery.json": {
|
||||
"get": {
|
||||
"summary": "Network Discovery",
|
||||
"description": "Returns complete network information for agent auto-discovery",
|
||||
"operationId": "getDiscovery",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Network discovery information",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/DiscoveryResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/agent/islands.json": {
|
||||
"get": {
|
||||
"summary": "List Islands",
|
||||
"description": "Returns all islands in the network with current status",
|
||||
"operationId": "getIslands",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of islands",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/IslandsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/agent/chains.json": {
|
||||
"get": {
|
||||
"summary": "List Chains",
|
||||
"description": "Returns all chains in the network with configuration",
|
||||
"operationId": "getChains",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "List of chains",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ChainsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/agent/join/{chain_id}.json": {
|
||||
"get": {
|
||||
"summary": "Join Information",
|
||||
"description": "Returns detailed instructions for joining a specific chain",
|
||||
"operationId": "getJoinInfo",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "chain_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"enum": ["ait-mainnet", "ait-testnet"]
|
||||
},
|
||||
"description": "Chain ID to get join information for"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Join instructions",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/JoinInfoResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/rpc/head": {
|
||||
"get": {
|
||||
"summary": "Get Chain Head",
|
||||
"description": "Returns the current head block of the chain",
|
||||
"operationId": "getHead",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Current head block",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HeadResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/rpc/info": {
|
||||
"get": {
|
||||
"summary": "Get Chain Info",
|
||||
"description": "Returns general information about the blockchain",
|
||||
"operationId": "getInfo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Chain information",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/InfoResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/rpc/islands": {
|
||||
"get": {
|
||||
"summary": "List Island Memberships",
|
||||
"description": "Returns island memberships for this node",
|
||||
"operationId": "listIslands",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Island memberships",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/IslandMembershipsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/rpc/islands/{island_id}": {
|
||||
"get": {
|
||||
"summary": "Get Island Details",
|
||||
"description": "Returns detailed information about a specific island",
|
||||
"operationId": "getIsland",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "island_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Island ID"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Island details",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/IslandDetailResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"DiscoveryResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"network": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"version": { "type": "string" },
|
||||
"apis": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rpc": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": { "type": "string" },
|
||||
"documentation": { "type": "string" },
|
||||
"version": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"agent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"discovery": { "type": "string" },
|
||||
"islands": { "type": "string" },
|
||||
"chains": { "type": "string" },
|
||||
"health": { "type": "string" },
|
||||
"join": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"islands": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/IslandSummary"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"this_node": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"node_id": { "type": "string" },
|
||||
"role": { "type": "string" },
|
||||
"is_hub": { "type": "boolean" },
|
||||
"block_production": { "type": "boolean" },
|
||||
"chains": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"IslandSummary": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"island_id": { "type": "string" },
|
||||
"name": { "type": "string" },
|
||||
"chain_id": { "type": "string" },
|
||||
"status": { "type": "string", "enum": ["active", "inactive"] },
|
||||
"endpoints": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rpc": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"p2p": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"IslandsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"islands": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/IslandDetail"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"IslandDetail": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"island_id": { "type": "string" },
|
||||
"island_name": { "type": "string" },
|
||||
"chain_id": { "type": "string" },
|
||||
"status": { "type": "string" },
|
||||
"role": { "type": "string" },
|
||||
"chain_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"block_time": { "type": "integer" },
|
||||
"consensus": { "type": "string" },
|
||||
"network_id": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"endpoints": {
|
||||
"type": "object"
|
||||
},
|
||||
"this_node": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChainsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chains": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ChainInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChainInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chain_id": { "type": "string" },
|
||||
"name": { "type": "string" },
|
||||
"island_id": { "type": "string" },
|
||||
"type": { "type": "string" },
|
||||
"config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"block_time": { "type": "integer" },
|
||||
"consensus": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"join": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JoinInfoResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chain_id": { "type": "string" },
|
||||
"island_id": { "type": "string" },
|
||||
"how_to_join": {
|
||||
"type": "object"
|
||||
},
|
||||
"endpoints": {
|
||||
"type": "object"
|
||||
},
|
||||
"configuration_templates": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"HeadResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"height": { "type": "integer" },
|
||||
"hash": { "type": "string" },
|
||||
"timestamp": { "type": "string" },
|
||||
"tx_count": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"InfoResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chain_id": { "type": "string" },
|
||||
"network_id": { "type": "integer" },
|
||||
"block_time": { "type": "integer" },
|
||||
"version": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"IslandMembershipsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"islands": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"island_id": { "type": "string" },
|
||||
"island_name": { "type": "string" },
|
||||
"chain_id": { "type": "string" },
|
||||
"status": { "type": "string" },
|
||||
"role": { "type": "string" },
|
||||
"peer_count": { "type": "integer" },
|
||||
"is_hub": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"IslandDetailResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"island_id": { "type": "string" },
|
||||
"island_name": { "type": "string" },
|
||||
"chain_id": { "type": "string" },
|
||||
"status": { "type": "string" },
|
||||
"role": { "type": "string" },
|
||||
"peer_count": { "type": "integer" },
|
||||
"is_hub": { "type": "boolean" },
|
||||
"joined_at": { "type": "number" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,46 @@ server {
|
||||
proxy_buffers 8 4k;
|
||||
}
|
||||
|
||||
# Agent API - CORS enabled for cross-origin agent access
|
||||
location /agent/ {
|
||||
proxy_pass http://10.1.223.93/agent/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# CORS headers for agent access
|
||||
add_header Access-Control-Allow-Origin * always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "Content-Type, Accept" always;
|
||||
add_header Access-Control-Max-Age 86400 always;
|
||||
|
||||
# Handle preflight requests
|
||||
if ($request_method = 'OPTIONS') {
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# RPC endpoints - CORS enabled
|
||||
location /rpc/ {
|
||||
proxy_pass http://10.1.223.93:8006/rpc/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# CORS headers for agent access
|
||||
add_header Access-Control-Allow-Origin * always;
|
||||
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "Content-Type, Accept, Authorization" always;
|
||||
add_header Access-Control-Max-Age 86400 always;
|
||||
|
||||
# Handle preflight requests
|
||||
if ($request_method = 'OPTIONS') {
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
proxy_pass http://10.1.223.93/health;
|
||||
|
||||
@@ -16,6 +16,39 @@
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://aitbc.bubuit.net">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<!-- Agent Discovery -->
|
||||
<link rel="alternate" type="application/json" href="/agent/discovery.json" title="AITBC Network Discovery for Agents">
|
||||
<!-- Structured Data for Agent Discovery -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"name": "AITBC Network",
|
||||
"url": "https://aitbc.bubuit.net",
|
||||
"description": "AI-powered blockchain platform with multi-island architecture",
|
||||
"potentialAction": {
|
||||
"@type": "SearchAction",
|
||||
"target": "https://aitbc.bubuit.net/agent/discovery.json",
|
||||
"query-input": "required"
|
||||
},
|
||||
"subjectOf": {
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "AITBC Blockchain Node",
|
||||
"applicationCategory": "BlockchainApplication",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"featureList": [
|
||||
"Multi-island architecture",
|
||||
"PoA consensus",
|
||||
"Agent-first API",
|
||||
"Auto-discovery"
|
||||
]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- Performance optimization: resource hints -->
|
||||
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
|
||||
<link rel="dns-prefetch" href="//aitbc.bubuit.net">
|
||||
@@ -50,6 +83,7 @@
|
||||
<a href="/marketplace/" class="global-nav__link">Marketplace</a>
|
||||
<a href="/Exchange/" class="global-nav__link">Exchange</a>
|
||||
<a href="/docs/index.html" class="global-nav__link">Docs</a>
|
||||
<a href="/agent/" class="global-nav__link">Agent API</a>
|
||||
</nav>
|
||||
<div class="global-header__actions">
|
||||
<button onclick="toggleDarkMode()" class="global-dark-toggle" title="Toggle dark mode">
|
||||
|
||||
Reference in New Issue
Block a user