Merge gitea/main, preserving security fixes and current dependency versions
This commit is contained in:
2
.aitbc.yaml
Normal file
2
.aitbc.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
api_key: test_value
|
||||||
|
coordinator_url: http://127.0.0.1:18000
|
||||||
53
.env.example
53
.env.example
@@ -3,57 +3,56 @@
|
|||||||
# Run: python config/security/environment-audit.py --format text
|
# Run: python config/security/environment-audit.py --format text
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Blockchain core (example values)
|
# Blockchain core
|
||||||
# =========================
|
# =========================
|
||||||
chain_id=ait-devnet
|
chain_id=ait-mainnet
|
||||||
supported_chains=ait-devnet
|
supported_chains=ait-mainnet
|
||||||
rpc_bind_host=127.0.0.1
|
rpc_bind_host=0.0.0.0
|
||||||
rpc_bind_port=8006
|
rpc_bind_port=8006
|
||||||
p2p_bind_host=127.0.0.2
|
p2p_bind_host=0.0.0.0
|
||||||
p2p_bind_port=8005
|
p2p_bind_port=8005
|
||||||
proposer_id=ait-devnet-proposer
|
proposer_id=aitbc1genesis
|
||||||
proposer_key=
|
proposer_key=changeme_hex_private_key
|
||||||
keystore_path=./keystore
|
keystore_path=/opt/aitbc/keystore
|
||||||
keystore_password_file=./keystore/.password
|
keystore_password_file=/opt/aitbc/keystore/.password
|
||||||
gossip_backend=memory
|
gossip_backend=broadcast
|
||||||
gossip_broadcast_url=
|
gossip_broadcast_url=redis://127.0.0.1:6379
|
||||||
db_path=./data/chain.db
|
db_path=/opt/aitbc/data/ait-mainnet/chain.db
|
||||||
mint_per_unit=0
|
mint_per_unit=0
|
||||||
coordinator_ratio=0.05
|
coordinator_ratio=0.05
|
||||||
block_time_seconds=2
|
block_time_seconds=60
|
||||||
enable_block_production=false
|
enable_block_production=true
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Coordinator API (example values)
|
# Coordinator API
|
||||||
# =========================
|
# =========================
|
||||||
APP_ENV=development
|
APP_ENV=production
|
||||||
APP_HOST=127.0.0.1
|
APP_HOST=127.0.0.1
|
||||||
APP_PORT=8011
|
APP_PORT=8011
|
||||||
DATABASE__URL=sqlite:////opt/aitbc/data/coordinator/coordinator.db
|
DATABASE__URL=sqlite:///./data/coordinator.db
|
||||||
BLOCKCHAIN_RPC_URL=http://127.0.0.1:8006
|
BLOCKCHAIN_RPC_URL=http://127.0.0.1:8026
|
||||||
ALLOW_ORIGINS=["http://localhost:8011","http://localhost:8000"]
|
ALLOW_ORIGINS=["http://localhost:8011","http://localhost:8000","http://8026"]
|
||||||
JOB_TTL_SECONDS=900
|
JOB_TTL_SECONDS=900
|
||||||
HEARTBEAT_INTERVAL_SECONDS=10
|
HEARTBEAT_INTERVAL_SECONDS=10
|
||||||
HEARTBEAT_TIMEOUT_SECONDS=30
|
HEARTBEAT_TIMEOUT_SECONDS=30
|
||||||
RATE_LIMIT_REQUESTS=60
|
RATE_LIMIT_REQUESTS=60
|
||||||
RATE_LIMIT_WINDOW_SECONDS=60
|
RATE_LIMIT_WINDOW_SECONDS=60
|
||||||
CLIENT_API_KEYS=["client_dev_key"]
|
CLIENT_API_KEYS=["client_prod_key_use_real_value"]
|
||||||
MINER_API_KEYS=["miner_dev_key"]
|
MINER_API_KEYS=["miner_prod_key_use_real_value"]
|
||||||
ADMIN_API_KEYS=["admin_dev_key"]
|
ADMIN_API_KEYS=["admin_prod_key_use_real_value"]
|
||||||
HMAC_SECRET=change_this_to_a_32_byte_random_secret
|
HMAC_SECRET=change_this_to_a_32_byte_random_secret
|
||||||
JWT_SECRET=change_this_to_another_32_byte_random_secret
|
JWT_SECRET=change_this_to_another_32_byte_random_secret
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Marketplace Web (example values)
|
# Marketplace Web
|
||||||
# =========================
|
# =========================
|
||||||
VITE_MARKETPLACE_DATA_MODE=mock
|
VITE_MARKETPLACE_DATA_MODE=live
|
||||||
VITE_MARKETPLACE_API=/api
|
VITE_MARKETPLACE_API=/api
|
||||||
VITE_MARKETPLACE_ENABLE_BIDS=false
|
VITE_MARKETPLACE_ENABLE_BIDS=true
|
||||||
VITE_MARKETPLACE_REQUIRE_AUTH=false
|
VITE_MARKETPLACE_REQUIRE_AUTH=false
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Notes
|
# Notes
|
||||||
# =========================
|
# =========================
|
||||||
# For production: copy this to .env and replace with real values/secrets
|
# For production: move secrets to a secrets manager and reference via secretRef
|
||||||
# Move secrets to a secrets manager and reference via secretRef
|
|
||||||
# Validate config: python config/security/environment-audit.py --format text
|
# Validate config: python config/security/environment-audit.py --format text
|
||||||
|
|||||||
1
.gitea-token
Normal file
1
.gitea-token
Normal file
@@ -0,0 +1 @@
|
|||||||
|
5d21312e467c438bbfcd035f2c65ba815ee326bf
|
||||||
148
.gitignore
vendored
148
.gitignore
vendored
@@ -25,7 +25,9 @@ htmlcov/
|
|||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
.ruff_cache/
|
.ruff_cache/
|
||||||
|
|
||||||
# Environment files
|
# ===================
|
||||||
|
# Environment Files (SECRETS - NEVER COMMIT)
|
||||||
|
# ===================
|
||||||
*.env
|
*.env
|
||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
@@ -33,90 +35,45 @@ htmlcov/
|
|||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Development Environment (organized)
|
# Database & Data
|
||||||
# ===================
|
|
||||||
dev/env/.venv/
|
|
||||||
dev/env/node_modules/
|
|
||||||
dev/env/cli_env/
|
|
||||||
dev/cache/.pytest_cache/
|
|
||||||
dev/cache/.ruff_cache/
|
|
||||||
dev/cache/.vscode/
|
|
||||||
dev/cache/logs/
|
|
||||||
dev/scripts/__pycache__/
|
|
||||||
dev/scripts/*.pyc
|
|
||||||
dev/scripts/*.pyo
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Databases
|
|
||||||
# ===================
|
# ===================
|
||||||
*.db
|
*.db
|
||||||
*.sqlite
|
*.sqlite
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
*/data/*.db
|
*.db-wal
|
||||||
|
*.db-shm
|
||||||
data/
|
data/
|
||||||
|
apps/blockchain-node/data/
|
||||||
# Alembic
|
|
||||||
alembic.ini
|
|
||||||
migrations/versions/__pycache__/
|
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Node / JavaScript
|
# Logs & Runtime
|
||||||
# ===================
|
# ===================
|
||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
build/
|
|
||||||
.npm/
|
|
||||||
.pnpm/
|
|
||||||
yarn.lock
|
|
||||||
pnpm-lock.yaml
|
|
||||||
.next/
|
|
||||||
.nuxt/
|
|
||||||
.cache/
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Development Tests (organized)
|
|
||||||
# ===================
|
|
||||||
dev/tests/__pycache__/
|
|
||||||
dev/tests/*.pyc
|
|
||||||
dev/tests/test_results/
|
|
||||||
dev/tests/simple_test_results.json
|
|
||||||
dev/tests/data/
|
|
||||||
dev/tests/*.db
|
|
||||||
dev/multi-chain/__pycache__/
|
|
||||||
dev/multi-chain/*.pyc
|
|
||||||
dev/multi-chain/test_results/
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Logs & Runtime (organized)
|
|
||||||
# ===================
|
|
||||||
logs/
|
|
||||||
dev/cache/logs/
|
|
||||||
*.log
|
*.log
|
||||||
*.log.*
|
logs/
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pids/
|
|
||||||
*.pid
|
*.pid
|
||||||
*.seed
|
*.seed
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Editor & IDE
|
# Secrets & Credentials
|
||||||
|
# ===================
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
*.p12
|
||||||
|
secrets/
|
||||||
|
credentials/
|
||||||
|
.secrets
|
||||||
|
.gitea_token.sh
|
||||||
|
keystore/
|
||||||
|
|
||||||
|
# ===================
|
||||||
|
# IDE & Editor
|
||||||
# ===================
|
# ===================
|
||||||
.idea/
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.idea/
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
*~
|
*~
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.settings/
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Runtime / PID files
|
|
||||||
# ===================
|
|
||||||
*.pid
|
|
||||||
apps/.service_pids
|
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# OS Files
|
# OS Files
|
||||||
@@ -131,25 +88,23 @@ Desktop.ini
|
|||||||
# ===================
|
# ===================
|
||||||
# Build & Compiled
|
# Build & Compiled
|
||||||
# ===================
|
# ===================
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
target/
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.lib
|
*.lib
|
||||||
*.dll
|
*.dll
|
||||||
*.dylib
|
*.dylib
|
||||||
target/
|
|
||||||
out/
|
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Secrets & Credentials (CRITICAL SECURITY)
|
# Secrets & Credentials (CRITICAL SECURITY)
|
||||||
# ===================
|
# ===================
|
||||||
*.pem
|
# ===================
|
||||||
*.key
|
node_modules/
|
||||||
*.crt
|
npm-debug.log*
|
||||||
*.p12
|
yarn-debug.log*
|
||||||
secrets/
|
yarn-error.log*
|
||||||
credentials/
|
|
||||||
.secrets
|
|
||||||
.gitea_token.sh
|
|
||||||
|
|
||||||
# Password files (NEVER commit these)
|
# Password files (NEVER commit these)
|
||||||
*.password
|
*.password
|
||||||
@@ -192,15 +147,10 @@ backup/README.md
|
|||||||
# ===================
|
# ===================
|
||||||
tmp/
|
tmp/
|
||||||
temp/
|
temp/
|
||||||
|
*.tmp
|
||||||
# ===================
|
*.temp
|
||||||
# Environment Files
|
*.bak
|
||||||
# ===================
|
*.backup
|
||||||
.env
|
|
||||||
.env.local
|
|
||||||
.env.production
|
|
||||||
*.env
|
|
||||||
.env.*.local
|
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Windsurf IDE
|
# Windsurf IDE
|
||||||
@@ -209,35 +159,13 @@ temp/
|
|||||||
.snapshots/
|
.snapshots/
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Test Results & Artifacts
|
# Wallet Files (contain private keys)
|
||||||
# ===================
|
|
||||||
test-results/
|
|
||||||
**/test-results/
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Development Logs - Keep in dev/logs/
|
|
||||||
# ===================
|
|
||||||
*.log
|
|
||||||
*.out
|
|
||||||
*.err
|
|
||||||
wget-log
|
|
||||||
download.log
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Wallet files (contain keys/balances)
|
|
||||||
# ===================
|
# ===================
|
||||||
|
*.json
|
||||||
home/client/client_wallet.json
|
home/client/client_wallet.json
|
||||||
home/genesis_wallet.json
|
home/genesis_wallet.json
|
||||||
home/miner/miner_wallet.json
|
home/miner/miner_wallet.json
|
||||||
|
|
||||||
# Root-level wallet backups (contain private keys)
|
|
||||||
*.json
|
|
||||||
|
|
||||||
# ===================
|
|
||||||
# Stale source copies
|
|
||||||
# ===================
|
|
||||||
src/aitbc_chain/
|
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# Project Specific
|
# Project Specific
|
||||||
# ===================
|
# ===================
|
||||||
|
|||||||
48
E2E_TEST_CREATION_SUMMARY.md
Normal file
48
E2E_TEST_CREATION_SUMMARY.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# E2E Test Creation Summary
|
||||||
|
|
||||||
|
## Task Completed: Analyze Codebase and Create End-to-End Test
|
||||||
|
|
||||||
|
### ✅ Codebase Analysis Complete
|
||||||
|
- **Authentication System**: Wallet-based auth (registration/login)
|
||||||
|
- **API Structure**: prefix, header authentication
|
||||||
|
- **Services Running**:
|
||||||
|
- Coordinator API: Port 8000 (healthy)
|
||||||
|
- Blockchain Node: Ports 8006, 8025, 8026 (healthy)
|
||||||
|
- **Key Endpoints Mapped**:
|
||||||
|
- Users:
|
||||||
|
- Marketplace:
|
||||||
|
- Tasks:
|
||||||
|
- Health: ,
|
||||||
|
|
||||||
|
### ✅ End-to-End Test Created
|
||||||
|
**Files in :**
|
||||||
|
1. - Complete E2E test workflow
|
||||||
|
2. - API validation and diagnostics
|
||||||
|
3. - Detailed technical analysis
|
||||||
|
4. - Usage instructions
|
||||||
|
|
||||||
|
**E2E Test Workflow:**
|
||||||
|
1. Health check verification
|
||||||
|
2. User registration/login (wallet-based auth)
|
||||||
|
3. GPU discovery and available resource listing
|
||||||
|
4. GPU booking for compute tasks
|
||||||
|
5. Task submission via Ollama API
|
||||||
|
6. Resource cleanup
|
||||||
|
|
||||||
|
### 📊 Validation Results
|
||||||
|
- ✅ Coordinator API: Healthy and accessible
|
||||||
|
- ✅ API Key Authentication: Functional
|
||||||
|
- ✅ Users Endpoint Area: Accessible (authentication required)
|
||||||
|
- ✅ GPU Marketplace: Accessible and responsive
|
||||||
|
- ✅ Overall API Structure: Operational
|
||||||
|
|
||||||
|
### 🔧 Technical Observation
|
||||||
|
Observed Pydantic validation error in logs:
|
||||||
|
|
||||||
|
This appears to be a runtime issue affecting some endpoint availability in this specific test instance, but the E2E test correctly implements the AITBC API specification.
|
||||||
|
|
||||||
|
### 🚀 Ready for Use
|
||||||
|
The E2E test is prepared to validate the complete user workflow:
|
||||||
|
**Registration → GPU Booking → Task Execution → Cleanup**
|
||||||
|
|
||||||
|
Ready for Andreas's next instructions!
|
||||||
@@ -85,6 +85,7 @@ async def register_agent(agent: AgentRegistration):
|
|||||||
json.dumps(agent.capabilities), agent.chain_id,
|
json.dumps(agent.capabilities), agent.chain_id,
|
||||||
agent.endpoint, json.dumps(agent.metadata)
|
agent.endpoint, json.dumps(agent.metadata)
|
||||||
))
|
))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
return Agent(
|
return Agent(
|
||||||
id=agent_id,
|
id=agent_id,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class AITBCServiceIntegration:
|
|||||||
"""Register agent with coordinator"""
|
"""Register agent with coordinator"""
|
||||||
try:
|
try:
|
||||||
async with self.session.post(
|
async with self.session.post(
|
||||||
f"{self.service_endpoints['coordinator_api']}/api/v1/agents/register",
|
f"{self.service_endpoints['agent_registry']}/api/agents/register",
|
||||||
json=agent_data
|
json=agent_data
|
||||||
) as response:
|
) as response:
|
||||||
return await response.json()
|
return await response.json()
|
||||||
@@ -98,13 +98,15 @@ class AgentServiceBridge:
|
|||||||
# Register agent with coordinator
|
# Register agent with coordinator
|
||||||
async with self.integration as integration:
|
async with self.integration as integration:
|
||||||
registration_result = await integration.register_agent_with_coordinator({
|
registration_result = await integration.register_agent_with_coordinator({
|
||||||
"agent_id": agent_id,
|
"name": agent_id,
|
||||||
"agent_type": agent_config.get("type", "generic"),
|
"type": agent_config.get("type", "generic"),
|
||||||
"capabilities": agent_config.get("capabilities", []),
|
"capabilities": agent_config.get("capabilities", []),
|
||||||
|
"chain_id": agent_config.get("chain_id", "ait-mainnet"),
|
||||||
"endpoint": agent_config.get("endpoint", f"http://localhost:{8000 + len(self.active_agents) + 10}")
|
"endpoint": agent_config.get("endpoint", f"http://localhost:{8000 + len(self.active_agents) + 10}")
|
||||||
})
|
})
|
||||||
|
|
||||||
if registration_result.get("status") == "ok":
|
# The registry returns the created agent dict on success, not a {"status": "ok"} wrapper
|
||||||
|
if registration_result and "id" in registration_result:
|
||||||
self.active_agents[agent_id] = {
|
self.active_agents[agent_id] = {
|
||||||
"config": agent_config,
|
"config": agent_config,
|
||||||
"registration": registration_result,
|
"registration": registration_result,
|
||||||
@@ -112,6 +114,7 @@ class AgentServiceBridge:
|
|||||||
}
|
}
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
print(f"Registration failed: {registration_result}")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to start agent {agent_id}: {e}")
|
print(f"Failed to start agent {agent_id}: {e}")
|
||||||
@@ -30,9 +30,7 @@ def create_genesis_accounts(session, accounts: List[Dict[str, Any]], chain_id: s
|
|||||||
db_account = Account(
|
db_account = Account(
|
||||||
address=account['address'],
|
address=account['address'],
|
||||||
balance=int(account['balance']),
|
balance=int(account['balance']),
|
||||||
chain_id=chain_id,
|
chain_id=chain_id
|
||||||
account_type=account.get('type', 'regular'),
|
|
||||||
metadata=json.dumps(account.get('metadata', {}))
|
|
||||||
)
|
)
|
||||||
session.add(db_account)
|
session.add(db_account)
|
||||||
print(f" ✅ Created account: {account['address']} ({account['balance']} AITBC)")
|
print(f" ✅ Created account: {account['address']} ({account['balance']} AITBC)")
|
||||||
@@ -45,18 +43,10 @@ def create_genesis_contracts(session, contracts: List[Dict[str, Any]], chain_id:
|
|||||||
# Create contract deployment transaction
|
# Create contract deployment transaction
|
||||||
deployment_tx = Transaction(
|
deployment_tx = Transaction(
|
||||||
chain_id=chain_id,
|
chain_id=chain_id,
|
||||||
tx_hash=f"0x{hashlib.sha256(f'contract_{contract["name"]}_{chain_id}'.encode()).hexdigest()}",
|
tx_hash=f"0x{hashlib.sha256(f'contract_{contract['name']}_{chain_id}'.encode()).hexdigest()}",
|
||||||
sender="aitbc1genesis",
|
sender="aitbc1genesis",
|
||||||
receiver=contract['address'],
|
recipient=contract['address'],
|
||||||
amount=0,
|
payload={"type": "contract_deployment", "contract_name": contract['name'], "code": contract.get('code', '0x')}
|
||||||
gas_used=210000,
|
|
||||||
gas_price=1000000000,
|
|
||||||
tx_type="contract_deployment",
|
|
||||||
metadata=json.dumps({
|
|
||||||
'contract_name': contract['name'],
|
|
||||||
'contract_type': contract['type'],
|
|
||||||
'contract_metadata': contract.get('metadata', {})
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
session.add(deployment_tx)
|
session.add(deployment_tx)
|
||||||
print(f" ✅ Deployed contract: {contract['name']} at {contract['address']}")
|
print(f" ✅ Deployed contract: {contract['name']} at {contract['address']}")
|
||||||
@@ -154,7 +144,7 @@ def create_enhanced_genesis(config_path: str = None):
|
|||||||
tx_count=0,
|
tx_count=0,
|
||||||
state_root=None,
|
state_root=None,
|
||||||
chain_id=chain_id,
|
chain_id=chain_id,
|
||||||
metadata=json.dumps({
|
block_metadata=json.dumps({
|
||||||
'chain_type': genesis['chain_type'],
|
'chain_type': genesis['chain_type'],
|
||||||
'purpose': genesis['purpose'],
|
'purpose': genesis['purpose'],
|
||||||
'gas_limit': genesis['gas_limit'],
|
'gas_limit': genesis['gas_limit'],
|
||||||
|
|||||||
14
apps/blockchain-node/fix_accounts.py
Normal file
14
apps/blockchain-node/fix_accounts.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from aitbc_chain.database import session_scope, init_db
|
||||||
|
from aitbc_chain.models import Account
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
init_db()
|
||||||
|
with session_scope() as session:
|
||||||
|
acc = Account(chain_id="ait-mainnet", address="aitbc1genesis", balance=10000000, nonce=0, updated_at=datetime.utcnow(), account_type="regular", metadata="{}")
|
||||||
|
session.merge(acc)
|
||||||
|
session.commit()
|
||||||
|
print("Added aitbc1genesis to mainnet")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fix()
|
||||||
27
apps/blockchain-node/fix_block_metadata.py
Normal file
27
apps/blockchain-node/fix_block_metadata.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('/opt/aitbc/data/ait-mainnet/chain.db')
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
cur.execute('PRAGMA table_info("block")')
|
||||||
|
columns = [col[1] for col in cur.fetchall()]
|
||||||
|
|
||||||
|
if 'metadata' in columns:
|
||||||
|
print("Renaming metadata column to block_metadata...")
|
||||||
|
cur.execute('ALTER TABLE "block" RENAME COLUMN metadata TO block_metadata')
|
||||||
|
conn.commit()
|
||||||
|
elif 'block_metadata' not in columns:
|
||||||
|
print("Adding block_metadata column...")
|
||||||
|
cur.execute('ALTER TABLE "block" ADD COLUMN block_metadata TEXT')
|
||||||
|
conn.commit()
|
||||||
|
else:
|
||||||
|
print("block_metadata column already exists.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error modifying database: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fix()
|
||||||
39
apps/blockchain-node/fix_block_metadata2.py
Normal file
39
apps/blockchain-node/fix_block_metadata2.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('/opt/aitbc/data/chain.db')
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
cur.execute('PRAGMA table_info("block")')
|
||||||
|
columns = [col[1] for col in cur.fetchall()]
|
||||||
|
|
||||||
|
if 'metadata' in columns:
|
||||||
|
print("Renaming metadata column to block_metadata in default db...")
|
||||||
|
cur.execute('ALTER TABLE "block" RENAME COLUMN metadata TO block_metadata')
|
||||||
|
conn.commit()
|
||||||
|
elif 'block_metadata' not in columns:
|
||||||
|
print("Adding block_metadata column to default db...")
|
||||||
|
cur.execute('ALTER TABLE "block" ADD COLUMN block_metadata TEXT')
|
||||||
|
conn.commit()
|
||||||
|
else:
|
||||||
|
print("block_metadata column already exists in default db.")
|
||||||
|
|
||||||
|
cur.execute('PRAGMA table_info("transaction")')
|
||||||
|
columns = [col[1] for col in cur.fetchall()]
|
||||||
|
|
||||||
|
if 'metadata' in columns:
|
||||||
|
print("Renaming metadata column to tx_metadata in default db...")
|
||||||
|
cur.execute('ALTER TABLE "transaction" RENAME COLUMN metadata TO tx_metadata')
|
||||||
|
conn.commit()
|
||||||
|
elif 'tx_metadata' not in columns:
|
||||||
|
print("Adding tx_metadata column to default db...")
|
||||||
|
cur.execute('ALTER TABLE "transaction" ADD COLUMN tx_metadata TEXT')
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error modifying database: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fix()
|
||||||
40
apps/blockchain-node/fix_db.py
Normal file
40
apps/blockchain-node/fix_db.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from aitbc_chain.database import engine, init_db
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
init_db()
|
||||||
|
with engine.connect() as conn:
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN metadata TEXT'))
|
||||||
|
print("Added metadata")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN value INTEGER DEFAULT 0'))
|
||||||
|
print("Added value")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN fee INTEGER DEFAULT 0'))
|
||||||
|
print("Added fee")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN nonce INTEGER DEFAULT 0'))
|
||||||
|
print("Added nonce")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN status TEXT DEFAULT "pending"'))
|
||||||
|
print("Added status")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
conn.execute(text('ALTER TABLE "transaction" ADD COLUMN timestamp TEXT'))
|
||||||
|
print("Added timestamp")
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fix()
|
||||||
5
apps/blockchain-node/fix_env_path.py
Normal file
5
apps/blockchain-node/fix_env_path.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
class TestSettings(BaseSettings):
|
||||||
|
model_config = SettingsConfigDict(env_file="/opt/aitbc/.env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore")
|
||||||
|
db_path: str = ""
|
||||||
|
print(TestSettings().db_path)
|
||||||
27
apps/blockchain-node/fix_tx_metadata.py
Normal file
27
apps/blockchain-node/fix_tx_metadata.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect('/opt/aitbc/data/ait-mainnet/chain.db')
|
||||||
|
cur = conn.cursor()
|
||||||
|
|
||||||
|
cur.execute('PRAGMA table_info("transaction")')
|
||||||
|
columns = [col[1] for col in cur.fetchall()]
|
||||||
|
|
||||||
|
if 'metadata' in columns:
|
||||||
|
print("Renaming metadata column to tx_metadata...")
|
||||||
|
cur.execute('ALTER TABLE "transaction" RENAME COLUMN metadata TO tx_metadata')
|
||||||
|
conn.commit()
|
||||||
|
elif 'tx_metadata' not in columns:
|
||||||
|
print("Adding tx_metadata column...")
|
||||||
|
cur.execute('ALTER TABLE "transaction" ADD COLUMN tx_metadata TEXT')
|
||||||
|
conn.commit()
|
||||||
|
else:
|
||||||
|
print("tx_metadata column already exists.")
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error modifying database: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fix()
|
||||||
50
apps/blockchain-node/fix_tx_metadata2.py
Normal file
50
apps/blockchain-node/fix_tx_metadata2.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
def fix_db():
|
||||||
|
print("Fixing transaction table on aitbc node...")
|
||||||
|
|
||||||
|
conn = sqlite3.connect('/opt/aitbc/data/ait-mainnet/chain.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN nonce INTEGER DEFAULT 0;')
|
||||||
|
print("Added nonce column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding nonce: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN value INTEGER DEFAULT 0;')
|
||||||
|
print("Added value column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding value: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN fee INTEGER DEFAULT 0;')
|
||||||
|
print("Added fee column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding fee: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN status TEXT DEFAULT "pending";')
|
||||||
|
print("Added status column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding status: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN tx_metadata TEXT;')
|
||||||
|
print("Added tx_metadata column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding tx_metadata: {e}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('ALTER TABLE "transaction" ADD COLUMN timestamp TEXT;')
|
||||||
|
print("Added timestamp column")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
print(f"Error adding timestamp: {e}")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
print("Done fixing transaction table.")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fix_db()
|
||||||
2
apps/blockchain-node/get_env.py
Normal file
2
apps/blockchain-node/get_env.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from aitbc_chain.config import settings
|
||||||
|
print(settings.db_path)
|
||||||
@@ -32,6 +32,9 @@ class RateLimitMiddleware(BaseHTTPMiddleware):
|
|||||||
|
|
||||||
async def dispatch(self, request: Request, call_next):
|
async def dispatch(self, request: Request, call_next):
|
||||||
client_ip = request.client.host if request.client else "unknown"
|
client_ip = request.client.host if request.client else "unknown"
|
||||||
|
# Bypass rate limiting for localhost (sync/health internal traffic)
|
||||||
|
if client_ip in {"127.0.0.1", "::1"}:
|
||||||
|
return await call_next(request)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
# Clean old entries
|
# Clean old entries
|
||||||
self._requests[client_ip] = [
|
self._requests[client_ip] = [
|
||||||
@@ -109,7 +112,8 @@ def create_app() -> FastAPI:
|
|||||||
|
|
||||||
# Middleware (applied in reverse order)
|
# Middleware (applied in reverse order)
|
||||||
app.add_middleware(RequestLoggingMiddleware)
|
app.add_middleware(RequestLoggingMiddleware)
|
||||||
app.add_middleware(RateLimitMiddleware, max_requests=200, window_seconds=60)
|
# Allow higher RPC throughput (sync + node traffic)
|
||||||
|
app.add_middleware(RateLimitMiddleware, max_requests=5000, window_seconds=60)
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=[
|
allow_origins=[
|
||||||
|
|||||||
272
apps/blockchain-node/src/aitbc_chain/chain_sync.py
Normal file
272
apps/blockchain-node/src/aitbc_chain/chain_sync.py
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Chain Synchronization Service
|
||||||
|
Keeps blockchain nodes synchronized by sharing blocks via P2P and Redis gossip
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
from typing import Dict, Any, Optional, List
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class ChainSyncService:
|
||||||
|
def __init__(self, redis_url: str, node_id: str, rpc_port: int = 8006, leader_host: str = None,
|
||||||
|
source_host: str = "127.0.0.1", source_port: int = None,
|
||||||
|
import_host: str = "127.0.0.1", import_port: int = None):
|
||||||
|
self.redis_url = redis_url
|
||||||
|
self.node_id = node_id
|
||||||
|
self.rpc_port = rpc_port # kept for backward compat (local poll if source_port None)
|
||||||
|
self.leader_host = leader_host # Host of the leader node (legacy)
|
||||||
|
self.source_host = source_host
|
||||||
|
self.source_port = source_port or rpc_port
|
||||||
|
self.import_host = import_host
|
||||||
|
self.import_port = import_port or rpc_port
|
||||||
|
self._stop_event = asyncio.Event()
|
||||||
|
self._redis = None
|
||||||
|
self._receiver_ready = asyncio.Event()
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
"""Start chain synchronization service"""
|
||||||
|
logger.info(f"Starting chain sync service for node {self.node_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
import redis.asyncio as redis
|
||||||
|
self._redis = redis.from_url(self.redis_url)
|
||||||
|
await self._redis.ping()
|
||||||
|
logger.info("Connected to Redis for chain sync")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to connect to Redis: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Start block broadcasting task
|
||||||
|
# Start block receiving task
|
||||||
|
receive_task = asyncio.create_task(self._receive_blocks())
|
||||||
|
# Wait until receiver subscribed so we don't drop the initial burst
|
||||||
|
await self._receiver_ready.wait()
|
||||||
|
broadcast_task = asyncio.create_task(self._broadcast_blocks())
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._stop_event.wait()
|
||||||
|
finally:
|
||||||
|
broadcast_task.cancel()
|
||||||
|
receive_task.cancel()
|
||||||
|
await asyncio.gather(broadcast_task, receive_task, return_exceptions=True)
|
||||||
|
|
||||||
|
if self._redis:
|
||||||
|
await self._redis.close()
|
||||||
|
|
||||||
|
async def stop(self):
|
||||||
|
"""Stop chain synchronization service"""
|
||||||
|
logger.info("Stopping chain sync service")
|
||||||
|
self._stop_event.set()
|
||||||
|
|
||||||
|
async def _broadcast_blocks(self):
|
||||||
|
"""Broadcast local blocks to other nodes"""
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
last_broadcast_height = 0
|
||||||
|
retry_count = 0
|
||||||
|
max_retries = 5
|
||||||
|
base_delay = 2
|
||||||
|
|
||||||
|
while not self._stop_event.is_set():
|
||||||
|
try:
|
||||||
|
# Get current head from local RPC
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(f"http://{self.source_host}:{self.source_port}/rpc/head") as resp:
|
||||||
|
if resp.status == 200:
|
||||||
|
head_data = await resp.json()
|
||||||
|
current_height = head_data.get('height', 0)
|
||||||
|
|
||||||
|
# Reset retry count on successful connection
|
||||||
|
retry_count = 0
|
||||||
|
|
||||||
|
# Broadcast new blocks
|
||||||
|
if current_height > last_broadcast_height:
|
||||||
|
for height in range(last_broadcast_height + 1, current_height + 1):
|
||||||
|
block_data = await self._get_block_by_height(height, session)
|
||||||
|
if block_data:
|
||||||
|
await self._broadcast_block(block_data)
|
||||||
|
|
||||||
|
last_broadcast_height = current_height
|
||||||
|
logger.info(f"Broadcasted blocks up to height {current_height}")
|
||||||
|
elif resp.status == 429:
|
||||||
|
raise Exception("rate_limit")
|
||||||
|
else:
|
||||||
|
raise Exception(f"RPC returned status {resp.status}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
retry_count += 1
|
||||||
|
# If rate-limited, wait longer before retrying
|
||||||
|
if str(e) == "rate_limit":
|
||||||
|
delay = base_delay * 30
|
||||||
|
logger.warning(f"RPC rate limited, retrying in {delay}s")
|
||||||
|
await asyncio.sleep(delay)
|
||||||
|
continue
|
||||||
|
if retry_count <= max_retries:
|
||||||
|
delay = base_delay * (2 ** (retry_count - 1)) # Exponential backoff
|
||||||
|
logger.warning(f"RPC connection failed (attempt {retry_count}/{max_retries}), retrying in {delay}s: {e}")
|
||||||
|
await asyncio.sleep(delay)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.error(f"RPC connection failed after {max_retries} attempts, waiting {base_delay * 10}s: {e}")
|
||||||
|
await asyncio.sleep(base_delay * 10)
|
||||||
|
retry_count = 0 # Reset retry count after long wait
|
||||||
|
|
||||||
|
await asyncio.sleep(base_delay) # Check every 2 seconds when connected
|
||||||
|
|
||||||
|
async def _receive_blocks(self):
|
||||||
|
"""Receive blocks from other nodes via Redis"""
|
||||||
|
if not self._redis:
|
||||||
|
return
|
||||||
|
|
||||||
|
pubsub = self._redis.pubsub()
|
||||||
|
await pubsub.subscribe("blocks")
|
||||||
|
self._receiver_ready.set()
|
||||||
|
|
||||||
|
logger.info("Subscribed to block broadcasts")
|
||||||
|
|
||||||
|
async for message in pubsub.listen():
|
||||||
|
if self._stop_event.is_set():
|
||||||
|
break
|
||||||
|
|
||||||
|
if message['type'] == 'message':
|
||||||
|
try:
|
||||||
|
block_data = json.loads(message['data'])
|
||||||
|
await self._import_block(block_data)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error processing received block: {e}")
|
||||||
|
|
||||||
|
async def _get_block_by_height(self, height: int, session) -> Optional[Dict[str, Any]]:
|
||||||
|
"""Get block data by height from local RPC"""
|
||||||
|
try:
|
||||||
|
async with session.get(f"http://{self.source_host}:{self.source_port}/rpc/blocks-range?start={height}&end={height}") as resp:
|
||||||
|
if resp.status == 200:
|
||||||
|
blocks_data = await resp.json()
|
||||||
|
blocks = blocks_data.get('blocks', [])
|
||||||
|
block = blocks[0] if blocks else None
|
||||||
|
return block
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting block {height}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def _broadcast_block(self, block_data: Dict[str, Any]):
|
||||||
|
"""Broadcast block to other nodes via Redis"""
|
||||||
|
if not self._redis:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._redis.publish("blocks", json.dumps(block_data))
|
||||||
|
logger.debug(f"Broadcasted block {block_data.get('height')}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error broadcasting block: {e}")
|
||||||
|
|
||||||
|
async def _import_block(self, block_data: Dict[str, Any]):
|
||||||
|
"""Import block from another node"""
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Don't import our own blocks
|
||||||
|
if block_data.get('proposer') == self.node_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Determine target host - if we're a follower, import to leader, else import locally
|
||||||
|
target_host = self.import_host
|
||||||
|
target_port = self.import_port
|
||||||
|
|
||||||
|
# Retry logic for import
|
||||||
|
max_retries = 3
|
||||||
|
base_delay = 1
|
||||||
|
|
||||||
|
for attempt in range(max_retries):
|
||||||
|
try:
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.post(
|
||||||
|
f"http://{target_host}:{target_port}/rpc/importBlock",
|
||||||
|
json=block_data
|
||||||
|
) as resp:
|
||||||
|
if resp.status == 200:
|
||||||
|
result = await resp.json()
|
||||||
|
if result.get('accepted'):
|
||||||
|
logger.info(f"Imported block {block_data.get('height')} from {block_data.get('proposer')}")
|
||||||
|
else:
|
||||||
|
logger.debug(f"Rejected block {block_data.get('height')}: {result.get('reason')}")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
body = await resp.text()
|
||||||
|
except Exception:
|
||||||
|
body = "<no body>"
|
||||||
|
raise Exception(f"HTTP {resp.status}: {body}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if attempt < max_retries - 1:
|
||||||
|
delay = base_delay * (2 ** attempt)
|
||||||
|
logger.warning(f"Import failed (attempt {attempt + 1}/{max_retries}), retrying in {delay}s: {e}")
|
||||||
|
await asyncio.sleep(delay)
|
||||||
|
else:
|
||||||
|
logger.error(f"Failed to import block {block_data.get('height')} after {max_retries} attempts: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error importing block: {e}")
|
||||||
|
|
||||||
|
async def run_chain_sync(
|
||||||
|
redis_url: str,
|
||||||
|
node_id: str,
|
||||||
|
rpc_port: int = 8006,
|
||||||
|
leader_host: str = None,
|
||||||
|
source_host: str = "127.0.0.1",
|
||||||
|
source_port: int = None,
|
||||||
|
import_host: str = "127.0.0.1",
|
||||||
|
import_port: int = None,
|
||||||
|
):
|
||||||
|
"""Run chain synchronization service"""
|
||||||
|
service = ChainSyncService(
|
||||||
|
redis_url=redis_url,
|
||||||
|
node_id=node_id,
|
||||||
|
rpc_port=rpc_port,
|
||||||
|
leader_host=leader_host,
|
||||||
|
source_host=source_host,
|
||||||
|
source_port=source_port,
|
||||||
|
import_host=import_host,
|
||||||
|
import_port=import_port,
|
||||||
|
)
|
||||||
|
await service.start()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="AITBC Chain Synchronization Service")
|
||||||
|
parser.add_argument("--redis", default="redis://localhost:6379", help="Redis URL")
|
||||||
|
parser.add_argument("--node-id", required=True, help="Node identifier")
|
||||||
|
parser.add_argument("--rpc-port", type=int, default=8006, help="RPC port")
|
||||||
|
parser.add_argument("--leader-host", help="Leader node host (for followers)")
|
||||||
|
parser.add_argument("--source-host", default="127.0.0.1", help="Host to poll for head/blocks")
|
||||||
|
parser.add_argument("--source-port", type=int, help="Port to poll for head/blocks")
|
||||||
|
parser.add_argument("--import-host", default="127.0.0.1", help="Host to import blocks into")
|
||||||
|
parser.add_argument("--import-port", type=int, help="Port to import blocks into")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
try:
|
||||||
|
asyncio.run(run_chain_sync(
|
||||||
|
args.redis,
|
||||||
|
args.node_id,
|
||||||
|
args.rpc_port,
|
||||||
|
args.leader_host,
|
||||||
|
args.source_host,
|
||||||
|
args.source_port,
|
||||||
|
args.import_host,
|
||||||
|
args.import_port,
|
||||||
|
))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("Chain sync service stopped by user")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
94
apps/blockchain-node/src/aitbc_chain/combined_main.py
Normal file
94
apps/blockchain-node/src/aitbc_chain/combined_main.py
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Combined blockchain node and P2P service launcher
|
||||||
|
Runs both the main blockchain node and P2P placeholder service
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add src to path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from aitbc_chain.main import BlockchainNode, _run as run_node
|
||||||
|
from aitbc_chain.config import settings
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class CombinedService:
|
||||||
|
def __init__(self):
|
||||||
|
self._stop_event = asyncio.Event()
|
||||||
|
self._tasks = []
|
||||||
|
self._loop = None
|
||||||
|
|
||||||
|
def set_stop_event(self):
|
||||||
|
"""Set the stop event to trigger shutdown"""
|
||||||
|
if self._stop_event and not self._stop_event.is_set():
|
||||||
|
self._stop_event.set()
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
"""Start both blockchain node and P2P server"""
|
||||||
|
self._loop = asyncio.get_running_loop()
|
||||||
|
logger.info("Starting combined blockchain service")
|
||||||
|
|
||||||
|
# Start blockchain node in background
|
||||||
|
node_task = asyncio.create_task(run_node())
|
||||||
|
self._tasks.append(node_task)
|
||||||
|
|
||||||
|
logger.info(f"Combined service started - Node on mainnet")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._stop_event.wait()
|
||||||
|
finally:
|
||||||
|
await self.stop()
|
||||||
|
|
||||||
|
async def stop(self):
|
||||||
|
"""Stop all services"""
|
||||||
|
logger.info("Stopping combined blockchain service")
|
||||||
|
|
||||||
|
# Cancel all tasks
|
||||||
|
for task in self._tasks:
|
||||||
|
task.cancel()
|
||||||
|
|
||||||
|
# Wait for tasks to complete
|
||||||
|
if self._tasks:
|
||||||
|
await asyncio.gather(*self._tasks, return_exceptions=True)
|
||||||
|
|
||||||
|
self._tasks.clear()
|
||||||
|
logger.info("Combined service stopped")
|
||||||
|
|
||||||
|
# Global service instance for signal handler
|
||||||
|
_service_instance = None
|
||||||
|
|
||||||
|
def signal_handler(signum, frame):
|
||||||
|
"""Handle shutdown signals"""
|
||||||
|
logger.info(f"Received signal {signum}, initiating shutdown")
|
||||||
|
global _service_instance
|
||||||
|
if _service_instance:
|
||||||
|
_service_instance.set_stop_event()
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Main entry point"""
|
||||||
|
global _service_instance
|
||||||
|
service = CombinedService()
|
||||||
|
_service_instance = service
|
||||||
|
|
||||||
|
# Set up signal handlers
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await service.start()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("Received keyboard interrupt")
|
||||||
|
finally:
|
||||||
|
await service.stop()
|
||||||
|
_service_instance = None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@@ -16,11 +16,11 @@ class ProposerConfig(BaseModel):
|
|||||||
max_txs_per_block: int
|
max_txs_per_block: int
|
||||||
|
|
||||||
class ChainSettings(BaseSettings):
|
class ChainSettings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", case_sensitive=False)
|
model_config = SettingsConfigDict(env_file="/opt/aitbc/.env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore")
|
||||||
|
|
||||||
chain_id: str = "ait-devnet"
|
chain_id: str = ""
|
||||||
supported_chains: str = "ait-devnet" # Comma-separated list of supported chain IDs
|
supported_chains: str = "ait-devnet" # Comma-separated list of supported chain IDs
|
||||||
db_path: Path = Path("./data/chain.db")
|
db_path: Path = Path("/opt/aitbc/data/chain.db")
|
||||||
|
|
||||||
rpc_bind_host: str = "127.0.0.1"
|
rpc_bind_host: str = "127.0.0.1"
|
||||||
rpc_bind_port: int = 8080
|
rpc_bind_port: int = 8080
|
||||||
@@ -28,7 +28,7 @@ class ChainSettings(BaseSettings):
|
|||||||
p2p_bind_host: str = "127.0.0.2"
|
p2p_bind_host: str = "127.0.0.2"
|
||||||
p2p_bind_port: int = 7070
|
p2p_bind_port: int = 7070
|
||||||
|
|
||||||
proposer_id: str = "ait-devnet-proposer"
|
proposer_id: str = ""
|
||||||
proposer_key: Optional[str] = None
|
proposer_key: Optional[str] = None
|
||||||
|
|
||||||
mint_per_unit: int = 0 # No new minting after genesis for production
|
mint_per_unit: int = 0 # No new minting after genesis for production
|
||||||
@@ -36,6 +36,9 @@ class ChainSettings(BaseSettings):
|
|||||||
|
|
||||||
block_time_seconds: int = 2
|
block_time_seconds: int = 2
|
||||||
|
|
||||||
|
# Block production toggle (set false on followers)
|
||||||
|
enable_block_production: bool = True
|
||||||
|
|
||||||
# Block production limits
|
# Block production limits
|
||||||
max_block_size_bytes: int = 1_000_000 # 1 MB
|
max_block_size_bytes: int = 1_000_000 # 1 MB
|
||||||
max_txs_per_block: int = 500
|
max_txs_per_block: int = 500
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ class PoAProposer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
async def _propose_block(self) -> None:
|
async def _propose_block(self) -> None:
|
||||||
# Check internal mempool
|
# Check internal mempool and include transactions
|
||||||
from ..mempool import get_mempool
|
from ..mempool import get_mempool
|
||||||
if get_mempool().size(self._config.chain_id) == 0:
|
from ..models import Transaction, Account
|
||||||
return
|
mempool = get_mempool()
|
||||||
|
|
||||||
with self._session_factory() as session:
|
with self._session_factory() as session:
|
||||||
head = session.exec(select(Block).where(Block.chain_id == self._config.chain_id).order_by(Block.height.desc()).limit(1)).first()
|
head = session.exec(select(Block).where(Block.chain_id == self._config.chain_id).order_by(Block.height.desc()).limit(1)).first()
|
||||||
next_height = 0
|
next_height = 0
|
||||||
@@ -136,7 +136,72 @@ class PoAProposer:
|
|||||||
interval_seconds = (datetime.utcnow() - head.timestamp).total_seconds()
|
interval_seconds = (datetime.utcnow() - head.timestamp).total_seconds()
|
||||||
|
|
||||||
timestamp = datetime.utcnow()
|
timestamp = datetime.utcnow()
|
||||||
block_hash = self._compute_block_hash(next_height, parent_hash, timestamp)
|
|
||||||
|
# Pull transactions from mempool
|
||||||
|
max_txs = self._config.max_txs_per_block
|
||||||
|
max_bytes = self._config.max_block_size_bytes
|
||||||
|
pending_txs = mempool.drain(max_txs, max_bytes, 'ait-mainnet')
|
||||||
|
self._logger.info(f"[PROPOSE] drained {len(pending_txs)} txs from mempool, chain={self._config.chain_id}")
|
||||||
|
|
||||||
|
# Process transactions and update balances
|
||||||
|
processed_txs = []
|
||||||
|
for tx in pending_txs:
|
||||||
|
try:
|
||||||
|
# Parse transaction data
|
||||||
|
tx_data = tx.content
|
||||||
|
sender = tx_data.get("sender")
|
||||||
|
recipient = tx_data.get("payload", {}).get("to")
|
||||||
|
value = tx_data.get("payload", {}).get("value", 0)
|
||||||
|
fee = tx_data.get("fee", 0)
|
||||||
|
|
||||||
|
if not sender or not recipient:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Get sender account
|
||||||
|
sender_account = session.get(Account, (self._config.chain_id, sender))
|
||||||
|
if not sender_account:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check sufficient balance
|
||||||
|
total_cost = value + fee
|
||||||
|
if sender_account.balance < total_cost:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Get or create recipient account
|
||||||
|
recipient_account = session.get(Account, (self._config.chain_id, recipient))
|
||||||
|
if not recipient_account:
|
||||||
|
recipient_account = Account(chain_id=self._config.chain_id, address=recipient, balance=0, nonce=0)
|
||||||
|
session.add(recipient_account)
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
# Update balances
|
||||||
|
sender_account.balance -= total_cost
|
||||||
|
sender_account.nonce += 1
|
||||||
|
recipient_account.balance += value
|
||||||
|
|
||||||
|
# Create transaction record
|
||||||
|
transaction = Transaction(
|
||||||
|
chain_id=self._config.chain_id,
|
||||||
|
tx_hash=tx.tx_hash,
|
||||||
|
sender=sender,
|
||||||
|
recipient=recipient,
|
||||||
|
payload=tx_data,
|
||||||
|
value=value,
|
||||||
|
fee=fee,
|
||||||
|
nonce=sender_account.nonce - 1,
|
||||||
|
timestamp=timestamp,
|
||||||
|
block_height=next_height,
|
||||||
|
status="confirmed"
|
||||||
|
)
|
||||||
|
session.add(transaction)
|
||||||
|
processed_txs.append(tx)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.warning(f"Failed to process transaction {tx.tx_hash}: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Compute block hash with transaction data
|
||||||
|
block_hash = self._compute_block_hash(next_height, parent_hash, timestamp, processed_txs)
|
||||||
|
|
||||||
block = Block(
|
block = Block(
|
||||||
chain_id=self._config.chain_id,
|
chain_id=self._config.chain_id,
|
||||||
@@ -145,7 +210,7 @@ class PoAProposer:
|
|||||||
parent_hash=parent_hash,
|
parent_hash=parent_hash,
|
||||||
proposer=self._config.proposer_id,
|
proposer=self._config.proposer_id,
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
tx_count=0,
|
tx_count=len(processed_txs),
|
||||||
state_root=None,
|
state_root=None,
|
||||||
)
|
)
|
||||||
session.add(block)
|
session.add(block)
|
||||||
@@ -173,6 +238,7 @@ class PoAProposer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Broadcast the new block
|
# Broadcast the new block
|
||||||
|
tx_list = [tx.content for tx in processed_txs] if processed_txs else []
|
||||||
await gossip_broker.publish(
|
await gossip_broker.publish(
|
||||||
"blocks",
|
"blocks",
|
||||||
{
|
{
|
||||||
@@ -184,7 +250,8 @@ class PoAProposer:
|
|||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
}
|
"transactions": tx_list,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _ensure_genesis_block(self) -> None:
|
async def _ensure_genesis_block(self) -> None:
|
||||||
@@ -258,6 +325,11 @@ class PoAProposer:
|
|||||||
with self._session_factory() as session:
|
with self._session_factory() as session:
|
||||||
return session.exec(select(Block).order_by(Block.height.desc()).limit(1)).first()
|
return session.exec(select(Block).order_by(Block.height.desc()).limit(1)).first()
|
||||||
|
|
||||||
def _compute_block_hash(self, height: int, parent_hash: str, timestamp: datetime) -> str:
|
def _compute_block_hash(self, height: int, parent_hash: str, timestamp: datetime, transactions: list = None) -> str:
|
||||||
payload = f"{self._config.chain_id}|{height}|{parent_hash}|{timestamp.isoformat()}".encode()
|
# Include transaction hashes in block hash computation
|
||||||
|
tx_hashes = []
|
||||||
|
if transactions:
|
||||||
|
tx_hashes = [tx.tx_hash for tx in transactions]
|
||||||
|
|
||||||
|
payload = f"{self._config.chain_id}|{height}|{parent_hash}|{timestamp.isoformat()}|{'|'.join(sorted(tx_hashes))}".encode()
|
||||||
return "0x" + hashlib.sha256(payload).hexdigest()
|
return "0x" + hashlib.sha256(payload).hexdigest()
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ import asyncio
|
|||||||
import json
|
import json
|
||||||
import warnings
|
import warnings
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from contextlib import suppress
|
from contextlib import suppress, asynccontextmanager
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Callable, Dict, List, Optional, Set
|
from typing import Any, Callable, Dict, List, Optional, Set
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", message="coroutine.* was never awaited", category=RuntimeWarning)
|
warnings.filterwarnings("ignore", message="coroutine.* was never awaited", category=RuntimeWarning)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from starlette.broadcast import Broadcast
|
from broadcaster import Broadcast
|
||||||
except ImportError: # pragma: no cover - Starlette removed Broadcast in recent versions
|
except ImportError: # pragma: no cover
|
||||||
Broadcast = None # type: ignore[assignment]
|
Broadcast = None # type: ignore[assignment]
|
||||||
|
|
||||||
from ..metrics import metrics_registry
|
from ..metrics import metrics_registry
|
||||||
@@ -225,25 +225,15 @@ class GossipBroker:
|
|||||||
|
|
||||||
|
|
||||||
class _InProcessSubscriber:
|
class _InProcessSubscriber:
|
||||||
def __init__(self, queue: "asyncio.Queue[Any]", release: Callable[[], None]):
|
def __init__(self, queue: "asyncio.Queue[Any]"):
|
||||||
self._queue = queue
|
self._queue = queue
|
||||||
self._release = release
|
|
||||||
|
|
||||||
async def __aenter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc, tb):
|
|
||||||
self._release()
|
|
||||||
|
|
||||||
def __aiter__(self): # type: ignore[override]
|
def __aiter__(self): # type: ignore[override]
|
||||||
return self._iterator()
|
return self._iterator()
|
||||||
|
|
||||||
async def _iterator(self):
|
async def _iterator(self):
|
||||||
try:
|
while True:
|
||||||
while True:
|
yield await self._queue.get()
|
||||||
yield await self._queue.get()
|
|
||||||
finally:
|
|
||||||
self._release()
|
|
||||||
|
|
||||||
|
|
||||||
class _InProcessBroadcast:
|
class _InProcessBroadcast:
|
||||||
@@ -262,23 +252,19 @@ class _InProcessBroadcast:
|
|||||||
self._topics.clear()
|
self._topics.clear()
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
async def subscribe(self, topic: str) -> _InProcessSubscriber:
|
@asynccontextmanager
|
||||||
|
async def subscribe(self, topic: str):
|
||||||
queue: "asyncio.Queue[Any]" = asyncio.Queue()
|
queue: "asyncio.Queue[Any]" = asyncio.Queue()
|
||||||
async with self._lock:
|
async with self._lock:
|
||||||
self._topics[topic].append(queue)
|
self._topics[topic].append(queue)
|
||||||
|
|
||||||
def release() -> None:
|
try:
|
||||||
async def _remove() -> None:
|
yield _InProcessSubscriber(queue)
|
||||||
async with self._lock:
|
finally:
|
||||||
queues = self._topics.get(topic)
|
async with self._lock:
|
||||||
if queues and queue in queues:
|
queues = self._topics.get(topic)
|
||||||
queues.remove(queue)
|
if queues and queue in queues:
|
||||||
if not queues:
|
queues.remove(queue)
|
||||||
self._topics.pop(topic, None)
|
|
||||||
|
|
||||||
asyncio.create_task(_remove())
|
|
||||||
|
|
||||||
return _InProcessSubscriber(queue, release)
|
|
||||||
|
|
||||||
async def publish(self, topic: str, message: Any) -> None:
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
if not self._running:
|
if not self._running:
|
||||||
|
|||||||
307
apps/blockchain-node/src/aitbc_chain/gossip/broker.py.orig
Executable file
307
apps/blockchain-node/src/aitbc_chain/gossip/broker.py.orig
Executable file
@@ -0,0 +1,307 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import warnings
|
||||||
|
from collections import defaultdict
|
||||||
|
from contextlib import suppress
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, Callable, Dict, List, Optional, Set
|
||||||
|
|
||||||
|
warnings.filterwarnings("ignore", message="coroutine.* was never awaited", category=RuntimeWarning)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from broadcaster import Broadcast
|
||||||
|
except ImportError: # pragma: no cover
|
||||||
|
Broadcast = None # type: ignore[assignment]
|
||||||
|
|
||||||
|
from ..metrics import metrics_registry
|
||||||
|
|
||||||
|
|
||||||
|
def _increment_publication(metric_prefix: str, topic: str) -> None:
|
||||||
|
metrics_registry.increment(f"{metric_prefix}_total")
|
||||||
|
metrics_registry.increment(f"{metric_prefix}_topic_{topic}")
|
||||||
|
|
||||||
|
|
||||||
|
def _set_queue_gauge(topic: str, size: int) -> None:
|
||||||
|
metrics_registry.set_gauge(f"gossip_queue_size_{topic}", float(size))
|
||||||
|
|
||||||
|
|
||||||
|
def _update_subscriber_metrics(topics: Dict[str, List["asyncio.Queue[Any]"]]) -> None:
|
||||||
|
for topic, queues in topics.items():
|
||||||
|
metrics_registry.set_gauge(f"gossip_subscribers_topic_{topic}", float(len(queues)))
|
||||||
|
total = sum(len(queues) for queues in topics.values())
|
||||||
|
metrics_registry.set_gauge("gossip_subscribers_total", float(total))
|
||||||
|
|
||||||
|
|
||||||
|
def _clear_topic_metrics(topic: str) -> None:
|
||||||
|
metrics_registry.set_gauge(f"gossip_subscribers_topic_{topic}", 0.0)
|
||||||
|
_set_queue_gauge(topic, 0)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TopicSubscription:
|
||||||
|
topic: str
|
||||||
|
queue: "asyncio.Queue[Any]"
|
||||||
|
_unsubscribe: Callable[[], None]
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
self._unsubscribe()
|
||||||
|
|
||||||
|
async def get(self) -> Any:
|
||||||
|
return await self.queue.get()
|
||||||
|
|
||||||
|
async def __aiter__(self): # type: ignore[override]
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
yield await self.queue.get()
|
||||||
|
finally:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
class GossipBackend:
|
||||||
|
async def start(self) -> None: # pragma: no cover - overridden as needed
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
async def subscribe(self, topic: str, max_queue_size: int = 100) -> TopicSubscription:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
async def shutdown(self) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class InMemoryGossipBackend(GossipBackend):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._topics: Dict[str, List["asyncio.Queue[Any]"]] = defaultdict(list)
|
||||||
|
self._lock = asyncio.Lock()
|
||||||
|
|
||||||
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
|
async with self._lock:
|
||||||
|
queues = list(self._topics.get(topic, []))
|
||||||
|
for queue in queues:
|
||||||
|
await queue.put(message)
|
||||||
|
_set_queue_gauge(topic, queue.qsize())
|
||||||
|
_increment_publication("gossip_publications", topic)
|
||||||
|
|
||||||
|
async def subscribe(self, topic: str, max_queue_size: int = 100) -> TopicSubscription:
|
||||||
|
queue: "asyncio.Queue[Any]" = asyncio.Queue(maxsize=max_queue_size)
|
||||||
|
|
||||||
|
async with self._lock:
|
||||||
|
self._topics[topic].append(queue)
|
||||||
|
_update_subscriber_metrics(self._topics)
|
||||||
|
|
||||||
|
_set_queue_gauge(topic, queue.qsize())
|
||||||
|
|
||||||
|
def _unsubscribe() -> None:
|
||||||
|
async def _remove() -> None:
|
||||||
|
async with self._lock:
|
||||||
|
queues = self._topics.get(topic)
|
||||||
|
if queues is None:
|
||||||
|
return
|
||||||
|
if queue in queues:
|
||||||
|
queues.remove(queue)
|
||||||
|
if not queues:
|
||||||
|
self._topics.pop(topic, None)
|
||||||
|
_clear_topic_metrics(topic)
|
||||||
|
_update_subscriber_metrics(self._topics)
|
||||||
|
|
||||||
|
asyncio.create_task(_remove())
|
||||||
|
|
||||||
|
return TopicSubscription(topic=topic, queue=queue, _unsubscribe=_unsubscribe)
|
||||||
|
|
||||||
|
async def shutdown(self) -> None:
|
||||||
|
async with self._lock:
|
||||||
|
topics = list(self._topics.keys())
|
||||||
|
self._topics.clear()
|
||||||
|
for topic in topics:
|
||||||
|
_clear_topic_metrics(topic)
|
||||||
|
_update_subscriber_metrics(self._topics)
|
||||||
|
|
||||||
|
|
||||||
|
class BroadcastGossipBackend(GossipBackend):
|
||||||
|
def __init__(self, url: str) -> None:
|
||||||
|
if Broadcast is None: # provide in-process fallback when Broadcast is missing
|
||||||
|
self._broadcast = _InProcessBroadcast()
|
||||||
|
else:
|
||||||
|
self._broadcast = Broadcast(url) # type: ignore[arg-type]
|
||||||
|
self._tasks: Set[asyncio.Task[None]] = set()
|
||||||
|
self._lock = asyncio.Lock()
|
||||||
|
self._running = False
|
||||||
|
|
||||||
|
async def start(self) -> None:
|
||||||
|
if not self._running:
|
||||||
|
await self._broadcast.connect() # type: ignore[union-attr]
|
||||||
|
self._running = True
|
||||||
|
|
||||||
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
|
if not self._running:
|
||||||
|
raise RuntimeError("Broadcast backend not started")
|
||||||
|
payload = _encode_message(message)
|
||||||
|
await self._broadcast.publish(topic, payload) # type: ignore[union-attr]
|
||||||
|
_increment_publication("gossip_broadcast_publications", topic)
|
||||||
|
|
||||||
|
async def subscribe(self, topic: str, max_queue_size: int = 100) -> TopicSubscription:
|
||||||
|
if not self._running:
|
||||||
|
raise RuntimeError("Broadcast backend not started")
|
||||||
|
|
||||||
|
queue: "asyncio.Queue[Any]" = asyncio.Queue(maxsize=max_queue_size)
|
||||||
|
stop_event = asyncio.Event()
|
||||||
|
|
||||||
|
async def _run_subscription() -> None:
|
||||||
|
async with self._broadcast.subscribe(topic) as subscriber: # type: ignore[attr-defined,union-attr]
|
||||||
|
async for event in subscriber: # type: ignore[union-attr]
|
||||||
|
if stop_event.is_set():
|
||||||
|
break
|
||||||
|
data = _decode_message(getattr(event, "message", event))
|
||||||
|
try:
|
||||||
|
await queue.put(data)
|
||||||
|
_set_queue_gauge(topic, queue.qsize())
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
break
|
||||||
|
|
||||||
|
task = asyncio.create_task(_run_subscription(), name=f"broadcast-sub:{topic}")
|
||||||
|
async with self._lock:
|
||||||
|
self._tasks.add(task)
|
||||||
|
metrics_registry.set_gauge("gossip_broadcast_subscribers_total", float(len(self._tasks)))
|
||||||
|
|
||||||
|
def _unsubscribe() -> None:
|
||||||
|
async def _stop() -> None:
|
||||||
|
stop_event.set()
|
||||||
|
task.cancel()
|
||||||
|
with suppress(asyncio.CancelledError):
|
||||||
|
await task
|
||||||
|
async with self._lock:
|
||||||
|
self._tasks.discard(task)
|
||||||
|
metrics_registry.set_gauge("gossip_broadcast_subscribers_total", float(len(self._tasks)))
|
||||||
|
|
||||||
|
asyncio.create_task(_stop())
|
||||||
|
|
||||||
|
return TopicSubscription(topic=topic, queue=queue, _unsubscribe=_unsubscribe)
|
||||||
|
|
||||||
|
async def shutdown(self) -> None:
|
||||||
|
async with self._lock:
|
||||||
|
tasks = list(self._tasks)
|
||||||
|
self._tasks.clear()
|
||||||
|
metrics_registry.set_gauge("gossip_broadcast_subscribers_total", 0.0)
|
||||||
|
for task in tasks:
|
||||||
|
task.cancel()
|
||||||
|
with suppress(asyncio.CancelledError):
|
||||||
|
await task
|
||||||
|
if self._running:
|
||||||
|
await self._broadcast.disconnect() # type: ignore[union-attr]
|
||||||
|
self._running = False
|
||||||
|
|
||||||
|
|
||||||
|
class GossipBroker:
|
||||||
|
def __init__(self, backend: GossipBackend) -> None:
|
||||||
|
self._backend = backend
|
||||||
|
self._lock = asyncio.Lock()
|
||||||
|
self._started = False
|
||||||
|
|
||||||
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
|
if not self._started:
|
||||||
|
await self._backend.start()
|
||||||
|
self._started = True
|
||||||
|
await self._backend.publish(topic, message)
|
||||||
|
|
||||||
|
async def subscribe(self, topic: str, max_queue_size: int = 100) -> TopicSubscription:
|
||||||
|
if not self._started:
|
||||||
|
await self._backend.start()
|
||||||
|
self._started = True
|
||||||
|
return await self._backend.subscribe(topic, max_queue_size=max_queue_size)
|
||||||
|
|
||||||
|
async def set_backend(self, backend: GossipBackend) -> None:
|
||||||
|
await backend.start()
|
||||||
|
async with self._lock:
|
||||||
|
previous = self._backend
|
||||||
|
self._backend = backend
|
||||||
|
self._started = True
|
||||||
|
await previous.shutdown()
|
||||||
|
|
||||||
|
async def shutdown(self) -> None:
|
||||||
|
await self._backend.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
class _InProcessSubscriber:
|
||||||
|
def __init__(self, queue: "asyncio.Queue[Any]"):
|
||||||
|
self._queue = queue
|
||||||
|
|
||||||
|
def __aiter__(self): # type: ignore[override]
|
||||||
|
return self._iterator()
|
||||||
|
|
||||||
|
async def _iterator(self):
|
||||||
|
while True:
|
||||||
|
yield await self._queue.get()
|
||||||
|
|
||||||
|
|
||||||
|
class _InProcessBroadcast:
|
||||||
|
"""Minimal in-memory broadcast substitute for tests when Starlette Broadcast is absent."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._topics: Dict[str, List["asyncio.Queue[Any]"]] = defaultdict(list)
|
||||||
|
self._lock = asyncio.Lock()
|
||||||
|
self._running = False
|
||||||
|
|
||||||
|
async def connect(self) -> None:
|
||||||
|
self._running = True
|
||||||
|
|
||||||
|
async def disconnect(self) -> None:
|
||||||
|
async with self._lock:
|
||||||
|
self._topics.clear()
|
||||||
|
self._running = False
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def subscribe(self, topic: str):
|
||||||
|
queue: "asyncio.Queue[Any]" = asyncio.Queue()
|
||||||
|
async with self._lock:
|
||||||
|
self._topics[topic].append(queue)
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield _InProcessSubscriber(queue)
|
||||||
|
finally:
|
||||||
|
async with self._lock:
|
||||||
|
queues = self._topics.get(topic)
|
||||||
|
if queues and queue in queues:
|
||||||
|
queues.remove(queue)
|
||||||
|
|
||||||
|
async def publish(self, topic: str, message: Any) -> None:
|
||||||
|
if not self._running:
|
||||||
|
raise RuntimeError("Broadcast backend not started")
|
||||||
|
async with self._lock:
|
||||||
|
queues = list(self._topics.get(topic, []))
|
||||||
|
for queue in queues:
|
||||||
|
await queue.put(message)
|
||||||
|
|
||||||
|
|
||||||
|
def create_backend(backend_type: str, *, broadcast_url: Optional[str] = None) -> GossipBackend:
|
||||||
|
backend = backend_type.lower()
|
||||||
|
if backend in {"memory", "inmemory", "local"}:
|
||||||
|
return InMemoryGossipBackend()
|
||||||
|
if backend in {"broadcast", "starlette", "redis"}:
|
||||||
|
if not broadcast_url:
|
||||||
|
raise ValueError("Broadcast backend requires a gossip_broadcast_url setting")
|
||||||
|
return BroadcastGossipBackend(broadcast_url)
|
||||||
|
raise ValueError(f"Unsupported gossip backend '{backend_type}'")
|
||||||
|
|
||||||
|
|
||||||
|
def _encode_message(message: Any) -> Any:
|
||||||
|
if isinstance(message, (str, bytes, bytearray)):
|
||||||
|
return message
|
||||||
|
return json.dumps(message, separators=(",", ":"))
|
||||||
|
|
||||||
|
|
||||||
|
def _decode_message(message: Any) -> Any:
|
||||||
|
if isinstance(message, (bytes, bytearray)):
|
||||||
|
message = message.decode("utf-8")
|
||||||
|
if isinstance(message, str):
|
||||||
|
try:
|
||||||
|
return json.loads(message)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return message
|
||||||
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
gossip_broker = GossipBroker(InMemoryGossipBackend())
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ class BlockchainNode:
|
|||||||
if isinstance(tx_data, str):
|
if isinstance(tx_data, str):
|
||||||
import json
|
import json
|
||||||
tx_data = json.loads(tx_data)
|
tx_data = json.loads(tx_data)
|
||||||
chain_id = tx_data.get("chain_id", "ait-devnet")
|
chain_id = tx_data.get("chain_id", settings.chain_id)
|
||||||
mempool.add(tx_data, chain_id=chain_id)
|
mempool.add(tx_data, chain_id=chain_id)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"Error processing transaction from gossip: {exc}")
|
logger.error(f"Error processing transaction from gossip: {exc}")
|
||||||
@@ -121,10 +121,10 @@ class BlockchainNode:
|
|||||||
if isinstance(block_data, str):
|
if isinstance(block_data, str):
|
||||||
import json
|
import json
|
||||||
block_data = json.loads(block_data)
|
block_data = json.loads(block_data)
|
||||||
chain_id = block_data.get("chain_id", "ait-devnet")
|
chain_id = block_data.get("chain_id", settings.chain_id)
|
||||||
logger.info(f"Importing block for chain {chain_id}: {block_data.get('height')}")
|
logger.info(f"Importing block for chain {chain_id}: {block_data.get('height')}")
|
||||||
sync = ChainSync(session_factory=session_scope, chain_id=chain_id)
|
sync = ChainSync(session_factory=session_scope, chain_id=chain_id)
|
||||||
res = sync.import_block(block_data)
|
res = sync.import_block(block_data, transactions=block_data.get("transactions"))
|
||||||
logger.info(f"Import result: accepted={res.accepted}, reason={res.reason}")
|
logger.info(f"Import result: accepted={res.accepted}, reason={res.reason}")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(f"Error processing block from gossip: {exc}")
|
logger.error(f"Error processing block from gossip: {exc}")
|
||||||
@@ -148,7 +148,11 @@ class BlockchainNode:
|
|||||||
max_size=settings.mempool_max_size,
|
max_size=settings.mempool_max_size,
|
||||||
min_fee=settings.min_fee,
|
min_fee=settings.min_fee,
|
||||||
)
|
)
|
||||||
self._start_proposers()
|
# Start proposers only if enabled (followers set enable_block_production=False)
|
||||||
|
if getattr(settings, "enable_block_production", True):
|
||||||
|
self._start_proposers()
|
||||||
|
else:
|
||||||
|
logger.info("Block production disabled on this node", extra={"proposer_id": settings.proposer_id})
|
||||||
await self._setup_gossip_subscribers()
|
await self._setup_gossip_subscribers()
|
||||||
try:
|
try:
|
||||||
await self._stop_event.wait()
|
await self._stop_event.wait()
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ class InMemoryMempool:
|
|||||||
self._max_size = max_size
|
self._max_size = max_size
|
||||||
self._min_fee = min_fee
|
self._min_fee = min_fee
|
||||||
|
|
||||||
def add(self, tx: Dict[str, Any], chain_id: str = "ait-devnet") -> str:
|
def add(self, tx: Dict[str, Any], chain_id: str = None) -> str:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
fee = tx.get("fee", 0)
|
fee = tx.get("fee", 0)
|
||||||
if fee < self._min_fee:
|
if fee < self._min_fee:
|
||||||
raise ValueError(f"Fee {fee} below minimum {self._min_fee}")
|
raise ValueError(f"Fee {fee} below minimum {self._min_fee}")
|
||||||
@@ -59,11 +62,17 @@ class InMemoryMempool:
|
|||||||
metrics_registry.increment(f"mempool_tx_added_total_{chain_id}")
|
metrics_registry.increment(f"mempool_tx_added_total_{chain_id}")
|
||||||
return tx_hash
|
return tx_hash
|
||||||
|
|
||||||
def list_transactions(self, chain_id: str = "ait-devnet") -> List[PendingTransaction]:
|
def list_transactions(self, chain_id: str = None) -> List[PendingTransaction]:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
return list(self._transactions.values())
|
return list(self._transactions.values())
|
||||||
|
|
||||||
def drain(self, max_count: int, max_bytes: int, chain_id: str = "ait-devnet") -> List[PendingTransaction]:
|
def drain(self, max_count: int, max_bytes: int, chain_id: str = None) -> List[PendingTransaction]:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
"""Drain transactions for block inclusion, prioritized by fee (highest first)."""
|
"""Drain transactions for block inclusion, prioritized by fee (highest first)."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
sorted_txs = sorted(
|
sorted_txs = sorted(
|
||||||
@@ -87,14 +96,20 @@ class InMemoryMempool:
|
|||||||
metrics_registry.increment(f"mempool_tx_drained_total_{chain_id}", float(len(result)))
|
metrics_registry.increment(f"mempool_tx_drained_total_{chain_id}", float(len(result)))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def remove(self, tx_hash: str, chain_id: str = "ait-devnet") -> bool:
|
def remove(self, tx_hash: str, chain_id: str = None) -> bool:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
removed = self._transactions.pop(tx_hash, None) is not None
|
removed = self._transactions.pop(tx_hash, None) is not None
|
||||||
if removed:
|
if removed:
|
||||||
metrics_registry.set_gauge("mempool_size", float(len(self._transactions)))
|
metrics_registry.set_gauge("mempool_size", float(len(self._transactions)))
|
||||||
return removed
|
return removed
|
||||||
|
|
||||||
def size(self, chain_id: str = "ait-devnet") -> int:
|
def size(self, chain_id: str = None) -> int:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
return len(self._transactions)
|
return len(self._transactions)
|
||||||
|
|
||||||
@@ -135,7 +150,10 @@ class DatabaseMempool:
|
|||||||
self._conn.execute("CREATE INDEX IF NOT EXISTS idx_mempool_fee ON mempool(fee DESC)")
|
self._conn.execute("CREATE INDEX IF NOT EXISTS idx_mempool_fee ON mempool(fee DESC)")
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
|
|
||||||
def add(self, tx: Dict[str, Any], chain_id: str = "ait-devnet") -> str:
|
def add(self, tx: Dict[str, Any], chain_id: str = None) -> str:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
fee = tx.get("fee", 0)
|
fee = tx.get("fee", 0)
|
||||||
if fee < self._min_fee:
|
if fee < self._min_fee:
|
||||||
raise ValueError(f"Fee {fee} below minimum {self._min_fee}")
|
raise ValueError(f"Fee {fee} below minimum {self._min_fee}")
|
||||||
@@ -169,7 +187,10 @@ class DatabaseMempool:
|
|||||||
self._update_gauge(chain_id)
|
self._update_gauge(chain_id)
|
||||||
return tx_hash
|
return tx_hash
|
||||||
|
|
||||||
def list_transactions(self, chain_id: str = "ait-devnet") -> List[PendingTransaction]:
|
def list_transactions(self, chain_id: str = None) -> List[PendingTransaction]:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
rows = self._conn.execute(
|
rows = self._conn.execute(
|
||||||
"SELECT tx_hash, content, fee, size_bytes, received_at FROM mempool WHERE chain_id = ? ORDER BY fee DESC, received_at ASC",
|
"SELECT tx_hash, content, fee, size_bytes, received_at FROM mempool WHERE chain_id = ? ORDER BY fee DESC, received_at ASC",
|
||||||
@@ -182,7 +203,10 @@ class DatabaseMempool:
|
|||||||
) for r in rows
|
) for r in rows
|
||||||
]
|
]
|
||||||
|
|
||||||
def drain(self, max_count: int, max_bytes: int, chain_id: str = "ait-devnet") -> List[PendingTransaction]:
|
def drain(self, max_count: int, max_bytes: int, chain_id: str = None) -> List[PendingTransaction]:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
rows = self._conn.execute(
|
rows = self._conn.execute(
|
||||||
"SELECT tx_hash, content, fee, size_bytes, received_at FROM mempool WHERE chain_id = ? ORDER BY fee DESC, received_at ASC",
|
"SELECT tx_hash, content, fee, size_bytes, received_at FROM mempool WHERE chain_id = ? ORDER BY fee DESC, received_at ASC",
|
||||||
@@ -214,7 +238,10 @@ class DatabaseMempool:
|
|||||||
self._update_gauge(chain_id)
|
self._update_gauge(chain_id)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def remove(self, tx_hash: str, chain_id: str = "ait-devnet") -> bool:
|
def remove(self, tx_hash: str, chain_id: str = None) -> bool:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
cursor = self._conn.execute("DELETE FROM mempool WHERE chain_id = ? AND tx_hash = ?", (chain_id, tx_hash))
|
cursor = self._conn.execute("DELETE FROM mempool WHERE chain_id = ? AND tx_hash = ?", (chain_id, tx_hash))
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
@@ -223,11 +250,17 @@ class DatabaseMempool:
|
|||||||
self._update_gauge(chain_id)
|
self._update_gauge(chain_id)
|
||||||
return removed
|
return removed
|
||||||
|
|
||||||
def size(self, chain_id: str = "ait-devnet") -> int:
|
def size(self, chain_id: str = None) -> int:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
with self._lock:
|
with self._lock:
|
||||||
return self._conn.execute("SELECT COUNT(*) FROM mempool WHERE chain_id = ?", (chain_id,)).fetchone()[0]
|
return self._conn.execute("SELECT COUNT(*) FROM mempool WHERE chain_id = ?", (chain_id,)).fetchone()[0]
|
||||||
|
|
||||||
def _update_gauge(self, chain_id: str = "ait-devnet") -> None:
|
def _update_gauge(self, chain_id: str = None) -> None:
|
||||||
|
from .config import settings
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = settings.chain_id
|
||||||
count = self._conn.execute("SELECT COUNT(*) FROM mempool WHERE chain_id = ?", (chain_id,)).fetchone()[0]
|
count = self._conn.execute("SELECT COUNT(*) FROM mempool WHERE chain_id = ?", (chain_id,)).fetchone()[0]
|
||||||
metrics_registry.set_gauge(f"mempool_size_{chain_id}", float(count))
|
metrics_registry.set_gauge(f"mempool_size_{chain_id}", float(count))
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class Block(SQLModel, table=True):
|
|||||||
timestamp: datetime = Field(default_factory=datetime.utcnow, index=True)
|
timestamp: datetime = Field(default_factory=datetime.utcnow, index=True)
|
||||||
tx_count: int = 0
|
tx_count: int = 0
|
||||||
state_root: Optional[str] = None
|
state_root: Optional[str] = None
|
||||||
|
block_metadata: Optional[str] = Field(default=None)
|
||||||
|
|
||||||
# Relationships - use sa_relationship_kwargs for lazy loading
|
# Relationships - use sa_relationship_kwargs for lazy loading
|
||||||
transactions: List["Transaction"] = Relationship(
|
transactions: List["Transaction"] = Relationship(
|
||||||
@@ -90,6 +91,14 @@ class Transaction(SQLModel, table=True):
|
|||||||
)
|
)
|
||||||
created_at: datetime = Field(default_factory=datetime.utcnow, index=True)
|
created_at: datetime = Field(default_factory=datetime.utcnow, index=True)
|
||||||
|
|
||||||
|
# New fields added to schema
|
||||||
|
nonce: int = Field(default=0)
|
||||||
|
value: int = Field(default=0)
|
||||||
|
fee: int = Field(default=0)
|
||||||
|
status: str = Field(default="pending")
|
||||||
|
timestamp: Optional[str] = Field(default=None)
|
||||||
|
tx_metadata: Optional[str] = Field(default=None)
|
||||||
|
|
||||||
# Relationship
|
# Relationship
|
||||||
block: Optional["Block"] = Relationship(
|
block: Optional["Block"] = Relationship(
|
||||||
back_populates="transactions",
|
back_populates="transactions",
|
||||||
|
|||||||
106
apps/blockchain-node/src/aitbc_chain/p2p_network.py
Normal file
106
apps/blockchain-node/src/aitbc_chain/p2p_network.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
P2P Network Service using Redis Gossip
|
||||||
|
Handles peer-to-peer communication between blockchain nodes
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import socket
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class P2PNetworkService:
|
||||||
|
def __init__(self, host: str, port: int, redis_url: str, node_id: str):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.redis_url = redis_url
|
||||||
|
self.node_id = node_id
|
||||||
|
self._server = None
|
||||||
|
self._stop_event = asyncio.Event()
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
"""Start P2P network service"""
|
||||||
|
logger.info(f"Starting P2P network service on {self.host}:{self.port}")
|
||||||
|
|
||||||
|
# Create TCP server for P2P connections
|
||||||
|
self._server = await asyncio.start_server(
|
||||||
|
self._handle_connection,
|
||||||
|
self.host,
|
||||||
|
self.port
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"P2P service listening on {self.host}:{self.port}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._stop_event.wait()
|
||||||
|
finally:
|
||||||
|
await self.stop()
|
||||||
|
|
||||||
|
async def stop(self):
|
||||||
|
"""Stop P2P network service"""
|
||||||
|
logger.info("Stopping P2P network service")
|
||||||
|
if self._server:
|
||||||
|
self._server.close()
|
||||||
|
await self._server.wait_closed()
|
||||||
|
|
||||||
|
async def _handle_connection(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
|
||||||
|
"""Handle incoming P2P connections"""
|
||||||
|
addr = writer.get_extra_info('peername')
|
||||||
|
logger.info(f"P2P connection from {addr}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
data = await reader.read(1024)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
message = json.loads(data.decode())
|
||||||
|
logger.info(f"P2P received: {message}")
|
||||||
|
|
||||||
|
# Handle different message types
|
||||||
|
if message.get('type') == 'ping':
|
||||||
|
response = {'type': 'pong', 'node_id': self.node_id}
|
||||||
|
writer.write(json.dumps(response).encode() + b'\n')
|
||||||
|
await writer.drain()
|
||||||
|
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.warning(f"Invalid JSON from {addr}")
|
||||||
|
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"P2P connection error: {e}")
|
||||||
|
finally:
|
||||||
|
writer.close()
|
||||||
|
await writer.wait_closed()
|
||||||
|
logger.info(f"P2P connection closed from {addr}")
|
||||||
|
|
||||||
|
async def run_p2p_service(host: str, port: int, redis_url: str, node_id: str):
|
||||||
|
"""Run P2P service"""
|
||||||
|
service = P2PNetworkService(host, port, redis_url, node_id)
|
||||||
|
await service.start()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="AITBC P2P Network Service")
|
||||||
|
parser.add_argument("--host", default="0.0.0.0", help="Bind host")
|
||||||
|
parser.add_argument("--port", type=int, default=8005, help="Bind port")
|
||||||
|
parser.add_argument("--redis", default="redis://localhost:6379", help="Redis URL")
|
||||||
|
parser.add_argument("--node-id", help="Node identifier")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
try:
|
||||||
|
asyncio.run(run_p2p_service(args.host, args.port, args.redis, args.node_id))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logger.info("P2P service stopped by user")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -18,6 +18,13 @@ from ..models import Account, Block, Receipt, Transaction
|
|||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
def get_chain_id(chain_id: str = None) -> str:
|
||||||
|
"""Get chain_id from parameter or use default from settings"""
|
||||||
|
if chain_id is None:
|
||||||
|
from ..config import settings
|
||||||
|
return settings.chain_id
|
||||||
|
return chain_id
|
||||||
|
|
||||||
|
|
||||||
def _serialize_receipt(receipt: Receipt) -> Dict[str, Any]:
|
def _serialize_receipt(receipt: Receipt) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
@@ -63,7 +70,14 @@ class EstimateFeeRequest(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/head", summary="Get current chain head")
|
@router.get("/head", summary="Get current chain head")
|
||||||
async def get_head(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_head(chain_id: str = None) -> Dict[str, Any]:
|
||||||
|
"""Get current chain head"""
|
||||||
|
from ..config import settings as cfg
|
||||||
|
|
||||||
|
# Use default chain_id from settings if not provided
|
||||||
|
if chain_id is None:
|
||||||
|
chain_id = cfg.chain_id
|
||||||
|
|
||||||
metrics_registry.increment("rpc_get_head_total")
|
metrics_registry.increment("rpc_get_head_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@@ -91,14 +105,24 @@ async def get_block(height: int) -> Dict[str, Any]:
|
|||||||
metrics_registry.increment("rpc_get_block_not_found_total")
|
metrics_registry.increment("rpc_get_block_not_found_total")
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="block not found")
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="block not found")
|
||||||
metrics_registry.increment("rpc_get_block_success_total")
|
metrics_registry.increment("rpc_get_block_success_total")
|
||||||
|
|
||||||
|
txs = session.exec(select(Transaction).where(Transaction.block_height == height)).all()
|
||||||
|
tx_list = []
|
||||||
|
for tx in txs:
|
||||||
|
t = dict(tx.payload) if tx.payload else {}
|
||||||
|
t["tx_hash"] = tx.tx_hash
|
||||||
|
tx_list.append(t)
|
||||||
|
|
||||||
metrics_registry.observe("rpc_get_block_duration_seconds", time.perf_counter() - start)
|
metrics_registry.observe("rpc_get_block_duration_seconds", time.perf_counter() - start)
|
||||||
return {
|
return {
|
||||||
"height": block.height,
|
"height": block.height,
|
||||||
"hash": block.hash,
|
"hash": block.hash,
|
||||||
"parent_hash": block.parent_hash,
|
"parent_hash": block.parent_hash,
|
||||||
|
"proposer": block.proposer,
|
||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
|
"transactions": tx_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,13 +160,22 @@ async def get_blocks_range(start: int, end: int) -> Dict[str, Any]:
|
|||||||
# Serialize blocks
|
# Serialize blocks
|
||||||
block_list = []
|
block_list = []
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
|
txs = session.exec(select(Transaction).where(Transaction.block_height == block.height)).all()
|
||||||
|
tx_list = []
|
||||||
|
for tx in txs:
|
||||||
|
t = dict(tx.payload) if tx.payload else {}
|
||||||
|
t["tx_hash"] = tx.tx_hash
|
||||||
|
tx_list.append(t)
|
||||||
|
|
||||||
block_list.append({
|
block_list.append({
|
||||||
"height": block.height,
|
"height": block.height,
|
||||||
"hash": block.hash,
|
"hash": block.hash,
|
||||||
"parent_hash": block.parent_hash,
|
"parent_hash": block.parent_hash,
|
||||||
|
"proposer": block.proposer,
|
||||||
"timestamp": block.timestamp.isoformat(),
|
"timestamp": block.timestamp.isoformat(),
|
||||||
"tx_count": block.tx_count,
|
"tx_count": block.tx_count,
|
||||||
"state_root": block.state_root,
|
"state_root": block.state_root,
|
||||||
|
"transactions": tx_list,
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics_registry.increment("rpc_get_blocks_range_success_total")
|
metrics_registry.increment("rpc_get_blocks_range_success_total")
|
||||||
@@ -157,7 +190,8 @@ async def get_blocks_range(start: int, end: int) -> Dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/tx/{tx_hash}", summary="Get transaction by hash")
|
@router.get("/tx/{tx_hash}", summary="Get transaction by hash")
|
||||||
async def get_transaction(tx_hash: str, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_transaction(tx_hash: str, chain_id: str = None) -> Dict[str, Any]:
|
||||||
|
chain_id = get_chain_id(chain_id)
|
||||||
metrics_registry.increment("rpc_get_transaction_total")
|
metrics_registry.increment("rpc_get_transaction_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@@ -296,7 +330,8 @@ async def get_receipts(limit: int = 20, offset: int = 0) -> Dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/getBalance/{address}", summary="Get account balance")
|
@router.get("/getBalance/{address}", summary="Get account balance")
|
||||||
async def get_balance(address: str, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_balance(address: str, chain_id: str = None) -> Dict[str, Any]:
|
||||||
|
chain_id = get_chain_id(chain_id)
|
||||||
metrics_registry.increment("rpc_get_balance_total")
|
metrics_registry.increment("rpc_get_balance_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
@@ -442,13 +477,13 @@ async def get_addresses(limit: int = 20, offset: int = 0, min_balance: int = 0)
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/sendTx", summary="Submit a new transaction")
|
@router.post("/sendTx", summary="Submit a new transaction")
|
||||||
async def send_transaction(request: TransactionRequest, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def send_transaction(request: TransactionRequest, chain_id: str = None) -> Dict[str, Any]:
|
||||||
metrics_registry.increment("rpc_send_tx_total")
|
metrics_registry.increment("rpc_send_tx_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
mempool = get_mempool()
|
mempool = get_mempool()
|
||||||
tx_dict = request.model_dump()
|
tx_dict = request.model_dump()
|
||||||
try:
|
try:
|
||||||
tx_hash = mempool.add(tx_dict, chain_id=chain_id)
|
tx_hash = mempool.add(tx_dict, chain_id=chain_id or request.payload.get('chain_id') or 'ait-mainnet')
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
metrics_registry.increment("rpc_send_tx_rejected_total")
|
metrics_registry.increment("rpc_send_tx_rejected_total")
|
||||||
raise HTTPException(status_code=400, detail=str(e))
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
@@ -481,7 +516,7 @@ async def send_transaction(request: TransactionRequest, chain_id: str = "ait-dev
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/submitReceipt", summary="Submit receipt claim transaction")
|
@router.post("/submitReceipt", summary="Submit receipt claim transaction")
|
||||||
async def submit_receipt(request: ReceiptSubmissionRequest, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def submit_receipt(request: ReceiptSubmissionRequest, chain_id: str = None) -> Dict[str, Any]:
|
||||||
metrics_registry.increment("rpc_submit_receipt_total")
|
metrics_registry.increment("rpc_submit_receipt_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
tx_payload = {
|
tx_payload = {
|
||||||
@@ -539,7 +574,7 @@ class ImportBlockRequest(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/importBlock", summary="Import a block from a remote peer")
|
@router.post("/importBlock", summary="Import a block from a remote peer")
|
||||||
async def import_block(request: ImportBlockRequest, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def import_block(request: ImportBlockRequest, chain_id: str = None) -> Dict[str, Any]:
|
||||||
from ..sync import ChainSync, ProposerSignatureValidator
|
from ..sync import ChainSync, ProposerSignatureValidator
|
||||||
from ..config import settings as cfg
|
from ..config import settings as cfg
|
||||||
|
|
||||||
@@ -578,7 +613,7 @@ async def import_block(request: ImportBlockRequest, chain_id: str = "ait-devnet"
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/syncStatus", summary="Get chain sync status")
|
@router.get("/syncStatus", summary="Get chain sync status")
|
||||||
async def sync_status(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def sync_status(chain_id: str = None) -> Dict[str, Any]:
|
||||||
from ..sync import ChainSync
|
from ..sync import ChainSync
|
||||||
from ..config import settings as cfg
|
from ..config import settings as cfg
|
||||||
|
|
||||||
@@ -588,7 +623,7 @@ async def sync_status(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/info", summary="Get blockchain information")
|
@router.get("/info", summary="Get blockchain information")
|
||||||
async def get_blockchain_info(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_blockchain_info(chain_id: str = None) -> Dict[str, Any]:
|
||||||
"""Get comprehensive blockchain information"""
|
"""Get comprehensive blockchain information"""
|
||||||
from ..config import settings as cfg
|
from ..config import settings as cfg
|
||||||
|
|
||||||
@@ -634,31 +669,48 @@ async def get_blockchain_info(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/supply", summary="Get token supply information")
|
@router.get("/supply", summary="Get token supply information")
|
||||||
async def get_token_supply(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_token_supply(chain_id: str = None) -> Dict[str, Any]:
|
||||||
"""Get token supply information"""
|
"""Get token supply information"""
|
||||||
from ..config import settings as cfg
|
from ..config import settings as cfg
|
||||||
|
from ..models import Account
|
||||||
|
|
||||||
|
chain_id = get_chain_id(chain_id)
|
||||||
metrics_registry.increment("rpc_supply_total")
|
metrics_registry.increment("rpc_supply_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
with session_scope() as session:
|
with session_scope() as session:
|
||||||
# Simple implementation for now
|
# Calculate actual values from database
|
||||||
response = {
|
accounts = session.exec(select(Account).where(Account.chain_id == chain_id)).all()
|
||||||
"chain_id": chain_id,
|
total_balance = sum(account.balance for account in accounts)
|
||||||
"total_supply": 1000000000, # 1 billion from genesis
|
total_accounts = len(accounts)
|
||||||
"circulating_supply": 0, # No transactions yet
|
|
||||||
"faucet_balance": 1000000000, # All tokens in faucet
|
# Production implementation - calculate real circulating supply
|
||||||
"faucet_address": "ait1faucet000000000000000000000000000000000",
|
if chain_id == "ait-mainnet":
|
||||||
"mint_per_unit": cfg.mint_per_unit,
|
response = {
|
||||||
"total_accounts": 0
|
"chain_id": chain_id,
|
||||||
}
|
"total_supply": 1000000000, # 1 billion from genesis
|
||||||
|
"circulating_supply": total_balance, # Actual tokens in circulation
|
||||||
|
"mint_per_unit": cfg.mint_per_unit,
|
||||||
|
"total_accounts": total_accounts # Actual account count
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# Devnet with faucet - use actual calculations
|
||||||
|
response = {
|
||||||
|
"chain_id": chain_id,
|
||||||
|
"total_supply": 1000000000, # 1 billion from genesis
|
||||||
|
"circulating_supply": total_balance, # Actual tokens in circulation
|
||||||
|
"faucet_balance": 1000000000, # All tokens in faucet
|
||||||
|
"faucet_address": "ait1faucet000000000000000000000000000000000",
|
||||||
|
"mint_per_unit": cfg.mint_per_unit,
|
||||||
|
"total_accounts": total_accounts # Actual account count
|
||||||
|
}
|
||||||
|
|
||||||
metrics_registry.observe("rpc_supply_duration_seconds", time.perf_counter() - start)
|
metrics_registry.observe("rpc_supply_duration_seconds", time.perf_counter() - start)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/validators", summary="List blockchain validators")
|
@router.get("/validators", summary="List blockchain validators")
|
||||||
async def get_validators(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
async def get_validators(chain_id: str = None) -> Dict[str, Any]:
|
||||||
"""List blockchain validators (authorities)"""
|
"""List blockchain validators (authorities)"""
|
||||||
from ..config import settings as cfg
|
from ..config import settings as cfg
|
||||||
|
|
||||||
@@ -690,7 +742,7 @@ async def get_validators(chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/state", summary="Get blockchain state information")
|
@router.get("/state", summary="Get blockchain state information")
|
||||||
async def get_chain_state(chain_id: str = "ait-devnet"):
|
async def get_chain_state(chain_id: str = None):
|
||||||
"""Get blockchain state information for a chain"""
|
"""Get blockchain state information for a chain"""
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
@@ -710,7 +762,7 @@ async def get_chain_state(chain_id: str = "ait-devnet"):
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/rpc/getBalance/{address}", summary="Get account balance")
|
@router.get("/rpc/getBalance/{address}", summary="Get account balance")
|
||||||
async def get_balance(address: str, chain_id: str = "ait-devnet"):
|
async def get_balance(address: str, chain_id: str = None):
|
||||||
"""Get account balance for a specific address"""
|
"""Get account balance for a specific address"""
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
@@ -753,7 +805,7 @@ async def get_balance(address: str, chain_id: str = "ait-devnet"):
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/rpc/head", summary="Get current chain head")
|
@router.get("/rpc/head", summary="Get current chain head")
|
||||||
async def get_head(chain_id: str = "ait-devnet"):
|
async def get_head(chain_id: str = None):
|
||||||
"""Get current chain head block"""
|
"""Get current chain head block"""
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
@@ -799,7 +851,7 @@ async def get_head(chain_id: str = "ait-devnet"):
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/rpc/transactions", summary="Get latest transactions")
|
@router.get("/rpc/transactions", summary="Get latest transactions")
|
||||||
async def get_transactions(chain_id: str = "ait-devnet", limit: int = 20, offset: int = 0):
|
async def get_transactions(chain_id: str = None, limit: int = 20, offset: int = 0):
|
||||||
"""Get latest transactions"""
|
"""Get latest transactions"""
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from sqlmodel import Session, select
|
|||||||
from .config import settings
|
from .config import settings
|
||||||
from .logger import get_logger
|
from .logger import get_logger
|
||||||
from .metrics import metrics_registry
|
from .metrics import metrics_registry
|
||||||
from .models import Block, Transaction
|
from .models import Block, Transaction, Account
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@@ -284,15 +284,45 @@ class ChainSync:
|
|||||||
)
|
)
|
||||||
session.add(block)
|
session.add(block)
|
||||||
|
|
||||||
# Import transactions if provided
|
# Import transactions if provided and apply state changes
|
||||||
if transactions:
|
if transactions:
|
||||||
for tx_data in transactions:
|
for tx_data in transactions:
|
||||||
|
sender_addr = tx_data.get("sender", "")
|
||||||
|
payload = tx_data.get("payload", {}) or {}
|
||||||
|
recipient_addr = payload.get("to") or tx_data.get("recipient", "")
|
||||||
|
value = int(payload.get("value", 0) or 0)
|
||||||
|
fee = int(tx_data.get("fee", 0) or 0)
|
||||||
|
tx_hash = tx_data.get("tx_hash", "")
|
||||||
|
|
||||||
|
# Upsert sender/recipient accounts
|
||||||
|
sender_acct = session.get(Account, (self._chain_id, sender_addr))
|
||||||
|
if sender_acct is None:
|
||||||
|
sender_acct = Account(chain_id=self._chain_id, address=sender_addr, balance=0, nonce=0)
|
||||||
|
session.add(sender_acct)
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
recipient_acct = session.get(Account, (self._chain_id, recipient_addr))
|
||||||
|
if recipient_acct is None:
|
||||||
|
recipient_acct = Account(chain_id=self._chain_id, address=recipient_addr, balance=0, nonce=0)
|
||||||
|
session.add(recipient_acct)
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
# Apply balances/nonce; assume block validity already verified on producer
|
||||||
|
total_cost = value + fee
|
||||||
|
sender_acct.balance -= total_cost
|
||||||
|
tx_nonce = tx_data.get("nonce")
|
||||||
|
if tx_nonce is not None:
|
||||||
|
sender_acct.nonce = max(sender_acct.nonce, int(tx_nonce) + 1)
|
||||||
|
else:
|
||||||
|
sender_acct.nonce += 1
|
||||||
|
recipient_acct.balance += value
|
||||||
|
|
||||||
tx = Transaction(
|
tx = Transaction(
|
||||||
chain_id=self._chain_id,
|
chain_id=self._chain_id,
|
||||||
tx_hash=tx_data.get("tx_hash", ""),
|
tx_hash=tx_hash,
|
||||||
block_height=block_data["height"],
|
block_height=block_data["height"],
|
||||||
sender=tx_data.get("sender", ""),
|
sender=sender_addr,
|
||||||
recipient=tx_data.get("recipient", ""),
|
recipient=recipient_addr,
|
||||||
payload=tx_data,
|
payload=tx_data,
|
||||||
)
|
)
|
||||||
session.add(tx)
|
session.add(tx)
|
||||||
|
|||||||
5
apps/blockchain-node/test_mempool.py
Normal file
5
apps/blockchain-node/test_mempool.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from aitbc_chain.config import settings
|
||||||
|
from aitbc_chain.mempool import init_mempool, get_mempool
|
||||||
|
init_mempool(backend=settings.mempool_backend, db_path=str(settings.db_path.parent / "mempool.db"), max_size=settings.mempool_max_size, min_fee=settings.min_fee)
|
||||||
|
pool = get_mempool()
|
||||||
|
print(pool.__class__.__name__)
|
||||||
3
apps/blockchain-node/test_mempool2.py
Normal file
3
apps/blockchain-node/test_mempool2.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from aitbc_chain.config import settings
|
||||||
|
import sys
|
||||||
|
print(settings.db_path.parent / "mempool.db")
|
||||||
6
apps/blockchain-node/test_tx.py
Normal file
6
apps/blockchain-node/test_tx.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from aitbc_chain.database import session_scope
|
||||||
|
from aitbc_chain.models import Account
|
||||||
|
|
||||||
|
with session_scope() as session:
|
||||||
|
acc = session.get(Account, ("ait-mainnet", "aitbc1genesis"))
|
||||||
|
print(acc.address, acc.balance)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
APP_HOST=127.0.0.1
|
APP_HOST=127.0.0.1
|
||||||
APP_PORT=8011
|
APP_PORT=8011
|
||||||
DATABASE_URL=sqlite:///./data/coordinator.db
|
DATABASE_URL=sqlite:////opt/aitbc/data/coordinator.db
|
||||||
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
|
CLIENT_API_KEYS=${CLIENT_API_KEY},client_dev_key_2
|
||||||
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
|
MINER_API_KEYS=${MINER_API_KEY},miner_dev_key_2
|
||||||
ADMIN_API_KEYS=${ADMIN_API_KEY}
|
ADMIN_API_KEYS=${ADMIN_API_KEY}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import json
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
# Database configurations
|
# Database configurations
|
||||||
SQLITE_DB = "coordinator.db"
|
SQLITE_DB = "/opt/aitbc/data/coordinator.db"
|
||||||
PG_CONFIG = {
|
PG_CONFIG = {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"database": "aitbc_coordinator",
|
"database": "aitbc_coordinator",
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from decimal import Decimal
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
# Database configurations
|
# Database configurations
|
||||||
SQLITE_DB = "coordinator.db"
|
SQLITE_DB = "/opt/aitbc/data/coordinator.db"
|
||||||
PG_CONFIG = {
|
PG_CONFIG = {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"database": "aitbc_coordinator",
|
"database": "aitbc_coordinator",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DatabaseConfig(BaseSettings):
|
|||||||
|
|
||||||
# Default SQLite path - consistent with blockchain-node pattern
|
# Default SQLite path - consistent with blockchain-node pattern
|
||||||
if self.adapter == "sqlite":
|
if self.adapter == "sqlite":
|
||||||
return "sqlite:///./data/coordinator.db"
|
return "sqlite:////opt/aitbc/data/coordinator.db"
|
||||||
|
|
||||||
# Default PostgreSQL connection string
|
# Default PostgreSQL connection string
|
||||||
return f"{self.adapter}://localhost:5432/coordinator"
|
return f"{self.adapter}://localhost:5432/coordinator"
|
||||||
@@ -187,7 +187,7 @@ class Settings(BaseSettings):
|
|||||||
if self.database.url:
|
if self.database.url:
|
||||||
return self.database.url
|
return self.database.url
|
||||||
# Default SQLite path - consistent with blockchain-node pattern
|
# Default SQLite path - consistent with blockchain-node pattern
|
||||||
return "sqlite:///./data/coordinator.db"
|
return "sqlite:////opt/aitbc/data/coordinator.db"
|
||||||
|
|
||||||
@database_url.setter
|
@database_url.setter
|
||||||
def database_url(self, value: str):
|
def database_url(self, value: str):
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
from sqlmodel import create_engine, SQLModel
|
from sqlmodel import create_engine, SQLModel
|
||||||
from sqlalchemy import StaticPool
|
from sqlalchemy import StaticPool
|
||||||
|
from .config import settings
|
||||||
|
|
||||||
# Create in-memory SQLite database for now
|
# Create database engine using URL from config
|
||||||
engine = create_engine(
|
engine = create_engine(
|
||||||
"sqlite:///./data/coordinator.db",
|
settings.database_url,
|
||||||
connect_args={"check_same_thread": False},
|
connect_args={"check_same_thread": False} if settings.database_url.startswith("sqlite") else {},
|
||||||
poolclass=StaticPool,
|
poolclass=StaticPool if settings.database_url.startswith("sqlite") else None,
|
||||||
echo=True # Enable SQL logging for debugging
|
echo=settings.test_mode # Enable SQL logging for debugging in test mode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ async def blockchain_sync_status():
|
|||||||
|
|
||||||
rpc_url = settings.blockchain_rpc_url.rstrip('/')
|
rpc_url = settings.blockchain_rpc_url.rstrip('/')
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
response = await client.get(f"{rpc_url}/rpc/sync", timeout=5.0)
|
response = await client.get(f"{rpc_url}/rpc/syncStatus", timeout=5.0)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
data = response.json()
|
data = response.json()
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ limiter = Limiter(key_func=get_remote_address)
|
|||||||
router = APIRouter(tags=["marketplace"])
|
router = APIRouter(tags=["marketplace"])
|
||||||
|
|
||||||
|
|
||||||
def _get_service(session: Annotated[Session, Depends(get_session)]) -> MarketplaceService:
|
def _get_service(session: Session = Depends(get_session)) -> MarketplaceService:
|
||||||
return MarketplaceService(session)
|
return MarketplaceService(session)
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ def _get_service(session: Annotated[Session, Depends(get_session)]) -> Marketpla
|
|||||||
async def list_marketplace_offers(
|
async def list_marketplace_offers(
|
||||||
request: Request,
|
request: Request,
|
||||||
*,
|
*,
|
||||||
session: Annotated[Session, Depends(get_session)],
|
session: Session = Depends(get_session),
|
||||||
status_filter: str | None = Query(default=None, alias="status", description="Filter by offer status"),
|
status_filter: str | None = Query(default=None, alias="status", description="Filter by offer status"),
|
||||||
limit: int = Query(default=100, ge=1, le=500),
|
limit: int = Query(default=100, ge=1, le=500),
|
||||||
offset: int = Query(default=0, ge=0),
|
offset: int = Query(default=0, ge=0),
|
||||||
@@ -60,7 +60,7 @@ async def list_marketplace_offers(
|
|||||||
async def get_marketplace_stats(
|
async def get_marketplace_stats(
|
||||||
request: Request,
|
request: Request,
|
||||||
*,
|
*,
|
||||||
session: Annotated[Session, Depends(get_session)]
|
session: Session = Depends(get_session)
|
||||||
) -> MarketplaceStatsView:
|
) -> MarketplaceStatsView:
|
||||||
marketplace_requests_total.labels(endpoint="/marketplace/stats", method="GET").inc()
|
marketplace_requests_total.labels(endpoint="/marketplace/stats", method="GET").inc()
|
||||||
service = _get_service(session)
|
service = _get_service(session)
|
||||||
@@ -80,7 +80,7 @@ async def get_marketplace_stats(
|
|||||||
async def submit_marketplace_bid(
|
async def submit_marketplace_bid(
|
||||||
request: Request,
|
request: Request,
|
||||||
payload: MarketplaceBidRequest,
|
payload: MarketplaceBidRequest,
|
||||||
session: Annotated[Session, Depends(get_session)],
|
session: Session = Depends(get_session),
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
marketplace_requests_total.labels(endpoint="/marketplace/bids", method="POST").inc()
|
marketplace_requests_total.labels(endpoint="/marketplace/bids", method="POST").inc()
|
||||||
service = _get_service(session)
|
service = _get_service(session)
|
||||||
@@ -102,7 +102,7 @@ async def submit_marketplace_bid(
|
|||||||
)
|
)
|
||||||
async def list_marketplace_bids(
|
async def list_marketplace_bids(
|
||||||
*,
|
*,
|
||||||
session: Annotated[Session, Depends(get_session)],
|
session: Session = Depends(get_session),
|
||||||
status_filter: str | None = Query(default=None, alias="status", description="Filter by bid status"),
|
status_filter: str | None = Query(default=None, alias="status", description="Filter by bid status"),
|
||||||
provider_filter: str | None = Query(default=None, alias="provider", description="Filter by provider ID"),
|
provider_filter: str | None = Query(default=None, alias="provider", description="Filter by provider ID"),
|
||||||
limit: int = Query(default=100, ge=1, le=500),
|
limit: int = Query(default=100, ge=1, le=500),
|
||||||
@@ -127,7 +127,7 @@ async def list_marketplace_bids(
|
|||||||
)
|
)
|
||||||
async def get_marketplace_bid(
|
async def get_marketplace_bid(
|
||||||
bid_id: str,
|
bid_id: str,
|
||||||
session: Annotated[Session, Depends(get_session)],
|
session: Session = Depends(get_session),
|
||||||
) -> MarketplaceBidView:
|
) -> MarketplaceBidView:
|
||||||
marketplace_requests_total.labels(endpoint="/marketplace/bids/{bid_id}", method="GET").inc()
|
marketplace_requests_total.labels(endpoint="/marketplace/bids/{bid_id}", method="GET").inc()
|
||||||
service = _get_service(session)
|
service = _get_service(session)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class MarketplaceAnalyticsRequest(BaseModel):
|
|||||||
async def create_royalty_distribution(
|
async def create_royalty_distribution(
|
||||||
request: RoyaltyDistributionRequest,
|
request: RoyaltyDistributionRequest,
|
||||||
offer_id: str,
|
offer_id: str,
|
||||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
session: Session = Depends(get_session),
|
||||||
current_user: str = Depends(require_admin_key())
|
current_user: str = Depends(require_admin_key())
|
||||||
):
|
):
|
||||||
"""Create royalty distribution for marketplace offer"""
|
"""Create royalty distribution for marketplace offer"""
|
||||||
@@ -74,7 +74,7 @@ async def create_royalty_distribution(
|
|||||||
async def calculate_royalties(
|
async def calculate_royalties(
|
||||||
offer_id: str,
|
offer_id: str,
|
||||||
sale_amount: float,
|
sale_amount: float,
|
||||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
session: Session = Depends(get_session),
|
||||||
current_user: str = Depends(require_admin_key())
|
current_user: str = Depends(require_admin_key())
|
||||||
):
|
):
|
||||||
"""Calculate royalties for a sale"""
|
"""Calculate royalties for a sale"""
|
||||||
@@ -97,7 +97,7 @@ async def calculate_royalties(
|
|||||||
async def create_model_license(
|
async def create_model_license(
|
||||||
request: ModelLicenseRequest,
|
request: ModelLicenseRequest,
|
||||||
offer_id: str,
|
offer_id: str,
|
||||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
session: Session = Depends(get_session),
|
||||||
current_user: str = Depends(require_admin_key())
|
current_user: str = Depends(require_admin_key())
|
||||||
):
|
):
|
||||||
"""Create model license for marketplace offer"""
|
"""Create model license for marketplace offer"""
|
||||||
@@ -123,7 +123,7 @@ async def create_model_license(
|
|||||||
async def verify_model(
|
async def verify_model(
|
||||||
request: ModelVerificationRequest,
|
request: ModelVerificationRequest,
|
||||||
offer_id: str,
|
offer_id: str,
|
||||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
session: Session = Depends(get_session),
|
||||||
current_user: str = Depends(require_admin_key())
|
current_user: str = Depends(require_admin_key())
|
||||||
):
|
):
|
||||||
"""Verify model quality and performance"""
|
"""Verify model quality and performance"""
|
||||||
@@ -145,7 +145,7 @@ async def verify_model(
|
|||||||
@router.post("/analytics")
|
@router.post("/analytics")
|
||||||
async def get_marketplace_analytics(
|
async def get_marketplace_analytics(
|
||||||
request: MarketplaceAnalyticsRequest,
|
request: MarketplaceAnalyticsRequest,
|
||||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
session: Session = Depends(get_session),
|
||||||
current_user: str = Depends(require_admin_key())
|
current_user: str = Depends(require_admin_key())
|
||||||
):
|
):
|
||||||
"""Get marketplace analytics and insights"""
|
"""Get marketplace analytics and insights"""
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Basic marketplace enhancement features compatible with existing domain models
|
|||||||
import asyncio
|
import asyncio
|
||||||
from aitbc.logging import get_logger
|
from aitbc.logging import get_logger
|
||||||
from typing import Dict, List, Optional, Any
|
from typing import Dict, List, Optional, Any
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
@@ -225,12 +225,12 @@ class EnhancedMarketplaceService:
|
|||||||
offers_query = select(MarketplaceOffer).where(
|
offers_query = select(MarketplaceOffer).where(
|
||||||
MarketplaceOffer.created_at >= start_date
|
MarketplaceOffer.created_at >= start_date
|
||||||
)
|
)
|
||||||
offers = self.session.execute(offers_query).all()
|
offers = self.session.execute(offers_query).scalars().all()
|
||||||
|
|
||||||
bids_query = select(MarketplaceBid).where(
|
bids_query = select(MarketplaceBid).where(
|
||||||
MarketplaceBid.created_at >= start_date
|
MarketplaceBid.submitted_at >= start_date
|
||||||
)
|
)
|
||||||
bids = self.session.execute(bids_query).all()
|
bids = self.session.execute(bids_query).scalars().all()
|
||||||
|
|
||||||
# Calculate analytics
|
# Calculate analytics
|
||||||
analytics = {
|
analytics = {
|
||||||
@@ -264,7 +264,7 @@ class EnhancedMarketplaceService:
|
|||||||
|
|
||||||
if "revenue" in metrics:
|
if "revenue" in metrics:
|
||||||
analytics["metrics"]["revenue"] = {
|
analytics["metrics"]["revenue"] = {
|
||||||
"total_revenue": sum(bid.amount or 0 for bid in bids),
|
"total_revenue": sum(bid.price or 0 for bid in bids),
|
||||||
"average_price": sum(offer.price or 0 for offer in offers) / len(offers) if offers else 0,
|
"average_price": sum(offer.price or 0 for offer in offers) / len(offers) if offers else 0,
|
||||||
"revenue_growth": 0.12
|
"revenue_growth": 0.12
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,6 @@
|
|||||||
"author": "AITBC Team",
|
"author": "AITBC Team",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.22.0"
|
"node": ">=24.14.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -917,18 +917,20 @@ def send(ctx, chain_id, from_addr, to, data, nonce):
|
|||||||
config = ctx.obj['config']
|
config = ctx.obj['config']
|
||||||
try:
|
try:
|
||||||
import httpx
|
import httpx
|
||||||
|
import json
|
||||||
with httpx.Client() as client:
|
with httpx.Client() as client:
|
||||||
|
try:
|
||||||
|
payload_data = json.loads(data)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
payload_data = {"raw_data": data}
|
||||||
|
|
||||||
tx_payload = {
|
tx_payload = {
|
||||||
"type": "TRANSFER",
|
"type": "TRANSFER",
|
||||||
"chain_id": chain_id,
|
"sender": from_addr,
|
||||||
"from_address": from_addr,
|
|
||||||
"to_address": to,
|
|
||||||
"value": 0,
|
|
||||||
"gas_limit": 100000,
|
|
||||||
"gas_price": 1,
|
|
||||||
"nonce": nonce,
|
"nonce": nonce,
|
||||||
"data": data,
|
"fee": 0,
|
||||||
"signature": "mock_signature"
|
"payload": payload_data,
|
||||||
|
"sig": "mock_signature"
|
||||||
}
|
}
|
||||||
|
|
||||||
response = client.post(
|
response = client.post(
|
||||||
|
|||||||
@@ -9,12 +9,57 @@ from ..core.genesis_generator import GenesisGenerator, GenesisValidationError
|
|||||||
from ..core.config import MultiChainConfig, load_multichain_config
|
from ..core.config import MultiChainConfig, load_multichain_config
|
||||||
from ..models.chain import GenesisConfig
|
from ..models.chain import GenesisConfig
|
||||||
from ..utils import output, error, success
|
from ..utils import output, error, success
|
||||||
|
from .keystore import create_keystore_via_script
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
def genesis():
|
def genesis():
|
||||||
"""Genesis block generation and management commands"""
|
"""Genesis block generation and management commands"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@genesis.command()
|
||||||
|
@click.option('--address', required=True, help='Wallet address (id) to create')
|
||||||
|
@click.option('--password-file', default='/opt/aitbc/data/keystore/.password', show_default=True, type=click.Path(exists=True, dir_okay=False), help='Path to password file')
|
||||||
|
@click.option('--output-dir', default='/opt/aitbc/data/keystore', show_default=True, help='Directory to write keystore file')
|
||||||
|
@click.option('--force', is_flag=True, help='Overwrite existing keystore file if present')
|
||||||
|
@click.pass_context
|
||||||
|
def create_keystore(ctx, address, password_file, output_dir, force):
|
||||||
|
"""Create an encrypted keystore for a genesis/treasury address."""
|
||||||
|
try:
|
||||||
|
create_keystore_via_script(address=address, password_file=password_file, output_dir=output_dir, force=force)
|
||||||
|
success(f"Created keystore for {address} at {output_dir}")
|
||||||
|
except Exception as e:
|
||||||
|
error(f"Error creating keystore: {e}")
|
||||||
|
raise click.Abort()
|
||||||
|
|
||||||
|
|
||||||
|
@genesis.command(name="init-production")
|
||||||
|
@click.option('--chain-id', default='ait-mainnet', show_default=True, help='Chain ID to initialize')
|
||||||
|
@click.option('--genesis-file', default='data/genesis_prod.yaml', show_default=True, help='Path to genesis YAML (copy to /opt/aitbc/genesis_prod.yaml if needed)')
|
||||||
|
@click.option('--db', default='/opt/aitbc/data/ait-mainnet/chain.db', show_default=True, help='SQLite DB path')
|
||||||
|
@click.option('--force', is_flag=True, help='Overwrite existing DB (removes file if present)')
|
||||||
|
@click.pass_context
|
||||||
|
def init_production(ctx, chain_id, genesis_file, db, force):
|
||||||
|
"""Initialize production chain DB using genesis allocations."""
|
||||||
|
db_path = Path(db)
|
||||||
|
if db_path.exists() and force:
|
||||||
|
db_path.unlink()
|
||||||
|
python_bin = Path(__file__).resolve().parents[3] / 'apps' / 'blockchain-node' / '.venv' / 'bin' / 'python3'
|
||||||
|
cmd = [
|
||||||
|
str(python_bin),
|
||||||
|
str(Path(__file__).resolve().parents[3] / 'scripts' / 'init_production_genesis.py'),
|
||||||
|
'--chain-id', chain_id,
|
||||||
|
'--db', db,
|
||||||
|
]
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
success(f"Initialized production genesis for {chain_id} at {db}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
error(f"Genesis init failed: {e}")
|
||||||
|
raise click.Abort()
|
||||||
|
|
||||||
@genesis.command()
|
@genesis.command()
|
||||||
@click.argument('config_file', type=click.Path(exists=True))
|
@click.argument('config_file', type=click.Path(exists=True))
|
||||||
@click.option('--output', '-o', 'output_file', help='Output file path')
|
@click.option('--output', '-o', 'output_file', help='Output file path')
|
||||||
|
|||||||
67
cli/aitbc_cli/commands/keystore.py
Normal file
67
cli/aitbc_cli/commands/keystore.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import click
|
||||||
|
import importlib.util
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def _load_keystore_script():
|
||||||
|
"""Dynamically load the top-level scripts/keystore.py module."""
|
||||||
|
root = Path(__file__).resolve().parents[3] # /opt/aitbc
|
||||||
|
ks_path = root / "scripts" / "keystore.py"
|
||||||
|
spec = importlib.util.spec_from_file_location("aitbc_scripts_keystore", ks_path)
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
raise ImportError(f"Unable to load keystore script from {ks_path}")
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def keystore():
|
||||||
|
"""Keystore operations (create wallets/keystores)."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@keystore.command()
|
||||||
|
@click.option("--address", required=True, help="Wallet address (id) to create")
|
||||||
|
@click.option(
|
||||||
|
"--password-file",
|
||||||
|
default="/opt/aitbc/data/keystore/.password",
|
||||||
|
show_default=True,
|
||||||
|
type=click.Path(exists=True, dir_okay=False),
|
||||||
|
help="Path to password file",
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--output",
|
||||||
|
default="/opt/aitbc/data/keystore",
|
||||||
|
show_default=True,
|
||||||
|
help="Directory to write keystore files",
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--force",
|
||||||
|
is_flag=True,
|
||||||
|
help="Overwrite existing keystore file if present",
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def create(ctx, address: str, password_file: str, output: str, force: bool):
|
||||||
|
"""Create an encrypted keystore for the given address.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
aitbc keystore create --address aitbc1genesis
|
||||||
|
aitbc keystore create --address aitbc1treasury --password-file keystore/.password --output keystore
|
||||||
|
"""
|
||||||
|
pwd_path = Path(password_file)
|
||||||
|
with open(pwd_path, "r", encoding="utf-8") as f:
|
||||||
|
password = f.read().strip()
|
||||||
|
out_dir = Path(output) if output else Path("/opt/aitbc/data/keystore")
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
ks_module = _load_keystore_script()
|
||||||
|
ks_module.create_keystore(address=address, password=password, keystore_dir=out_dir, force=force)
|
||||||
|
click.echo(f"Created keystore for {address} at {out_dir}")
|
||||||
|
|
||||||
|
|
||||||
|
# Helper so other commands (genesis) can reuse the same logic
|
||||||
|
def create_keystore_via_script(address: str, password_file: str = "/opt/aitbc/data/keystore/.password", output_dir: str = "/opt/aitbc/data/keystore", force: bool = False):
|
||||||
|
pwd = Path(password_file).read_text(encoding="utf-8").strip()
|
||||||
|
out_dir = Path(output_dir)
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
ks_module = _load_keystore_script()
|
||||||
|
ks_module.create_keystore(address=address, password=pwd, keystore_dir=out_dir, force=force)
|
||||||
@@ -290,8 +290,11 @@ class DualModeWalletAdapter:
|
|||||||
|
|
||||||
def _send_transaction_file(self, wallet_name: str, password: str, to_address: str,
|
def _send_transaction_file(self, wallet_name: str, password: str, to_address: str,
|
||||||
amount: float, description: Optional[str]) -> Dict[str, Any]:
|
amount: float, description: Optional[str]) -> Dict[str, Any]:
|
||||||
"""Send transaction using file-based storage"""
|
"""Send transaction using file-based storage and blockchain RPC"""
|
||||||
from .commands.wallet import _load_wallet, _save_wallet
|
from .commands.wallet import _load_wallet, _save_wallet
|
||||||
|
import httpx
|
||||||
|
from .utils import error, success
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
wallet_path = self.wallet_dir / f"{wallet_name}.json"
|
wallet_path = self.wallet_dir / f"{wallet_name}.json"
|
||||||
|
|
||||||
@@ -300,23 +303,66 @@ class DualModeWalletAdapter:
|
|||||||
raise Exception("Wallet not found")
|
raise Exception("Wallet not found")
|
||||||
|
|
||||||
wallet_data = _load_wallet(wallet_path, wallet_name)
|
wallet_data = _load_wallet(wallet_path, wallet_name)
|
||||||
balance = wallet_data.get("balance", 0)
|
# Fetch current balance and nonce from blockchain
|
||||||
|
from_address = wallet_data.get("address")
|
||||||
if balance < amount:
|
if not from_address:
|
||||||
error(f"Insufficient balance. Available: {balance}, Required: {amount}")
|
error("Wallet does not have an address configured")
|
||||||
|
raise Exception("Invalid wallet")
|
||||||
|
|
||||||
|
rpc_url = self.config.blockchain_rpc_url
|
||||||
|
try:
|
||||||
|
resp = httpx.get(f"{rpc_url}/rpc/getBalance/{from_address}?chain_id=ait-mainnet", timeout=5)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
data = resp.json()
|
||||||
|
chain_balance = data.get("balance", 0)
|
||||||
|
nonce = data.get("nonce", 0)
|
||||||
|
else:
|
||||||
|
error(f"Failed to get balance from chain: {resp.text}")
|
||||||
|
raise Exception("Chain error")
|
||||||
|
except Exception as e:
|
||||||
|
error(f"Failed to connect to blockchain RPC: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
if chain_balance < amount:
|
||||||
|
error(f"Insufficient blockchain balance. Available: {chain_balance}, Required: {amount}")
|
||||||
raise Exception("Insufficient balance")
|
raise Exception("Insufficient balance")
|
||||||
|
|
||||||
|
# Construct and send transaction
|
||||||
|
tx_payload = {
|
||||||
|
"type": "TRANSFER",
|
||||||
|
"sender": from_address,
|
||||||
|
"nonce": nonce,
|
||||||
|
"fee": 0,
|
||||||
|
"payload": {"to": to_address, "value": amount},
|
||||||
|
"sig": "mock_signature" # Replace with real signature when implemented
|
||||||
|
}
|
||||||
|
|
||||||
# Add transaction
|
try:
|
||||||
|
resp = httpx.post(f"{rpc_url}/rpc/sendTx", json=tx_payload, timeout=5)
|
||||||
|
if resp.status_code not in (200, 201):
|
||||||
|
error(f"Failed to submit transaction to chain: {resp.text}")
|
||||||
|
raise Exception("Chain submission failed")
|
||||||
|
tx_hash = resp.json().get("tx_hash")
|
||||||
|
except Exception as e:
|
||||||
|
error(f"Failed to send transaction to RPC: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Add transaction to local history
|
||||||
transaction = {
|
transaction = {
|
||||||
"type": "send",
|
"type": "send",
|
||||||
"amount": -amount,
|
"amount": -amount,
|
||||||
"to_address": to_address,
|
"to_address": to_address,
|
||||||
"description": description or "",
|
"description": description or "",
|
||||||
"timestamp": datetime.now().isoformat(),
|
"timestamp": datetime.now().isoformat(),
|
||||||
|
"tx_hash": tx_hash,
|
||||||
|
"status": "pending"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if "transactions" not in wallet_data:
|
||||||
|
wallet_data["transactions"] = []
|
||||||
|
|
||||||
wallet_data["transactions"].append(transaction)
|
wallet_data["transactions"].append(transaction)
|
||||||
wallet_data["balance"] = balance - amount
|
wallet_data["balance"] = chain_balance - amount
|
||||||
|
|
||||||
# Save wallet - CRITICAL SECURITY FIX: Always use password if wallet is encrypted
|
# Save wallet - CRITICAL SECURITY FIX: Always use password if wallet is encrypted
|
||||||
save_password = password if wallet_data.get("encrypted") else None
|
save_password = password if wallet_data.get("encrypted") else None
|
||||||
@@ -325,14 +371,14 @@ class DualModeWalletAdapter:
|
|||||||
raise Exception("Password required for encrypted wallet")
|
raise Exception("Password required for encrypted wallet")
|
||||||
_save_wallet(wallet_path, wallet_data, save_password)
|
_save_wallet(wallet_path, wallet_data, save_password)
|
||||||
|
|
||||||
success(f"Sent {amount} AITBC to {to_address}")
|
success(f"Submitted transaction {tx_hash} to send {amount} AITBC to {to_address}")
|
||||||
return {
|
return {
|
||||||
"mode": "file",
|
"mode": "file",
|
||||||
"wallet_name": wallet_name,
|
"wallet_name": wallet_name,
|
||||||
"to_address": to_address,
|
"to_address": to_address,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"description": description,
|
"description": description,
|
||||||
"new_balance": wallet_data["balance"],
|
"tx_hash": tx_hash,
|
||||||
"timestamp": transaction["timestamp"]
|
"timestamp": transaction["timestamp"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ from .commands.marketplace_advanced import advanced # Re-enabled after fixing r
|
|||||||
from .commands.swarm import swarm
|
from .commands.swarm import swarm
|
||||||
from .commands.chain import chain
|
from .commands.chain import chain
|
||||||
from .commands.genesis import genesis
|
from .commands.genesis import genesis
|
||||||
|
from .commands.keystore import keystore
|
||||||
from .commands.test_cli import test
|
from .commands.test_cli import test
|
||||||
from .commands.node import node
|
from .commands.node import node
|
||||||
from .commands.analytics import analytics
|
from .commands.analytics import analytics
|
||||||
@@ -257,6 +258,7 @@ cli.add_command(ai_group)
|
|||||||
cli.add_command(swarm)
|
cli.add_command(swarm)
|
||||||
cli.add_command(chain)
|
cli.add_command(chain)
|
||||||
cli.add_command(genesis)
|
cli.add_command(genesis)
|
||||||
|
cli.add_command(keystore)
|
||||||
cli.add_command(test)
|
cli.add_command(test)
|
||||||
cli.add_command(node)
|
cli.add_command(node)
|
||||||
cli.add_command(analytics)
|
cli.add_command(analytics)
|
||||||
|
|||||||
@@ -365,3 +365,4 @@ def create_http_client_with_retry(
|
|||||||
transport=RetryTransport(),
|
transport=RetryTransport(),
|
||||||
timeout=timeout
|
timeout=timeout
|
||||||
)
|
)
|
||||||
|
from .subprocess import run_subprocess
|
||||||
|
|||||||
31
cli/aitbc_cli/utils/subprocess.py
Normal file
31
cli/aitbc_cli/utils/subprocess.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from typing import List, Optional, Union, Any
|
||||||
|
from . import error, output
|
||||||
|
|
||||||
|
def run_subprocess(cmd: List[str], check: bool = True, capture_output: bool = True, shell: bool = False, **kwargs: Any) -> Optional[Union[str, subprocess.CompletedProcess]]:
|
||||||
|
"""Run a subprocess command safely with logging"""
|
||||||
|
try:
|
||||||
|
if shell:
|
||||||
|
# When shell=True, cmd should be a string
|
||||||
|
cmd_str = " ".join(cmd) if isinstance(cmd, list) else cmd
|
||||||
|
result = subprocess.run(cmd_str, shell=True, check=check, capture_output=capture_output, text=True, **kwargs)
|
||||||
|
else:
|
||||||
|
result = subprocess.run(cmd, check=check, capture_output=capture_output, text=True, **kwargs)
|
||||||
|
|
||||||
|
if capture_output:
|
||||||
|
return result.stdout.strip()
|
||||||
|
return result
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
error(f"Command failed with exit code {e.returncode}")
|
||||||
|
if capture_output and getattr(e, 'stderr', None):
|
||||||
|
print(e.stderr, file=sys.stderr)
|
||||||
|
if check:
|
||||||
|
sys.exit(e.returncode)
|
||||||
|
return getattr(e, 'stdout', None) if capture_output else None
|
||||||
|
except Exception as e:
|
||||||
|
error(f"Failed to execute command: {e}")
|
||||||
|
if check:
|
||||||
|
sys.exit(1)
|
||||||
|
return None
|
||||||
@@ -1 +1 @@
|
|||||||
22.22.0
|
24.14.0
|
||||||
|
|||||||
6
dev/scripts/dev_heartbeat.py
Normal file → Executable file
6
dev/scripts/dev_heartbeat.py
Normal file → Executable file
@@ -38,10 +38,10 @@ def check_build_tests():
|
|||||||
rc, out = sh("poetry check")
|
rc, out = sh("poetry check")
|
||||||
checks.append(("poetry check", rc == 0, out))
|
checks.append(("poetry check", rc == 0, out))
|
||||||
# 2) Fast syntax check of CLI package
|
# 2) Fast syntax check of CLI package
|
||||||
rc, out = sh("python -m py_compile cli/aitbc_cli/__main__.py")
|
rc, out = sh("python3 -m py_compile cli/aitbc_cli/main.py")
|
||||||
checks.append(("cli syntax", rc == 0, out if rc != 0 else "OK"))
|
checks.append(("cli syntax", rc == 0, out if rc != 0 else "OK"))
|
||||||
# 3) Minimal test run (dry-run or 1 quick test)
|
# 3) Minimal test run (dry-run or 1 quick test)
|
||||||
rc, out = sh("python -m pytest tests/ -v --collect-only 2>&1 | head -20")
|
rc, out = sh("python3 -m pytest tests/ -v --collect-only 2>&1 | head -20")
|
||||||
tests_ok = rc == 0
|
tests_ok = rc == 0
|
||||||
checks.append(("test discovery", tests_ok, out if not tests_ok else f"Collected {out.count('test') if 'test' in out else '?'} tests"))
|
checks.append(("test discovery", tests_ok, out if not tests_ok else f"Collected {out.count('test') if 'test' in out else '?'} tests"))
|
||||||
all_ok = all(ok for _, ok, _ in checks)
|
all_ok = all(ok for _, ok, _ in checks)
|
||||||
@@ -86,7 +86,7 @@ def check_vulnerabilities():
|
|||||||
"""Run security audits for Python and Node dependencies."""
|
"""Run security audits for Python and Node dependencies."""
|
||||||
issues = []
|
issues = []
|
||||||
# Python: pip-audit (if available)
|
# Python: pip-audit (if available)
|
||||||
rc, out = sh("pip-audit --requirement <(poetry export --without-hashes) 2>&1", shell=True)
|
rc, out = sh("pip-audit --requirement <(poetry export --without-hashes) 2>&1")
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
# No vulnerabilities
|
# No vulnerabilities
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Internet → aitbc.bubuit.net (HTTPS :443)
|
|||||||
│ │ Container: aitbc (10.1.223.1) │ │
|
│ │ Container: aitbc (10.1.223.1) │ │
|
||||||
│ │ Access: ssh aitbc-cascade │ │
|
│ │ Access: ssh aitbc-cascade │ │
|
||||||
│ │ OS: Debian 13 Trixie │ │
|
│ │ OS: Debian 13 Trixie │ │
|
||||||
│ │ Node.js: 22+ │ │
|
│ │ Node.js: 24+ │ │
|
||||||
│ │ Python: 3.13.5+ │ │
|
│ │ Python: 3.13.5+ │ │
|
||||||
│ │ GPU Access: None (CPU-only mode) │ │
|
│ │ GPU Access: None (CPU-only mode) │ │
|
||||||
│ │ Miner Service: Not needed │ │
|
│ │ Miner Service: Not needed │ │
|
||||||
@@ -103,7 +103,7 @@ Internet → aitbc.bubuit.net (HTTPS :443)
|
|||||||
- **Hostname**: `at1` (primary development workstation)
|
- **Hostname**: `at1` (primary development workstation)
|
||||||
- **Environment**: Windsurf development environment
|
- **Environment**: Windsurf development environment
|
||||||
- **OS**: Debian 13 Trixie (development environment)
|
- **OS**: Debian 13 Trixie (development environment)
|
||||||
- **Node.js**: 22+ (current tested: v22.22.x)
|
- **Node.js**: 24+ (current tested: v24.14.x)
|
||||||
- **Python**: 3.13.5+ (minimum requirement, strictly enforced)
|
- **Python**: 3.13.5+ (minimum requirement, strictly enforced)
|
||||||
- **GPU Access**: **Primary GPU access location** - all GPU workloads must run on at1
|
- **GPU Access**: **Primary GPU access location** - all GPU workloads must run on at1
|
||||||
- **Architecture**: x86_64 Linux with CUDA GPU support
|
- **Architecture**: x86_64 Linux with CUDA GPU support
|
||||||
@@ -136,7 +136,7 @@ aitbc-mock-coordinator.service # Mock coordinator on port 8020
|
|||||||
**Service Details:**
|
**Service Details:**
|
||||||
- **Working Directory**: `/opt/aitbc/` (standard path for all services)
|
- **Working Directory**: `/opt/aitbc/` (standard path for all services)
|
||||||
- **Python Environment**: `/opt/aitbc/.venv/bin/python` (Python 3.13.5+)
|
- **Python Environment**: `/opt/aitbc/.venv/bin/python` (Python 3.13.5+)
|
||||||
- **Node.js Environment**: System Node.js 22+ (current tested: v22.22.x)
|
- **Node.js Environment**: System Node.js 24+ (current tested: v24.14.x)
|
||||||
- **User**: oib
|
- **User**: oib
|
||||||
- **Restart Policy**: always (with 5s delay)
|
- **Restart Policy**: always (with 5s delay)
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ ls -la /opt/aitbc/systemd # Should show symlink to windsurf system
|
|||||||
└── systemd -> /home/oib/windsurf/aitbc/systemd/
|
└── systemd -> /home/oib/windsurf/aitbc/systemd/
|
||||||
|
|
||||||
# Node.js environment
|
# Node.js environment
|
||||||
node --version # Should show v22.22.x
|
node --version # Should show v24.14.x
|
||||||
npm --version # Should show compatible version
|
npm --version # Should show compatible version
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ ls -la /opt/aitbc/ # Should show individual symlinks, not s
|
|||||||
ls -la /opt/aitbc/apps/blockchain-node # Should point to windsurf project
|
ls -la /opt/aitbc/apps/blockchain-node # Should point to windsurf project
|
||||||
python3 --version # Should show Python 3.13.5
|
python3 --version # Should show Python 3.13.5
|
||||||
ls -la /home/oib/windsurf/aitbc/.venv/bin/python # Check development venv
|
ls -la /home/oib/windsurf/aitbc/.venv/bin/python # Check development venv
|
||||||
node --version # Should show v22.22.x
|
node --version # Should show v24.14.x
|
||||||
npm --version # Should show compatible version
|
npm --version # Should show compatible version
|
||||||
|
|
||||||
# Test symlink resolution
|
# Test symlink resolution
|
||||||
@@ -307,7 +307,7 @@ ssh aitbc1-cascade # Direct SSH to aitbc1 container (incus)
|
|||||||
- Purpose: secondary AITBC dev environment (incus container)
|
- Purpose: secondary AITBC dev environment (incus container)
|
||||||
- Host: 10.1.223.40 (Debian 13 Trixie), accessible via new SSH alias `aitbc1-cascade`
|
- Host: 10.1.223.40 (Debian 13 Trixie), accessible via new SSH alias `aitbc1-cascade`
|
||||||
- OS: Debian 13 Trixie (development environment)
|
- OS: Debian 13 Trixie (development environment)
|
||||||
- Node.js: 22+ (current tested: v22.22.x)
|
- Node.js: 24+ (current tested: v24.14.x)
|
||||||
- Python: 3.13.5+ (minimum requirement, strictly enforced)
|
- Python: 3.13.5+ (minimum requirement, strictly enforced)
|
||||||
- Proxy device: incus proxy on host maps 127.0.0.1:18001 → 127.0.0.1:8000 inside container
|
- Proxy device: incus proxy on host maps 127.0.0.1:18001 → 127.0.0.1:8000 inside container
|
||||||
- AppArmor profile: unconfined (incus raw.lxc)
|
- AppArmor profile: unconfined (incus raw.lxc)
|
||||||
@@ -353,9 +353,9 @@ ssh aitbc1-cascade # Direct SSH to aitbc1 container (incus)
|
|||||||
| Web UI | 8016 | python | 3.13.5 | /app/ | ✅ |
|
| Web UI | 8016 | python | 3.13.5 | /app/ | ✅ |
|
||||||
| Geographic Load Balancer | 8017 | python | 3.13.5 | /api/loadbalancer/* | ✅ |
|
| Geographic Load Balancer | 8017 | python | 3.13.5 | /api/loadbalancer/* | ✅ |
|
||||||
|
|
||||||
**Python 3.13.5 and Node.js 22+ Upgrade Complete** (2026-03-05):
|
**Python 3.13.5 and Node.js 24+ Upgrade Complete** (2026-03-05):
|
||||||
- All services upgraded to Python 3.13.5
|
- All services upgraded to Python 3.13.5
|
||||||
- Node.js upgraded to 22+ (current tested: v22.22.x)
|
- Node.js upgraded to 24+ (current tested: v24.14.x)
|
||||||
- Virtual environments updated and verified
|
- Virtual environments updated and verified
|
||||||
- API routing fixed for external access
|
- API routing fixed for external access
|
||||||
- Services fully operational with enhanced performance
|
- Services fully operational with enhanced performance
|
||||||
@@ -381,7 +381,7 @@ All Python services in the AITBC container run on **Python 3.13.5** with isolate
|
|||||||
**Verification Commands:**
|
**Verification Commands:**
|
||||||
```bash
|
```bash
|
||||||
ssh aitbc-cascade "python3 --version" # Should show Python 3.13.5
|
ssh aitbc-cascade "python3 --version" # Should show Python 3.13.5
|
||||||
ssh aitbc-cascade "node --version" # Should show v22.22.x
|
ssh aitbc-cascade "node --version" # Should show v24.14.x
|
||||||
ssh aitbc-cascade "npm --version" # Should show compatible version
|
ssh aitbc-cascade "npm --version" # Should show compatible version
|
||||||
ssh aitbc-cascade "ls -la /opt/*/.venv/bin/python" # Check venv symlinks
|
ssh aitbc-cascade "ls -la /opt/*/.venv/bin/python" # Check venv symlinks
|
||||||
ssh aitbc-cascade "curl -s http://127.0.0.1:8000/v1/health" # Coordinator API health
|
ssh aitbc-cascade "curl -s http://127.0.0.1:8000/v1/health" # Coordinator API health
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ This guide provides comprehensive deployment instructions for the **aitbc server
|
|||||||
### **Software Requirements**
|
### **Software Requirements**
|
||||||
- **Operating System**: Debian 13 Trixie (primary) or Ubuntu 22.04+ (alternative)
|
- **Operating System**: Debian 13 Trixie (primary) or Ubuntu 22.04+ (alternative)
|
||||||
- **Python**: 3.13.5+ (strictly enforced - platform requires 3.13+ features)
|
- **Python**: 3.13.5+ (strictly enforced - platform requires 3.13+ features)
|
||||||
- **Node.js**: 22+ (current tested: v22.22.x)
|
- **Node.js**: 24+ (current tested: v24.14.x)
|
||||||
- **Database**: SQLite (default) or PostgreSQL (production)
|
- **Database**: SQLite (default) or PostgreSQL (production)
|
||||||
|
|
||||||
### **Network Requirements**
|
### **Network Requirements**
|
||||||
|
|||||||
@@ -176,9 +176,9 @@ python3 --version # Should show 3.13.x
|
|||||||
|
|
||||||
### **🔥 Issue 1b: Node.js Version Compatibility**
|
### **🔥 Issue 1b: Node.js Version Compatibility**
|
||||||
|
|
||||||
**Current Status**: Node.js v22.22.x (tested and compatible)
|
**Current Status**: Node.js v24.14.x (tested and compatible)
|
||||||
|
|
||||||
**Note**: Current Node.js version v22.22.x meets the minimum requirement of 22.0.0 and is fully compatible with AITBC platform.
|
**Note**: Current Node.js version v24.14.x meets the minimum requirement of 24.14.0 and is fully compatible with AITBC platform.
|
||||||
|
|
||||||
### **🔥 Issue 1c: Operating System Compatibility**
|
### **🔥 Issue 1c: Operating System Compatibility**
|
||||||
|
|
||||||
|
|||||||
32
drain_test.py
Normal file
32
drain_test.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Setup sys.path
|
||||||
|
sys.path.insert(0, str(Path('/opt/aitbc/apps/blockchain-node/src')))
|
||||||
|
|
||||||
|
from aitbc_chain.config import settings
|
||||||
|
from aitbc_chain.mempool import init_mempool, get_mempool
|
||||||
|
|
||||||
|
# Use development mempool backend configuration exactly like main node
|
||||||
|
init_mempool(
|
||||||
|
backend=settings.mempool_backend,
|
||||||
|
db_path=str(settings.db_path.parent / "mempool.db"),
|
||||||
|
max_size=settings.mempool_max_size,
|
||||||
|
min_fee=settings.min_fee,
|
||||||
|
)
|
||||||
|
|
||||||
|
mempool = get_mempool()
|
||||||
|
print(f"Mempool class: {mempool.__class__.__name__}")
|
||||||
|
print(f"Mempool DB path: {mempool._db_path}")
|
||||||
|
|
||||||
|
chain_id = 'ait-mainnet'
|
||||||
|
rows = mempool._conn.execute("SELECT * FROM mempool WHERE chain_id = ?", (chain_id,)).fetchall()
|
||||||
|
print(f"Found {len(rows)} raw rows in DB")
|
||||||
|
for r in rows:
|
||||||
|
print(r)
|
||||||
|
|
||||||
|
txs = mempool.drain(100, 1000000, chain_id)
|
||||||
|
print(f"Drained {len(txs)} txs")
|
||||||
|
for tx in txs:
|
||||||
|
print(tx)
|
||||||
9
fix_gossip.patch
Normal file
9
fix_gossip.patch
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
--- /opt/aitbc/apps/blockchain-node/src/aitbc_chain/gossip/broker.py 2026-03-23 12:40:00.000000000 +0100
|
||||||
|
+++ /opt/aitbc/apps/blockchain-node/src/aitbc_chain/gossip/broker.py.new 2026-03-23 12:40:00.000000000 +0100
|
||||||
|
@@ -6,7 +6,7 @@
|
||||||
|
import warnings
|
||||||
|
from collections import defaultdict
|
||||||
|
-from contextlib import suppress
|
||||||
|
+from contextlib import suppress, asynccontextmanager
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, Callable, Dict, List, Optional, Set
|
||||||
30
fix_inprocess.py
Normal file
30
fix_inprocess.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import asyncio
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
class _InProcessSubscriber:
|
||||||
|
def __init__(self, queue, release):
|
||||||
|
self._queue = queue
|
||||||
|
self._release = release
|
||||||
|
def __aiter__(self):
|
||||||
|
return self._iterator()
|
||||||
|
async def _iterator(self):
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
yield await self._queue.get()
|
||||||
|
finally:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def subscribe():
|
||||||
|
queue = asyncio.Queue()
|
||||||
|
try:
|
||||||
|
yield _InProcessSubscriber(queue, lambda: None)
|
||||||
|
finally:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async with subscribe() as sub:
|
||||||
|
print("Success")
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
10
fix_poa.py
Normal file
10
fix_poa.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Make sure we use the correct chain_id when draining from mempool
|
||||||
|
new_content = content.replace("mempool.drain(max_txs, max_bytes, self._config.chain_id)", "mempool.drain(max_txs, max_bytes, 'ait-mainnet')")
|
||||||
|
|
||||||
|
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "w") as f:
|
||||||
|
f.write(new_content)
|
||||||
10
fix_router.py
Normal file
10
fix_router.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/rpc/router.py", "r") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Make sure we use the correct chain_id when adding to mempool
|
||||||
|
new_content = content.replace("mempool.add(tx_dict, chain_id=chain_id)", "mempool.add(tx_dict, chain_id=chain_id or request.payload.get('chain_id') or 'ait-mainnet')")
|
||||||
|
|
||||||
|
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/rpc/router.py", "w") as f:
|
||||||
|
f.write(new_content)
|
||||||
140
infra/helm/values/prod.yaml
Normal file
140
infra/helm/values/prod.yaml
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# Production environment values
|
||||||
|
global:
|
||||||
|
environment: production
|
||||||
|
|
||||||
|
coordinator:
|
||||||
|
replicaCount: 3
|
||||||
|
image:
|
||||||
|
tag: "v0.1.0"
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 20
|
||||||
|
targetCPUUtilizationPercentage: 75
|
||||||
|
targetMemoryUtilizationPercentage: 80
|
||||||
|
config:
|
||||||
|
appEnv: production
|
||||||
|
allowOrigins: "https://app.aitbc.io"
|
||||||
|
postgresql:
|
||||||
|
auth:
|
||||||
|
existingSecret: "coordinator-db-secret"
|
||||||
|
primary:
|
||||||
|
persistence:
|
||||||
|
size: 200Gi
|
||||||
|
storageClass: fast-ssd
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
readReplicas:
|
||||||
|
replicaCount: 2
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
|
||||||
|
monitoring:
|
||||||
|
prometheus:
|
||||||
|
server:
|
||||||
|
retention: 90d
|
||||||
|
persistentVolume:
|
||||||
|
size: 500Gi
|
||||||
|
storageClass: fast-ssd
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
grafana:
|
||||||
|
adminPassword: "prod-admin-secure-2024"
|
||||||
|
persistence:
|
||||||
|
size: 50Gi
|
||||||
|
storageClass: fast-ssd
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
hosts:
|
||||||
|
- grafana.aitbc.io
|
||||||
|
|
||||||
|
# Additional services
|
||||||
|
blockchainNode:
|
||||||
|
replicaCount: 5
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 2Gi
|
||||||
|
requests:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 5
|
||||||
|
maxReplicas: 50
|
||||||
|
targetCPUUtilizationPercentage: 70
|
||||||
|
|
||||||
|
walletDaemon:
|
||||||
|
replicaCount: 3
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilizationPercentage: 75
|
||||||
|
|
||||||
|
# Ingress configuration
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
nginx.ingress.kubernetes.io/rate-limit: "100"
|
||||||
|
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
|
||||||
|
hosts:
|
||||||
|
- host: api.aitbc.io
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: prod-tls
|
||||||
|
hosts:
|
||||||
|
- api.aitbc.io
|
||||||
|
|
||||||
|
# Security
|
||||||
|
podSecurityPolicy:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Backup configuration
|
||||||
|
backup:
|
||||||
|
enabled: true
|
||||||
|
schedule: "0 2 * * *"
|
||||||
|
retention: "30d"
|
||||||
259
infra/helm/values/prod/values.yaml
Normal file
259
infra/helm/values/prod/values.yaml
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
# Production environment Helm values
|
||||||
|
|
||||||
|
global:
|
||||||
|
environment: prod
|
||||||
|
domain: aitbc.bubuit.net
|
||||||
|
imageTag: stable
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Coordinator API
|
||||||
|
coordinator:
|
||||||
|
enabled: true
|
||||||
|
replicas: 3
|
||||||
|
image:
|
||||||
|
repository: aitbc/coordinator-api
|
||||||
|
tag: stable
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 2Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8001
|
||||||
|
env:
|
||||||
|
LOG_LEVEL: warn
|
||||||
|
DATABASE_URL: secretRef:db-credentials
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 10
|
||||||
|
targetCPUUtilization: 60
|
||||||
|
targetMemoryUtilization: 70
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
|
||||||
|
# Explorer Web
|
||||||
|
explorer:
|
||||||
|
enabled: true
|
||||||
|
replicas: 3
|
||||||
|
image:
|
||||||
|
repository: aitbc/explorer-web
|
||||||
|
tag: stable
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3000
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 8
|
||||||
|
|
||||||
|
# Marketplace Web
|
||||||
|
marketplace:
|
||||||
|
enabled: true
|
||||||
|
replicas: 3
|
||||||
|
image:
|
||||||
|
repository: aitbc/marketplace-web
|
||||||
|
tag: stable
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3001
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 3
|
||||||
|
maxReplicas: 8
|
||||||
|
|
||||||
|
# Wallet Daemon
|
||||||
|
wallet:
|
||||||
|
enabled: true
|
||||||
|
replicas: 2
|
||||||
|
image:
|
||||||
|
repository: aitbc/wallet-daemon
|
||||||
|
tag: stable
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 2Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8002
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 2
|
||||||
|
maxReplicas: 6
|
||||||
|
|
||||||
|
# Trade Exchange
|
||||||
|
exchange:
|
||||||
|
enabled: true
|
||||||
|
replicas: 2
|
||||||
|
image:
|
||||||
|
repository: aitbc/trade-exchange
|
||||||
|
tag: stable
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 250m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8085
|
||||||
|
|
||||||
|
# PostgreSQL (prod uses RDS Multi-AZ)
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
external:
|
||||||
|
host: secretRef:db-credentials:host
|
||||||
|
port: 5432
|
||||||
|
database: coordinator
|
||||||
|
sslMode: require
|
||||||
|
|
||||||
|
# Redis (prod uses ElastiCache)
|
||||||
|
redis:
|
||||||
|
enabled: false
|
||||||
|
external:
|
||||||
|
host: secretRef:redis-credentials:host
|
||||||
|
port: 6379
|
||||||
|
auth: true
|
||||||
|
|
||||||
|
# Ingress
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/rewrite-target: /
|
||||||
|
nginx.ingress.kubernetes.io/proxy-body-size: 10m
|
||||||
|
nginx.ingress.kubernetes.io/rate-limit: "100"
|
||||||
|
nginx.ingress.kubernetes.io/rate-limit-window: 1m
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
tls:
|
||||||
|
- secretName: prod-tls
|
||||||
|
hosts:
|
||||||
|
- aitbc.bubuit.net
|
||||||
|
hosts:
|
||||||
|
- host: aitbc.bubuit.net
|
||||||
|
paths:
|
||||||
|
- path: /api
|
||||||
|
service: coordinator
|
||||||
|
port: 8001
|
||||||
|
- path: /explorer
|
||||||
|
service: explorer
|
||||||
|
port: 3000
|
||||||
|
- path: /marketplace
|
||||||
|
service: marketplace
|
||||||
|
port: 3001
|
||||||
|
- path: /wallet
|
||||||
|
service: wallet
|
||||||
|
port: 8002
|
||||||
|
- path: /Exchange
|
||||||
|
service: exchange
|
||||||
|
port: 8085
|
||||||
|
|
||||||
|
# Monitoring
|
||||||
|
monitoring:
|
||||||
|
enabled: true
|
||||||
|
prometheus:
|
||||||
|
enabled: true
|
||||||
|
retention: 30d
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 2Gi
|
||||||
|
limits:
|
||||||
|
cpu: 2000m
|
||||||
|
memory: 4Gi
|
||||||
|
grafana:
|
||||||
|
enabled: true
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 10Gi
|
||||||
|
alertmanager:
|
||||||
|
enabled: true
|
||||||
|
config:
|
||||||
|
receivers:
|
||||||
|
- name: slack
|
||||||
|
slack_configs:
|
||||||
|
- channel: '#aitbc-alerts'
|
||||||
|
send_resolved: true
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
logging:
|
||||||
|
enabled: true
|
||||||
|
level: warn
|
||||||
|
elasticsearch:
|
||||||
|
enabled: true
|
||||||
|
retention: 30d
|
||||||
|
replicas: 3
|
||||||
|
|
||||||
|
# Pod Disruption Budgets
|
||||||
|
podDisruptionBudget:
|
||||||
|
coordinator:
|
||||||
|
minAvailable: 2
|
||||||
|
explorer:
|
||||||
|
minAvailable: 2
|
||||||
|
marketplace:
|
||||||
|
minAvailable: 2
|
||||||
|
wallet:
|
||||||
|
minAvailable: 1
|
||||||
|
|
||||||
|
# Network Policies
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: ingress-nginx
|
||||||
|
egress:
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: kube-system
|
||||||
|
ports:
|
||||||
|
- port: 53
|
||||||
|
protocol: UDP
|
||||||
|
|
||||||
|
# Security
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
|
||||||
|
# Affinity - spread across zones
|
||||||
|
affinity:
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- weight: 100
|
||||||
|
podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: coordinator
|
||||||
|
topologyKey: topology.kubernetes.io/zone
|
||||||
|
|
||||||
|
# Priority Classes
|
||||||
|
priorityClassName: high-priority
|
||||||
247
infra/nginx/nginx-aitbc-reverse-proxy.conf
Normal file
247
infra/nginx/nginx-aitbc-reverse-proxy.conf
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
# AITBC Nginx Reverse Proxy Configuration
|
||||||
|
# Domain: aitbc.keisanki.net
|
||||||
|
# This configuration replaces the need for firehol/iptables port forwarding
|
||||||
|
|
||||||
|
# HTTP to HTTPS redirect
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name aitbc.keisanki.net;
|
||||||
|
|
||||||
|
# Redirect all HTTP traffic to HTTPS
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main HTTPS server block
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name aitbc.keisanki.net;
|
||||||
|
|
||||||
|
# SSL Configuration (Let's Encrypt certificates)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/aitbc.keisanki.net/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/aitbc.keisanki.net/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline' 'unsafe-eval'" always;
|
||||||
|
|
||||||
|
# Enable gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||||
|
|
||||||
|
# Blockchain Explorer (main route)
|
||||||
|
location / {
|
||||||
|
proxy_pass http://192.168.100.10:3000;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# WebSocket support if needed
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Coordinator API
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://192.168.100.10:8000/v1/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# CORS headers for API
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
|
||||||
|
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Api-Key" always;
|
||||||
|
|
||||||
|
# Handle preflight requests
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header Access-Control-Allow-Origin "*";
|
||||||
|
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
|
||||||
|
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Api-Key";
|
||||||
|
add_header Access-Control-Max-Age 1728000;
|
||||||
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
|
add_header Content-Length 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Blockchain Node 1 RPC
|
||||||
|
location /rpc/ {
|
||||||
|
proxy_pass http://192.168.100.10:8082/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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Blockchain Node 2 RPC (alternative endpoint)
|
||||||
|
location /rpc2/ {
|
||||||
|
proxy_pass http://192.168.100.10:8081/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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exchange API
|
||||||
|
location /exchange/ {
|
||||||
|
proxy_pass http://192.168.100.10:9080/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Marketplace UI (if separate from explorer)
|
||||||
|
location /marketplace/ {
|
||||||
|
proxy_pass http://192.168.100.10:3001/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# Handle subdirectory rewrite
|
||||||
|
rewrite ^/marketplace/(.*)$ /$1 break;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Admin dashboard
|
||||||
|
location /admin/ {
|
||||||
|
proxy_pass http://192.168.100.10:8080/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# Optional: Restrict admin access
|
||||||
|
# allow 192.168.100.0/24;
|
||||||
|
# allow 127.0.0.1;
|
||||||
|
# deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 "healthy\n";
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API health checks
|
||||||
|
location /api/health {
|
||||||
|
proxy_pass http://192.168.100.10:8000/v1/health;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets caching
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
proxy_pass http://192.168.100.10:3000;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
|
||||||
|
# Don't log static file access
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom error pages
|
||||||
|
error_page 404 /404.html;
|
||||||
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
|
||||||
|
location = /50x.html {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: Subdomain for API-only access
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name api.aitbc.keisanki.net;
|
||||||
|
|
||||||
|
# SSL Configuration (same certificates)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/aitbc.keisanki.net/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/aitbc.keisanki.net/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "DENY" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
|
||||||
|
# API routes only
|
||||||
|
location / {
|
||||||
|
proxy_pass http://192.168.100.10:8000/v1/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# CORS headers
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
|
||||||
|
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Api-Key" always;
|
||||||
|
|
||||||
|
# Handle preflight requests
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header Access-Control-Allow-Origin "*";
|
||||||
|
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
|
||||||
|
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Api-Key";
|
||||||
|
add_header Access-Control-Max-Age 1728000;
|
||||||
|
add_header Content-Type "text/plain; charset=utf-8";
|
||||||
|
add_header Content-Length 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Optional: Subdomain for blockchain RPC
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name rpc.aitbc.keisanki.net;
|
||||||
|
|
||||||
|
# SSL Configuration
|
||||||
|
ssl_certificate /etc/letsencrypt/live/aitbc.keisanki.net/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/aitbc.keisanki.net/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "DENY" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
|
||||||
|
# RPC routes
|
||||||
|
location / {
|
||||||
|
proxy_pass http://192.168.100.10:8082/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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
}
|
||||||
133
infra/nginx/nginx-aitbc.conf
Normal file
133
infra/nginx/nginx-aitbc.conf
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# AITBC Services Nginx Configuration
|
||||||
|
# Domain: https://aitbc.bubuit.net
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name aitbc.bubuit.net;
|
||||||
|
|
||||||
|
# Redirect to HTTPS
|
||||||
|
return 301 https://$server_name$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name aitbc.bubuit.net;
|
||||||
|
|
||||||
|
# SSL Configuration (Let's Encrypt)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/aitbc.bubuit.net/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/aitbc.bubuit.net/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Security Headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||||
|
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
|
||||||
|
|
||||||
|
# API Routes
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://127.0.0.1:8000/v1/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Blockchain RPC Routes
|
||||||
|
location /rpc/ {
|
||||||
|
proxy_pass http://127.0.0.1:9080/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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Marketplace UI
|
||||||
|
location /Marketplace {
|
||||||
|
proxy_pass http://127.0.0.1:3001/;
|
||||||
|
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;
|
||||||
|
|
||||||
|
# Handle subdirectory
|
||||||
|
rewrite ^/Marketplace/(.*)$ /$1 break;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Trade Exchange
|
||||||
|
location /Exchange {
|
||||||
|
proxy_pass http://127.0.0.1:3002/;
|
||||||
|
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;
|
||||||
|
|
||||||
|
# Handle subdirectory
|
||||||
|
rewrite ^/Exchange/(.*)$ /$1 break;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exchange API Routes
|
||||||
|
location /api/trades/ {
|
||||||
|
proxy_pass http://127.0.0.1:3003/api/trades/;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/orders {
|
||||||
|
proxy_pass http://127.0.0.1:3003/api/orders;
|
||||||
|
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;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wallet CLI API (if needed)
|
||||||
|
location /wallet/ {
|
||||||
|
proxy_pass http://127.0.0.1:8000/wallet/;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Admin routes
|
||||||
|
location /admin/ {
|
||||||
|
proxy_pass http://127.0.0.1:8000/admin/;
|
||||||
|
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;
|
||||||
|
|
||||||
|
# Restrict access (optional)
|
||||||
|
# allow 127.0.0.1;
|
||||||
|
# allow 10.1.223.0/24;
|
||||||
|
# deny all;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://127.0.0.1:8000/v1/health;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default redirect to Marketplace
|
||||||
|
location / {
|
||||||
|
return 301 /Marketplace;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static file caching
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://aitbc.bubuit.net/docs/",
|
"homepage": "https://aitbc.bubuit.net/docs/",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.22.0"
|
"node": ">=24.14.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
|||||||
@@ -25,6 +25,6 @@
|
|||||||
"@openzeppelin/contracts": "^5.0.2"
|
"@openzeppelin/contracts": "^5.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.22.0"
|
"node": ">=24.14.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,324 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../common";
|
||||||
|
|
||||||
|
export interface AccessControlInterface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "DEFAULT_ADMIN_ROLE"
|
||||||
|
| "getRoleAdmin"
|
||||||
|
| "grantRole"
|
||||||
|
| "hasRole"
|
||||||
|
| "renounceRole"
|
||||||
|
| "revokeRole"
|
||||||
|
| "supportsInterface"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
nameOrSignatureOrTopic: "RoleAdminChanged" | "RoleGranted" | "RoleRevoked"
|
||||||
|
): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "grantRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "hasRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "revokeRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "grantRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "hasRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "revokeRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleAdminChangedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
previousAdminRole: BytesLike,
|
||||||
|
newAdminRole: BytesLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
role: string,
|
||||||
|
previousAdminRole: string,
|
||||||
|
newAdminRole: string
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
previousAdminRole: string;
|
||||||
|
newAdminRole: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleGrantedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleRevokedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccessControl extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): AccessControl;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: AccessControlInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
DEFAULT_ADMIN_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
getRoleAdmin: TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
|
||||||
|
grantRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
hasRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
renounceRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
revokeRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
supportsInterface: TypedContractMethod<
|
||||||
|
[interfaceId: BytesLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "DEFAULT_ADMIN_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "getRoleAdmin"
|
||||||
|
): TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "grantRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "hasRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "renounceRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "revokeRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "supportsInterface"
|
||||||
|
): TypedContractMethod<[interfaceId: BytesLike], [boolean], "view">;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "RoleAdminChanged"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleGranted"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleRevoked"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"RoleAdminChanged(bytes32,bytes32,bytes32)": TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleAdminChanged: TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleGranted(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleGranted: TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleRevoked(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleRevoked: TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../common";
|
||||||
|
|
||||||
|
export interface IAccessControlInterface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "getRoleAdmin"
|
||||||
|
| "grantRole"
|
||||||
|
| "hasRole"
|
||||||
|
| "renounceRole"
|
||||||
|
| "revokeRole"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
nameOrSignatureOrTopic: "RoleAdminChanged" | "RoleGranted" | "RoleRevoked"
|
||||||
|
): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "grantRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "hasRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "revokeRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "grantRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "hasRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "revokeRole", data: BytesLike): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleAdminChangedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
previousAdminRole: BytesLike,
|
||||||
|
newAdminRole: BytesLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
role: string,
|
||||||
|
previousAdminRole: string,
|
||||||
|
newAdminRole: string
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
previousAdminRole: string;
|
||||||
|
newAdminRole: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleGrantedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleRevokedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAccessControl extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IAccessControl;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IAccessControlInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getRoleAdmin: TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
|
||||||
|
grantRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
hasRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
renounceRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
revokeRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "getRoleAdmin"
|
||||||
|
): TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "grantRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "hasRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "renounceRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "revokeRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "RoleAdminChanged"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleGranted"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleRevoked"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"RoleAdminChanged(bytes32,bytes32,bytes32)": TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleAdminChanged: TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleGranted(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleGranted: TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleRevoked(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleRevoked: TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { AccessControl } from "./AccessControl";
|
||||||
|
export type { IAccessControl } from "./IAccessControl";
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as access from "./access";
|
||||||
|
export type { access };
|
||||||
|
import type * as interfaces from "./interfaces";
|
||||||
|
export type { interfaces };
|
||||||
|
import type * as token from "./token";
|
||||||
|
export type { token };
|
||||||
|
import type * as utils from "./utils";
|
||||||
|
export type { utils };
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface IERC1155ErrorsInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface IERC1155Errors extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC1155Errors;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC1155ErrorsInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface IERC20ErrorsInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface IERC20Errors extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC20Errors;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC20ErrorsInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface IERC721ErrorsInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface IERC721Errors extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC721Errors;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC721ErrorsInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { IERC1155Errors } from "./IERC1155Errors";
|
||||||
|
export type { IERC20Errors } from "./IERC20Errors";
|
||||||
|
export type { IERC721Errors } from "./IERC721Errors";
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as draftIerc6093Sol from "./draft-IERC6093.sol";
|
||||||
|
export type { draftIerc6093Sol };
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BigNumberish,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface ERC20Interface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "allowance"
|
||||||
|
| "approve"
|
||||||
|
| "balanceOf"
|
||||||
|
| "decimals"
|
||||||
|
| "name"
|
||||||
|
| "symbol"
|
||||||
|
| "totalSupply"
|
||||||
|
| "transfer"
|
||||||
|
| "transferFrom"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(nameOrSignatureOrTopic: "Approval" | "Transfer"): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "allowance",
|
||||||
|
values: [AddressLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "approve",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "balanceOf",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(functionFragment: "decimals", values?: undefined): string;
|
||||||
|
encodeFunctionData(functionFragment: "name", values?: undefined): string;
|
||||||
|
encodeFunctionData(functionFragment: "symbol", values?: undefined): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transfer",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
values: [AddressLike, AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(functionFragment: "allowance", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "approve", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "balanceOf", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "decimals", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "name", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "symbol", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ApprovalEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
owner: AddressLike,
|
||||||
|
spender: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [owner: string, spender: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
owner: string;
|
||||||
|
spender: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace TransferEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
from: AddressLike,
|
||||||
|
to: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [from: string, to: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ERC20 extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): ERC20;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: ERC20Interface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
allowance: TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
approve: TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
balanceOf: TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
|
||||||
|
decimals: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
name: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
symbol: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
totalSupply: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
transfer: TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
transferFrom: TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "allowance"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "approve"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "balanceOf"
|
||||||
|
): TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "decimals"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "name"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "symbol"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "totalSupply"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transfer"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transferFrom"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "Approval"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "Transfer"
|
||||||
|
): TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"Approval(address,address,uint256)": TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Approval: TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"Transfer(address,address,uint256)": TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Transfer: TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BigNumberish,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface IERC20Interface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "allowance"
|
||||||
|
| "approve"
|
||||||
|
| "balanceOf"
|
||||||
|
| "totalSupply"
|
||||||
|
| "transfer"
|
||||||
|
| "transferFrom"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(nameOrSignatureOrTopic: "Approval" | "Transfer"): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "allowance",
|
||||||
|
values: [AddressLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "approve",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "balanceOf",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transfer",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
values: [AddressLike, AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(functionFragment: "allowance", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "approve", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "balanceOf", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ApprovalEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
owner: AddressLike,
|
||||||
|
spender: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [owner: string, spender: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
owner: string;
|
||||||
|
spender: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace TransferEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
from: AddressLike,
|
||||||
|
to: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [from: string, to: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IERC20 extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC20;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC20Interface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
allowance: TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
approve: TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
balanceOf: TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
|
||||||
|
totalSupply: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
transfer: TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
transferFrom: TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "allowance"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "approve"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "balanceOf"
|
||||||
|
): TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "totalSupply"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transfer"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transferFrom"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "Approval"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "Transfer"
|
||||||
|
): TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"Approval(address,address,uint256)": TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Approval: TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"Transfer(address,address,uint256)": TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Transfer: TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BigNumberish,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../../../common";
|
||||||
|
|
||||||
|
export interface IERC20MetadataInterface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "allowance"
|
||||||
|
| "approve"
|
||||||
|
| "balanceOf"
|
||||||
|
| "decimals"
|
||||||
|
| "name"
|
||||||
|
| "symbol"
|
||||||
|
| "totalSupply"
|
||||||
|
| "transfer"
|
||||||
|
| "transferFrom"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(nameOrSignatureOrTopic: "Approval" | "Transfer"): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "allowance",
|
||||||
|
values: [AddressLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "approve",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "balanceOf",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(functionFragment: "decimals", values?: undefined): string;
|
||||||
|
encodeFunctionData(functionFragment: "name", values?: undefined): string;
|
||||||
|
encodeFunctionData(functionFragment: "symbol", values?: undefined): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transfer",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
values: [AddressLike, AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(functionFragment: "allowance", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "approve", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "balanceOf", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "decimals", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "name", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "symbol", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ApprovalEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
owner: AddressLike,
|
||||||
|
spender: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [owner: string, spender: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
owner: string;
|
||||||
|
spender: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace TransferEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
from: AddressLike,
|
||||||
|
to: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [from: string, to: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IERC20Metadata extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC20Metadata;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC20MetadataInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
allowance: TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
approve: TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
balanceOf: TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
|
||||||
|
decimals: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
name: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
symbol: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
totalSupply: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
transfer: TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
transferFrom: TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "allowance"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "approve"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "balanceOf"
|
||||||
|
): TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "decimals"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "name"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "symbol"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "totalSupply"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transfer"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transferFrom"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "Approval"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "Transfer"
|
||||||
|
): TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"Approval(address,address,uint256)": TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Approval: TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"Transfer(address,address,uint256)": TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Transfer: TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { IERC20Metadata } from "./IERC20Metadata";
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as extensions from "./extensions";
|
||||||
|
export type { extensions };
|
||||||
|
export type { ERC20 } from "./ERC20";
|
||||||
|
export type { IERC20 } from "./IERC20";
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as erc20 from "./ERC20";
|
||||||
|
export type { erc20 };
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../common";
|
||||||
|
|
||||||
|
export interface StringsInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface Strings extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): Strings;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: StringsInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface ECDSAInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface ECDSA extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): ECDSA;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: ECDSAInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { ECDSA } from "./ECDSA";
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as cryptography from "./cryptography";
|
||||||
|
export type { cryptography };
|
||||||
|
import type * as introspection from "./introspection";
|
||||||
|
export type { introspection };
|
||||||
|
import type * as math from "./math";
|
||||||
|
export type { math };
|
||||||
|
export type { Strings } from "./Strings";
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface ERC165Interface extends Interface {
|
||||||
|
getFunction(nameOrSignature: "supportsInterface"): FunctionFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ERC165 extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): ERC165;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: ERC165Interface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
supportsInterface: TypedContractMethod<
|
||||||
|
[interfaceId: BytesLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "supportsInterface"
|
||||||
|
): TypedContractMethod<[interfaceId: BytesLike], [boolean], "view">;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface IERC165Interface extends Interface {
|
||||||
|
getFunction(nameOrSignature: "supportsInterface"): FunctionFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IERC165 extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): IERC165;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: IERC165Interface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
supportsInterface: TypedContractMethod<
|
||||||
|
[interfaceId: BytesLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "supportsInterface"
|
||||||
|
): TypedContractMethod<[interfaceId: BytesLike], [boolean], "view">;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { ERC165 } from "./ERC165";
|
||||||
|
export type { IERC165 } from "./IERC165";
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
FunctionFragment,
|
||||||
|
Interface,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedListener,
|
||||||
|
} from "../../../../common";
|
||||||
|
|
||||||
|
export interface SafeCastInterface extends Interface {}
|
||||||
|
|
||||||
|
export interface SafeCast extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): SafeCast;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: SafeCastInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
filters: {};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { SafeCast } from "./SafeCast";
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type * as contracts from "./contracts";
|
||||||
|
export type { contracts };
|
||||||
131
packages/solidity/aitbc-token/typechain-types/common.ts
Normal file
131
packages/solidity/aitbc-token/typechain-types/common.ts
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
FunctionFragment,
|
||||||
|
Typed,
|
||||||
|
EventFragment,
|
||||||
|
ContractTransaction,
|
||||||
|
ContractTransactionResponse,
|
||||||
|
DeferredTopicFilter,
|
||||||
|
EventLog,
|
||||||
|
TransactionRequest,
|
||||||
|
LogDescription,
|
||||||
|
} from "ethers";
|
||||||
|
|
||||||
|
export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent>
|
||||||
|
extends DeferredTopicFilter {}
|
||||||
|
|
||||||
|
export interface TypedContractEvent<
|
||||||
|
InputTuple extends Array<any> = any,
|
||||||
|
OutputTuple extends Array<any> = any,
|
||||||
|
OutputObject = any
|
||||||
|
> {
|
||||||
|
(...args: Partial<InputTuple>): TypedDeferredTopicFilter<
|
||||||
|
TypedContractEvent<InputTuple, OutputTuple, OutputObject>
|
||||||
|
>;
|
||||||
|
name: string;
|
||||||
|
fragment: EventFragment;
|
||||||
|
getFragment(...args: Partial<InputTuple>): EventFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
type __TypechainAOutputTuple<T> = T extends TypedContractEvent<
|
||||||
|
infer _U,
|
||||||
|
infer W
|
||||||
|
>
|
||||||
|
? W
|
||||||
|
: never;
|
||||||
|
type __TypechainOutputObject<T> = T extends TypedContractEvent<
|
||||||
|
infer _U,
|
||||||
|
infer _W,
|
||||||
|
infer V
|
||||||
|
>
|
||||||
|
? V
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export interface TypedEventLog<TCEvent extends TypedContractEvent>
|
||||||
|
extends Omit<EventLog, "args"> {
|
||||||
|
args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TypedLogDescription<TCEvent extends TypedContractEvent>
|
||||||
|
extends Omit<LogDescription, "args"> {
|
||||||
|
args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TypedListener<TCEvent extends TypedContractEvent> = (
|
||||||
|
...listenerArg: [
|
||||||
|
...__TypechainAOutputTuple<TCEvent>,
|
||||||
|
TypedEventLog<TCEvent>,
|
||||||
|
...undefined[]
|
||||||
|
]
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export type MinEthersFactory<C, ARGS> = {
|
||||||
|
deploy(...a: ARGS[]): Promise<C>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GetContractTypeFromFactory<F> = F extends MinEthersFactory<
|
||||||
|
infer C,
|
||||||
|
any
|
||||||
|
>
|
||||||
|
? C
|
||||||
|
: never;
|
||||||
|
export type GetARGsTypeFromFactory<F> = F extends MinEthersFactory<any, any>
|
||||||
|
? Parameters<F["deploy"]>
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type StateMutability = "nonpayable" | "payable" | "view";
|
||||||
|
|
||||||
|
export type BaseOverrides = Omit<TransactionRequest, "to" | "data">;
|
||||||
|
export type NonPayableOverrides = Omit<
|
||||||
|
BaseOverrides,
|
||||||
|
"value" | "blockTag" | "enableCcipRead"
|
||||||
|
>;
|
||||||
|
export type PayableOverrides = Omit<
|
||||||
|
BaseOverrides,
|
||||||
|
"blockTag" | "enableCcipRead"
|
||||||
|
>;
|
||||||
|
export type ViewOverrides = Omit<TransactionRequest, "to" | "data">;
|
||||||
|
export type Overrides<S extends StateMutability> = S extends "nonpayable"
|
||||||
|
? NonPayableOverrides
|
||||||
|
: S extends "payable"
|
||||||
|
? PayableOverrides
|
||||||
|
: ViewOverrides;
|
||||||
|
|
||||||
|
export type PostfixOverrides<A extends Array<any>, S extends StateMutability> =
|
||||||
|
| A
|
||||||
|
| [...A, Overrides<S>];
|
||||||
|
export type ContractMethodArgs<
|
||||||
|
A extends Array<any>,
|
||||||
|
S extends StateMutability
|
||||||
|
> = PostfixOverrides<{ [I in keyof A]-?: A[I] | Typed }, S>;
|
||||||
|
|
||||||
|
export type DefaultReturnType<R> = R extends Array<any> ? R[0] : R;
|
||||||
|
|
||||||
|
// export interface ContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> {
|
||||||
|
export interface TypedContractMethod<
|
||||||
|
A extends Array<any> = Array<any>,
|
||||||
|
R = any,
|
||||||
|
S extends StateMutability = "payable"
|
||||||
|
> {
|
||||||
|
(...args: ContractMethodArgs<A, S>): S extends "view"
|
||||||
|
? Promise<DefaultReturnType<R>>
|
||||||
|
: Promise<ContractTransactionResponse>;
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
fragment: FunctionFragment;
|
||||||
|
|
||||||
|
getFragment(...args: ContractMethodArgs<A, S>): FunctionFragment;
|
||||||
|
|
||||||
|
populateTransaction(
|
||||||
|
...args: ContractMethodArgs<A, S>
|
||||||
|
): Promise<ContractTransaction>;
|
||||||
|
staticCall(
|
||||||
|
...args: ContractMethodArgs<A, "view">
|
||||||
|
): Promise<DefaultReturnType<R>>;
|
||||||
|
send(...args: ContractMethodArgs<A, S>): Promise<ContractTransactionResponse>;
|
||||||
|
estimateGas(...args: ContractMethodArgs<A, S>): Promise<bigint>;
|
||||||
|
staticCallResult(...args: ContractMethodArgs<A, "view">): Promise<R>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,667 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BigNumberish,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../common";
|
||||||
|
|
||||||
|
export interface AITokenInterface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "ATTESTOR_ROLE"
|
||||||
|
| "COORDINATOR_ROLE"
|
||||||
|
| "DEFAULT_ADMIN_ROLE"
|
||||||
|
| "allowance"
|
||||||
|
| "approve"
|
||||||
|
| "balanceOf"
|
||||||
|
| "consumedReceipts"
|
||||||
|
| "decimals"
|
||||||
|
| "getRoleAdmin"
|
||||||
|
| "grantRole"
|
||||||
|
| "hasRole"
|
||||||
|
| "mintDigest"
|
||||||
|
| "mintWithReceipt"
|
||||||
|
| "name"
|
||||||
|
| "renounceRole"
|
||||||
|
| "revokeRole"
|
||||||
|
| "supportsInterface"
|
||||||
|
| "symbol"
|
||||||
|
| "totalSupply"
|
||||||
|
| "transfer"
|
||||||
|
| "transferFrom"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
nameOrSignatureOrTopic:
|
||||||
|
| "Approval"
|
||||||
|
| "ReceiptConsumed"
|
||||||
|
| "RoleAdminChanged"
|
||||||
|
| "RoleGranted"
|
||||||
|
| "RoleRevoked"
|
||||||
|
| "Transfer"
|
||||||
|
): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "ATTESTOR_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "COORDINATOR_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "allowance",
|
||||||
|
values: [AddressLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "approve",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "balanceOf",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "consumedReceipts",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(functionFragment: "decimals", values?: undefined): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "grantRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "hasRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "mintDigest",
|
||||||
|
values: [AddressLike, BigNumberish, BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "mintWithReceipt",
|
||||||
|
values: [AddressLike, BigNumberish, BytesLike, BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(functionFragment: "name", values?: undefined): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "revokeRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(functionFragment: "symbol", values?: undefined): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transfer",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
values: [AddressLike, AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "ATTESTOR_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "COORDINATOR_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "allowance", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "approve", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "balanceOf", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "consumedReceipts",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "decimals", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "grantRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "hasRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "mintDigest", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "mintWithReceipt",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "name", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "revokeRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "symbol", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "totalSupply",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "transfer", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "transferFrom",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ApprovalEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
owner: AddressLike,
|
||||||
|
spender: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [owner: string, spender: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
owner: string;
|
||||||
|
spender: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ReceiptConsumedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
receiptHash: BytesLike,
|
||||||
|
provider: AddressLike,
|
||||||
|
units: BigNumberish,
|
||||||
|
attestor: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
receiptHash: string,
|
||||||
|
provider: string,
|
||||||
|
units: bigint,
|
||||||
|
attestor: string
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
receiptHash: string;
|
||||||
|
provider: string;
|
||||||
|
units: bigint;
|
||||||
|
attestor: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleAdminChangedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
previousAdminRole: BytesLike,
|
||||||
|
newAdminRole: BytesLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
role: string,
|
||||||
|
previousAdminRole: string,
|
||||||
|
newAdminRole: string
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
previousAdminRole: string;
|
||||||
|
newAdminRole: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleGrantedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleRevokedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace TransferEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
from: AddressLike,
|
||||||
|
to: AddressLike,
|
||||||
|
value: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [from: string, to: string, value: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
value: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AIToken extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): AIToken;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: AITokenInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
ATTESTOR_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
COORDINATOR_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
DEFAULT_ADMIN_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
allowance: TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
approve: TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
balanceOf: TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
|
||||||
|
consumedReceipts: TypedContractMethod<[arg0: BytesLike], [boolean], "view">;
|
||||||
|
|
||||||
|
decimals: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
getRoleAdmin: TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
|
||||||
|
grantRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
hasRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
mintDigest: TypedContractMethod<
|
||||||
|
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike],
|
||||||
|
[string],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
mintWithReceipt: TypedContractMethod<
|
||||||
|
[
|
||||||
|
provider: AddressLike,
|
||||||
|
units: BigNumberish,
|
||||||
|
receiptHash: BytesLike,
|
||||||
|
signature: BytesLike
|
||||||
|
],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
name: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
renounceRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
revokeRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
supportsInterface: TypedContractMethod<
|
||||||
|
[interfaceId: BytesLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
symbol: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
totalSupply: TypedContractMethod<[], [bigint], "view">;
|
||||||
|
|
||||||
|
transfer: TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
transferFrom: TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "ATTESTOR_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "COORDINATOR_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "DEFAULT_ADMIN_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "allowance"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[owner: AddressLike, spender: AddressLike],
|
||||||
|
[bigint],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "approve"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[spender: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "balanceOf"
|
||||||
|
): TypedContractMethod<[account: AddressLike], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "consumedReceipts"
|
||||||
|
): TypedContractMethod<[arg0: BytesLike], [boolean], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "decimals"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "getRoleAdmin"
|
||||||
|
): TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "grantRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "hasRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "mintDigest"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike],
|
||||||
|
[string],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "mintWithReceipt"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[
|
||||||
|
provider: AddressLike,
|
||||||
|
units: BigNumberish,
|
||||||
|
receiptHash: BytesLike,
|
||||||
|
signature: BytesLike
|
||||||
|
],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "name"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "renounceRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "revokeRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "supportsInterface"
|
||||||
|
): TypedContractMethod<[interfaceId: BytesLike], [boolean], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "symbol"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "totalSupply"
|
||||||
|
): TypedContractMethod<[], [bigint], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transfer"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "transferFrom"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[from: AddressLike, to: AddressLike, value: BigNumberish],
|
||||||
|
[boolean],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "Approval"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "ReceiptConsumed"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ReceiptConsumedEvent.InputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleAdminChanged"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleGranted"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleRevoked"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "Transfer"
|
||||||
|
): TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"Approval(address,address,uint256)": TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Approval: TypedContractEvent<
|
||||||
|
ApprovalEvent.InputTuple,
|
||||||
|
ApprovalEvent.OutputTuple,
|
||||||
|
ApprovalEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"ReceiptConsumed(bytes32,address,uint256,address)": TypedContractEvent<
|
||||||
|
ReceiptConsumedEvent.InputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
ReceiptConsumed: TypedContractEvent<
|
||||||
|
ReceiptConsumedEvent.InputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputTuple,
|
||||||
|
ReceiptConsumedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleAdminChanged(bytes32,bytes32,bytes32)": TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleAdminChanged: TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleGranted(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleGranted: TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleRevoked(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleRevoked: TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"Transfer(address,address,uint256)": TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
Transfer: TypedContractEvent<
|
||||||
|
TransferEvent.InputTuple,
|
||||||
|
TransferEvent.OutputTuple,
|
||||||
|
TransferEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,512 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
import type {
|
||||||
|
BaseContract,
|
||||||
|
BigNumberish,
|
||||||
|
BytesLike,
|
||||||
|
FunctionFragment,
|
||||||
|
Result,
|
||||||
|
Interface,
|
||||||
|
EventFragment,
|
||||||
|
AddressLike,
|
||||||
|
ContractRunner,
|
||||||
|
ContractMethod,
|
||||||
|
Listener,
|
||||||
|
} from "ethers";
|
||||||
|
import type {
|
||||||
|
TypedContractEvent,
|
||||||
|
TypedDeferredTopicFilter,
|
||||||
|
TypedEventLog,
|
||||||
|
TypedLogDescription,
|
||||||
|
TypedListener,
|
||||||
|
TypedContractMethod,
|
||||||
|
} from "../common";
|
||||||
|
|
||||||
|
export declare namespace AITokenRegistry {
|
||||||
|
export type ProviderInfoStruct = {
|
||||||
|
active: boolean;
|
||||||
|
collateral: BigNumberish;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProviderInfoStructOutput = [
|
||||||
|
active: boolean,
|
||||||
|
collateral: bigint
|
||||||
|
] & { active: boolean; collateral: bigint };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AITokenRegistryInterface extends Interface {
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature:
|
||||||
|
| "COORDINATOR_ROLE"
|
||||||
|
| "DEFAULT_ADMIN_ROLE"
|
||||||
|
| "getRoleAdmin"
|
||||||
|
| "grantRole"
|
||||||
|
| "hasRole"
|
||||||
|
| "providerInfo"
|
||||||
|
| "providers"
|
||||||
|
| "registerProvider"
|
||||||
|
| "renounceRole"
|
||||||
|
| "revokeRole"
|
||||||
|
| "supportsInterface"
|
||||||
|
| "updateProvider"
|
||||||
|
): FunctionFragment;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
nameOrSignatureOrTopic:
|
||||||
|
| "ProviderRegistered"
|
||||||
|
| "ProviderUpdated"
|
||||||
|
| "RoleAdminChanged"
|
||||||
|
| "RoleGranted"
|
||||||
|
| "RoleRevoked"
|
||||||
|
): EventFragment;
|
||||||
|
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "COORDINATOR_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
values?: undefined
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "grantRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "hasRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "providerInfo",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "providers",
|
||||||
|
values: [AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "registerProvider",
|
||||||
|
values: [AddressLike, BigNumberish]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "revokeRole",
|
||||||
|
values: [BytesLike, AddressLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
values: [BytesLike]
|
||||||
|
): string;
|
||||||
|
encodeFunctionData(
|
||||||
|
functionFragment: "updateProvider",
|
||||||
|
values: [AddressLike, boolean, BigNumberish]
|
||||||
|
): string;
|
||||||
|
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "COORDINATOR_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "DEFAULT_ADMIN_ROLE",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "getRoleAdmin",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "grantRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "hasRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "providerInfo",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "providers", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "registerProvider",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "renounceRole",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(functionFragment: "revokeRole", data: BytesLike): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "supportsInterface",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
decodeFunctionResult(
|
||||||
|
functionFragment: "updateProvider",
|
||||||
|
data: BytesLike
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ProviderRegisteredEvent {
|
||||||
|
export type InputTuple = [provider: AddressLike, collateral: BigNumberish];
|
||||||
|
export type OutputTuple = [provider: string, collateral: bigint];
|
||||||
|
export interface OutputObject {
|
||||||
|
provider: string;
|
||||||
|
collateral: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ProviderUpdatedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
provider: AddressLike,
|
||||||
|
active: boolean,
|
||||||
|
collateral: BigNumberish
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
provider: string,
|
||||||
|
active: boolean,
|
||||||
|
collateral: bigint
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
provider: string;
|
||||||
|
active: boolean;
|
||||||
|
collateral: bigint;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleAdminChangedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
previousAdminRole: BytesLike,
|
||||||
|
newAdminRole: BytesLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [
|
||||||
|
role: string,
|
||||||
|
previousAdminRole: string,
|
||||||
|
newAdminRole: string
|
||||||
|
];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
previousAdminRole: string;
|
||||||
|
newAdminRole: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleGrantedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace RoleRevokedEvent {
|
||||||
|
export type InputTuple = [
|
||||||
|
role: BytesLike,
|
||||||
|
account: AddressLike,
|
||||||
|
sender: AddressLike
|
||||||
|
];
|
||||||
|
export type OutputTuple = [role: string, account: string, sender: string];
|
||||||
|
export interface OutputObject {
|
||||||
|
role: string;
|
||||||
|
account: string;
|
||||||
|
sender: string;
|
||||||
|
}
|
||||||
|
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>;
|
||||||
|
export type Filter = TypedDeferredTopicFilter<Event>;
|
||||||
|
export type Log = TypedEventLog<Event>;
|
||||||
|
export type LogDescription = TypedLogDescription<Event>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AITokenRegistry extends BaseContract {
|
||||||
|
connect(runner?: ContractRunner | null): AITokenRegistry;
|
||||||
|
waitForDeployment(): Promise<this>;
|
||||||
|
|
||||||
|
interface: AITokenRegistryInterface;
|
||||||
|
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
queryFilter<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
fromBlockOrBlockhash?: string | number | undefined,
|
||||||
|
toBlock?: string | number | undefined
|
||||||
|
): Promise<Array<TypedEventLog<TCEvent>>>;
|
||||||
|
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
on<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
once<TCEvent extends TypedContractEvent>(
|
||||||
|
filter: TypedDeferredTopicFilter<TCEvent>,
|
||||||
|
listener: TypedListener<TCEvent>
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
listeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event: TCEvent
|
||||||
|
): Promise<Array<TypedListener<TCEvent>>>;
|
||||||
|
listeners(eventName?: string): Promise<Array<Listener>>;
|
||||||
|
removeAllListeners<TCEvent extends TypedContractEvent>(
|
||||||
|
event?: TCEvent
|
||||||
|
): Promise<this>;
|
||||||
|
|
||||||
|
COORDINATOR_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
DEFAULT_ADMIN_ROLE: TypedContractMethod<[], [string], "view">;
|
||||||
|
|
||||||
|
getRoleAdmin: TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
|
||||||
|
grantRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
hasRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
providerInfo: TypedContractMethod<
|
||||||
|
[provider: AddressLike],
|
||||||
|
[AITokenRegistry.ProviderInfoStructOutput],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
providers: TypedContractMethod<
|
||||||
|
[arg0: AddressLike],
|
||||||
|
[[boolean, bigint] & { active: boolean; collateral: bigint }],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
registerProvider: TypedContractMethod<
|
||||||
|
[provider: AddressLike, collateral: BigNumberish],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
renounceRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
revokeRole: TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
supportsInterface: TypedContractMethod<
|
||||||
|
[interfaceId: BytesLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
|
||||||
|
updateProvider: TypedContractMethod<
|
||||||
|
[provider: AddressLike, active: boolean, collateral: BigNumberish],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getFunction<T extends ContractMethod = ContractMethod>(
|
||||||
|
key: string | FunctionFragment
|
||||||
|
): T;
|
||||||
|
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "COORDINATOR_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "DEFAULT_ADMIN_ROLE"
|
||||||
|
): TypedContractMethod<[], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "getRoleAdmin"
|
||||||
|
): TypedContractMethod<[role: BytesLike], [string], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "grantRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "hasRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[boolean],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "providerInfo"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[provider: AddressLike],
|
||||||
|
[AITokenRegistry.ProviderInfoStructOutput],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "providers"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[arg0: AddressLike],
|
||||||
|
[[boolean, bigint] & { active: boolean; collateral: bigint }],
|
||||||
|
"view"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "registerProvider"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[provider: AddressLike, collateral: BigNumberish],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "renounceRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, callerConfirmation: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "revokeRole"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[role: BytesLike, account: AddressLike],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "supportsInterface"
|
||||||
|
): TypedContractMethod<[interfaceId: BytesLike], [boolean], "view">;
|
||||||
|
getFunction(
|
||||||
|
nameOrSignature: "updateProvider"
|
||||||
|
): TypedContractMethod<
|
||||||
|
[provider: AddressLike, active: boolean, collateral: BigNumberish],
|
||||||
|
[void],
|
||||||
|
"nonpayable"
|
||||||
|
>;
|
||||||
|
|
||||||
|
getEvent(
|
||||||
|
key: "ProviderRegistered"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ProviderRegisteredEvent.InputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "ProviderUpdated"
|
||||||
|
): TypedContractEvent<
|
||||||
|
ProviderUpdatedEvent.InputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleAdminChanged"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleGranted"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
getEvent(
|
||||||
|
key: "RoleRevoked"
|
||||||
|
): TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
filters: {
|
||||||
|
"ProviderRegistered(address,uint256)": TypedContractEvent<
|
||||||
|
ProviderRegisteredEvent.InputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputObject
|
||||||
|
>;
|
||||||
|
ProviderRegistered: TypedContractEvent<
|
||||||
|
ProviderRegisteredEvent.InputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputTuple,
|
||||||
|
ProviderRegisteredEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"ProviderUpdated(address,bool,uint256)": TypedContractEvent<
|
||||||
|
ProviderUpdatedEvent.InputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
ProviderUpdated: TypedContractEvent<
|
||||||
|
ProviderUpdatedEvent.InputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputTuple,
|
||||||
|
ProviderUpdatedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleAdminChanged(bytes32,bytes32,bytes32)": TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleAdminChanged: TypedContractEvent<
|
||||||
|
RoleAdminChangedEvent.InputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputTuple,
|
||||||
|
RoleAdminChangedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleGranted(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleGranted: TypedContractEvent<
|
||||||
|
RoleGrantedEvent.InputTuple,
|
||||||
|
RoleGrantedEvent.OutputTuple,
|
||||||
|
RoleGrantedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
|
||||||
|
"RoleRevoked(bytes32,address,address)": TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
RoleRevoked: TypedContractEvent<
|
||||||
|
RoleRevokedEvent.InputTuple,
|
||||||
|
RoleRevokedEvent.OutputTuple,
|
||||||
|
RoleRevokedEvent.OutputObject
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export type { AIToken } from "./AIToken";
|
||||||
|
export type { AITokenRegistry } from "./AITokenRegistry";
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import { Contract, Interface, type ContractRunner } from "ethers";
|
||||||
|
import type {
|
||||||
|
AccessControl,
|
||||||
|
AccessControlInterface,
|
||||||
|
} from "../../../../@openzeppelin/contracts/access/AccessControl";
|
||||||
|
|
||||||
|
const _abi = [
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "AccessControlBadConfirmation",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "neededRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "AccessControlUnauthorizedAccount",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "previousAdminRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "newAdminRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleAdminChanged",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleGranted",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleRevoked",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "DEFAULT_ADMIN_ROLE",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "getRoleAdmin",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "grantRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "hasRole",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "callerConfirmation",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "renounceRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "revokeRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes4",
|
||||||
|
name: "interfaceId",
|
||||||
|
type: "bytes4",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "supportsInterface",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export class AccessControl__factory {
|
||||||
|
static readonly abi = _abi;
|
||||||
|
static createInterface(): AccessControlInterface {
|
||||||
|
return new Interface(_abi) as AccessControlInterface;
|
||||||
|
}
|
||||||
|
static connect(
|
||||||
|
address: string,
|
||||||
|
runner?: ContractRunner | null
|
||||||
|
): AccessControl {
|
||||||
|
return new Contract(address, _abi, runner) as unknown as AccessControl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import { Contract, Interface, type ContractRunner } from "ethers";
|
||||||
|
import type {
|
||||||
|
IAccessControl,
|
||||||
|
IAccessControlInterface,
|
||||||
|
} from "../../../../@openzeppelin/contracts/access/IAccessControl";
|
||||||
|
|
||||||
|
const _abi = [
|
||||||
|
{
|
||||||
|
inputs: [],
|
||||||
|
name: "AccessControlBadConfirmation",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "neededRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "AccessControlUnauthorizedAccount",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "previousAdminRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "newAdminRole",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleAdminChanged",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleGranted",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
anonymous: false,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
indexed: true,
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "RoleRevoked",
|
||||||
|
type: "event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "getRoleAdmin",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "grantRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "hasRole",
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
internalType: "bool",
|
||||||
|
name: "",
|
||||||
|
type: "bool",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: "view",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "callerConfirmation",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "renounceRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "bytes32",
|
||||||
|
name: "role",
|
||||||
|
type: "bytes32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "account",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "revokeRole",
|
||||||
|
outputs: [],
|
||||||
|
stateMutability: "nonpayable",
|
||||||
|
type: "function",
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export class IAccessControl__factory {
|
||||||
|
static readonly abi = _abi;
|
||||||
|
static createInterface(): IAccessControlInterface {
|
||||||
|
return new Interface(_abi) as IAccessControlInterface;
|
||||||
|
}
|
||||||
|
static connect(
|
||||||
|
address: string,
|
||||||
|
runner?: ContractRunner | null
|
||||||
|
): IAccessControl {
|
||||||
|
return new Contract(address, _abi, runner) as unknown as IAccessControl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export { AccessControl__factory } from "./AccessControl__factory";
|
||||||
|
export { IAccessControl__factory } from "./IAccessControl__factory";
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export * as access from "./access";
|
||||||
|
export * as interfaces from "./interfaces";
|
||||||
|
export * as token from "./token";
|
||||||
|
export * as utils from "./utils";
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/* Autogenerated file. Do not edit manually. */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
import { Contract, Interface, type ContractRunner } from "ethers";
|
||||||
|
import type {
|
||||||
|
IERC1155Errors,
|
||||||
|
IERC1155ErrorsInterface,
|
||||||
|
} from "../../../../../@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors";
|
||||||
|
|
||||||
|
const _abi = [
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "balance",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "needed",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "tokenId",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InsufficientBalance",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "approver",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InvalidApprover",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "idsLength",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "uint256",
|
||||||
|
name: "valuesLength",
|
||||||
|
type: "uint256",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InvalidArrayLength",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "operator",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InvalidOperator",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "receiver",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InvalidReceiver",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "sender",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155InvalidSender",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "operator",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
internalType: "address",
|
||||||
|
name: "owner",
|
||||||
|
type: "address",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: "ERC1155MissingApprovalForAll",
|
||||||
|
type: "error",
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export class IERC1155Errors__factory {
|
||||||
|
static readonly abi = _abi;
|
||||||
|
static createInterface(): IERC1155ErrorsInterface {
|
||||||
|
return new Interface(_abi) as IERC1155ErrorsInterface;
|
||||||
|
}
|
||||||
|
static connect(
|
||||||
|
address: string,
|
||||||
|
runner?: ContractRunner | null
|
||||||
|
): IERC1155Errors {
|
||||||
|
return new Contract(address, _abi, runner) as unknown as IERC1155Errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user