mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-22 02:07:55 +00:00
fix: DEX improvements - Asset Hub balance fetching and Treasury admin support
- WalletContext: Use Asset Hub API for PEZ/wHEZ/wUSDT balance queries - AddLiquidityModal: Handle native token balance via system.account - auth.ts: Add Treasury accounts to admin list for pool creation and minting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+19
-4
@@ -8,11 +8,20 @@
|
||||
export const FOUNDER_ADDRESS_FALLBACK = '5GgTgG9sRmPQAYU1RsTejZYnZRjwzKZKWD3awtuqjHioki45';
|
||||
|
||||
/**
|
||||
* Check if given address is the sudo account (admin/founder)
|
||||
* SECURITY: Only allows admin access when connected to blockchain with valid sudo key
|
||||
* Treasury and admin accounts that have elevated permissions
|
||||
* These accounts can perform admin operations like creating pools, minting tokens, etc.
|
||||
*/
|
||||
export const TREASURY_ADDRESSES = [
|
||||
'5EhCpn82QtdU53MF6PoNFrKHgSrsfcAxFTMwrn3JYf9dioQw', // Treasury 1 - wUSDT issuer/admin
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Check if given address is the sudo account (admin/founder) or a treasury account
|
||||
* SECURITY: Only allows admin access when connected to blockchain with valid sudo key,
|
||||
* or if the address is a known treasury account
|
||||
* @param address - Substrate address to check
|
||||
* @param sudoKey - Sudo key fetched from blockchain (REQUIRED for admin access)
|
||||
* @returns true if address matches sudo key from blockchain
|
||||
* @returns true if address matches sudo key from blockchain or is a treasury account
|
||||
*/
|
||||
export const isFounderWallet = (
|
||||
address: string | null | undefined,
|
||||
@@ -20,6 +29,11 @@ export const isFounderWallet = (
|
||||
): boolean => {
|
||||
if (!address) return false;
|
||||
|
||||
// Check if address is a known treasury account
|
||||
if (TREASURY_ADDRESSES.includes(address as typeof TREASURY_ADDRESSES[number])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// SECURITY FIX: ONLY use dynamic sudo key from blockchain
|
||||
// No fallback to hardcoded address - admin access requires active blockchain connection
|
||||
if (!sudoKey || sudoKey === '') {
|
||||
@@ -99,6 +113,7 @@ export const getUserRole = (
|
||||
sudoKey?: string | null
|
||||
): string => {
|
||||
if (!address) return 'Guest';
|
||||
if (isFounderWallet(address, sudoKey)) return 'Sudo (Admin)';
|
||||
if (address === sudoKey) return 'Sudo (Admin)';
|
||||
if (TREASURY_ADDRESSES.includes(address as typeof TREASURY_ADDRESSES[number])) return 'Treasury (Admin)';
|
||||
return 'User';
|
||||
};
|
||||
|
||||
@@ -61,11 +61,23 @@ export const AddLiquidityModal: React.FC<AddLiquidityModalProps> = ({
|
||||
if (!assetHubApi || !isAssetHubReady || !account || !pool) return;
|
||||
|
||||
try {
|
||||
const balance1Data = await assetHubApi.query.assets.account(pool.asset1, account);
|
||||
const balance2Data = await assetHubApi.query.assets.account(pool.asset2, account);
|
||||
// Fetch balance for asset1 - handle native token differently
|
||||
if (pool.asset1 === NATIVE_TOKEN_ID) {
|
||||
const accountInfo = await assetHubApi.query.system.account(account);
|
||||
setBalance1(accountInfo.data.free.toString());
|
||||
} else {
|
||||
const balance1Data = await assetHubApi.query.assets.account(pool.asset1, account);
|
||||
setBalance1(balance1Data.isSome ? balance1Data.unwrap().balance.toString() : '0');
|
||||
}
|
||||
|
||||
setBalance1(balance1Data.isSome ? balance1Data.unwrap().balance.toString() : '0');
|
||||
setBalance2(balance2Data.isSome ? balance2Data.unwrap().balance.toString() : '0');
|
||||
// Fetch balance for asset2 - handle native token differently
|
||||
if (pool.asset2 === NATIVE_TOKEN_ID) {
|
||||
const accountInfo = await assetHubApi.query.system.account(account);
|
||||
setBalance2(accountInfo.data.free.toString());
|
||||
} else {
|
||||
const balance2Data = await assetHubApi.query.assets.account(pool.asset2, account);
|
||||
setBalance2(balance2Data.isSome ? balance2Data.unwrap().balance.toString() : '0');
|
||||
}
|
||||
} catch (error) {
|
||||
if (import.meta.env.DEV) console.error('Failed to fetch balances:', error);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
const [signer, setSigner] = useState<Signer | null>(null);
|
||||
|
||||
// Fetch all token balances when account changes
|
||||
// Uses relay chain API for native HEZ, Asset Hub API for PEZ/wHEZ/wUSDT
|
||||
const updateBalance = useCallback(async (address: string) => {
|
||||
if (!pezkuwi.api || !pezkuwi.isApiReady) {
|
||||
if (import.meta.env.DEV) console.warn('API not ready, cannot fetch balance');
|
||||
@@ -62,15 +63,25 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
try {
|
||||
if (import.meta.env.DEV) console.log('💰 Fetching all token balances for:', address);
|
||||
|
||||
// Fetch HEZ (native token)
|
||||
// Fetch HEZ (native token) from relay chain
|
||||
const { data: nativeBalance } = await pezkuwi.api.query.system.account(address);
|
||||
const hezBalance = formatBalance(nativeBalance.free.toString());
|
||||
setBalance(hezBalance); // Legacy support
|
||||
|
||||
// Fetch PEZ (Asset ID: 1)
|
||||
// For assets (PEZ, wHEZ, wUSDT), use Asset Hub API since they're on Asset Hub
|
||||
// Fall back to relay chain API if Asset Hub not ready (some chains have assets on relay)
|
||||
const assetApi = pezkuwi.assetHubApi && pezkuwi.isAssetHubReady
|
||||
? pezkuwi.assetHubApi
|
||||
: pezkuwi.api;
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log('📊 Using API for assets:', pezkuwi.assetHubApi && pezkuwi.isAssetHubReady ? 'Asset Hub' : 'Relay Chain');
|
||||
}
|
||||
|
||||
// Fetch PEZ (Asset ID: 1) from Asset Hub
|
||||
let pezBalance = '0';
|
||||
try {
|
||||
const pezData = await pezkuwi.api.query.assets.account(ASSET_IDS.PEZ, address);
|
||||
const pezData = await assetApi.query.assets.account(ASSET_IDS.PEZ, address);
|
||||
if (import.meta.env.DEV) console.log('📊 Raw PEZ data:', pezData.toHuman());
|
||||
|
||||
if (pezData.isSome) {
|
||||
@@ -85,10 +96,10 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
if (import.meta.env.DEV) console.error('❌ Failed to fetch PEZ balance:', err);
|
||||
}
|
||||
|
||||
// Fetch wHEZ (Asset ID: 0)
|
||||
// Fetch wHEZ (Asset ID: 2) from Asset Hub
|
||||
let whezBalance = '0';
|
||||
try {
|
||||
const whezData = await pezkuwi.api.query.assets.account(ASSET_IDS.WHEZ, address);
|
||||
const whezData = await assetApi.query.assets.account(ASSET_IDS.WHEZ, address);
|
||||
if (import.meta.env.DEV) console.log('📊 Raw wHEZ data:', whezData.toHuman());
|
||||
|
||||
if (whezData.isSome) {
|
||||
@@ -103,10 +114,10 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
if (import.meta.env.DEV) console.error('❌ Failed to fetch wHEZ balance:', err);
|
||||
}
|
||||
|
||||
// Fetch wUSDT (Asset ID: 2) - IMPORTANT: wUSDT has 6 decimals, not 12!
|
||||
// Fetch wUSDT (Asset ID: 1000) from Asset Hub - IMPORTANT: wUSDT has 6 decimals, not 12!
|
||||
let wusdtBalance = '0';
|
||||
try {
|
||||
const wusdtData = await pezkuwi.api.query.assets.account(ASSET_IDS.WUSDT, address);
|
||||
const wusdtData = await assetApi.query.assets.account(ASSET_IDS.WUSDT, address);
|
||||
if (import.meta.env.DEV) console.log('📊 Raw wUSDT data:', wusdtData.toHuman());
|
||||
|
||||
if (wusdtData.isSome) {
|
||||
@@ -133,7 +144,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
if (import.meta.env.DEV) console.error('Failed to fetch balances:', err);
|
||||
setError('Failed to fetch balances');
|
||||
}
|
||||
}, [pezkuwi.api, pezkuwi.isApiReady]);
|
||||
}, [pezkuwi.api, pezkuwi.isApiReady, pezkuwi.assetHubApi, pezkuwi.isAssetHubReady]);
|
||||
|
||||
// Connect wallet (Pezkuwi.js extension)
|
||||
const connectWallet = useCallback(async () => {
|
||||
@@ -268,18 +279,19 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr
|
||||
getSigner();
|
||||
}, [pezkuwi.selectedAccount]);
|
||||
|
||||
// Update balance when selected account changes
|
||||
// Update balance when selected account changes or Asset Hub becomes ready
|
||||
useEffect(() => {
|
||||
if (import.meta.env.DEV) console.log('🔄 WalletContext useEffect triggered!', {
|
||||
hasAccount: !!pezkuwi.selectedAccount,
|
||||
isApiReady: pezkuwi.isApiReady,
|
||||
isAssetHubReady: pezkuwi.isAssetHubReady,
|
||||
address: pezkuwi.selectedAccount?.address
|
||||
});
|
||||
|
||||
if (pezkuwi.selectedAccount && pezkuwi.isApiReady) {
|
||||
updateBalance(pezkuwi.selectedAccount.address);
|
||||
}
|
||||
}, [pezkuwi.selectedAccount, pezkuwi.isApiReady, updateBalance]);
|
||||
}, [pezkuwi.selectedAccount, pezkuwi.isApiReady, pezkuwi.isAssetHubReady, updateBalance]);
|
||||
|
||||
// Sync error state with PezkuwiContext
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user