mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-29 14:37:56 +00:00
feat: Add comprehensive GitHub security integration
Security Infrastructure: - Add .gitattributes for merge conflict protection and sensitive file handling - Add SECURITY.md with detailed security policies and procedures - Add pre-commit hook template for local secret detection - Add GitHub Actions workflow for automated security scanning - Add comprehensive documentation for git hooks Code Security Improvements: - Fix AuthContext.tsx: Remove hardcoded credentials, use environment variables - Migrate WalletContext.tsx: Replace Ethereum/MetaMask with Polkadot.js - Refactor lib/wallet.ts: Complete Substrate configuration with asset management - Update TokenSwap.tsx: Add real API integration for balance queries - Update StakingDashboard.tsx: Add blockchain integration placeholders Environment Management: - Update .env with proper security warnings - Update .env.example with comprehensive template - All sensitive data now uses environment variables - Demo mode controllable via VITE_ENABLE_DEMO_MODE flag Security Measures Implemented: ✅ 4-layer protection (gitignore + gitattributes + pre-commit + CI/CD) ✅ Automated secret scanning (TruffleHog + Gitleaks) ✅ Pre-commit hooks prevent accidental commits ✅ CI/CD pipeline validates all PRs ✅ Environment variable validation ✅ Dependency security auditing Breaking Changes: - WalletContext now uses Polkadot.js instead of MetaMask - lib/wallet.ts completely rewritten for Substrate - ASSET_IDs and CHAIN_CONFIG exported from lib/wallet.ts - Demo mode must be explicitly enabled Migration Notes: - Install pre-commit hook: cp .git-hooks/pre-commit.example .git/hooks/pre-commit - Copy environment: cp .env.example .env - Update .env with your credentials - Enable GitHub Actions in repository settings Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+7
-5
@@ -1,11 +1,13 @@
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
// Initialize Supabase client from environment variables
|
||||
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
|
||||
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
|
||||
|
||||
if (!supabaseUrl || !supabaseKey) {
|
||||
console.warn('Supabase credentials not found in environment variables');
|
||||
}
|
||||
|
||||
// Initialize Supabase client
|
||||
// Using direct values from project configuration
|
||||
const supabaseUrl = 'https://vbhftvdayqfmcgmzdxfv.supabase.co';
|
||||
const supabaseKey = 'sb_publishable_Aq6cShprdtxYyUsohmsquQ_OurU7w07';
|
||||
const supabase = createClient(supabaseUrl, supabaseKey);
|
||||
|
||||
|
||||
export { supabase };
|
||||
+114
-26
@@ -1,49 +1,137 @@
|
||||
// Wallet configuration and utilities for PezkuwiChain
|
||||
export const PEZKUWICHAIN_NETWORK = {
|
||||
chainId: '0x2329', // 9001 in hex
|
||||
chainName: 'PezkuwiChain',
|
||||
nativeCurrency: {
|
||||
name: 'Pezkuwi',
|
||||
symbol: 'PZK',
|
||||
decimals: 18
|
||||
},
|
||||
rpcUrls: ['https://rpc.pezkuwichain.app'],
|
||||
blockExplorerUrls: ['https://explorer.pezkuwichain.app']
|
||||
// ========================================
|
||||
// PezkuwiChain - Substrate/Polkadot.js Configuration
|
||||
// ========================================
|
||||
// This file configures wallet connectivity for Substrate-based chains
|
||||
|
||||
import type { InjectedAccountWithMeta } from '@polkadot/extension-inject/types';
|
||||
|
||||
// ========================================
|
||||
// NETWORK ENDPOINTS
|
||||
// ========================================
|
||||
export const NETWORK_ENDPOINTS = {
|
||||
local: import.meta.env.VITE_DEVELOPMENT_WS || 'ws://127.0.0.1:9944',
|
||||
testnet: import.meta.env.VITE_TESTNET_WS || 'wss://testnet.pezkuwichain.io',
|
||||
mainnet: import.meta.env.VITE_MAINNET_WS || 'wss://mainnet.pezkuwichain.io',
|
||||
staging: import.meta.env.VITE_STAGING_WS || 'wss://staging.pezkuwichain.io',
|
||||
beta: import.meta.env.VITE_BETA_WS || 'wss://beta.pezkuwichain.io',
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// CHAIN CONFIGURATION
|
||||
// ========================================
|
||||
export const CHAIN_CONFIG = {
|
||||
name: import.meta.env.VITE_CHAIN_NAME || 'PezkuwiChain',
|
||||
symbol: import.meta.env.VITE_CHAIN_TOKEN_SYMBOL || 'PEZ',
|
||||
decimals: parseInt(import.meta.env.VITE_CHAIN_TOKEN_DECIMALS || '12'),
|
||||
ss58Format: parseInt(import.meta.env.VITE_CHAIN_SS58_FORMAT || '42'),
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// SUBSTRATE ASSET IDs (Assets Pallet)
|
||||
// ========================================
|
||||
export const ASSET_IDS = {
|
||||
PEZ: parseInt(import.meta.env.VITE_ASSET_PEZ || '1'),
|
||||
HEZ: parseInt(import.meta.env.VITE_ASSET_HEZ || '2'),
|
||||
USDT: parseInt(import.meta.env.VITE_ASSET_USDT || '3'),
|
||||
BTC: parseInt(import.meta.env.VITE_ASSET_BTC || '4'),
|
||||
ETH: parseInt(import.meta.env.VITE_ASSET_ETH || '5'),
|
||||
DOT: parseInt(import.meta.env.VITE_ASSET_DOT || '6'),
|
||||
} as const;
|
||||
|
||||
// ========================================
|
||||
// EXPLORER URLS
|
||||
// ========================================
|
||||
export const EXPLORER_URLS = {
|
||||
polkadotJs: import.meta.env.VITE_EXPLORER_URL || 'https://polkadot.js.org/apps/?rpc=',
|
||||
custom: import.meta.env.VITE_CUSTOM_EXPLORER_URL || 'https://explorer.pezkuwichain.io',
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// WALLET ERROR MESSAGES
|
||||
// ========================================
|
||||
export const WALLET_ERRORS = {
|
||||
NO_WALLET: 'No wallet detected. Please install MetaMask or use WalletConnect.',
|
||||
NO_EXTENSION: 'No Polkadot.js extension detected. Please install Polkadot.js or compatible wallet.',
|
||||
NO_ACCOUNTS: 'No accounts found. Please create an account in your wallet extension.',
|
||||
CONNECTION_FAILED: 'Failed to connect wallet. Please try again.',
|
||||
NETWORK_ERROR: 'Failed to switch network. Please add PezkuwiChain manually.',
|
||||
TRANSACTION_FAILED: 'Transaction failed. Please check your balance and try again.',
|
||||
USER_REJECTED: 'User rejected the request.'
|
||||
USER_REJECTED: 'User rejected the request.',
|
||||
INSUFFICIENT_BALANCE: 'Insufficient balance to complete transaction.',
|
||||
INVALID_ADDRESS: 'Invalid address format.',
|
||||
API_NOT_READY: 'Blockchain API not ready. Please wait...',
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// UTILITY FUNCTIONS
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* Format Substrate address for display (SS58 format)
|
||||
* @param address - Full substrate address
|
||||
* @returns Shortened address string (e.g., "5GrwV...xQjz")
|
||||
*/
|
||||
export const formatAddress = (address: string): string => {
|
||||
if (!address) return '';
|
||||
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
||||
};
|
||||
|
||||
export const formatBalance = (balance: string, decimals = 18): string => {
|
||||
/**
|
||||
* Format balance from planck to human-readable format
|
||||
* @param balance - Balance in smallest unit (planck)
|
||||
* @param decimals - Token decimals (default 12 for PEZ)
|
||||
* @returns Formatted balance string
|
||||
*/
|
||||
export const formatBalance = (balance: string | number, decimals = 12): string => {
|
||||
if (!balance) return '0';
|
||||
const value = parseFloat(balance) / Math.pow(10, decimals);
|
||||
return value.toFixed(4);
|
||||
const value = typeof balance === 'string' ? parseFloat(balance) : balance;
|
||||
return (value / Math.pow(10, decimals)).toFixed(4);
|
||||
};
|
||||
|
||||
export interface WalletState {
|
||||
/**
|
||||
* Parse human-readable amount to planck (smallest unit)
|
||||
* @param amount - Human-readable amount
|
||||
* @param decimals - Token decimals
|
||||
* @returns Amount in planck
|
||||
*/
|
||||
export const parseAmount = (amount: string | number, decimals = 12): bigint => {
|
||||
const value = typeof amount === 'string' ? parseFloat(amount) : amount;
|
||||
return BigInt(Math.floor(value * Math.pow(10, decimals)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get asset symbol by ID
|
||||
* @param assetId - Asset ID from Assets pallet
|
||||
* @returns Asset symbol or 'UNKNOWN'
|
||||
*/
|
||||
export const getAssetSymbol = (assetId: number): string => {
|
||||
const entry = Object.entries(ASSET_IDS).find(([_, id]) => id === assetId);
|
||||
return entry ? entry[0] : 'UNKNOWN';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current network endpoint based on VITE_NETWORK env
|
||||
* @returns WebSocket endpoint URL
|
||||
*/
|
||||
export const getCurrentEndpoint = (): string => {
|
||||
const network = import.meta.env.VITE_NETWORK || 'local';
|
||||
return NETWORK_ENDPOINTS[network as keyof typeof NETWORK_ENDPOINTS] || NETWORK_ENDPOINTS.local;
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// TYPE DEFINITIONS
|
||||
// ========================================
|
||||
|
||||
export interface PolkadotWalletState {
|
||||
isConnected: boolean;
|
||||
address: string | null;
|
||||
accounts: InjectedAccountWithMeta[];
|
||||
selectedAccount: InjectedAccountWithMeta | null;
|
||||
balance: string;
|
||||
chainId: string | null;
|
||||
provider: any;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export const initialWalletState: WalletState = {
|
||||
export const initialPolkadotWalletState: PolkadotWalletState = {
|
||||
isConnected: false,
|
||||
address: null,
|
||||
accounts: [],
|
||||
selectedAccount: null,
|
||||
balance: '0',
|
||||
chainId: null,
|
||||
provider: null,
|
||||
error: null
|
||||
error: null,
|
||||
};
|
||||
Reference in New Issue
Block a user