diff --git a/package.json b/package.json index 10531db..5ef5bf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pezkuwi-telegram-miniapp", - "version": "1.0.167", + "version": "1.0.168", "type": "module", "description": "Pezkuwichain Telegram Mini App - Forum, Announcements, Rewards", "author": "Pezkuwichain Team", diff --git a/src/components/wallet/FundFeesModal.tsx b/src/components/wallet/FundFeesModal.tsx index a579235..3638ecc 100644 --- a/src/components/wallet/FundFeesModal.tsx +++ b/src/components/wallet/FundFeesModal.tsx @@ -4,7 +4,16 @@ */ import { useState, useEffect } from 'react'; -import { X, ArrowDown, Loader2, CheckCircle, AlertCircle, Fuel, Info } from 'lucide-react'; +import { + X, + ArrowDown, + ArrowUpDown, + Loader2, + CheckCircle, + AlertCircle, + Fuel, + Info, +} from 'lucide-react'; import { useWallet } from '@/contexts/WalletContext'; import { useTelegram } from '@/hooks/useTelegram'; @@ -45,6 +54,7 @@ export function FundFeesModal({ isOpen, onClose }: Props) { const { hapticImpact, showAlert } = useTelegram(); const [targetChain, setTargetChain] = useState('asset-hub'); + const [toRelay, setToRelay] = useState(false); // false = Relay→Teyrchain, true = Teyrchain→Relay const [amount, setAmount] = useState(''); const [isTransferring, setIsTransferring] = useState(false); const [txStatus, setTxStatus] = useState<'idle' | 'signing' | 'pending' | 'success' | 'error'>( @@ -121,28 +131,43 @@ export function FundFeesModal({ isOpen, onClose }: Props) { } }, [api, assetHubApi, peopleApi, address, isOpen]); - const getTargetBalance = () => { + const getTeyrchainBalance = () => { return targetChain === 'asset-hub' ? assetHubBalance : peopleBalance; }; + const getSourceBalance = () => (toRelay ? getTeyrchainBalance() : relayBalance); + const getDestBalance = () => (toRelay ? relayBalance : getTeyrchainBalance()); + const getSourceName = () => (toRelay ? selectedChain.name : 'Relay Chain'); + const getDestName = () => (toRelay ? 'Relay Chain' : selectedChain.name); + const handleTeleport = async () => { - if (!api || !address || !keypair) { + if (!address || !keypair) { showAlert('Cizdan girêdayî nîne'); return; } + // Get the correct API based on direction + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const sourceApi: any = toRelay ? (targetChain === 'asset-hub' ? assetHubApi : peopleApi) : api; + + if (!sourceApi) { + showAlert('API girêdayî nîne'); + return; + } + if (!amount || parseFloat(amount) <= 0) { showAlert('Mîqdarek rast binivîse'); return; } - if (relayBalance === '--') { - showAlert('Relay Chain girêdayî nîne'); + const sourceBalance = getSourceBalance(); + if (sourceBalance === '--') { + showAlert('Zincîr girêdayî nîne'); return; } const sendAmount = parseFloat(amount); - const currentBalance = parseFloat(relayBalance); + const currentBalance = parseFloat(sourceBalance); if (sendAmount > currentBalance) { showAlert('Bakiye têrê nake'); @@ -154,23 +179,88 @@ export function FundFeesModal({ isOpen, onClose }: Props) { hapticImpact('medium'); try { - // Convert to smallest unit (12 decimals) const amountInSmallestUnit = BigInt(Math.floor(parseFloat(amount) * 1e12)); - // Get target teyrchain ID - const targetTeyrchainId = selectedChain.teyrchainId; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let dest: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let assets: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let feeAssetId: any; - // Destination: Target teyrchain - const dest = { - V3: { - parents: 0, - interior: { - X1: { teyrchain: targetTeyrchainId }, + if (toRelay) { + // Teyrchain → Relay (aynı V3 format, parents: 1) + dest = { + V3: { + parents: 1, + interior: 'Here', }, - }, - }; + }; - // Beneficiary: Same account on target chain + assets = { + V3: [ + { + id: { + Concrete: { + parents: 1, + interior: 'Here', + }, + }, + fun: { + Fungible: amountInSmallestUnit.toString(), + }, + }, + ], + }; + + feeAssetId = { + V3: { + Concrete: { + parents: 1, + interior: 'Here', + }, + }, + }; + } else { + // Relay → Teyrchain (orijinal çalışan kod) + const targetTeyrchainId = selectedChain.teyrchainId; + + dest = { + V3: { + parents: 0, + interior: { + X1: { teyrchain: targetTeyrchainId }, + }, + }, + }; + + assets = { + V3: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: amountInSmallestUnit.toString(), + }, + }, + ], + }; + + feeAssetId = { + V3: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + }; + } + + // Beneficiary: aynı format her iki yön için const beneficiary = { V3: { parents: 0, @@ -178,44 +268,24 @@ export function FundFeesModal({ isOpen, onClose }: Props) { X1: { accountid32: { network: null, - id: api.createType('AccountId32', address).toHex(), + id: sourceApi.createType('AccountId32', address).toHex(), }, }, }, }, }; - // Assets: Native token (HEZ) - const assets = { - V3: [ - { - id: { - Concrete: { - parents: 0, - interior: 'Here', - }, - }, - fun: { - Fungible: amountInSmallestUnit.toString(), - }, - }, - ], - }; - - // Fee asset ID: Native HEZ token - const feeAssetId = { - V3: { - Concrete: { - parents: 0, - interior: 'Here', - }, - }, - }; - const weightLimit = 'Unlimited'; - // Create teleport transaction - const tx = api.tx.xcmPallet.limitedTeleportAssets( + // Pallet: relay'de xcmPallet, teyrchain'de pezkuwiXcm + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const xcmPallet = toRelay ? (sourceApi.tx as any).pezkuwiXcm : sourceApi.tx.xcmPallet; + + if (!xcmPallet?.limitedTeleportAssets) { + throw new Error('XCM pallet nehate dîtin'); + } + + const tx = xcmPallet.limitedTeleportAssets( dest, beneficiary, assets, @@ -225,35 +295,43 @@ export function FundFeesModal({ isOpen, onClose }: Props) { setTxStatus('pending'); - const unsub = await tx.signAndSend(keypair, ({ status, dispatchError }) => { - if (status.isFinalized) { - if (dispatchError) { - let errorMessage = 'Teleport neserketî'; + const unsub = await tx.signAndSend( + keypair, + ({ + status, + dispatchError, + }: { + status: { isFinalized: boolean }; + dispatchError?: { isModule: boolean; asModule: unknown }; + }) => { + if (status.isFinalized) { + if (dispatchError) { + let errorMessage = 'Teleport neserketî'; - if (dispatchError.isModule) { - const decoded = api.registry.findMetaError(dispatchError.asModule); - errorMessage = `${decoded.section}.${decoded.name}`; + if (dispatchError.isModule) { + const decoded = sourceApi.registry.findMetaError(dispatchError.asModule); + errorMessage = `${decoded.section}.${decoded.name}`; + } + + setTxStatus('error'); + hapticImpact('heavy'); + showAlert(errorMessage); + } else { + setTxStatus('success'); + hapticImpact('medium'); + + setTimeout(() => { + setAmount(''); + setTxStatus('idle'); + onClose(); + }, 2000); } - setTxStatus('error'); - hapticImpact('heavy'); - showAlert(errorMessage); - } else { - setTxStatus('success'); - hapticImpact('medium'); - - // Reset after success - setTimeout(() => { - setAmount(''); - setTxStatus('idle'); - onClose(); - }, 2000); + setIsTransferring(false); + unsub(); } - - setIsTransferring(false); - unsub(); } - }); + ); } catch (error) { console.error('Teleport error:', error); setTxStatus('error'); @@ -264,7 +342,7 @@ export function FundFeesModal({ isOpen, onClose }: Props) { }; const setQuickAmount = (percent: number) => { - const balance = parseFloat(relayBalance); + const balance = parseFloat(getSourceBalance()); if (balance > 0) { const quickAmount = ((balance * percent) / 100).toFixed(4); setAmount(quickAmount); @@ -301,7 +379,7 @@ export function FundFeesModal({ isOpen, onClose }: Props) {

Serketî!

- {amount} HEZ bo {selectedChain.name} hate şandin + {amount} HEZ bo {getDestName()} hate şandin

) : txStatus === 'error' ? ( @@ -348,14 +426,38 @@ export function FundFeesModal({ isOpen, onClose }: Props) { + {/* Direction Toggle */} + + {/* Balance Display */}
-
- Relay Chain +
+ {getSourceName()}
- {relayBalance} HEZ + {getSourceBalance()} HEZ
@@ -366,12 +468,16 @@ export function FundFeesModal({ isOpen, onClose }: Props) {
- {selectedChain.name} + {getDestName()}
- {getTargetBalance()} HEZ + {getDestBalance()} HEZ
@@ -458,7 +564,7 @@ export function FundFeesModal({ isOpen, onClose }: Props) { ) : ( <> - Bo {selectedChain.name} Bişîne + Bo {getDestName()} Bişîne )} diff --git a/src/version.json b/src/version.json index 196c5d3..be7af22 100644 --- a/src/version.json +++ b/src/version.json @@ -1,5 +1,5 @@ { - "version": "1.0.167", - "buildTime": "2026-02-07T21:08:36.401Z", - "buildNumber": 1770498516402 + "version": "1.0.168", + "buildTime": "2026-02-07T21:21:39.509Z", + "buildNumber": 1770499299510 }