From b1f3e4c911c49c9b50f39c52db28e5a62c7a42c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tokin=20=E2=AC=A2=20Cypher?= Date: Fri, 26 Jun 2026 21:13:33 -0700 Subject: [PATCH] Update swapUtils to prioritize window.solana while SDK issues are ironed out. This restores swaps in phantom. Small adjustment to clipboard behaviour for copy wallet address in status bar and sizing. Small CSS addition to help clipboard styling in wallet.html. Added SDK connection testing to testbed. --- assets/js/webapp/swapUtils.js | 156 ++++++++++------ assets/js/webapp/wallet.js | 27 ++- swap-test.html | 337 ++++++++++++++++++---------------- wallet.html | 16 ++ 4 files changed, 308 insertions(+), 228 deletions(-) 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; + }