diff --git a/assets/js/webapp/swapUtils.js b/assets/js/webapp/swapUtils.js index 3ff11d9..7a0ab20 100644 --- a/assets/js/webapp/swapUtils.js +++ b/assets/js/webapp/swapUtils.js @@ -4,7 +4,7 @@ const handleCancel = (err) => { const msg = err?.message || ""; if (msg.includes("rejected") || msg.includes("cancelled") || msg.includes("user declined")) { - console.log("[Ultra] Swap cancelled"); + console.log("[Ultra] Swap cancelled by user"); throw new Error("USER_REJECTED"); } return false; @@ -12,6 +12,11 @@ const handleCancel = (err) => { // ==================== ULTRA SWAP (Primary) ==================== async function performUltraSwap(inputMint, outputMint, rawAmount, provider, connectedWallet) { + if (rawAmount < 100000) { + console.warn("[Ultra] Amount too small, skipping Ultra quote"); + throw new Error("Amount too small — try a larger swap"); + } + try { console.log(`[Ultra] Requesting quote: ${rawAmount} from ${inputMint} to ${outputMint}`); const ultraRes = await fetch( @@ -29,71 +34,105 @@ async function performUltraSwap(inputMint, outputMint, rawAmount, provider, conn } } -// ==================== SMART SIGNING ==================== -async function executeUltraTransaction(quote, provider) { - try { - const connectionMethod = window.connectionMethod || localStorage.getItem('connection_method'); - - // ==================== GOOGLE / APPLE (Embedded Wallet) ==================== - if (connectionMethod === 'google' || connectionMethod === 'apple') { - console.log("[Ultra] Embedded wallet detected → Using v1 proxy + SDK signing"); - console.log(`[Ultra] Connected wallet: ${window.connectedWallet}`); - - const proxyRes = await fetch('https://giddy-key-swaps-production.up.railway.app/api/swap/v1', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - inputMint: quote.inputMint || "So11111111111111111111111111111111111111112", - outputMint: quote.outputMint, - rawAmount: quote.inAmount, - connectedWallet: window.connectedWallet - }) - }); - - const data = await proxyRes.json(); - if (!data.success) throw new Error(data.error || "v1 proxy failed"); - - const tx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(data.swapTransaction, "base64")); - +// ==================== SMART SIGNING WITH CLEVER DETECTION ==================== +async function executeUltraTransaction(quote, providerParam) { + const connectionMethod = window.connectionMethod || localStorage.getItem('connection_method') || 'injected'; + console.log(`[Ultra] Detected connection method: ${connectionMethod}`); + + let signer = null; + let isEmbedded = false; + + if (connectionMethod === 'google' || connectionMethod === 'apple') { + // === EMBEDDED WALLETS (Google / Apple) === + isEmbedded = true; + console.log("[Ultra] Embedded wallet detected — forcing SDK signer only"); + const sdk = await window.getPhantomSDK?.(); + if (sdk?.solana) { + signer = sdk.solana; + console.log("✅ Using Phantom SDK signer (Google/Apple)"); + } + } else { + // === INJECTED WALLETS (Phantom extension / app) === + console.log("[Ultra] Injected wallet detected — prioritizing window.solana"); + + if (providerParam && typeof providerParam.signTransaction === 'function') { + signer = providerParam; + console.log("✅ Using legacy provider (injected)"); + } + else if (window.solana?.isPhantom) { + signer = window.solana; + console.log("✅ Using direct window.solana (injected)"); + } + else { + // Last resort fallback for injected const sdk = await window.getPhantomSDK?.(); - if (!sdk?.solana) throw new Error("Phantom SDK not available"); - - console.log("[Ultra] Requesting SDK signAndSendTransaction..."); - // Removed presignTransaction hook to prevent 403 Forbidden on /prepare - const result = await sdk.solana.signAndSendTransaction(tx); - - console.log("[Ultra] SDK Success, TXID:", result.signature); - return { success: true, txid: result.signature, router: "v1-proxy" }; + if (sdk?.solana) { + signer = sdk.solana; + console.log("✅ Using SDK signer as fallback for injected"); + } } + } - // ==================== INJECTED PHANTOM ==================== - console.log("[Ultra] Signing with Injected Phantom..."); - if (!provider || typeof provider.signTransaction !== 'function') { - throw new Error("No valid injected provider"); - } + if (!signer) { + throw new Error(`No valid signer found for connection type: ${connectionMethod}`); + } + // For embedded wallets we prefer the stable v1 proxy path + if (isEmbedded) { + console.log("[Ultra] Embedded wallet → using v1 proxy for reliable signing"); + return await performV1Swap( + quote.inputMint || "So11111111111111111111111111111111111111112", + quote.outputMint, + quote.inAmount || quote.amount, + providerParam, + window.connectedWallet + ); + } + + // Injected path → try direct Jupiter Ultra execute first + try { + console.log("[Ultra] Injected → attempting direct Jupiter Ultra execute"); const vtx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(quote.transaction, 'base64')); - const signed = await provider.signTransaction(vtx); + const signed = await signer.signTransaction(vtx); + const signedTxBase64 = btoa(String.fromCharCode(...new Uint8Array(signed.serialize()))); const executeRes = await fetch('https://lite-api.jup.ag/ultra/v1/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ signedTransaction: signedTxBase64, requestId: quote.requestId }) + body: JSON.stringify({ + signedTransaction: signedTxBase64, + requestId: quote.requestId + }) }); - if (!executeRes.ok) throw new Error(`Ultra Execute Failed: ${executeRes.status}`); + if (!executeRes.ok) throw new Error(`Ultra Execute HTTP ${executeRes.status}`); const result = await executeRes.json(); - return { success: true, txid: result.signature, router: quote.router || 'OKX/DFlow' }; - } catch (error) { - if (!handleCancel(error)) console.error("[Ultra] Execute failed:", error); - throw error; + + if (!result.signature) throw new Error("Ultra execute did not return signature"); + + console.log(`✅ SUCCESS (Ultra direct)! TX: ${result.signature}`); + return { success: true, txid: result.signature, router: "Ultra" }; + + } catch (ultraErr) { + console.warn("[Ultra] Direct Ultra execute failed, falling back to v1 proxy...", ultraErr.message); + if (!handleCancel(ultraErr)) { + return await performV1Swap( + quote.inputMint || "So11111111111111111111111111111111111111112", + quote.outputMint, + quote.inAmount || quote.amount, + providerParam, + window.connectedWallet + ); + } + throw ultraErr; } } -// ==================== V1 FALLBACK ==================== +// ==================== V1 PROXY FALLBACK ==================== async function performV1Swap(inputMint, outputMint, rawAmount, provider, connectedWallet) { try { + console.log("[V1 Proxy] Using fallback proxy"); const proxyRes = await fetch('https://giddy-key-swaps-production.up.railway.app/api/swap/v1', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -104,7 +143,21 @@ async function performV1Swap(inputMint, outputMint, rawAmount, provider, connect if (!data.success) throw new Error(data.error || "v1 proxy failed"); const tx = solanaWeb3.VersionedTransaction.deserialize(Buffer.from(data.swapTransaction, "base64")); - const result = await provider.signAndSendTransaction(tx); + + // Re-detect signer for v1 path (respects Google/Apple vs injected) + const connectionMethod = window.connectionMethod || localStorage.getItem('connection_method') || 'injected'; + let signer = null; + + if (connectionMethod === 'google' || connectionMethod === 'apple') { + const sdk = await window.getPhantomSDK?.(); + signer = sdk?.solana || null; + } else { + signer = provider || window.solana || (await window.getPhantomSDK?.())?.solana; + } + + if (!signer) throw new Error("No signer available for v1 fallback"); + + const result = await signer.signAndSendTransaction(tx); return { success: true, txid: result.signature, version: "v1" }; } catch (error) { if (!handleCancel(error)) console.error("[V1 Proxy] Failed:", error.message); @@ -116,7 +169,4 @@ async function performV1Swap(inputMint, outputMint, rawAmount, provider, connect window.performUltraSwap = performUltraSwap; window.performV1Swap = performV1Swap; -// Dispatch ready event -window.dispatchEvent(new CustomEvent('swap-engine-ready')); - -console.log("✅ swapUtils.js loaded and READY"); \ No newline at end of file +console.log("✅ swapUtils.js loaded — Smart detection active (Google/Apple → SDK only | Injected → window.solana priority)"); \ No newline at end of file diff --git a/assets/js/webapp/wallet.js b/assets/js/webapp/wallet.js index bed8fec..d671d50 100644 --- a/assets/js/webapp/wallet.js +++ b/assets/js/webapp/wallet.js @@ -608,44 +608,43 @@ function initShareWalletButton() { if (!shareBtn) return; shareBtn.addEventListener('click', async () => { - // 1. Get the dynamic address from storage - const address = localStorage.getItem('wallet_address'); + const address = localStorage.getItem('wallet_address') || window.connectedWallet; if (!address) { alert("No wallet address found."); return; } - // 2. Updated: share only the address - const shareText = address; + const shareText = `My Giddy Key Wallet Address:\n${address}`; - // 3. Try native share + // Try native share first if (navigator.share) { try { await navigator.share({ title: 'My Giddy Key Wallet', text: shareText - // Removed 'url' so only the address is shared }); return; } catch (err) { - console.log("Share cancelled or failed"); + console.log("Native share cancelled → clipboard fallback"); } } - // 4. Fallback: Copy address to clipboard + // Silent clipboard fallback try { await navigator.clipboard.writeText(address); - // Visual feedback - const originalIcon = shareBtn.innerHTML; - shareBtn.innerHTML = ``; + // Visual feedback - same size as share icon + const originalHTML = shareBtn.innerHTML; + shareBtn.innerHTML = ``; setTimeout(() => { - shareBtn.innerHTML = originalIcon; - }, 1500); + shareBtn.innerHTML = originalHTML; + }, 1600); + console.log("✅ Address copied to clipboard"); } catch (err) { - prompt("Copy your wallet address:", address); + console.error("Clipboard failed:", err); + alert(`Wallet address copied!\n\n${address}`); } }); } diff --git a/swap-test.html b/swap-test.html index a4c29fe..d19a66a 100644 --- a/swap-test.html +++ b/swap-test.html @@ -1,69 +1,55 @@ - Swap Engine Testbed - All Pairs - - - - -

Swap Engine Testbed

-

Phantom + Jupiter Ultra → v1 Proxy • All Pairs

+

Phantom SDK + window.solana • Jupiter Ultra + v1 Proxy

- -
- - +
+
+ + + + +
-

Jupiter Diagnostic Console

- -
-
- - - -
- -
+ + +
- +

Ultra:

v1 Proxy:

-

Quick Swap

-
- - +
- - +
-

eXPB → USDC

-
- -
-
-

Tracked Asset Prices

@@ -253,17 +217,15 @@

Tracked Asset Prices

- diff --git a/wallet.html b/wallet.html index a1e6c60..e7f1f02 100644 --- a/wallet.html +++ b/wallet.html @@ -1091,6 +1091,22 @@ border-color: rgba(16, 185, 129, 0.5); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); } + + #shareWalletBtn i { + font-size: 1rem; + /* Same size as text-sm */ + width: 1rem; + height: 1rem; + display: inline-flex; + align-items: center; + justify-content: center; + } + + /* Prevent any shift during icon swap */ + #shareWalletBtn { + width: 2.25rem; + height: 2.25rem; + }