From 2cb2fbbeda6a7921075971d7f5c2c06a4f4e254c Mon Sep 17 00:00:00 2001 From: oib Date: Mon, 29 Dec 2025 18:04:04 +0100 Subject: [PATCH] ``` feat: add market stats endpoint, wallet integration, and browser wallet link - Update devnet genesis timestamp to 1767000206 - Add market statistics endpoint with 24h volume, price change, and payment counts - Add wallet balance and info API endpoints in exchange router - Remove unused SessionDep dependencies from exchange endpoints - Integrate real AITBC wallet extension connection in trade-exchange UI - Add market data fetching with API fallback for price and volume display - Add cache-busting query --- apps/blockchain-node/data/chain.db-journal | Bin 0 -> 21032 bytes apps/blockchain-node/data/devnet/genesis.json | 2 +- .../src/app/routers/exchange.py | 50 ++- .../src/app/services/bitcoin_wallet.py | 134 ++++++ apps/trade-exchange/admin.html | 316 +++++++++++++ apps/trade-exchange/index.html | 149 +++++-- assets/aitbc-wallet-firefox-v1.0.0.xpi | Bin 0 -> 21523 bytes assets/aitbc-wallet-firefox-v1.0.1.xpi | Bin 0 -> 21857 bytes assets/aitbc-wallet-firefox-v1.0.2.xpi | Bin 0 -> 22965 bytes assets/aitbc-wallet-firefox-v1.0.3.xpi | Bin 0 -> 22632 bytes assets/aitbc-wallet-firefox-v1.0.4.xpi | Bin 0 -> 22736 bytes assets/aitbc-wallet-firefox-v1.0.5.xpi | Bin 0 -> 22784 bytes deploy-exchange.sh | 74 ++++ extensions/README.md | 77 ++++ .../aitbc-wallet-firefox-simple/README.md | 133 ++++++ .../aitbc-wallet.xpi | Bin 0 -> 7748 bytes .../aitbc-wallet-firefox-simple/background.js | 160 +++++++ .../aitbc-wallet-firefox-simple/content.js | 42 ++ .../icons/icon-128.png | Bin 0 -> 1766 bytes .../icons/icon-16.png | Bin 0 -> 123 bytes .../icons/icon-32.png | Bin 0 -> 400 bytes .../icons/icon-48.png | Bin 0 -> 646 bytes .../icons/icon.svg | 13 + .../aitbc-wallet-firefox-simple/injected.js | 113 +++++ .../aitbc-wallet-firefox-simple/install.html | 149 +++++++ .../aitbc-wallet-firefox-simple/manifest.json | 46 ++ .../aitbc-wallet-firefox-simple/popup.html | 112 +++++ .../aitbc-wallet-firefox-simple/popup.js | 315 +++++++++++++ extensions/aitbc-wallet-firefox-v1.0.0.xpi | Bin 0 -> 21523 bytes extensions/aitbc-wallet-firefox-v1.0.1.xpi | Bin 0 -> 21857 bytes extensions/aitbc-wallet-firefox-v1.0.2.xpi | Bin 0 -> 22965 bytes extensions/aitbc-wallet-firefox-v1.0.3.xpi | Bin 0 -> 22632 bytes extensions/aitbc-wallet-firefox-v1.0.4.xpi | Bin 0 -> 22736 bytes extensions/aitbc-wallet-firefox-v1.0.5.xpi | Bin 0 -> 22784 bytes extensions/aitbc-wallet-firefox.zip | Bin 0 -> 6968 bytes extensions/aitbc-wallet-firefox/README.md | 133 ++++++ extensions/aitbc-wallet-firefox/background.js | 153 +++++++ extensions/aitbc-wallet-firefox/content.js | 35 ++ extensions/aitbc-wallet-firefox/injected.js | 106 +++++ extensions/aitbc-wallet-firefox/manifest.json | 46 ++ extensions/aitbc-wallet-firefox/popup.html | 109 +++++ extensions/aitbc-wallet-firefox/popup.js | 162 +++++++ extensions/aitbc-wallet-simple/README.md | 112 +++++ .../aitbc-wallet-simple/aitbc-wallet.zip | Bin 0 -> 5182 bytes extensions/aitbc-wallet-simple/content.js | 28 ++ extensions/aitbc-wallet-simple/injected.js | 106 +++++ extensions/aitbc-wallet-simple/install.html | 156 +++++++ extensions/aitbc-wallet-simple/manifest.json | 32 ++ extensions/aitbc-wallet-simple/popup.html | 109 +++++ extensions/aitbc-wallet-simple/popup.js | 162 +++++++ extensions/aitbc-wallet.zip | Bin 0 -> 5182 bytes extensions/aitbc-wallet/README.md | 112 +++++ extensions/aitbc-wallet/content.js | 28 ++ extensions/aitbc-wallet/injected.js | 106 +++++ extensions/aitbc-wallet/manifest.json | 32 ++ extensions/aitbc-wallet/popup.html | 109 +++++ extensions/aitbc-wallet/popup.js | 162 +++++++ scripts/return_testnet_btc.sh | 21 + website/BrowserWallet/index.html | 59 +++ website/docs-index.html | 4 + website/docs/browser-wallet.html | 416 ++++++++++++++++++ website/extensions/aitbc-wallet-firefox.zip | Bin 0 -> 6968 bytes website/extensions/aitbc-wallet.zip | Bin 0 -> 5182 bytes 63 files changed, 4329 insertions(+), 54 deletions(-) create mode 100644 apps/blockchain-node/data/chain.db-journal create mode 100644 apps/coordinator-api/src/app/services/bitcoin_wallet.py create mode 100644 apps/trade-exchange/admin.html create mode 100644 assets/aitbc-wallet-firefox-v1.0.0.xpi create mode 100644 assets/aitbc-wallet-firefox-v1.0.1.xpi create mode 100644 assets/aitbc-wallet-firefox-v1.0.2.xpi create mode 100644 assets/aitbc-wallet-firefox-v1.0.3.xpi create mode 100644 assets/aitbc-wallet-firefox-v1.0.4.xpi create mode 100644 assets/aitbc-wallet-firefox-v1.0.5.xpi create mode 100755 deploy-exchange.sh create mode 100644 extensions/README.md create mode 100644 extensions/aitbc-wallet-firefox-simple/README.md create mode 100644 extensions/aitbc-wallet-firefox-simple/aitbc-wallet.xpi create mode 100644 extensions/aitbc-wallet-firefox-simple/background.js create mode 100644 extensions/aitbc-wallet-firefox-simple/content.js create mode 100644 extensions/aitbc-wallet-firefox-simple/icons/icon-128.png create mode 100644 extensions/aitbc-wallet-firefox-simple/icons/icon-16.png create mode 100644 extensions/aitbc-wallet-firefox-simple/icons/icon-32.png create mode 100644 extensions/aitbc-wallet-firefox-simple/icons/icon-48.png create mode 100644 extensions/aitbc-wallet-firefox-simple/icons/icon.svg create mode 100644 extensions/aitbc-wallet-firefox-simple/injected.js create mode 100644 extensions/aitbc-wallet-firefox-simple/install.html create mode 100644 extensions/aitbc-wallet-firefox-simple/manifest.json create mode 100644 extensions/aitbc-wallet-firefox-simple/popup.html create mode 100644 extensions/aitbc-wallet-firefox-simple/popup.js create mode 100644 extensions/aitbc-wallet-firefox-v1.0.0.xpi create mode 100644 extensions/aitbc-wallet-firefox-v1.0.1.xpi create mode 100644 extensions/aitbc-wallet-firefox-v1.0.2.xpi create mode 100644 extensions/aitbc-wallet-firefox-v1.0.3.xpi create mode 100644 extensions/aitbc-wallet-firefox-v1.0.4.xpi create mode 100644 extensions/aitbc-wallet-firefox-v1.0.5.xpi create mode 100644 extensions/aitbc-wallet-firefox.zip create mode 100644 extensions/aitbc-wallet-firefox/README.md create mode 100644 extensions/aitbc-wallet-firefox/background.js create mode 100644 extensions/aitbc-wallet-firefox/content.js create mode 100644 extensions/aitbc-wallet-firefox/injected.js create mode 100644 extensions/aitbc-wallet-firefox/manifest.json create mode 100644 extensions/aitbc-wallet-firefox/popup.html create mode 100644 extensions/aitbc-wallet-firefox/popup.js create mode 100644 extensions/aitbc-wallet-simple/README.md create mode 100644 extensions/aitbc-wallet-simple/aitbc-wallet.zip create mode 100644 extensions/aitbc-wallet-simple/content.js create mode 100644 extensions/aitbc-wallet-simple/injected.js create mode 100644 extensions/aitbc-wallet-simple/install.html create mode 100644 extensions/aitbc-wallet-simple/manifest.json create mode 100644 extensions/aitbc-wallet-simple/popup.html create mode 100644 extensions/aitbc-wallet-simple/popup.js create mode 100644 extensions/aitbc-wallet.zip create mode 100644 extensions/aitbc-wallet/README.md create mode 100644 extensions/aitbc-wallet/content.js create mode 100644 extensions/aitbc-wallet/injected.js create mode 100644 extensions/aitbc-wallet/manifest.json create mode 100644 extensions/aitbc-wallet/popup.html create mode 100644 extensions/aitbc-wallet/popup.js create mode 100755 scripts/return_testnet_btc.sh create mode 100644 website/BrowserWallet/index.html create mode 100644 website/docs/browser-wallet.html create mode 100644 website/extensions/aitbc-wallet-firefox.zip create mode 100644 website/extensions/aitbc-wallet.zip diff --git a/apps/blockchain-node/data/chain.db-journal b/apps/blockchain-node/data/chain.db-journal new file mode 100644 index 0000000000000000000000000000000000000000..70fbcfce59cbeb49555c4998ad9dc13a120a511e GIT binary patch literal 21032 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 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 0000000000000000000000000000000000000000..aa7d6404e0e93d0cda5289dceb58e4d57411f5dc GIT binary patch literal 21523 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 b_TNSCe{oL$3uO?96nKr`fk5th*q{CnNt5PI literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4b31939ac679f483e65ea0425405a2728cc95d08 GIT binary patch literal 22965 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c4ff1bb1fbf6e1e30e6213e864cb58231ce44f2f GIT binary patch literal 22632 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�$Dh*-WqWi67tGwxMjE13L!BFB6@vl@OIdZ= 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d08590ff071f1dd22d0857ced8e964628d87a489 GIT binary patch literal 22784 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 MZ~MJ-t^Y#(A8yhm$p8QV literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ec7150b2aa895358f3391f0c59068cf622a8dc95 GIT binary patch literal 5182 zcmZ{obyQUA-^E85T96uP=|+a`knXM_C8c8km5@%6lpYWmV5B6Z1O_BTLPS!KP&$V$ z1r*-#-utfWMSo}3bJqFieCDjRzx$m1Y+VgZAU@#dQ4e`${@2AnCqe)%z{c6v*6#L0 z8#gxxU$BuO9stuvU*Fjpz3%%F0ImVoF#&+TPP%9eIr>IiKsg#CZ(ZqQdJO>B#sC1Q zuVUP7Je==2`1ta=_;`B!#r(fQ9WY%=?Nk1N_pS#jouv(F z?`?t7S1rfgY_K5&Mr%;1K*Q-ON(a8e6I`PTYT{qbnt>Uy+xpCL0q!J$=Ea<3ko{un zayjclz!`;9U|GK@9Qva!6?L<*7?BFYf_y=K483iMO51rW%H4Z|EG$m1p zpEr&kJh6jhGf?_+ekQ`Zb7?NI>#!k{G_EXZ=u~3ENbs?h`>pwptL(YpTTl}`;BN1h z#5u;lVpX8Uvd>_+Gk_M00SEw4ToudC)5F)ngT$mzPo{z&JrJa>sOQ3 zwq&5uMq6o&K319jLmOuj75lBpp5$rM8AgWnkU5iHJjP1!Mc@0J{bhfFuqb1qbj*PS z9y+&%uv2fJwonyg@^!%6MqRpD!lFB(smLg|V-43yldZ-O+(*|$3-`c1M6#-`)XQ>D z5lN@HI!LBa;SN?v_dlOy@W}%C&A!#cjD5^X#874$ zmxj|9#fa~ZUIf->EY{Q@o_zB)+wFY0Hm;9nS)v)cmB2zR0~5nPa{3-bFU540$<%3X z^a!v-%ej^x*CJ5h3L=+CoRv4=Xo#H0ZNFC+s@73Z5#O@e;Rp#A&uB>^U0B43RuL=* zodyR4dif<2`|93Vj(X-(lb|!QW?eWYT008CH z*>Lu7aj^4su>b$za6k{n&vj)uwoNp2X!wa=A9AmDdz5o9Krs>e1)NHSw^_@?3_$`& zGB4!ISBQ&Pptsl=6FzsD3z<`Q4w zcR5p7x4f=1WZm-=NO)Am+tKGHvxC^M5`)F|d2x2#AaT9X^$
z>nE2NTd_ zi4y5(YJTEDTadHM%OYicME0%p(~xit=Mo-Lqoy1BnR_*{v#y8|e^3#R&n29FrK{F5 zxT-W=J~?4Rp`^(oe)b(dpESjYu{(yN7h*Zf^}0fo8JmIISfN7!*5_BQNG@&i3s`{& z1wa2mqUsi|IDt7GGmbJ8O5dp6n(zfEE^vp0qV|O-%WMIke{vh0Ag`@Bs#rfKsZfzAW$yT5rneHTW>Cy2yEPOJ+aeIeZxszH>7EF1)5uhw2RzH7ns}Le=he)y6O~2K zh0r=qP5TXDu_QsS{(iRG50;^NVi^Wo=2RcV4Q-NX=<6qEovfWB7O*7g4Asj^wrbw6 zdO8UrJ@<7~1G*wvtqY+Q&VK5?OL4NuS;hqKMN`^KagQR5dk{cdOUL)pkJ-KIkw6>vPHqXGpQICb) zFgw;I4yx2G4a+m1HuE{0>4po_*@+ZYL{-sONuKf(P#C3ihIYn1P7HtHM-l27GxyMY zA(2&65hD6yT+9FYnw3XOkqE>Buh{yz=F68d(Mobu&&ueUK6n6&vW9sC5f)?hd@oj| zQxn`UY0TxPt&^Dcx!Kfea|o~aTkmlvMVg`fbB6Lr+Q%|GTPM_K3 zQRNTBE;~r^d525vv{RW!zUXKP z@p}}h^v0<65V?HZxqmians9kI?}wKZiz>uB9iZs8O6V^f@@+!})R@{Z}}-YwKLGZMG*Yqo$lr7b>EBE$=BWOuXnl=+Oj{_728%C>v_(I z5C`v8&kK>qhH<29wP*ikE3(sc}&vo-J-6vM?c)|e}juz$|~%=P

D!ZL=zW(q`1{m6XT+)r{_ z9-h0|x2RkO(@mGylyQ>QLzF-6Ook!4oZl(t6`b~^so8X0&y3$C^DUuV%~Z96D`MSBdjW>ZLv9aX~;iMJ0kG+@^QV>Im zL;RV|xojtIV_U;(Tlow!KIC|x_}T9oY@`gs5aC-28XknFv)^VyB4c$LM0jRmfZDg- zk3BIn6|xMV=^yJ~LJWnBf3xpGu7p2K>;*&|prQgfvEEo#4_@k<2+yac&Bv_c%(!)iJ z8LG@f7UiuTyFFn{jYq0KY!EkUJ)?QrY?^7*JSMV6@9 zLLi2E;2b%=Qjh)0G85J zrdprbSieNYJQqt+zL%rh<3JW3>gB#%e`q<=cG3Qve-rNuRZ?6pimE8jr*_fuW(8`e z%E}U15##_y?NIAX-6TnDcuhD9qM+S9dOc#L(0R5q_{Q^Vg=^MsCD-Dyth*1^_ofJG zUaIB|VcVg}vqWO+@dC-o@1%1EHxQ_#Yqp%%XJ31m*93DD8Ws}ko(V}~jtUFlcvHS$ zUM}(HeWso9!?2}?5o;k{>I*iIx)N^bO;KkZG^btgs$TB%*5`)a~#oq-^klVgOd9JCUTj@@8rJ| z3R|`hk{=^En!ee9~p;=P~_om!N1Q3^Ulc zDpy&`S^MrDm->TNYw&Tz?UXgz;I-iOeag0l`v%O}Ps)v*-eSQ9=cJ`o==l(ej0Z*} zY}_BP&u)80GH4DSNAb`+5nTd*#=M|4iMf3{(aIu1~hv=1D!wv|+|~x?G?Y*S6(JsK!#KdpB2Fda(Q0xQZ|ZpEOp?pV;s`AP}grYlvW+jP}C}Afo=sZ^Q-LB z;(i#OhPLB9aqewPl(w%adH6E9vCDSO%qn#3-a?)*`vpAV!uS(Qz^&s!3Aqxz9!exR zS&BH z^vx=NEvT&=l49$7Lepg$>hoX~uC(R?YKv@QqKhZg`Bb|LN{V>&d3(teI=3a3!FsK) zt(J9NV7v7JS&0dfnP3aK2YI)yBkO)WX^`4ekfy)*PHn$W%@989>q&R-3egH=h1E|R zmscX8J1)DrWXLh_8 zTu@g9b*$^;8X|*@qB@JUOmM^%bzX@sB@l?}$Osaow#hugU@Ewg2Z_cst>nJJ5KXAr zfZy0`=bl5N@4z}j=;^d@Jf5Ip>^cYs-Xo>qR(|WX-<;Cwe9F3&f7%wgA+w67QHBIEQy|FpTHsR5F zirLaqHSW1V7Zm8Qp~~!z(;dj_As5+SQ;VYr?mmo4ol>P+h;E5q#2|-tOncq-vNRTt zoQDxKWw|kd(;yk!?!zz(5e+3ZV?$S_`)cPtCre9r^E#w;k(+eyhbVZ~qKJOPXO%z( zt6WLRLX$|36t)m~1H#daVuOBLuXjc{5Uf&k@O+(!%dMc<@9gs)7>xoyFh`1VNuHQm z4ulQRU(>tW33dc`zB_x0i+$tO**G*&)19U3;x%h6_IV1tXLhx{Xi!8ky_N4!bMX!f zlz+Iba#@tWqp&NjIxxbZ>D~I1n~u6vA{(~KoHa1rl=M-hPh%S@f}A}e(cfQ-3BAc4 zuu8tzV{AcsZ|J=6X_4h_Cb7mCL@=H!Xj3AHGGRNhWH)$YlwY08o7&8O?zLS_!Bekd z8EIRn6TX9rUG@ z#x2bM)d5ld(*_X(e#rg2ywV6^{oM#%$&P;`|5qRMHxk`A0P4e3t|G6rLumdVnxS9$ zzgHN)@{iDe^Pfllwa`Gr|4?T93jci%{41Oo-I)9b{+}H&n*N8~@UQgWllrgpKAbD` zUvoPe{)f!|EByC-@GHC;y)pRDqyL*0(CD9O;WtUK&_M$Lz()Vr(6t^0I&uI2{|9SI B=e+;` literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ec7150b2aa895358f3391f0c59068cf622a8dc95 GIT binary patch literal 5182 zcmZ{obyQUA-^E85T96uP=|+a`knXM_C8c8km5@%6lpYWmV5B6Z1O_BTLPS!KP&$V$ z1r*-#-utfWMSo}3bJqFieCDjRzx$m1Y+VgZAU@#dQ4e`${@2AnCqe)%z{c6v*6#L0 z8#gxxU$BuO9stuvU*Fjpz3%%F0ImVoF#&+TPP%9eIr>IiKsg#CZ(ZqQdJO>B#sC1Q zuVUP7Je==2`1ta=_;`B!#r(fQ9WY%=?Nk1N_pS#jouv(F z?`?t7S1rfgY_K5&Mr%;1K*Q-ON(a8e6I`PTYT{qbnt>Uy+xpCL0q!J$=Ea<3ko{un zayjclz!`;9U|GK@9Qva!6?L<*7?BFYf_y=K483iMO51rW%H4Z|EG$m1p zpEr&kJh6jhGf?_+ekQ`Zb7?NI>#!k{G_EXZ=u~3ENbs?h`>pwptL(YpTTl}`;BN1h z#5u;lVpX8Uvd>_+Gk_M00SEw4ToudC)5F)ngT$mzPo{z&JrJa>sOQ3 zwq&5uMq6o&K319jLmOuj75lBpp5$rM8AgWnkU5iHJjP1!Mc@0J{bhfFuqb1qbj*PS z9y+&%uv2fJwonyg@^!%6MqRpD!lFB(smLg|V-43yldZ-O+(*|$3-`c1M6#-`)XQ>D z5lN@HI!LBa;SN?v_dlOy@W}%C&A!#cjD5^X#874$ zmxj|9#fa~ZUIf->EY{Q@o_zB)+wFY0Hm;9nS)v)cmB2zR0~5nPa{3-bFU540$<%3X z^a!v-%ej^x*CJ5h3L=+CoRv4=Xo#H0ZNFC+s@73Z5#O@e;Rp#A&uB>^U0B43RuL=* zodyR4dif<2`|93Vj(X-(lb|!QW?eWYT008CH z*>Lu7aj^4su>b$za6k{n&vj)uwoNp2X!wa=A9AmDdz5o9Krs>e1)NHSw^_@?3_$`& zGB4!ISBQ&Pptsl=6FzsD3z<`Q4w zcR5p7x4f=1WZm-=NO)Am+tKGHvxC^M5`)F|d2x2#AaT9X^$z>nE2NTd_ zi4y5(YJTEDTadHM%OYicME0%p(~xit=Mo-Lqoy1BnR_*{v#y8|e^3#R&n29FrK{F5 zxT-W=J~?4Rp`^(oe)b(dpESjYu{(yN7h*Zf^}0fo8JmIISfN7!*5_BQNG@&i3s`{& z1wa2mqUsi|IDt7GGmbJ8O5dp6n(zfEE^vp0qV|O-%WMIke{vh0Ag`@Bs#rfKsZfzAW$yT5rneHTW>Cy2yEPOJ+aeIeZxszH>7EF1)5uhw2RzH7ns}Le=he)y6O~2K zh0r=qP5TXDu_QsS{(iRG50;^NVi^Wo=2RcV4Q-NX=<6qEovfWB7O*7g4Asj^wrbw6 zdO8UrJ@<7~1G*wvtqY+Q&VK5?OL4NuS;hqKMN`^KagQR5dk{cdOUL)pkJ-KIkw6>vPHqXGpQICb) zFgw;I4yx2G4a+m1HuE{0>4po_*@+ZYL{-sONuKf(P#C3ihIYn1P7HtHM-l27GxyMY zA(2&65hD6yT+9FYnw3XOkqE>Buh{yz=F68d(Mobu&&ueUK6n6&vW9sC5f)?hd@oj| zQxn`UY0TxPt&^Dcx!Kfea|o~aTkmlvMVg`fbB6Lr+Q%|GTPM_K3 zQRNTBE;~r^d525vv{RW!zUXKP z@p}}h^v0<65V?HZxqmians9kI?}wKZiz>uB9iZs8O6V^f@@+!})R@{Z}}-YwKLGZMG*Yqo$lr7b>EBE$=BWOuXnl=+Oj{_728%C>v_(I z5C`v8&kK>qhH<29wP*ikE3(sc}&vo-J-6vM?c)|e}juz$|~%=P

D!ZL=zW(q`1{m6XT+)r{_ z9-h0|x2RkO(@mGylyQ>QLzF-6Ook!4oZl(t6`b~^so8X0&y3$C^DUuV%~Z96D`MSBdjW>ZLv9aX~;iMJ0kG+@^QV>Im zL;RV|xojtIV_U;(Tlow!KIC|x_}T9oY@`gs5aC-28XknFv)^VyB4c$LM0jRmfZDg- zk3BIn6|xMV=^yJ~LJWnBf3xpGu7p2K>;*&|prQgfvEEo#4_@k<2+yac&Bv_c%(!)iJ z8LG@f7UiuTyFFn{jYq0KY!EkUJ)?QrY?^7*JSMV6@9 zLLi2E;2b%=Qjh)0G85J zrdprbSieNYJQqt+zL%rh<3JW3>gB#%e`q<=cG3Qve-rNuRZ?6pimE8jr*_fuW(8`e z%E}U15##_y?NIAX-6TnDcuhD9qM+S9dOc#L(0R5q_{Q^Vg=^MsCD-Dyth*1^_ofJG zUaIB|VcVg}vqWO+@dC-o@1%1EHxQ_#Yqp%%XJ31m*93DD8Ws}ko(V}~jtUFlcvHS$ zUM}(HeWso9!?2}?5o;k{>I*iIx)N^bO;KkZG^btgs$TB%*5`)a~#oq-^klVgOd9JCUTj@@8rJ| z3R|`hk{=^En!ee9~p;=P~_om!N1Q3^Ulc zDpy&`S^MrDm->TNYw&Tz?UXgz;I-iOeag0l`v%O}Ps)v*-eSQ9=cJ`o==l(ej0Z*} zY}_BP&u)80GH4DSNAb`+5nTd*#=M|4iMf3{(aIu1~hv=1D!wv|+|~x?G?Y*S6(JsK!#KdpB2Fda(Q0xQZ|ZpEOp?pV;s`AP}grYlvW+jP}C}Afo=sZ^Q-LB z;(i#OhPLB9aqewPl(w%adH6E9vCDSO%qn#3-a?)*`vpAV!uS(Qz^&s!3Aqxz9!exR zS&BH z^vx=NEvT&=l49$7Lepg$>hoX~uC(R?YKv@QqKhZg`Bb|LN{V>&d3(teI=3a3!FsK) zt(J9NV7v7JS&0dfnP3aK2YI)yBkO)WX^`4ekfy)*PHn$W%@989>q&R-3egH=h1E|R zmscX8J1)DrWXLh_8 zTu@g9b*$^;8X|*@qB@JUOmM^%bzX@sB@l?}$Osaow#hugU@Ewg2Z_cst>nJJ5KXAr zfZy0`=bl5N@4z}j=;^d@Jf5Ip>^cYs-Xo>qR(|WX-<;Cwe9F3&f7%wgA+w67QHBIEQy|FpTHsR5F zirLaqHSW1V7Zm8Qp~~!z(;dj_As5+SQ;VYr?mmo4ol>P+h;E5q#2|-tOncq-vNRTt zoQDxKWw|kd(;yk!?!zz(5e+3ZV?$S_`)cPtCre9r^E#w;k(+eyhbVZ~qKJOPXO%z( zt6WLRLX$|36t)m~1H#daVuOBLuXjc{5Uf&k@O+(!%dMc<@9gs)7>xoyFh`1VNuHQm z4ulQRU(>tW33dc`zB_x0i+$tO**G*&)19U3;x%h6_IV1tXLhx{Xi!8ky_N4!bMX!f zlz+Iba#@tWqp&NjIxxbZ>D~I1n~u6vA{(~KoHa1rl=M-hPh%S@f}A}e(cfQ-3BAc4 zuu8tzV{AcsZ|J=6X_4h_Cb7mCL@=H!Xj3AHGGRNhWH)$YlwY08o7&8O?zLS_!Bekd z8EIRn6TX9rUG@ z#x2bM)d5ld(*_X(e#rg2ywV6^{oM#%$&P;`|5qRMHxk`A0P4e3t|G6rLumdVnxS9$ zzgHN)@{iDe^Pfllwa`Gr|4?T93jci%{41Oo-I)9b{+}H&n*N8~@UQgWllrgpKAbD` zUvoPe{)f!|EByC-@GHC;y)pRDqyL*0(CD9O;WtUK&_M$Lz()Vr(6t^0I&uI2{|9SI B=e+;` literal 0 HcmV?d00001 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... + + + + + +
+ + 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 +
  • +
+
+
+
+
+ + +
+
+
+
+

AITBC Wallet

+

+ The secure browser wallet for AITBC tokens +

+
+
+

Quick Links

+ +
+
+

Support

+

+ Need help? Check our documentation or create an issue on GitHub. +

+
+
+
+

© 2025 AITBC. All rights reserved.

+
+
+
+ + + + diff --git a/website/extensions/aitbc-wallet-firefox.zip b/website/extensions/aitbc-wallet-firefox.zip new file mode 100644 index 0000000000000000000000000000000000000000..69154c244f62036bf433cdebce3fc71b7814fea8 GIT binary patch literal 6968 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 MZ~MJ-t^Y#(A8yhm$p8QV literal 0 HcmV?d00001 diff --git a/website/extensions/aitbc-wallet.zip b/website/extensions/aitbc-wallet.zip new file mode 100644 index 0000000000000000000000000000000000000000..ec7150b2aa895358f3391f0c59068cf622a8dc95 GIT binary patch literal 5182 zcmZ{obyQUA-^E85T96uP=|+a`knXM_C8c8km5@%6lpYWmV5B6Z1O_BTLPS!KP&$V$ z1r*-#-utfWMSo}3bJqFieCDjRzx$m1Y+VgZAU@#dQ4e`${@2AnCqe)%z{c6v*6#L0 z8#gxxU$BuO9stuvU*Fjpz3%%F0ImVoF#&+TPP%9eIr>IiKsg#CZ(ZqQdJO>B#sC1Q zuVUP7Je==2`1ta=_;`B!#r(fQ9WY%=?Nk1N_pS#jouv(F z?`?t7S1rfgY_K5&Mr%;1K*Q-ON(a8e6I`PTYT{qbnt>Uy+xpCL0q!J$=Ea<3ko{un zayjclz!`;9U|GK@9Qva!6?L<*7?BFYf_y=K483iMO51rW%H4Z|EG$m1p zpEr&kJh6jhGf?_+ekQ`Zb7?NI>#!k{G_EXZ=u~3ENbs?h`>pwptL(YpTTl}`;BN1h z#5u;lVpX8Uvd>_+Gk_M00SEw4ToudC)5F)ngT$mzPo{z&JrJa>sOQ3 zwq&5uMq6o&K319jLmOuj75lBpp5$rM8AgWnkU5iHJjP1!Mc@0J{bhfFuqb1qbj*PS z9y+&%uv2fJwonyg@^!%6MqRpD!lFB(smLg|V-43yldZ-O+(*|$3-`c1M6#-`)XQ>D z5lN@HI!LBa;SN?v_dlOy@W}%C&A!#cjD5^X#874$ zmxj|9#fa~ZUIf->EY{Q@o_zB)+wFY0Hm;9nS)v)cmB2zR0~5nPa{3-bFU540$<%3X z^a!v-%ej^x*CJ5h3L=+CoRv4=Xo#H0ZNFC+s@73Z5#O@e;Rp#A&uB>^U0B43RuL=* zodyR4dif<2`|93Vj(X-(lb|!QW?eWYT008CH z*>Lu7aj^4su>b$za6k{n&vj)uwoNp2X!wa=A9AmDdz5o9Krs>e1)NHSw^_@?3_$`& zGB4!ISBQ&Pptsl=6FzsD3z<`Q4w zcR5p7x4f=1WZm-=NO)Am+tKGHvxC^M5`)F|d2x2#AaT9X^$z>nE2NTd_ zi4y5(YJTEDTadHM%OYicME0%p(~xit=Mo-Lqoy1BnR_*{v#y8|e^3#R&n29FrK{F5 zxT-W=J~?4Rp`^(oe)b(dpESjYu{(yN7h*Zf^}0fo8JmIISfN7!*5_BQNG@&i3s`{& z1wa2mqUsi|IDt7GGmbJ8O5dp6n(zfEE^vp0qV|O-%WMIke{vh0Ag`@Bs#rfKsZfzAW$yT5rneHTW>Cy2yEPOJ+aeIeZxszH>7EF1)5uhw2RzH7ns}Le=he)y6O~2K zh0r=qP5TXDu_QsS{(iRG50;^NVi^Wo=2RcV4Q-NX=<6qEovfWB7O*7g4Asj^wrbw6 zdO8UrJ@<7~1G*wvtqY+Q&VK5?OL4NuS;hqKMN`^KagQR5dk{cdOUL)pkJ-KIkw6>vPHqXGpQICb) zFgw;I4yx2G4a+m1HuE{0>4po_*@+ZYL{-sONuKf(P#C3ihIYn1P7HtHM-l27GxyMY zA(2&65hD6yT+9FYnw3XOkqE>Buh{yz=F68d(Mobu&&ueUK6n6&vW9sC5f)?hd@oj| zQxn`UY0TxPt&^Dcx!Kfea|o~aTkmlvMVg`fbB6Lr+Q%|GTPM_K3 zQRNTBE;~r^d525vv{RW!zUXKP z@p}}h^v0<65V?HZxqmians9kI?}wKZiz>uB9iZs8O6V^f@@+!})R@{Z}}-YwKLGZMG*Yqo$lr7b>EBE$=BWOuXnl=+Oj{_728%C>v_(I z5C`v8&kK>qhH<29wP*ikE3(sc}&vo-J-6vM?c)|e}juz$|~%=P

D!ZL=zW(q`1{m6XT+)r{_ z9-h0|x2RkO(@mGylyQ>QLzF-6Ook!4oZl(t6`b~^so8X0&y3$C^DUuV%~Z96D`MSBdjW>ZLv9aX~;iMJ0kG+@^QV>Im zL;RV|xojtIV_U;(Tlow!KIC|x_}T9oY@`gs5aC-28XknFv)^VyB4c$LM0jRmfZDg- zk3BIn6|xMV=^yJ~LJWnBf3xpGu7p2K>;*&|prQgfvEEo#4_@k<2+yac&Bv_c%(!)iJ z8LG@f7UiuTyFFn{jYq0KY!EkUJ)?QrY?^7*JSMV6@9 zLLi2E;2b%=Qjh)0G85J zrdprbSieNYJQqt+zL%rh<3JW3>gB#%e`q<=cG3Qve-rNuRZ?6pimE8jr*_fuW(8`e z%E}U15##_y?NIAX-6TnDcuhD9qM+S9dOc#L(0R5q_{Q^Vg=^MsCD-Dyth*1^_ofJG zUaIB|VcVg}vqWO+@dC-o@1%1EHxQ_#Yqp%%XJ31m*93DD8Ws}ko(V}~jtUFlcvHS$ zUM}(HeWso9!?2}?5o;k{>I*iIx)N^bO;KkZG^btgs$TB%*5`)a~#oq-^klVgOd9JCUTj@@8rJ| z3R|`hk{=^En!ee9~p;=P~_om!N1Q3^Ulc zDpy&`S^MrDm->TNYw&Tz?UXgz;I-iOeag0l`v%O}Ps)v*-eSQ9=cJ`o==l(ej0Z*} zY}_BP&u)80GH4DSNAb`+5nTd*#=M|4iMf3{(aIu1~hv=1D!wv|+|~x?G?Y*S6(JsK!#KdpB2Fda(Q0xQZ|ZpEOp?pV;s`AP}grYlvW+jP}C}Afo=sZ^Q-LB z;(i#OhPLB9aqewPl(w%adH6E9vCDSO%qn#3-a?)*`vpAV!uS(Qz^&s!3Aqxz9!exR zS&BH z^vx=NEvT&=l49$7Lepg$>hoX~uC(R?YKv@QqKhZg`Bb|LN{V>&d3(teI=3a3!FsK) zt(J9NV7v7JS&0dfnP3aK2YI)yBkO)WX^`4ekfy)*PHn$W%@989>q&R-3egH=h1E|R zmscX8J1)DrWXLh_8 zTu@g9b*$^;8X|*@qB@JUOmM^%bzX@sB@l?}$Osaow#hugU@Ewg2Z_cst>nJJ5KXAr zfZy0`=bl5N@4z}j=;^d@Jf5Ip>^cYs-Xo>qR(|WX-<;Cwe9F3&f7%wgA+w67QHBIEQy|FpTHsR5F zirLaqHSW1V7Zm8Qp~~!z(;dj_As5+SQ;VYr?mmo4ol>P+h;E5q#2|-tOncq-vNRTt zoQDxKWw|kd(;yk!?!zz(5e+3ZV?$S_`)cPtCre9r^E#w;k(+eyhbVZ~qKJOPXO%z( zt6WLRLX$|36t)m~1H#daVuOBLuXjc{5Uf&k@O+(!%dMc<@9gs)7>xoyFh`1VNuHQm z4ulQRU(>tW33dc`zB_x0i+$tO**G*&)19U3;x%h6_IV1tXLhx{Xi!8ky_N4!bMX!f zlz+Iba#@tWqp&NjIxxbZ>D~I1n~u6vA{(~KoHa1rl=M-hPh%S@f}A}e(cfQ-3BAc4 zuu8tzV{AcsZ|J=6X_4h_Cb7mCL@=H!Xj3AHGGRNhWH)$YlwY08o7&8O?zLS_!Bekd z8EIRn6TX9rUG@ z#x2bM)d5ld(*_X(e#rg2ywV6^{oM#%$&P;`|5qRMHxk`A0P4e3t|G6rLumdVnxS9$ zzgHN)@{iDe^Pfllwa`Gr|4?T93jci%{41Oo-I)9b{+}H&n*N8~@UQgWllrgpKAbD` zUvoPe{)f!|EByC-@GHC;y)pRDqyL*0(CD9O;WtUK&_M$Lz()Vr(6t^0I&uI2{|9SI B=e+;` literal 0 HcmV?d00001