diff --git a/apps/blockchain-node/data/chain.db-journal b/apps/blockchain-node/data/chain.db-journal new file mode 100644 index 00000000..70fbcfce Binary files /dev/null and b/apps/blockchain-node/data/chain.db-journal differ diff --git a/apps/blockchain-node/data/devnet/genesis.json b/apps/blockchain-node/data/devnet/genesis.json index 239dbe9d..0ab64e7e 100644 --- a/apps/blockchain-node/data/devnet/genesis.json +++ b/apps/blockchain-node/data/devnet/genesis.json @@ -19,5 +19,5 @@ "fee_per_byte": 1, "mint_per_unit": 1000 }, - "timestamp": 1766828620 + "timestamp": 1767000206 } diff --git a/apps/coordinator-api/src/app/routers/exchange.py b/apps/coordinator-api/src/app/routers/exchange.py index 4d4ca148..86946211 100644 --- a/apps/coordinator-api/src/app/routers/exchange.py +++ b/apps/coordinator-api/src/app/routers/exchange.py @@ -4,15 +4,13 @@ Bitcoin Exchange Router for AITBC from typing import Dict, Any from fastapi import APIRouter, HTTPException, BackgroundTasks -from sqlmodel import Session import uuid import time import json import os -from ..deps import SessionDep -from ..domain import Wallet from ..schemas import ExchangePaymentRequest, ExchangePaymentResponse +from ..services.bitcoin_wallet import get_wallet_balance, get_wallet_info router = APIRouter(tags=["exchange"]) @@ -31,7 +29,6 @@ BITCOIN_CONFIG = { @router.post("/exchange/create-payment", response_model=ExchangePaymentResponse) async def create_payment( request: ExchangePaymentRequest, - session: SessionDep, background_tasks: BackgroundTasks ) -> Dict[str, Any]: """Create a new Bitcoin payment request""" @@ -88,8 +85,7 @@ async def get_payment_status(payment_id: str) -> Dict[str, Any]: @router.post("/exchange/confirm-payment/{payment_id}") async def confirm_payment( payment_id: str, - tx_hash: str, - session: SessionDep + tx_hash: str ) -> Dict[str, Any]: """Confirm payment (webhook from payment processor)""" @@ -132,6 +128,48 @@ async def get_exchange_rates() -> Dict[str, float]: 'fee_percent': 0.5 } +@router.get("/exchange/market-stats") +async def get_market_stats() -> Dict[str, Any]: + """Get market statistics""" + + # Calculate 24h volume from payments + current_time = int(time.time()) + yesterday_time = current_time - 24 * 60 * 60 # 24 hours ago + + daily_volume = 0 + for payment in payments.values(): + if payment['status'] == 'confirmed' and payment.get('confirmed_at', 0) > yesterday_time: + daily_volume += payment['aitbc_amount'] + + # Calculate price change (simulated) + base_price = 1.0 / BITCOIN_CONFIG['exchange_rate'] + price_change_percent = 5.2 # Simulated +5.2% + + return { + 'price': base_price, + 'price_change_24h': price_change_percent, + 'daily_volume': daily_volume, + 'daily_volume_btc': daily_volume / BITCOIN_CONFIG['exchange_rate'], + 'total_payments': len([p for p in payments.values() if p['status'] == 'confirmed']), + 'pending_payments': len([p for p in payments.values() if p['status'] == 'pending']) + } + +@router.get("/exchange/wallet/balance") +async def get_wallet_balance_api() -> Dict[str, Any]: + """Get Bitcoin wallet balance""" + try: + return get_wallet_balance() + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@router.get("/exchange/wallet/info") +async def get_wallet_info_api() -> Dict[str, Any]: + """Get comprehensive wallet information""" + try: + return get_wallet_info() + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + async def monitor_payment(payment_id: str): """Monitor payment for confirmation (background task)""" diff --git a/apps/coordinator-api/src/app/services/bitcoin_wallet.py b/apps/coordinator-api/src/app/services/bitcoin_wallet.py new file mode 100644 index 00000000..d582aff1 --- /dev/null +++ b/apps/coordinator-api/src/app/services/bitcoin_wallet.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +""" +Bitcoin Wallet Integration for AITBC Exchange +Uses RPC to connect to Bitcoin Core (or alternative like Block.io) +""" + +import os +import json +import requests +from typing import Dict, Optional + +# Bitcoin wallet configuration +WALLET_CONFIG = { + # For development, we'll use testnet + 'testnet': True, + 'rpc_url': 'http://127.0.0.1:18332', # Testnet RPC port + 'rpc_user': 'aitbc_rpc', + 'rpc_password': 'REDACTED_RPC_PASSWORD', + 'wallet_name': 'aitbc_exchange', + 'fallback_address': 'tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh' # Testnet address +} + +class BitcoinWallet: + def __init__(self): + self.config = WALLET_CONFIG + self.session = requests.Session() + self.session.auth = (self.config['rpc_user'], self.config['rpc_password']) + + def get_balance(self) -> float: + """Get the current Bitcoin balance""" + try: + result = self._rpc_call('getbalance', ["*", 0, False]) + if result.get('error') is not None: + print(f"Bitcoin RPC error: {result['error']}") + return 0.0 + return result.get('result', 0.0) + except Exception as e: + print(f"Failed to get balance: {e}") + return 0.0 + + def get_new_address(self) -> str: + """Generate a new Bitcoin address for deposits""" + try: + result = self._rpc_call('getnewaddress', ["", "bech32"]) + if result.get('error') is not None: + print(f"Bitcoin RPC error: {result['error']}") + return self.config['fallback_address'] + return result.get('result', self.config['fallback_address']) + except Exception as e: + print(f"Failed to get new address: {e}") + return self.config['fallback_address'] + + def list_transactions(self, count: int = 10) -> list: + """List recent transactions""" + try: + result = self._rpc_call('listtransactions', ["*", count, 0, True]) + if result.get('error') is not None: + print(f"Bitcoin RPC error: {result['error']}") + return [] + return result.get('result', []) + except Exception as e: + print(f"Failed to list transactions: {e}") + return [] + + def _rpc_call(self, method: str, params: list = None) -> Dict: + """Make an RPC call to Bitcoin Core""" + if params is None: + params = [] + + payload = { + "jsonrpc": "2.0", + "id": 1, + "method": method, + "params": params + } + + try: + response = self.session.post( + self.config['rpc_url'], + json=payload, + timeout=30 + ) + response.raise_for_status() + return response.json() + except Exception as e: + print(f"RPC call failed: {e}") + return {"error": str(e)} + +# Create a wallet instance +wallet = BitcoinWallet() + +# API endpoints for wallet integration +def get_wallet_balance() -> Dict[str, any]: + """Get wallet balance for API""" + balance = wallet.get_balance() + return { + "balance": balance, + "address": wallet.get_new_address(), + "testnet": wallet.config['testnet'] + } + +def get_wallet_info() -> Dict[str, any]: + """Get comprehensive wallet information""" + try: + wallet = BitcoinWallet() + # Test connection to Bitcoin Core + blockchain_info = wallet._rpc_call('getblockchaininfo') + is_connected = blockchain_info.get('error') is None and blockchain_info.get('result') is not None + + return { + "balance": wallet.get_balance(), + "address": wallet.get_new_address(), + "transactions": wallet.list_transactions(10), + "testnet": wallet.config['testnet'], + "wallet_type": "Bitcoin Core (Real)" if is_connected else "Bitcoin Core (Disconnected)", + "connected": is_connected, + "blocks": blockchain_info.get('result', {}).get('blocks', 0) if is_connected else 0 + } + except Exception as e: + print(f"Error getting wallet info: {e}") + return { + "balance": 0.0, + "address": "tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", + "transactions": [], + "testnet": True, + "wallet_type": "Bitcoin Core (Error)", + "connected": False, + "blocks": 0 + } + +if __name__ == "__main__": + # Test the wallet integration + info = get_wallet_info() + print(json.dumps(info, indent=2)) diff --git a/apps/trade-exchange/admin.html b/apps/trade-exchange/admin.html new file mode 100644 index 00000000..18fcc98e --- /dev/null +++ b/apps/trade-exchange/admin.html @@ -0,0 +1,316 @@ + + + + + + AITBC Exchange - Admin Dashboard + + + + + + +
+
+ ⚠️ DEMO MODE - This is simulated data for demonstration purposes +
+
+
+
+ +

Exchange Admin Dashboard

+
+
+ Bank Director Portal + +
+
+
+
+ +
+ +
+

Bitcoin Wallet

+
+
+
Current Balance
+
0.00000000 BTC
+
+
+
Wallet Address
+
tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh
+
+
+
+ + +
+
+ +
0
+
Total AITBC Sold
+
+
+ +
0 BTC
+
Total BTC Received
+
+
+ +
0
+
Total Users
+
+
+ +
0
+
Pending Payments
+
+
+ + +
+

+ + Available AITBC for Sale +

+
+
+
10,000,000
+
AITBC tokens available
+
+
+
100 BTC
+
Estimated value at current rate
+
+
+
+ + +
+

+ + Recent Payments +

+
+
Loading payments...
+
+
+
+ + +
+ +
+ + + + diff --git a/apps/trade-exchange/index.html b/apps/trade-exchange/index.html index d2dfe05b..bd5ddaa5 100644 --- a/apps/trade-exchange/index.html +++ b/apps/trade-exchange/index.html @@ -4,10 +4,12 @@ AITBC Trade Exchange - Buy AITBC with Bitcoin - - - - + + + + + + + + +
+ +

AITBC Wallet

+

The secure wallet for AITBC tokens

+ + + Download XPI File + + +
+

Installation Steps:

+
    +
  1. Download the XPI file using the button above
  2. +
  3. Open Firefox and type about:debugging in the address bar
  4. +
  5. Click "This Firefox" on the left
  6. +
  7. Click "Load Temporary Add-on..."
  8. +
  9. Select the downloaded XPI file
  10. +
+
+ +
+
Secure local key storage
+
One-click dApp connection
+
Transaction signing
+
Balance tracking
+
+ +

+ After installation, click the AITBC icon in your toolbar to create or import a wallet. +

+
+ + diff --git a/extensions/aitbc-wallet-firefox-simple/manifest.json b/extensions/aitbc-wallet-firefox-simple/manifest.json new file mode 100644 index 00000000..96d37ece --- /dev/null +++ b/extensions/aitbc-wallet-firefox-simple/manifest.json @@ -0,0 +1,46 @@ +{ + "manifest_version": 2, + "name": "AITBC Wallet", + "version": "1.0.0", + "description": "AITBC Browser Wallet for trading and managing AITBC tokens", + + "permissions": [ + "storage", + "activeTab" + ], + + "content_scripts": [ + { + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"], + "js": ["content.js"], + "run_at": "document_start" + } + ], + + "browser_action": { + "default_popup": "popup.html", + "default_title": "AITBC Wallet", + "default_icon": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + } + }, + + "web_accessible_resources": [ + "injected.js" + ], + + "icons": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + }, + + "background": { + "scripts": ["background.js"], + "persistent": false + } +} diff --git a/extensions/aitbc-wallet-firefox-simple/popup.html b/extensions/aitbc-wallet-firefox-simple/popup.html new file mode 100644 index 00000000..346b983a --- /dev/null +++ b/extensions/aitbc-wallet-firefox-simple/popup.html @@ -0,0 +1,112 @@ + + + + + + + +
+ +

Wallet

+
+ +
+
Account Address:
+ +
Not connected
+
0 AITBC
+
+ +
+ + + + + +
+ +
+

Recent Transactions

+
+
No transactions yet
+
+
+ + + + diff --git a/extensions/aitbc-wallet-firefox-simple/popup.js b/extensions/aitbc-wallet-firefox-simple/popup.js new file mode 100644 index 00000000..79d1455f --- /dev/null +++ b/extensions/aitbc-wallet-firefox-simple/popup.js @@ -0,0 +1,315 @@ +// Popup script for AITBC Wallet extension +let currentAccount = null; +let accounts = []; + +// Load wallet data on popup open +document.addEventListener('DOMContentLoaded', async function() { + await loadWalletData(); + updateUI(); + + // Check for pending connection request + const pending = await browser.storage.local.get(['pendingConnection']); + if (pending.pendingConnection) { + showConnectionDialog(pending.pendingConnection); + } + + // Add event listeners + document.getElementById('createAccountBtn').addEventListener('click', createAccount); + document.getElementById('importAccountBtn').addEventListener('click', importAccount); + document.getElementById('sendTokensBtn').addEventListener('click', sendTokens); + document.getElementById('receiveTokensBtn').addEventListener('click', receiveTokens); + document.getElementById('viewOnExplorerBtn').addEventListener('click', viewOnExplorer); + document.getElementById('accountSelector').addEventListener('change', switchAccount); +}); + +// Load wallet data from storage +async function loadWalletData() { + const result = await browser.storage.local.get(['accounts', 'currentAccount']); + accounts = result.accounts || []; + currentAccount = result.currentAccount || null; +} + +// Save wallet data to storage +async function saveWalletData() { + await browser.storage.local.set({ + accounts: accounts, + currentAccount: currentAccount + }); +} + +// Update UI with current wallet state +function updateUI() { + const addressEl = document.getElementById('accountAddress'); + const balanceEl = document.getElementById('balance'); + const selectorEl = document.getElementById('accountSelector'); + + // Update account selector + selectorEl.innerHTML = ''; + if (accounts.length === 0) { + const option = document.createElement('option'); + option.value = ''; + option.textContent = 'No accounts'; + selectorEl.appendChild(option); + } else { + accounts.forEach((account, index) => { + const option = document.createElement('option'); + option.value = index; + option.textContent = `Account ${index + 1} - ${account.address.substring(0, 20)}...`; + if (currentAccount && currentAccount.address === account.address) { + option.selected = true; + } + selectorEl.appendChild(option); + }); + } + + // Update current account display + if (currentAccount) { + addressEl.textContent = currentAccount.address; + balanceEl.textContent = `${currentAccount.balance || 0} AITBC`; + } else { + addressEl.textContent = 'Not connected'; + balanceEl.textContent = '0 AITBC'; + } +} + +// Show connection dialog +function showConnectionDialog(pendingConnection) { + const dialog = document.createElement('div'); + dialog.className = 'connection-dialog'; + dialog.innerHTML = ` +
+

Connection Request

+

${pendingConnection.origin} wants to connect to your AITBC Wallet

+

Address: ${pendingConnection.address}

+
+ + +
+
+ `; + + // Add styles for the dialog + const style = document.createElement('style'); + style.textContent = ` + .connection-dialog { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + } + .dialog-content { + background: white; + color: black; + padding: 20px; + border-radius: 8px; + max-width: 300px; + text-align: center; + } + .dialog-content h3 { + margin-top: 0; + } + .dialog-content .address { + font-family: monospace; + font-size: 12px; + word-break: break-all; + background: #f0f0f0; + padding: 5px; + border-radius: 4px; + margin: 10px 0; + } + .dialog-buttons { + display: flex; + gap: 10px; + justify-content: center; + margin-top: 20px; + } + .approve-btn { + background: #28a745; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + } + .reject-btn { + background: #dc3545; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + } + `; + + document.head.appendChild(style); + document.body.appendChild(dialog); + + // Handle button clicks + document.getElementById('approveConnection').addEventListener('click', async () => { + await browser.storage.local.set({ + connectionResponse: { + id: pendingConnection.id, + approved: true + } + }); + await browser.storage.local.remove(['pendingConnection']); + dialog.remove(); + style.remove(); + }); + + document.getElementById('rejectConnection').addEventListener('click', async () => { + await browser.storage.local.set({ + connectionResponse: { + id: pendingConnection.id, + approved: false + } + }); + await browser.storage.local.remove(['pendingConnection']); + dialog.remove(); + style.remove(); + }); +} + +// Switch to a different account +async function switchAccount() { + const selectorEl = document.getElementById('accountSelector'); + const selectedIndex = parseInt(selectorEl.value); + + if (isNaN(selectedIndex) || selectedIndex < 0 || selectedIndex >= accounts.length) { + return; + } + + currentAccount = accounts[selectedIndex]; + await saveWalletData(); + updateUI(); +} + +// Create a new account +async function createAccount() { + // Generate a new private key and address + const privateKey = generatePrivateKey(); + const address = await generateAddress(privateKey); + + const newAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + + accounts.push(newAccount); + currentAccount = newAccount; + await saveWalletData(); + updateUI(); + + alert('New account created! Please save your private key securely.'); +} + +// Import account from private key +async function importAccount() { + const privateKey = prompt('Enter your private key:'); + if (!privateKey) return; + + try { + const address = await generateAddress(privateKey); + + // Check if account already exists + const existing = accounts.find(a => a.address === address); + if (existing) { + currentAccount = existing; + } else { + currentAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + accounts.push(currentAccount); + } + + await saveWalletData(); + updateUI(); + alert('Account imported successfully!'); + } catch (error) { + alert('Invalid private key!'); + } +} + +// Send tokens +async function sendTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + const to = prompt('Send to address:'); + const amount = prompt('Amount:'); + + if (!to || !amount) return; + + // In a real implementation, this would create and sign a transaction + alert(`Would send ${amount} AITBC to ${to}`); +} + +// Receive tokens +function receiveTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + alert(`Your receiving address:\n${currentAccount.address}`); +} + +// View on explorer +function viewOnExplorer() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + browser.tabs.create({ url: `https://aitbc.bubuit.net/explorer/?address=${currentAccount.address}` }); +} + +// Generate a random private key (demo only) +function generatePrivateKey() { + const array = new Uint8Array(32); + crypto.getRandomValues(array); + return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''); +} + +// Generate address from private key (demo only) +async function generateAddress(privateKey) { + // In a real implementation, this would derive the address from the private key + // using the appropriate cryptographic algorithm + const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(privateKey)); + return 'aitbc1' + Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('').substring(0, 40); +} + +// Listen for connection requests from dApps +browser.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.method === 'connect') { + // Show connection dialog + const connected = confirm(`Allow this site to connect to your AITBC Wallet?`); + + if (connected && currentAccount) { + sendResponse({ + success: true, + address: currentAccount.address + }); + } else { + sendResponse({ + success: false, + error: 'User rejected connection' + }); + } + } + + return true; // Keep the message channel open for async response +}); diff --git a/extensions/aitbc-wallet-firefox-v1.0.0.xpi b/extensions/aitbc-wallet-firefox-v1.0.0.xpi new file mode 100644 index 00000000..aa7d6404 Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.0.xpi differ diff --git a/extensions/aitbc-wallet-firefox-v1.0.1.xpi b/extensions/aitbc-wallet-firefox-v1.0.1.xpi new file mode 100644 index 00000000..9bb79d48 Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.1.xpi differ diff --git a/extensions/aitbc-wallet-firefox-v1.0.2.xpi b/extensions/aitbc-wallet-firefox-v1.0.2.xpi new file mode 100644 index 00000000..4b31939a Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.2.xpi differ diff --git a/extensions/aitbc-wallet-firefox-v1.0.3.xpi b/extensions/aitbc-wallet-firefox-v1.0.3.xpi new file mode 100644 index 00000000..c4ff1bb1 Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.3.xpi differ diff --git a/extensions/aitbc-wallet-firefox-v1.0.4.xpi b/extensions/aitbc-wallet-firefox-v1.0.4.xpi new file mode 100644 index 00000000..f224febb Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.4.xpi differ diff --git a/extensions/aitbc-wallet-firefox-v1.0.5.xpi b/extensions/aitbc-wallet-firefox-v1.0.5.xpi new file mode 100644 index 00000000..d08590ff Binary files /dev/null and b/extensions/aitbc-wallet-firefox-v1.0.5.xpi differ diff --git a/extensions/aitbc-wallet-firefox.zip b/extensions/aitbc-wallet-firefox.zip new file mode 100644 index 00000000..69154c24 Binary files /dev/null and b/extensions/aitbc-wallet-firefox.zip differ diff --git a/extensions/aitbc-wallet-firefox/README.md b/extensions/aitbc-wallet-firefox/README.md new file mode 100644 index 00000000..f1896532 --- /dev/null +++ b/extensions/aitbc-wallet-firefox/README.md @@ -0,0 +1,133 @@ +# AITBC Wallet Extension for Firefox + +A Firefox browser extension that provides AITBC wallet functionality for interacting with the AITBC Trade Exchange and other dApps. + +## Differences from Chrome Version + +This version is specifically built for Firefox with the following differences: + +- Uses Manifest V2 (Firefox still requires V2 for full functionality) +- Uses `browser_action` instead of `action` (V2 syntax) +- Uses `chrome.runtime.connect()` for background script communication +- Background script uses persistent connections via ports + +## Installation + +### Development Installation + +1. Clone this repository +2. Open Firefox and navigate to `about:debugging` +3. Click "This Firefox" in the left sidebar +4. Click "Load Temporary Add-on..." +5. Select the `manifest.json` file from the `aitbc-wallet-firefox` folder + +### Production Installation + +The extension will be published to the Firefox Add-on Store (AMO). Installation instructions will be available once published. + +## Usage + +The usage is identical to the Chrome version: + +1. Install the AITBC Wallet extension +2. Navigate to https://aitbc.bubuit.net/Exchange +3. Toggle the switch from "Demo Mode" to "Real Mode" +4. Click "Connect AITBC Wallet" +5. Approve the connection request in the popup + +## Features + +- **Wallet Management**: Create new accounts or import existing private keys +- **Secure Storage**: Private keys are stored locally in Firefox's storage +- **dApp Integration**: Connect to AITBC Trade Exchange and other supported dApps +- **Transaction Signing**: Sign transactions and messages securely +- **Balance Tracking**: View your AITBC token balance + +## API Reference + +The extension injects a `window.aitbcWallet` object into supported dApps with the following methods: + +### `aitbcWallet.connect()` +Connect the dApp to the wallet. +```javascript +const response = await aitbcWallet.connect(); +console.log(response.address); // User's AITBC address +``` + +### `aitbcWallet.getAccount()` +Get the current account address. +```javascript +const address = await aitbcWallet.getAccount(); +``` + +### `aitbcWallet.getBalance(address)` +Get the AITBC balance for an address. +```javascript +const balance = await aitbcWallet.getBalance('aitbc1...'); +console.log(balance.amount); // Balance in AITBC +``` + +### `aitbcWallet.sendTransaction(to, amount, data)` +Send AITBC tokens to another address. +```javascript +const tx = await aitbcWallet.sendTransaction('aitbc1...', 100); +console.log(tx.hash); // Transaction hash +``` + +### `aitbcWallet.signMessage(message)` +Sign a message with the private key. +```javascript +const signature = await aitbcWallet.signMessage('Hello AITBC!'); +``` + +## Security Considerations + +- Private keys are stored locally in Firefox's storage +- Always verify you're on the correct domain before connecting +- Never share your private key with anyone +- Keep your browser and extension updated + +## Development + +To modify the extension: + +1. Make changes to the source files +2. Go to `about:debugging` in Firefox +3. Find "AITBC Wallet" and click "Reload" +4. Test your changes + +## File Structure + +``` +aitbc-wallet-firefox/ +β”œβ”€β”€ manifest.json # Extension configuration (Manifest V2) +β”œβ”€β”€ background.js # Background script for wallet operations +β”œβ”€β”€ content.js # Content script for dApp communication +β”œβ”€β”€ injected.js # Script injected into dApps +β”œβ”€β”€ popup.html # Extension popup UI +β”œβ”€β”€ popup.js # Popup logic +β”œβ”€β”€ icons/ # Extension icons +└── README.md # This file +``` + +## Firefox-Specific Notes + +- Firefox requires Manifest V2 for extensions that use content scripts in this manner +- The `browser_action` API is used instead of the newer `action` API +- Background scripts use port-based communication for better performance +- Storage APIs use `chrome.storage` which is compatible with Firefox + +## Troubleshooting + +### Extension not loading +- Ensure you're loading the `manifest.json` file, not the folder +- Check the Browser Console for error messages (`Ctrl+Shift+J`) + +### dApp connection not working +- Refresh the dApp page after installing/updating the extension +- Check that the site is in the `matches` pattern in manifest.json +- Look for errors in the Browser Console + +### Permission errors +- Firefox may show additional permission prompts +- Make sure to allow all requested permissions when installing diff --git a/extensions/aitbc-wallet-firefox/background.js b/extensions/aitbc-wallet-firefox/background.js new file mode 100644 index 00000000..76c57e3b --- /dev/null +++ b/extensions/aitbc-wallet-firefox/background.js @@ -0,0 +1,153 @@ +// Background script for Firefox extension +// Handles messages from content scripts and manages wallet state + +let currentPort = null; + +// Listen for connection from content script +chrome.runtime.onConnect.addListener(function(port) { + if (port.name === "aitbc-wallet") { + currentPort = port; + + port.onMessage.addListener(function(request) { + handleWalletRequest(request, port); + }); + + port.onDisconnect.addListener(function() { + currentPort = null; + }); + } +}); + +// Handle wallet requests from dApps +async function handleWalletRequest(request, port) { + const { method, params, id } = request; + + try { + switch (method) { + case 'connect': + const response = await handleConnect(); + port.postMessage({ id, result: response }); + break; + + case 'accounts': + const accounts = await getAccounts(); + port.postMessage({ id, result: accounts }); + break; + + case 'getBalance': + const balance = await getBalance(params.address); + port.postMessage({ id, result: balance }); + break; + + case 'sendTransaction': + const txResult = await sendTransaction(params); + port.postMessage({ id, result: txResult }); + break; + + case 'signMessage': + const signature = await signMessage(params.message); + port.postMessage({ id, result: signature }); + break; + + default: + port.postMessage({ id, error: 'Unknown method: ' + method }); + } + } catch (error) { + port.postMessage({ id, error: error.message }); + } +} + +// Handle connection request from dApp +async function handleConnect() { + // Get current account + const result = await chrome.storage.local.get(['currentAccount']); + + if (!result.currentAccount) { + throw new Error('No account found. Please create or import an account first.'); + } + + // Show connection prompt (in a real implementation, this would show a proper UI) + const connected = confirm(`Allow this site to connect to your AITBC Wallet?\n\nAddress: ${result.currentAccount.address}`); + + if (!connected) { + throw new Error('User rejected connection'); + } + + return { + success: true, + address: result.currentAccount.address + }; +} + +// Get all accounts +async function getAccounts() { + const result = await chrome.storage.local.get(['accounts']); + const accounts = result.accounts || []; + return accounts.map(acc => acc.address); +} + +// Get balance for an address +async function getBalance(address) { + // In a real implementation, this would query the blockchain + // For demo, return stored balance + const result = await chrome.storage.local.get(['accounts']); + const accounts = result.accounts || []; + const account = accounts.find(acc => acc.address === address); + + return { + address: address, + balance: account ? account.balance || 0 : 0, + symbol: 'AITBC' + }; +} + +// Send transaction +async function sendTransaction(params) { + // In a real implementation, this would create, sign, and broadcast a transaction + const { to, amount, data } = params; + + // Get current account + const result = await chrome.storage.local.get(['currentAccount']); + const account = result.currentAccount; + + if (!account) { + throw new Error('No account connected'); + } + + // Confirm transaction + const confirmed = confirm(`Send ${amount} AITBC to ${to}?\n\nFrom: ${account.address}`); + if (!confirmed) { + throw new Error('Transaction rejected'); + } + + // Return mock transaction hash + return { + hash: '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)), b => b.toString(16).padStart(2, '0')).join(''), + status: 'pending' + }; +} + +// Sign message +async function signMessage(message) { + // Get current account + const result = await chrome.storage.local.get(['currentAccount']); + const account = result.currentAccount; + + if (!account) { + throw new Error('No account connected'); + } + + // Confirm signing + const confirmed = confirm(`Sign the following message?\n\n"${message}"\n\nAccount: ${account.address}`); + if (!confirmed) { + throw new Error('Message signing rejected'); + } + + // In a real implementation, this would sign with the private key + // For demo, return a mock signature + const encoder = new TextEncoder(); + const data = encoder.encode(message + account.privateKey); + const hash = await crypto.subtle.digest('SHA-256', data); + + return Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join(''); +} diff --git a/extensions/aitbc-wallet-firefox/content.js b/extensions/aitbc-wallet-firefox/content.js new file mode 100644 index 00000000..1a208d68 --- /dev/null +++ b/extensions/aitbc-wallet-firefox/content.js @@ -0,0 +1,35 @@ +// Content script for AITBC Wallet Firefox extension +(function() { + // Inject the wallet API into the page + const script = document.createElement('script'); + script.src = chrome.runtime.getURL('injected.js'); + script.onload = function() { + this.remove(); + }; + (document.head || document.documentElement).appendChild(script); + + // Create a port to background script + const port = chrome.runtime.connect({ name: "aitbc-wallet" }); + + // Listen for messages from the injected script + window.addEventListener('message', function(event) { + // Only accept messages from our own window + if (event.source !== window) return; + + if (event.data.type && event.data.type === 'AITBC_WALLET_REQUEST') { + // Forward the request to the background script + port.postMessage(event.data); + } + }); + + // Listen for responses from background script + port.onMessage.addListener(function(response) { + // Send the response back to the page + window.postMessage({ + type: 'AITBC_WALLET_RESPONSE', + id: response.id, + result: response.result, + error: response.error + }, '*'); + }); +})(); diff --git a/extensions/aitbc-wallet-firefox/injected.js b/extensions/aitbc-wallet-firefox/injected.js new file mode 100644 index 00000000..e4cd6a0e --- /dev/null +++ b/extensions/aitbc-wallet-firefox/injected.js @@ -0,0 +1,106 @@ +// Injected script that provides the AITBC wallet API to the dApp +(function() { + // Create the wallet API object + const aitbcWallet = { + // Check if wallet is available + isAvailable: function() { + return true; + }, + + // Connect to wallet + connect: async function() { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + // Send request to content script + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: 'connect' + }, '*'); + + // Listen for response + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + // Timeout after 30 seconds + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Connection timeout')); + }, 30000); + }); + }, + + // Get account address + getAccount: async function() { + const accounts = await this.request({ method: 'accounts' }); + return accounts[0]; + }, + + // Get balance + getBalance: async function(address) { + return this.request({ method: 'getBalance', params: { address } }); + }, + + // Send transaction + sendTransaction: async function(to, amount, data = null) { + return this.request({ + method: 'sendTransaction', + params: { to, amount, data } + }); + }, + + // Sign message + signMessage: async function(message) { + return this.request({ method: 'signMessage', params: { message } }); + }, + + // Generic request method + request: async function(payload) { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: payload.method, + params: payload.params || {} + }, '*'); + + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Request timeout')); + }, 30000); + }); + } + }; + + // Inject the wallet API into the window object + window.aitbcWallet = aitbcWallet; + + // Fire an event to notify the dApp that the wallet is ready + window.dispatchEvent(new Event('aitbcWalletReady')); +})(); diff --git a/extensions/aitbc-wallet-firefox/manifest.json b/extensions/aitbc-wallet-firefox/manifest.json new file mode 100644 index 00000000..7b97484f --- /dev/null +++ b/extensions/aitbc-wallet-firefox/manifest.json @@ -0,0 +1,46 @@ +{ + "manifest_version": 2, + "name": "AITBC Wallet", + "version": "1.0.0", + "description": "AITBC Browser Wallet for trading and managing AITBC tokens", + + "permissions": [ + "storage", + "activeTab" + ], + + "content_scripts": [ + { + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"], + "js": ["content.js"], + "run_at": "document_start" + } + ], + + "browser_action": { + "default_popup": "popup.html", + "default_title": "AITBC Wallet", + "default_icon": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + } + }, + + "web_accessible_resources": [ + ["injected.js"] + ], + + "icons": { + "16": "icons/icon-16.png", + "32": "icons/icon-32.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + }, + + "background": { + "scripts": ["background.js"], + "persistent": false + } +} diff --git a/extensions/aitbc-wallet-firefox/popup.html b/extensions/aitbc-wallet-firefox/popup.html new file mode 100644 index 00000000..16612b8c --- /dev/null +++ b/extensions/aitbc-wallet-firefox/popup.html @@ -0,0 +1,109 @@ + + + + + + + +
+ +

Wallet

+
+ +
+
Account Address:
+
Not connected
+
0 AITBC
+
+ +
+ + + + + +
+ +
+

Recent Transactions

+
+
No transactions yet
+
+
+ + + + diff --git a/extensions/aitbc-wallet-firefox/popup.js b/extensions/aitbc-wallet-firefox/popup.js new file mode 100644 index 00000000..dee47403 --- /dev/null +++ b/extensions/aitbc-wallet-firefox/popup.js @@ -0,0 +1,162 @@ +// Popup script for AITBC Wallet extension +let currentAccount = null; +let accounts = []; + +// Load wallet data on popup open +document.addEventListener('DOMContentLoaded', async function() { + await loadWalletData(); + updateUI(); +}); + +// Load wallet data from storage +async function loadWalletData() { + const result = await chrome.storage.local.get(['accounts', 'currentAccount']); + accounts = result.accounts || []; + currentAccount = result.currentAccount || null; +} + +// Save wallet data to storage +async function saveWalletData() { + await chrome.storage.local.set({ + accounts: accounts, + currentAccount: currentAccount + }); +} + +// Update UI with current wallet state +function updateUI() { + const addressEl = document.getElementById('accountAddress'); + const balanceEl = document.getElementById('balance'); + + if (currentAccount) { + addressEl.textContent = currentAccount.address; + balanceEl.textContent = `${currentAccount.balance || 0} AITBC`; + } else { + addressEl.textContent = 'Not connected'; + balanceEl.textContent = '0 AITBC'; + } +} + +// Create a new account +async function createAccount() { + // Generate a new private key and address + const privateKey = generatePrivateKey(); + const address = await generateAddress(privateKey); + + const newAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + + accounts.push(newAccount); + currentAccount = newAccount; + await saveWalletData(); + updateUI(); + + alert('New account created! Please save your private key securely.'); +} + +// Import account from private key +async function importAccount() { + const privateKey = prompt('Enter your private key:'); + if (!privateKey) return; + + try { + const address = await generateAddress(privateKey); + + // Check if account already exists + const existing = accounts.find(a => a.address === address); + if (existing) { + currentAccount = existing; + } else { + currentAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + accounts.push(currentAccount); + } + + await saveWalletData(); + updateUI(); + alert('Account imported successfully!'); + } catch (error) { + alert('Invalid private key!'); + } +} + +// Send tokens +async function sendTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + const to = prompt('Send to address:'); + const amount = prompt('Amount:'); + + if (!to || !amount) return; + + // In a real implementation, this would create and sign a transaction + alert(`Would send ${amount} AITBC to ${to}`); +} + +// Receive tokens +function receiveTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + alert(`Your receiving address:\n${currentAccount.address}`); +} + +// View on explorer +function viewOnExplorer() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + chrome.tabs.create({ url: `https://aitbc.bubuit.net/explorer/address/${currentAccount.address}` }); +} + +// Generate a random private key (demo only) +function generatePrivateKey() { + const array = new Uint8Array(32); + crypto.getRandomValues(array); + return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''); +} + +// Generate address from private key (demo only) +async function generateAddress(privateKey) { + // In a real implementation, this would derive the address from the private key + // using the appropriate cryptographic algorithm + const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(privateKey)); + return 'aitbc1' + Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('').substring(0, 40); +} + +// Listen for connection requests from dApps +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.method === 'connect') { + // Show connection dialog + const connected = confirm(`Allow this site to connect to your AITBC Wallet?`); + + if (connected && currentAccount) { + sendResponse({ + success: true, + address: currentAccount.address + }); + } else { + sendResponse({ + success: false, + error: 'User rejected connection' + }); + } + } + + return true; // Keep the message channel open for async response +}); diff --git a/extensions/aitbc-wallet-simple/README.md b/extensions/aitbc-wallet-simple/README.md new file mode 100644 index 00000000..d632d7ef --- /dev/null +++ b/extensions/aitbc-wallet-simple/README.md @@ -0,0 +1,112 @@ +# AITBC Browser Wallet Extension + +A browser extension that provides AITBC wallet functionality for interacting with the AITBC Trade Exchange and other dApps. + +## Features + +- **Wallet Management**: Create new accounts or import existing private keys +- **Secure Storage**: Private keys are stored locally in the browser +- **dApp Integration**: Connect to AITBC Trade Exchange and other supported dApps +- **Transaction Signing**: Sign transactions and messages securely +- **Balance Tracking**: View your AITBC token balance + +## Installation + +### Development Installation + +1. Clone this repository +2. Open Chrome and navigate to `chrome://extensions/` +3. Enable "Developer mode" in the top right +4. Click "Load unpacked" +5. Select the `aitbc-wallet` folder + +### Production Installation + +The extension will be published to the Chrome Web Store. Installation instructions will be available once published. + +## Usage + +### Connecting to the Exchange + +1. Install the AITBC Wallet extension +2. Navigate to https://aitbc.bubuit.net/Exchange +3. Toggle the switch from "Demo Mode" to "Real Mode" +4. Click "Connect AITBC Wallet" +5. Approve the connection request in the popup + +### Managing Accounts + +1. Click the AITBC Wallet icon in your browser toolbar +2. Use "Create New Account" to generate a new wallet +3. Use "Import Private Key" to restore an existing wallet +4. **Important**: Save your private key securely! It cannot be recovered if lost. + +## API Reference + +The extension injects a `window.aitbcWallet` object into supported dApps with the following methods: + +### `aitbcWallet.connect()` +Connect the dApp to the wallet. +```javascript +const response = await aitbcWallet.connect(); +console.log(response.address); // User's AITBC address +``` + +### `aitbcWallet.getAccount()` +Get the current account address. +```javascript +const address = await aitbcWallet.getAccount(); +``` + +### `aitbcWallet.getBalance(address)` +Get the AITBC balance for an address. +```javascript +const balance = await aitbcWallet.getBalance('aitbc1...'); +console.log(balance.amount); // Balance in AITBC +``` + +### `aitbcWallet.sendTransaction(to, amount, data)` +Send AITBC tokens to another address. +```javascript +const tx = await aitbcWallet.sendTransaction('aitbc1...', 100); +console.log(tx.hash); // Transaction hash +``` + +### `aitbcWallet.signMessage(message)` +Sign a message with the private key. +```javascript +const signature = await aitbcWallet.signMessage('Hello AITBC!'); +``` + +## Security Considerations + +- Private keys are stored locally in Chrome's storage +- Always verify you're on the correct domain before connecting +- Never share your private key with anyone +- Keep your browser and extension updated + +## Development + +To modify the extension: + +1. Make changes to the source files +2. Go to `chrome://extensions/` +3. Click the refresh button on the AITBC Wallet card +4. Test your changes + +## File Structure + +``` +aitbc-wallet/ +β”œβ”€β”€ manifest.json # Extension configuration +β”œβ”€β”€ content.js # Content script for dApp communication +β”œβ”€β”€ injected.js # Script injected into dApps +β”œβ”€β”€ popup.html # Extension popup UI +β”œβ”€β”€ popup.js # Popup logic +β”œβ”€β”€ icons/ # Extension icons +└── README.md # This file +``` + +## Support + +For issues or feature requests, please create an issue in the repository. diff --git a/extensions/aitbc-wallet-simple/aitbc-wallet.zip b/extensions/aitbc-wallet-simple/aitbc-wallet.zip new file mode 100644 index 00000000..ec7150b2 Binary files /dev/null and b/extensions/aitbc-wallet-simple/aitbc-wallet.zip differ diff --git a/extensions/aitbc-wallet-simple/content.js b/extensions/aitbc-wallet-simple/content.js new file mode 100644 index 00000000..da5f8e6e --- /dev/null +++ b/extensions/aitbc-wallet-simple/content.js @@ -0,0 +1,28 @@ +// Content script for AITBC Wallet extension +(function() { + // Inject the wallet API into the page + const script = document.createElement('script'); + script.src = chrome.runtime.getURL('injected.js'); + script.onload = function() { + this.remove(); + }; + (document.head || document.documentElement).appendChild(script); + + // Listen for messages from the injected script + window.addEventListener('message', function(event) { + // Only accept messages from our own window + if (event.source !== window) return; + + if (event.data.type && event.data.type === 'AITBC_WALLET_REQUEST') { + // Forward the request to the background script + chrome.runtime.sendMessage(event.data, function(response) { + // Send the response back to the page + window.postMessage({ + type: 'AITBC_WALLET_RESPONSE', + id: event.data.id, + response: response + }, '*'); + }); + } + }); +})(); diff --git a/extensions/aitbc-wallet-simple/injected.js b/extensions/aitbc-wallet-simple/injected.js new file mode 100644 index 00000000..e4cd6a0e --- /dev/null +++ b/extensions/aitbc-wallet-simple/injected.js @@ -0,0 +1,106 @@ +// Injected script that provides the AITBC wallet API to the dApp +(function() { + // Create the wallet API object + const aitbcWallet = { + // Check if wallet is available + isAvailable: function() { + return true; + }, + + // Connect to wallet + connect: async function() { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + // Send request to content script + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: 'connect' + }, '*'); + + // Listen for response + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + // Timeout after 30 seconds + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Connection timeout')); + }, 30000); + }); + }, + + // Get account address + getAccount: async function() { + const accounts = await this.request({ method: 'accounts' }); + return accounts[0]; + }, + + // Get balance + getBalance: async function(address) { + return this.request({ method: 'getBalance', params: { address } }); + }, + + // Send transaction + sendTransaction: async function(to, amount, data = null) { + return this.request({ + method: 'sendTransaction', + params: { to, amount, data } + }); + }, + + // Sign message + signMessage: async function(message) { + return this.request({ method: 'signMessage', params: { message } }); + }, + + // Generic request method + request: async function(payload) { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: payload.method, + params: payload.params || {} + }, '*'); + + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Request timeout')); + }, 30000); + }); + } + }; + + // Inject the wallet API into the window object + window.aitbcWallet = aitbcWallet; + + // Fire an event to notify the dApp that the wallet is ready + window.dispatchEvent(new Event('aitbcWalletReady')); +})(); diff --git a/extensions/aitbc-wallet-simple/install.html b/extensions/aitbc-wallet-simple/install.html new file mode 100644 index 00000000..b1b80faa --- /dev/null +++ b/extensions/aitbc-wallet-simple/install.html @@ -0,0 +1,156 @@ + + + + + + Install AITBC Wallet for Chrome + + + +
+ +

AITBC Wallet

+

The secure wallet for AITBC tokens

+ + + Download Extension + + +
+
+
1
+
+
Download the extension
+
Click the download button above
+
+
+ +
+
2
+
+
Open Chrome Extensions
+
Navigate to chrome://extensions/
+
+
+ +
+
3
+
+
Enable Developer Mode
+
Toggle the switch in the top right
+
+
+ +
+
4
+
+
Load Extension
+
Click "Load unpacked" and select the extracted folder
+
+
+
+ +

+ Chrome requires developer mode for security. This ensures you know exactly what you're installing. +

+
+ + diff --git a/extensions/aitbc-wallet-simple/manifest.json b/extensions/aitbc-wallet-simple/manifest.json new file mode 100644 index 00000000..7215abba --- /dev/null +++ b/extensions/aitbc-wallet-simple/manifest.json @@ -0,0 +1,32 @@ +{ + "manifest_version": 3, + "name": "AITBC Wallet", + "version": "1.0.0", + "description": "AITBC Browser Wallet for trading and managing AITBC tokens", + "permissions": [ + "storage", + "activeTab" + ], + "content_scripts": [ + { + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"], + "js": ["content.js"], + "run_at": "document_start" + } + ], + "action": { + "default_popup": "popup.html", + "default_title": "AITBC Wallet" + }, + "web_accessible_resources": [ + { + "resources": ["injected.js"], + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"] + } + ], + "icons": { + "16": "icons/icon-16.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + } +} diff --git a/extensions/aitbc-wallet-simple/popup.html b/extensions/aitbc-wallet-simple/popup.html new file mode 100644 index 00000000..16612b8c --- /dev/null +++ b/extensions/aitbc-wallet-simple/popup.html @@ -0,0 +1,109 @@ + + + + + + + +
+ +

Wallet

+
+ +
+
Account Address:
+
Not connected
+
0 AITBC
+
+ +
+ + + + + +
+ +
+

Recent Transactions

+
+
No transactions yet
+
+
+ + + + diff --git a/extensions/aitbc-wallet-simple/popup.js b/extensions/aitbc-wallet-simple/popup.js new file mode 100644 index 00000000..dee47403 --- /dev/null +++ b/extensions/aitbc-wallet-simple/popup.js @@ -0,0 +1,162 @@ +// Popup script for AITBC Wallet extension +let currentAccount = null; +let accounts = []; + +// Load wallet data on popup open +document.addEventListener('DOMContentLoaded', async function() { + await loadWalletData(); + updateUI(); +}); + +// Load wallet data from storage +async function loadWalletData() { + const result = await chrome.storage.local.get(['accounts', 'currentAccount']); + accounts = result.accounts || []; + currentAccount = result.currentAccount || null; +} + +// Save wallet data to storage +async function saveWalletData() { + await chrome.storage.local.set({ + accounts: accounts, + currentAccount: currentAccount + }); +} + +// Update UI with current wallet state +function updateUI() { + const addressEl = document.getElementById('accountAddress'); + const balanceEl = document.getElementById('balance'); + + if (currentAccount) { + addressEl.textContent = currentAccount.address; + balanceEl.textContent = `${currentAccount.balance || 0} AITBC`; + } else { + addressEl.textContent = 'Not connected'; + balanceEl.textContent = '0 AITBC'; + } +} + +// Create a new account +async function createAccount() { + // Generate a new private key and address + const privateKey = generatePrivateKey(); + const address = await generateAddress(privateKey); + + const newAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + + accounts.push(newAccount); + currentAccount = newAccount; + await saveWalletData(); + updateUI(); + + alert('New account created! Please save your private key securely.'); +} + +// Import account from private key +async function importAccount() { + const privateKey = prompt('Enter your private key:'); + if (!privateKey) return; + + try { + const address = await generateAddress(privateKey); + + // Check if account already exists + const existing = accounts.find(a => a.address === address); + if (existing) { + currentAccount = existing; + } else { + currentAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + accounts.push(currentAccount); + } + + await saveWalletData(); + updateUI(); + alert('Account imported successfully!'); + } catch (error) { + alert('Invalid private key!'); + } +} + +// Send tokens +async function sendTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + const to = prompt('Send to address:'); + const amount = prompt('Amount:'); + + if (!to || !amount) return; + + // In a real implementation, this would create and sign a transaction + alert(`Would send ${amount} AITBC to ${to}`); +} + +// Receive tokens +function receiveTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + alert(`Your receiving address:\n${currentAccount.address}`); +} + +// View on explorer +function viewOnExplorer() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + chrome.tabs.create({ url: `https://aitbc.bubuit.net/explorer/address/${currentAccount.address}` }); +} + +// Generate a random private key (demo only) +function generatePrivateKey() { + const array = new Uint8Array(32); + crypto.getRandomValues(array); + return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''); +} + +// Generate address from private key (demo only) +async function generateAddress(privateKey) { + // In a real implementation, this would derive the address from the private key + // using the appropriate cryptographic algorithm + const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(privateKey)); + return 'aitbc1' + Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('').substring(0, 40); +} + +// Listen for connection requests from dApps +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.method === 'connect') { + // Show connection dialog + const connected = confirm(`Allow this site to connect to your AITBC Wallet?`); + + if (connected && currentAccount) { + sendResponse({ + success: true, + address: currentAccount.address + }); + } else { + sendResponse({ + success: false, + error: 'User rejected connection' + }); + } + } + + return true; // Keep the message channel open for async response +}); diff --git a/extensions/aitbc-wallet.zip b/extensions/aitbc-wallet.zip new file mode 100644 index 00000000..ec7150b2 Binary files /dev/null and b/extensions/aitbc-wallet.zip differ diff --git a/extensions/aitbc-wallet/README.md b/extensions/aitbc-wallet/README.md new file mode 100644 index 00000000..d632d7ef --- /dev/null +++ b/extensions/aitbc-wallet/README.md @@ -0,0 +1,112 @@ +# AITBC Browser Wallet Extension + +A browser extension that provides AITBC wallet functionality for interacting with the AITBC Trade Exchange and other dApps. + +## Features + +- **Wallet Management**: Create new accounts or import existing private keys +- **Secure Storage**: Private keys are stored locally in the browser +- **dApp Integration**: Connect to AITBC Trade Exchange and other supported dApps +- **Transaction Signing**: Sign transactions and messages securely +- **Balance Tracking**: View your AITBC token balance + +## Installation + +### Development Installation + +1. Clone this repository +2. Open Chrome and navigate to `chrome://extensions/` +3. Enable "Developer mode" in the top right +4. Click "Load unpacked" +5. Select the `aitbc-wallet` folder + +### Production Installation + +The extension will be published to the Chrome Web Store. Installation instructions will be available once published. + +## Usage + +### Connecting to the Exchange + +1. Install the AITBC Wallet extension +2. Navigate to https://aitbc.bubuit.net/Exchange +3. Toggle the switch from "Demo Mode" to "Real Mode" +4. Click "Connect AITBC Wallet" +5. Approve the connection request in the popup + +### Managing Accounts + +1. Click the AITBC Wallet icon in your browser toolbar +2. Use "Create New Account" to generate a new wallet +3. Use "Import Private Key" to restore an existing wallet +4. **Important**: Save your private key securely! It cannot be recovered if lost. + +## API Reference + +The extension injects a `window.aitbcWallet` object into supported dApps with the following methods: + +### `aitbcWallet.connect()` +Connect the dApp to the wallet. +```javascript +const response = await aitbcWallet.connect(); +console.log(response.address); // User's AITBC address +``` + +### `aitbcWallet.getAccount()` +Get the current account address. +```javascript +const address = await aitbcWallet.getAccount(); +``` + +### `aitbcWallet.getBalance(address)` +Get the AITBC balance for an address. +```javascript +const balance = await aitbcWallet.getBalance('aitbc1...'); +console.log(balance.amount); // Balance in AITBC +``` + +### `aitbcWallet.sendTransaction(to, amount, data)` +Send AITBC tokens to another address. +```javascript +const tx = await aitbcWallet.sendTransaction('aitbc1...', 100); +console.log(tx.hash); // Transaction hash +``` + +### `aitbcWallet.signMessage(message)` +Sign a message with the private key. +```javascript +const signature = await aitbcWallet.signMessage('Hello AITBC!'); +``` + +## Security Considerations + +- Private keys are stored locally in Chrome's storage +- Always verify you're on the correct domain before connecting +- Never share your private key with anyone +- Keep your browser and extension updated + +## Development + +To modify the extension: + +1. Make changes to the source files +2. Go to `chrome://extensions/` +3. Click the refresh button on the AITBC Wallet card +4. Test your changes + +## File Structure + +``` +aitbc-wallet/ +β”œβ”€β”€ manifest.json # Extension configuration +β”œβ”€β”€ content.js # Content script for dApp communication +β”œβ”€β”€ injected.js # Script injected into dApps +β”œβ”€β”€ popup.html # Extension popup UI +β”œβ”€β”€ popup.js # Popup logic +β”œβ”€β”€ icons/ # Extension icons +└── README.md # This file +``` + +## Support + +For issues or feature requests, please create an issue in the repository. diff --git a/extensions/aitbc-wallet/content.js b/extensions/aitbc-wallet/content.js new file mode 100644 index 00000000..da5f8e6e --- /dev/null +++ b/extensions/aitbc-wallet/content.js @@ -0,0 +1,28 @@ +// Content script for AITBC Wallet extension +(function() { + // Inject the wallet API into the page + const script = document.createElement('script'); + script.src = chrome.runtime.getURL('injected.js'); + script.onload = function() { + this.remove(); + }; + (document.head || document.documentElement).appendChild(script); + + // Listen for messages from the injected script + window.addEventListener('message', function(event) { + // Only accept messages from our own window + if (event.source !== window) return; + + if (event.data.type && event.data.type === 'AITBC_WALLET_REQUEST') { + // Forward the request to the background script + chrome.runtime.sendMessage(event.data, function(response) { + // Send the response back to the page + window.postMessage({ + type: 'AITBC_WALLET_RESPONSE', + id: event.data.id, + response: response + }, '*'); + }); + } + }); +})(); diff --git a/extensions/aitbc-wallet/injected.js b/extensions/aitbc-wallet/injected.js new file mode 100644 index 00000000..e4cd6a0e --- /dev/null +++ b/extensions/aitbc-wallet/injected.js @@ -0,0 +1,106 @@ +// Injected script that provides the AITBC wallet API to the dApp +(function() { + // Create the wallet API object + const aitbcWallet = { + // Check if wallet is available + isAvailable: function() { + return true; + }, + + // Connect to wallet + connect: async function() { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + // Send request to content script + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: 'connect' + }, '*'); + + // Listen for response + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + // Timeout after 30 seconds + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Connection timeout')); + }, 30000); + }); + }, + + // Get account address + getAccount: async function() { + const accounts = await this.request({ method: 'accounts' }); + return accounts[0]; + }, + + // Get balance + getBalance: async function(address) { + return this.request({ method: 'getBalance', params: { address } }); + }, + + // Send transaction + sendTransaction: async function(to, amount, data = null) { + return this.request({ + method: 'sendTransaction', + params: { to, amount, data } + }); + }, + + // Sign message + signMessage: async function(message) { + return this.request({ method: 'signMessage', params: { message } }); + }, + + // Generic request method + request: async function(payload) { + return new Promise((resolve, reject) => { + const requestId = Date.now().toString(); + + window.postMessage({ + type: 'AITBC_WALLET_REQUEST', + id: requestId, + method: payload.method, + params: payload.params || {} + }, '*'); + + const messageHandler = function(event) { + if (event.data.type === 'AITBC_WALLET_RESPONSE' && event.data.id === requestId) { + window.removeEventListener('message', messageHandler); + if (event.data.response.error) { + reject(new Error(event.data.response.error)); + } else { + resolve(event.data.response); + } + } + }; + + window.addEventListener('message', messageHandler); + + setTimeout(() => { + window.removeEventListener('message', messageHandler); + reject(new Error('Request timeout')); + }, 30000); + }); + } + }; + + // Inject the wallet API into the window object + window.aitbcWallet = aitbcWallet; + + // Fire an event to notify the dApp that the wallet is ready + window.dispatchEvent(new Event('aitbcWalletReady')); +})(); diff --git a/extensions/aitbc-wallet/manifest.json b/extensions/aitbc-wallet/manifest.json new file mode 100644 index 00000000..7215abba --- /dev/null +++ b/extensions/aitbc-wallet/manifest.json @@ -0,0 +1,32 @@ +{ + "manifest_version": 3, + "name": "AITBC Wallet", + "version": "1.0.0", + "description": "AITBC Browser Wallet for trading and managing AITBC tokens", + "permissions": [ + "storage", + "activeTab" + ], + "content_scripts": [ + { + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"], + "js": ["content.js"], + "run_at": "document_start" + } + ], + "action": { + "default_popup": "popup.html", + "default_title": "AITBC Wallet" + }, + "web_accessible_resources": [ + { + "resources": ["injected.js"], + "matches": ["https://aitbc.bubuit.net/*", "http://localhost:3002/*"] + } + ], + "icons": { + "16": "icons/icon-16.png", + "48": "icons/icon-48.png", + "128": "icons/icon-128.png" + } +} diff --git a/extensions/aitbc-wallet/popup.html b/extensions/aitbc-wallet/popup.html new file mode 100644 index 00000000..16612b8c --- /dev/null +++ b/extensions/aitbc-wallet/popup.html @@ -0,0 +1,109 @@ + + + + + + + +
+ +

Wallet

+
+ +
+
Account Address:
+
Not connected
+
0 AITBC
+
+ +
+ + + + + +
+ +
+

Recent Transactions

+
+
No transactions yet
+
+
+ + + + diff --git a/extensions/aitbc-wallet/popup.js b/extensions/aitbc-wallet/popup.js new file mode 100644 index 00000000..dee47403 --- /dev/null +++ b/extensions/aitbc-wallet/popup.js @@ -0,0 +1,162 @@ +// Popup script for AITBC Wallet extension +let currentAccount = null; +let accounts = []; + +// Load wallet data on popup open +document.addEventListener('DOMContentLoaded', async function() { + await loadWalletData(); + updateUI(); +}); + +// Load wallet data from storage +async function loadWalletData() { + const result = await chrome.storage.local.get(['accounts', 'currentAccount']); + accounts = result.accounts || []; + currentAccount = result.currentAccount || null; +} + +// Save wallet data to storage +async function saveWalletData() { + await chrome.storage.local.set({ + accounts: accounts, + currentAccount: currentAccount + }); +} + +// Update UI with current wallet state +function updateUI() { + const addressEl = document.getElementById('accountAddress'); + const balanceEl = document.getElementById('balance'); + + if (currentAccount) { + addressEl.textContent = currentAccount.address; + balanceEl.textContent = `${currentAccount.balance || 0} AITBC`; + } else { + addressEl.textContent = 'Not connected'; + balanceEl.textContent = '0 AITBC'; + } +} + +// Create a new account +async function createAccount() { + // Generate a new private key and address + const privateKey = generatePrivateKey(); + const address = await generateAddress(privateKey); + + const newAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + + accounts.push(newAccount); + currentAccount = newAccount; + await saveWalletData(); + updateUI(); + + alert('New account created! Please save your private key securely.'); +} + +// Import account from private key +async function importAccount() { + const privateKey = prompt('Enter your private key:'); + if (!privateKey) return; + + try { + const address = await generateAddress(privateKey); + + // Check if account already exists + const existing = accounts.find(a => a.address === address); + if (existing) { + currentAccount = existing; + } else { + currentAccount = { + address: address, + privateKey: privateKey, + balance: 0, + created: new Date().toISOString() + }; + accounts.push(currentAccount); + } + + await saveWalletData(); + updateUI(); + alert('Account imported successfully!'); + } catch (error) { + alert('Invalid private key!'); + } +} + +// Send tokens +async function sendTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + const to = prompt('Send to address:'); + const amount = prompt('Amount:'); + + if (!to || !amount) return; + + // In a real implementation, this would create and sign a transaction + alert(`Would send ${amount} AITBC to ${to}`); +} + +// Receive tokens +function receiveTokens() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + alert(`Your receiving address:\n${currentAccount.address}`); +} + +// View on explorer +function viewOnExplorer() { + if (!currentAccount) { + alert('Please create or import an account first!'); + return; + } + + chrome.tabs.create({ url: `https://aitbc.bubuit.net/explorer/address/${currentAccount.address}` }); +} + +// Generate a random private key (demo only) +function generatePrivateKey() { + const array = new Uint8Array(32); + crypto.getRandomValues(array); + return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join(''); +} + +// Generate address from private key (demo only) +async function generateAddress(privateKey) { + // In a real implementation, this would derive the address from the private key + // using the appropriate cryptographic algorithm + const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(privateKey)); + return 'aitbc1' + Array.from(new Uint8Array(hash), b => b.toString(16).padStart(2, '0')).join('').substring(0, 40); +} + +// Listen for connection requests from dApps +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.method === 'connect') { + // Show connection dialog + const connected = confirm(`Allow this site to connect to your AITBC Wallet?`); + + if (connected && currentAccount) { + sendResponse({ + success: true, + address: currentAccount.address + }); + } else { + sendResponse({ + success: false, + error: 'User rejected connection' + }); + } + } + + return true; // Keep the message channel open for async response +}); diff --git a/scripts/return_testnet_btc.sh b/scripts/return_testnet_btc.sh new file mode 100755 index 00000000..48472ca6 --- /dev/null +++ b/scripts/return_testnet_btc.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Script to return testnet Bitcoin + +RETURN_ADDRESS="tb1qerzrlxcfu24davlur5sqmgzzgsal6wusda40er" + +echo "Checking balance..." +BALANCE=$(bitcoin-cli -testnet -rpcwallet=aitbc_exchange getbalance) + +if [ "$(echo "$BALANCE > 0" | bc)" -eq 1 ]; then + echo "Current balance: $BALANCE BTC" + echo "Sending to return address: $RETURN_ADDRESS" + + # Calculate amount to send (balance minus small fee) + SEND_AMOUNT=$(echo "$BALANCE - 0.00001" | bc) + + TXID=$(bitcoin-cli -testnet -rpcwallet=aitbc_exchange sendtoaddress "$RETURN_ADDRESS" "$SEND_AMOUNT") + echo "Transaction sent! TXID: $TXID" + echo "Explorer: https://blockstream.info/testnet/tx/$TXID" +else + echo "No Bitcoin to return. Current balance: $BALANCE BTC" +fi diff --git a/website/BrowserWallet/index.html b/website/BrowserWallet/index.html new file mode 100644 index 00000000..c588e7e6 --- /dev/null +++ b/website/BrowserWallet/index.html @@ -0,0 +1,59 @@ + + + + + + AITBC Browser Wallet - Redirecting... + + + + + +
+
+

AITBC Browser Wallet

+

Redirecting to the installation page...

+

If you're not redirected automatically, click here.

+
+ + diff --git a/website/docs-index.html b/website/docs-index.html index a4a9007f..91c2f4f1 100644 --- a/website/docs-index.html +++ b/website/docs-index.html @@ -509,6 +509,10 @@ Trade Exchange + + + Browser Wallet + Source Code diff --git a/website/docs/browser-wallet.html b/website/docs/browser-wallet.html new file mode 100644 index 00000000..be40f647 --- /dev/null +++ b/website/docs/browser-wallet.html @@ -0,0 +1,416 @@ + + + + + + AITBC Browser Wallet - Secure Crypto Wallet + + + + + + +
+ + +
+

AITBC Browser Wallet

+

+ The most secure way to store, send, and receive AITBC tokens. + Connect to the AITBC Trade Exchange with just one click. +

+ +
+
+ + +
+
+

Why Choose AITBC Wallet?

+
+
+ +

Bank-Grade Security

+

+ Your private keys never leave your device. + Encrypted locally with military-grade security. +

+
+
+ +

Seamless dApp Integration

+

+ Connect to any AITBC-powered dApp with a single click. + No more copying and pasting addresses. +

+
+
+ +

Lightning Fast

+

+ Built for performance. + Instant transactions and real-time balance updates. +

+
+
+
+
+ + +
+
+

Install for Chrome / Edge / Brave

+ +
+
+

+ + Chrome Installation Steps +

+ +
+
+
1
+
+

Download the Extension

+

+ Download the AITBC Wallet extension files to your computer. +

+ + + Download Chrome Extension + +
+
+ +
+
2
+
+

Open Chrome Extensions

+

+ Open Chrome and navigate to the extensions page: +

+
chrome://extensions/
+
+
+ +
+
3
+
+

Enable Developer Mode

+

+ Toggle the "Developer mode" switch in the top right corner. +

+
+
+ +
+
4
+
+

Load Extension

+

+ Click "Load unpacked" and select the aitbc-wallet folder. +

+
+
+ +
+
5
+
+

Start Using!

+

+ Click the AITBC Wallet icon in your toolbar to create or import an account. +

+
+
+
+
+
+
+
+ + +
+
+

Install for Firefox

+ +
+
+

+ + Firefox Installation Steps +

+ +
+
+
1
+
+

Visit Install Page

+

+ Click the button below to go to the Firefox installation page. +

+ + + Install Firefox Extension + +
+
+ +
+
2
+
+

Click "Add to Firefox"

+

+ On the install page, click the "Add to Firefox" button to install the extension. +

+
+
+ +
+
3
+
+

Start Using!

+

+ The AITBC Wallet will appear in your toolbar with an orange icon. Click to create your first account! +

+
+
+
+
+
+
+
+ + +
+
+

Using Your AITBC Wallet

+ +
+
+

+ + Create a New Wallet +

+
    +
  1. 1. Click the AITBC Wallet icon
  2. +
  3. 2. Select "Create New Account"
  4. +
  5. 3. Securely save your private key
  6. +
  7. 4. Your wallet is ready!
  8. +
+
+ +
+

+ + Import Existing Wallet +

+
    +
  1. 1. Click the AITBC Wallet icon
  2. +
  3. 2. Select "Import Private Key"
  4. +
  5. 3. Enter your private key
  6. +
  7. 4. Access your restored wallet
  8. +
+
+ +
+

+ + Connect to Exchange +

+
    +
  1. 1. Visit AITBC Exchange
  2. +
  3. 2. Toggle to "Real Mode"
  4. +
  5. 3. Click "Connect AITBC Wallet"
  6. +
  7. 4. Approve the connection
  8. +
+
+ +
+

+ + Send & Receive Tokens +

+
    +
  1. 1. Click "Send" to transfer tokens
  2. +
  3. 2. Click "Receive" to get your address
  4. +
  5. 3. All transactions require confirmation
  6. +
  7. 4. View history in the wallet
  8. +
+
+
+
+
+ + +
+
+

Security Best Practices

+ +
+
+

+ + Important Security Reminders +

+ +
    +
  • + + Never share your private key - Anyone with your private key has full control of your funds +
  • +
  • + + Backup your private key - Write it down and store it in a secure, offline location +
  • +
  • + + Verify URLs - Always ensure you're on aitbc.bubuit.net before connecting +
  • +
  • + + Use a password manager - Protect your browser with a strong, unique password +
  • +
  • + + Keep updated - Regularly update your browser and the wallet extension +
  • +
+
+
+
+
+ + + + + + + diff --git a/website/extensions/aitbc-wallet-firefox.zip b/website/extensions/aitbc-wallet-firefox.zip new file mode 100644 index 00000000..69154c24 Binary files /dev/null and b/website/extensions/aitbc-wallet-firefox.zip differ diff --git a/website/extensions/aitbc-wallet.zip b/website/extensions/aitbc-wallet.zip new file mode 100644 index 00000000..ec7150b2 Binary files /dev/null and b/website/extensions/aitbc-wallet.zip differ