From 06a7ec9424d12bcbb7fc580f6ff130f340edc124 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Thu, 20 Nov 2025 19:52:48 +0300 Subject: [PATCH] feat(frontend): align wUSDT Asset ID with SDK (1000) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit aligns the frontend wUSDT implementation with the SDK runtime constants, ensuring consistency across the entire stack. Changes: - Update ASSET_IDS.WUSDT from 2 → 1000 (matches SDK constants) - Add ASSET_CONFIGS with wUSDT configuration (6 decimals, min balance) - Update all asset queries in AccountBalance.tsx to use ASSET_IDS.WUSDT - Update pool queries for wHEZ/wUSDT and PEZ/wUSDT pools - Update USDTBridge.tsx burn transaction to use ASSET_IDS.WUSDT - Refactor usdt.ts to reference ASSET_CONFIGS instead of hardcoded values Asset ID Allocation Strategy: - 0-999: Reserved for protocol tokens (wHEZ, PEZ, etc.) - 1000+: Bridged/wrapped external assets (wUSDT, etc.) Technical Details: - wUSDT uses 6 decimals (USDT standard), not 12 like native HEZ - All frontend code now uses centralized ASSET_CONFIGS - ESLint passes with 0 errors (8 pre-existing warnings unrelated to changes) This is part of Phase 1 wUSDT infrastructure setup, working in parallel with SDK benchmarking builds currently running in background. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- shared/lib/usdt.ts | 6 ++--- shared/lib/wallet.ts | 33 ++++++++++++++++++++++++++- web/src/components/AccountBalance.tsx | 16 ++++++------- web/src/components/USDTBridge.tsx | 3 ++- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/shared/lib/usdt.ts b/shared/lib/usdt.ts index 1d27a53b..058f09f6 100644 --- a/shared/lib/usdt.ts +++ b/shared/lib/usdt.ts @@ -4,15 +4,15 @@ // Handles wUSDT minting, burning, and reserve management import type { ApiPromise } from '@polkadot/api'; -import { ASSET_IDS } from './wallet'; +import { ASSET_IDS, ASSET_CONFIGS } from './wallet'; import { getMultisigMembers, createMultisigTx } from './multisig'; // ======================================== // CONSTANTS // ======================================== -export const WUSDT_ASSET_ID = ASSET_IDS.WUSDT; -export const WUSDT_DECIMALS = 6; // USDT has 6 decimals +export const WUSDT_ASSET_ID = ASSET_CONFIGS.WUSDT.id; +export const WUSDT_DECIMALS = ASSET_CONFIGS.WUSDT.decimals; // Withdrawal limits and timeouts export const WITHDRAWAL_LIMITS = { diff --git a/shared/lib/wallet.ts b/shared/lib/wallet.ts index e012876b..c15d9d4b 100644 --- a/shared/lib/wallet.ts +++ b/shared/lib/wallet.ts @@ -31,16 +31,47 @@ export const CHAIN_CONFIG = { // ======================================== // ⚠️ IMPORTANT: HEZ is the native token and does NOT have an Asset ID // Only wrapped/asset tokens are listed here +// +// Asset ID Allocation: +// - 0-999: Reserved for protocol tokens (wHEZ, PEZ, etc.) +// - 1000+: Bridged/wrapped external assets (wUSDT, etc.) export const ASSET_IDS = { WHEZ: parseInt(import.meta.env.VITE_ASSET_WHEZ || '0'), // Wrapped HEZ PEZ: parseInt(import.meta.env.VITE_ASSET_PEZ || '1'), // PEZ utility token - WUSDT: parseInt(import.meta.env.VITE_ASSET_WUSDT || '2'), // Wrapped USDT (multisig backed) + WUSDT: parseInt(import.meta.env.VITE_ASSET_WUSDT || '1000'), // Wrapped USDT (6 decimals, matches SDK) 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; +// ======================================== +// ASSET CONFIGURATIONS +// ======================================== +export const ASSET_CONFIGS = { + WHEZ: { + id: ASSET_IDS.WHEZ, + symbol: 'wHEZ', + name: 'Wrapped HEZ', + decimals: 12, + minBalance: 1_000_000_000, // 0.001 HEZ + }, + PEZ: { + id: ASSET_IDS.PEZ, + symbol: 'PEZ', + name: 'PEZ Utility Token', + decimals: 12, + minBalance: 1_000_000_000, // 0.001 PEZ + }, + WUSDT: { + id: ASSET_IDS.WUSDT, + symbol: 'wUSDT', + name: 'Wrapped USDT', + decimals: 6, // ⚠️ CRITICAL: wUSDT uses 6 decimals (USDT standard), not 12! + minBalance: 1_000, // 0.001 USDT + }, +} as const; + // ======================================== // EXPLORER URLS // ======================================== diff --git a/web/src/components/AccountBalance.tsx b/web/src/components/AccountBalance.tsx index c33f94f9..f4bea319 100644 --- a/web/src/components/AccountBalance.tsx +++ b/web/src/components/AccountBalance.tsx @@ -89,15 +89,15 @@ export const AccountBalance: React.FC = () => { const { blake2AsU8a } = await import('@polkadot/util-crypto'); const PALLET_ID = stringToU8a('py/ascon'); - // Fetch wHEZ/wUSDT pool reserves (Asset 0 / Asset 2) - const whezPoolId = api.createType('(u32, u32)', [0, 2]); + // Fetch wHEZ/wUSDT pool reserves (Asset 0 / Asset 1000) + const whezPoolId = api.createType('(u32, u32)', [0, ASSET_IDS.WUSDT]); const whezPalletIdType = api.createType('[u8; 8]', PALLET_ID); const whezFullTuple = api.createType('([u8; 8], (u32, u32))', [whezPalletIdType, whezPoolId]); const whezAccountHash = blake2AsU8a(whezFullTuple.toU8a(), 256); const whezPoolAccountId = api.createType('AccountId32', whezAccountHash); const whezReserve0Query = await api.query.assets.account(0, whezPoolAccountId); - const whezReserve1Query = await api.query.assets.account(2, whezPoolAccountId); + const whezReserve1Query = await api.query.assets.account(ASSET_IDS.WUSDT, whezPoolAccountId); if (whezReserve0Query.isSome && whezReserve1Query.isSome) { const reserve0Data = whezReserve0Query.unwrap(); @@ -114,15 +114,15 @@ export const AccountBalance: React.FC = () => { if (import.meta.env.DEV) console.warn('⚠️ wHEZ/wUSDT pool has no reserves'); } - // Fetch PEZ/wUSDT pool reserves (Asset 1 / Asset 2) - const pezPoolId = api.createType('(u32, u32)', [1, 2]); + // Fetch PEZ/wUSDT pool reserves (Asset 1 / Asset 1000) + const pezPoolId = api.createType('(u32, u32)', [1, ASSET_IDS.WUSDT]); const pezPalletIdType = api.createType('[u8; 8]', PALLET_ID); const pezFullTuple = api.createType('([u8; 8], (u32, u32))', [pezPalletIdType, pezPoolId]); const pezAccountHash = blake2AsU8a(pezFullTuple.toU8a(), 256); const pezPoolAccountId = api.createType('AccountId32', pezAccountHash); const pezReserve0Query = await api.query.assets.account(1, pezPoolAccountId); - const pezReserve1Query = await api.query.assets.account(2, pezPoolAccountId); + const pezReserve1Query = await api.query.assets.account(ASSET_IDS.WUSDT, pezPoolAccountId); if (pezReserve0Query.isSome && pezReserve1Query.isSome) { const reserve0Data = pezReserve0Query.unwrap(); @@ -262,9 +262,9 @@ export const AccountBalance: React.FC = () => { setPezBalance('0'); } - // Fetch USDT balance (wUSDT - Asset ID: 2) + // Fetch USDT balance (wUSDT - Asset ID: 1000) try { - const usdtAssetBalance = await api.query.assets.account(2, selectedAccount.address); + const usdtAssetBalance = await api.query.assets.account(ASSET_IDS.WUSDT, selectedAccount.address); if (usdtAssetBalance.isSome) { const assetData = usdtAssetBalance.unwrap(); diff --git a/web/src/components/USDTBridge.tsx b/web/src/components/USDTBridge.tsx index c56cd145..aa6d2062 100644 --- a/web/src/components/USDTBridge.tsx +++ b/web/src/components/USDTBridge.tsx @@ -15,6 +15,7 @@ import { formatWUSDT, } from '@pezkuwi/lib/usdt'; import { isMultisigMember } from '@pezkuwi/lib/multisig'; +import { ASSET_IDS } from '@pezkuwi/lib/wallet'; interface USDTBridgeProps { isOpen: boolean; @@ -115,7 +116,7 @@ export const USDTBridge: React.FC = ({ // Burn wUSDT const amountBN = BigInt(Math.floor(amount * 1e6)); // 6 decimals - const burnTx = api.tx.assets.burn(2, selectedAccount.address, amountBN.toString()); + const burnTx = api.tx.assets.burn(ASSET_IDS.WUSDT, selectedAccount.address, amountBN.toString()); await burnTx.signAndSend(selectedAccount.address, { signer: injector.signer }, ({ status }) => { if (status.isFinalized) {