Skip to content

Commit 50ffe26

Browse files
committed
fix arbitrum too
1 parent dcfd951 commit 50ffe26

File tree

2 files changed

+156
-153
lines changed

2 files changed

+156
-153
lines changed

packages/frontend/src/components/BridgeUINew.tsx

Lines changed: 155 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,11 @@ export function BridgeUINew() {
249249

250250
// Calculate fee based on current source amount
251251
const feeInfo = useMemo(() => {
252-
const amount = parseFloat(sourceAmount) || 0;
253-
return getFeeInfo(amount);
252+
const receiveAmount = parseFloat(sourceAmount);
253+
const usdcValue = activeSourceToken.symbol !== 'USDC' && sourcePriceInUsdc
254+
? receiveAmount * sourcePriceInUsdc
255+
: receiveAmount;
256+
return getFeeInfo(usdcValue);
254257
}, [sourceAmount]);
255258

256259
// Validate form and compute validation error message
@@ -630,185 +633,185 @@ export function BridgeUINew() {
630633
const sourceChainName = 'solana';
631634
const destChainName = 'base';
632635

633-
// Calculate fee based on amount ($0.69 flat or 0.20%)
634-
const fee = calculateBridgeFee(parseFloat(sourceAmount)).toFixed(6);
635-
636-
// Step 1: Create transaction in DB
637-
console.info('💾 Creating transaction record...');
638-
// Convert amount and fee from display units to base units (6 decimals for USDC)
639-
const amountInBaseUnits = (parseFloat(sourceAmount) * 1_000_000).toString();
640-
const feeInBaseUnits = (parseFloat(fee) * 1_000_000).toString();
641-
642-
const createResult = await api.createBridgeTransaction({
643-
sourceChain: sourceChainName,
644-
destinationChain: destChainName,
645-
sourceWallet: sourceWallet.address,
646-
destinationWallet: destAddress,
647-
amount: amountInBaseUnits,
648-
fee: feeInBaseUnits,
649-
selectedDestinationToken: destToken.symbol,
650-
userDestinationWallet: destAddress,
651-
});
636+
// Calculate fee based on amount ($0.69 flat or 0.20%)
637+
const fee = calculateBridgeFee(parseFloat(sourceAmount)).toFixed(6);
652638

653-
transactionId = createResult.id;
654-
console.info('✅ Transaction created:', transactionId);
639+
// Step 1: Create transaction in DB
640+
console.info('💾 Creating transaction record...');
641+
// Convert amount and fee from display units to base units (6 decimals for USDC)
642+
const amountInBaseUnits = (parseFloat(sourceAmount) * 1_000_000).toString();
643+
const feeInBaseUnits = (parseFloat(fee) * 1_000_000).toString();
655644

656-
// Step 2: Check if we need to swap source token to USDC first
657-
const needsSwap = activeSourceToken.symbol !== 'USDC';
658-
let burnAmount = sourceAmount; // Default to source amount (for USDC)
645+
const createResult = await api.createBridgeTransaction({
646+
sourceChain: sourceChainName,
647+
destinationChain: destChainName,
648+
sourceWallet: sourceWallet.address,
649+
destinationWallet: destAddress,
650+
amount: amountInBaseUnits,
651+
fee: feeInBaseUnits,
652+
selectedDestinationToken: destToken.symbol,
653+
userDestinationWallet: destAddress,
654+
});
659655

660-
if (needsSwap) {
661-
console.info(`🔄 Swapping ${activeSourceToken.symbol} to USDC before burn...`);
662-
setCurrentStatus(`Swapping ${activeSourceToken.symbol} to USDC`);
663-
setProgressStep(0);
656+
transactionId = createResult.id;
657+
console.info('✅ Transaction created:', transactionId);
664658

665-
// Calculate how much extra SOL we need to cover the bridge fee
666-
// Bridge fee is in USDC, convert to source token
667-
const bridgeFeeInSourceToken = sourcePriceInUsdc ? feeInfo.fee / sourcePriceInUsdc : 0;
659+
// Step 2: Check if we need to swap source token to USDC first
660+
const needsSwap = activeSourceToken.symbol !== 'USDC';
661+
let burnAmount = sourceAmount; // Default to source amount (for USDC)
668662

669-
// Swap amount = user input + enough to cover bridge fee
670-
const swapAmount = parseFloat(sourceAmount) + bridgeFeeInSourceToken;
663+
if (needsSwap) {
664+
console.info(`🔄 Swapping ${activeSourceToken.symbol} to USDC before burn...`);
665+
setCurrentStatus(`Swapping ${activeSourceToken.symbol} to USDC`);
666+
setProgressStep(0);
671667

672-
console.info(`💰 Swapping ${swapAmount.toFixed(6)} ${activeSourceToken.symbol} (includes ${bridgeFeeInSourceToken.toFixed(6)} ${activeSourceToken.symbol} for bridge fee)`);
668+
// Calculate how much extra SOL we need to cover the bridge fee
669+
// Bridge fee is in USDC, convert to source token
670+
const bridgeFeeInSourceToken = sourcePriceInUsdc ? feeInfo.fee / sourcePriceInUsdc : 0;
673671

674-
// Convert swap amount to lamports (SOL has 9 decimals)
675-
const sourceAmountLamports = Math.floor(swapAmount * 1_000_000_000).toString();
672+
// Swap amount = user input + enough to cover bridge fee
673+
const swapAmount = parseFloat(sourceAmount) + bridgeFeeInSourceToken;
676674

677-
// Build swap transaction
678-
console.info('🏗️ Building swap transaction on backend...');
679-
const swapBuildResult = await api.buildSwapTransaction({
680-
transactionId,
681-
sourceWallet: sourceWallet.address,
682-
sourceToken: activeSourceToken.symbol,
683-
amount: sourceAmountLamports,
684-
originalAmount: sourceAmount, // Pass the original user input (e.g., "0.015" for display)
685-
});
675+
console.info(`💰 Swapping ${swapAmount.toFixed(6)} ${activeSourceToken.symbol} (includes ${bridgeFeeInSourceToken.toFixed(6)} ${activeSourceToken.symbol} for bridge fee)`);
686676

687-
console.info('✅ Swap transaction built:', {
688-
inputAmount: swapBuildResult.inputAmount,
689-
outputAmount: swapBuildResult.outputAmount,
690-
priceImpact: swapBuildResult.priceImpactPct,
691-
});
677+
// Convert swap amount to lamports (SOL has 9 decimals)
678+
const sourceAmountLamports = Math.floor(swapAmount * 1_000_000_000).toString();
692679

693-
// Calculate burn amount: swap output MINUS the bridge fee
694-
// Jupiter returns outputAmount in raw USDC units (6 decimals)
695-
const swapOutputUsdc = parseFloat(swapBuildResult.outputAmount) / 1_000_000;
696-
burnAmount = (swapOutputUsdc - feeInfo.fee).toFixed(6);
697-
console.info(`💰 Swap output: ${swapOutputUsdc.toFixed(6)} USDC`);
698-
console.info(`💰 Bridge fee: ${feeInfo.fee.toFixed(6)} USDC`);
699-
console.info(`💰 Burn amount (output - fee): ${burnAmount} USDC`);
700-
701-
// Deserialize and sign swap transaction (versioned transaction from Jupiter)
702-
const { VersionedTransaction } = await import('@solana/web3.js');
703-
const swapTx = VersionedTransaction.deserialize(
704-
Buffer.from(swapBuildResult.transaction, 'base64')
705-
);
680+
// Build swap transaction
681+
console.info('🏗️ Building swap transaction on backend...');
682+
const swapBuildResult = await api.buildSwapTransaction({
683+
transactionId,
684+
sourceWallet: sourceWallet.address,
685+
sourceToken: activeSourceToken.symbol,
686+
amount: sourceAmountLamports,
687+
originalAmount: sourceAmount, // Pass the original user input (e.g., "0.015" for display)
688+
});
706689

707-
console.info('🔐 Requesting wallet signature for swap transaction...');
708-
if (!signTransaction) {
709-
throw new Error('Wallet does not support transaction signing');
710-
}
690+
console.info('✅ Swap transaction built:', {
691+
inputAmount: swapBuildResult.inputAmount,
692+
outputAmount: swapBuildResult.outputAmount,
693+
priceImpact: swapBuildResult.priceImpactPct,
694+
});
711695

712-
const signedSwapTx = await signTransaction(swapTx);
713-
console.info('✅ Swap transaction signed by wallet');
696+
// Calculate burn amount: swap output MINUS the bridge fee
697+
// Jupiter returns outputAmount in raw USDC units (6 decimals)
698+
const swapOutputUsdc = parseFloat(swapBuildResult.outputAmount) / 1_000_000;
699+
burnAmount = (swapOutputUsdc - feeInfo.fee).toFixed(6);
700+
console.info(`💰 Swap output: ${swapOutputUsdc.toFixed(6)} USDC`);
701+
console.info(`💰 Bridge fee: ${feeInfo.fee.toFixed(6)} USDC`);
702+
console.info(`💰 Burn amount (output - fee): ${burnAmount} USDC`);
703+
704+
// Deserialize and sign swap transaction (versioned transaction from Jupiter)
705+
const { VersionedTransaction } = await import('@solana/web3.js');
706+
const swapTx = VersionedTransaction.deserialize(
707+
Buffer.from(swapBuildResult.transaction, 'base64')
708+
);
709+
710+
console.info('🔐 Requesting wallet signature for swap transaction...');
711+
if (!signTransaction) {
712+
throw new Error('Wallet does not support transaction signing');
713+
}
714714

715-
// Submit swap transaction
716-
console.info('📤 Submitting signed swap transaction to backend...');
717-
await api.submitSwapTransaction({
718-
transactionId,
719-
signedSwapTransaction: Buffer.from(signedSwapTx.serialize()).toString('base64'),
720-
});
715+
const signedSwapTx = await signTransaction(swapTx);
716+
console.info('✅ Swap transaction signed by wallet');
721717

722-
console.info('✅ Swap transaction submitted to backend queue');
718+
// Submit swap transaction
719+
console.info('📤 Submitting signed swap transaction to backend...');
720+
await api.submitSwapTransaction({
721+
transactionId,
722+
signedSwapTransaction: Buffer.from(signedSwapTx.serialize()).toString('base64'),
723+
});
723724

724-
// Poll for swap completion
725-
console.info('🔄 Polling for swap completion...');
726-
const maxSwapAttempts = 60; // 60 attempts × 2 seconds = 2 minutes
727-
let swapAttempts = 0;
725+
console.info('✅ Swap transaction submitted to backend queue');
728726

729-
while (swapAttempts < maxSwapAttempts) {
730-
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
731-
swapAttempts++;
727+
// Poll for swap completion
728+
console.info('🔄 Polling for swap completion...');
729+
const maxSwapAttempts = 60; // 60 attempts × 2 seconds = 2 minutes
730+
let swapAttempts = 0;
732731

733-
try {
734-
const txStatus = await api.getBridgeTransaction(transactionId);
735-
console.info(`[SWAP POLL ${swapAttempts}/${maxSwapAttempts}] Swap Status: ${txStatus.swapStatus}`);
732+
while (swapAttempts < maxSwapAttempts) {
733+
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
734+
swapAttempts++;
736735

737-
if (txStatus.swapStatus === 'completed') {
738-
console.info('✅ Swap completed, proceeding to burn...');
739-
setCurrentStatus('Waiting departure confirmation...');
740-
break;
741-
}
736+
try {
737+
const txStatus = await api.getBridgeTransaction(transactionId);
738+
console.info(`[SWAP POLL ${swapAttempts}/${maxSwapAttempts}] Swap Status: ${txStatus.swapStatus}`);
739+
740+
if (txStatus.swapStatus === 'completed') {
741+
console.info('✅ Swap completed, proceeding to burn...');
742+
setCurrentStatus('Waiting departure confirmation...');
743+
break;
744+
}
742745

743-
if (txStatus.swapStatus === 'failed') {
744-
throw new Error('Swap transaction failed on-chain');
746+
if (txStatus.swapStatus === 'failed') {
747+
throw new Error('Swap transaction failed on-chain');
748+
}
749+
} catch (pollError) {
750+
console.error('Error polling swap status:', pollError);
751+
// Continue polling even if one request fails
745752
}
746-
} catch (pollError) {
747-
console.error('Error polling swap status:', pollError);
748-
// Continue polling even if one request fails
749753
}
750-
}
751754

752-
if (swapAttempts >= maxSwapAttempts) {
753-
throw new Error('Swap transaction timeout (2 minutes)');
755+
if (swapAttempts >= maxSwapAttempts) {
756+
throw new Error('Swap transaction timeout (2 minutes)');
757+
}
754758
}
755-
}
756759

757-
// Step 3: Generate message account keypair on frontend
758-
console.info('🔑 Generating message account keypair...');
759-
const { Keypair } = await import('@solana/web3.js');
760-
const messageAccount = Keypair.generate();
761-
console.info('✅ Message account generated:', messageAccount.publicKey.toBase58());
762-
763-
// Step 3: Build burn transaction on backend (send message account keys for storage)
764-
console.info('🏗️ Building burn transaction on backend...');
765-
const buildResult = await api.buildBurnTransaction({
766-
transactionId,
767-
sourceWallet: sourceWallet.address,
768-
destinationWallet: destAddress,
769-
amount: burnAmount, // Use burnAmount (either original USDC or swapped USDC amount)
770-
messageAccountPublicKey: messageAccount.publicKey.toBase58(),
771-
messageAccountSecretKey: Array.from(messageAccount.secretKey),
772-
});
760+
// Step 3: Generate message account keypair on frontend
761+
console.info('🔑 Generating message account keypair...');
762+
const { Keypair } = await import('@solana/web3.js');
763+
const messageAccount = Keypair.generate();
764+
console.info('✅ Message account generated:', messageAccount.publicKey.toBase58());
765+
766+
// Step 3: Build burn transaction on backend (send message account keys for storage)
767+
console.info('🏗️ Building burn transaction on backend...');
768+
const buildResult = await api.buildBurnTransaction({
769+
transactionId,
770+
sourceWallet: sourceWallet.address,
771+
destinationWallet: destAddress,
772+
amount: burnAmount, // Use burnAmount (either original USDC or swapped USDC amount)
773+
messageAccountPublicKey: messageAccount.publicKey.toBase58(),
774+
messageAccountSecretKey: Array.from(messageAccount.secretKey),
775+
});
773776

774-
console.info('✅ Backend built unsigned transaction');
777+
console.info('✅ Backend built unsigned transaction');
775778

776-
// Step 4: Deserialize and sign with Solana wallet
777-
const { Transaction } = await import('@solana/web3.js');
778-
const unsignedTx = Transaction.from(
779-
Buffer.from(buildResult.unsignedTransaction, 'base64')
780-
);
779+
// Step 4: Deserialize and sign with Solana wallet
780+
const { Transaction } = await import('@solana/web3.js');
781+
const unsignedTx = Transaction.from(
782+
Buffer.from(buildResult.unsignedTransaction, 'base64')
783+
);
781784

782-
console.info('🔐 Requesting Phantom wallet signature (must sign first)...');
783-
if (!signTransaction) {
784-
throw new Error('Wallet does not support transaction signing');
785-
}
785+
console.info('🔐 Requesting Phantom wallet signature (must sign first)...');
786+
if (!signTransaction) {
787+
throw new Error('Wallet does not support transaction signing');
788+
}
786789

787-
// Phantom wallet signs FIRST (per Phantom Lighthouse security requirements)
788-
const signedTx = await signTransaction(unsignedTx);
789-
console.info('✅ Transaction signed by Phantom wallet');
790-
791-
// Now add message account signature AFTER Phantom signed
792-
console.info('🔐 Adding message account signature...');
793-
signedTx.partialSign(messageAccount);
794-
console.info('✅ Message account signature added (Phantom signed first ✓)');
795-
796-
// Step 4: Serialize fully signed transaction
797-
const signedBase64 = Buffer.from(
798-
signedTx.serialize({
799-
requireAllSignatures: false,
800-
verifySignatures: false
801-
})
802-
).toString('base64');
803-
804-
// Step 5: Submit to backend queue
805-
console.info('📤 Submitting signed transaction to backend...');
806-
await api.submitBurnTransaction({
807-
transactionId,
808-
signedTransaction: signedBase64,
809-
});
790+
// Phantom wallet signs FIRST (per Phantom Lighthouse security requirements)
791+
const signedTx = await signTransaction(unsignedTx);
792+
console.info('✅ Transaction signed by Phantom wallet');
793+
794+
// Now add message account signature AFTER Phantom signed
795+
console.info('🔐 Adding message account signature...');
796+
signedTx.partialSign(messageAccount);
797+
console.info('✅ Message account signature added (Phantom signed first ✓)');
798+
799+
// Step 4: Serialize fully signed transaction
800+
const signedBase64 = Buffer.from(
801+
signedTx.serialize({
802+
requireAllSignatures: false,
803+
verifySignatures: false
804+
})
805+
).toString('base64');
806+
807+
// Step 5: Submit to backend queue
808+
console.info('📤 Submitting signed transaction to backend...');
809+
await api.submitBurnTransaction({
810+
transactionId,
811+
signedTransaction: signedBase64,
812+
});
810813

811-
console.info('✅ Transaction submitted to backend queue');
814+
console.info('✅ Transaction submitted to backend queue');
812815
} // End of Solana source chain flow
813816

814817
// =========================================================================

packages/frontend/src/components/EVMFromTokenSelector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const CHAIN_SECTIONS: ChainSection[] = [
6464
{
6565
label: 'Arbitrum',
6666
tokens: [
67-
{ symbol: 'ARB', name: 'ARB', address: '0x912CE59144191C1204E64559FE8253a0e49E6548', chain: 'arbitrum', iconPath: '/chain_icons/arb.png' },
67+
{ symbol: 'ETH', name: 'ETH', address: '0x0000000000000000000000000000000000000000', chain: 'arbitrum', iconPath: '/chain_icons/eth.png' },
6868
{ symbol: 'USDC', name: 'USDC', address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', chain: 'arbitrum', iconPath: '/chain_icons/usdc.png' },
6969
],
7070
},

0 commit comments

Comments
 (0)