1 2 3<!DOCTYPE html> 4<html lang="en"> 5<head> 6 <meta charset="UTF-8" /> 7 <link rel="icon" type="image/png" href="/favicon.png"> 8 9 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 10 <title>Amebo Wallet</title> 11 12 <!-- Clerk --> 13
13<script 14 async 15 crossorigin="anonymous" 16 data-clerk-publishable-key="pk_live_Y2xlcmsuYW1lYm9zb2NpYWwuY29tJA" 17 src="https://clerk.amebosocial.com/npm/@clerk/clerk-js@5/dist/clerk.browser.js" 18 type="text/javascript" 19></script>
19 20 21 <!-- Paystack --> 22
22<script src="https://js.paystack.co/v1/inline.js" defer></script>
22 23 24 <!-- Supabase --> 25
25<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2" defer></script>
25 26 27 <style> 28 body { 29 font-family: system-ui, sans-serif; 30 background: #f9f9f9; 31 color: #333; 32 margin: 0; 33 padding: 0; 34 } 35 #wallet-container { 36 display: none; 37 max-width: 500px; 38 margin: 80px auto; 39 padding: 30px; 40 background: #fff; 41 border-radius: 16px; 42 box-shadow: 0 4px 12px rgba(0,0,0,0.1); 43 text-align: center; 44 } 45 #wallet-container.active { display: block; } 46 h2 { color: #6c2bd9; } 47 button { 48 background: #6c2bd9; 49 color: #fff; 50 border: none; 51 padding: 12px 20px; 52 border-radius: 8px; 53 cursor: pointer; 54 margin: 6px; 55 font-weight: 600; 56 transition: background 0.2s ease; 57 } 58 button:hover { background: #5a1dc1; } 59 #logout-btn { background: #888; } 60 #logout-btn:hover { background: #666; } 61 62 .amount-buttons { 63 margin-top: 20px; 64 display: flex; 65 justify-content: center; 66 gap: 10px; 67 } 68 69 .custom-input { 70 width: 120px; 71 padding: 8px; 72 margin-top: 10px; 73 border-radius: 8px; 74 border: 1px solid #ccc; 75 text-align: center; 76 } /* Wallet info section */ 77 #wallet-info { 78 margin-top: 40px; 79 text-align: left; 80 background: #fafafa; 81 padding: 20px; 82 border-radius: 12px; 83 border: 1px solid #eee; 84 line-height: 1.6; 85 } 86 87 #wallet-info h3 { 88 color: #6c2bd9; 89 margin-top: 20px; 90 } 91 92 #wallet-info summary { 93 font-weight: 600; 94 color: #6c2bd9; 95 cursor: pointer; 96 font-size: 1rem; 97 margin-bottom: 8px; 98 } 99 100 #wallet-info p, #wallet-info li { 101 font-size: 0.9rem; 102 } 103 104 #wallet-info ul { 105 padding-left: 18px; 106 } 107 108 .creator-program-notice { 109 margin: 24px 0 8px; 110 padding: 20px; 111 text-align: left; 112 background: linear-gradient(135deg, #f4edff 0%, #ffffff 100%); 113 border: 1px solid #d8c3ff; 114 border-radius: 14px; 115 box-shadow: 0 6px 18px rgba(108, 43, 217, 0.08); 116 } 117 118 .creator-program-notice h3 { 119 margin: 0 0 10px; 120 color: #6c2bd9; 121 font-size: 1.05rem; 122 } 123 124 .creator-program-notice p { 125 margin: 8px 0; 126 font-size: 0.92rem; 127 line-height: 1.55; 128 } 129 130 .creator-program-notice ul { 131 margin: 10px 0; 132 padding-left: 20px; 133 font-size: 0.9rem; 134 line-height: 1.55; 135 } 136 137 .creator-program-badge { 138 display: inline-block; 139 margin-bottom: 10px; 140 padding: 5px 10px; 141 color: #fff; 142 background: #6c2bd9; 143 border-radius: 999px; 144 font-size: 0.75rem; 145 font-weight: 700; 146 letter-spacing: 0.02em; 147 } 148 </style> 149</head> 150 151<body> 152 <div id="app"></div> 153 <div id="wallet-container"> 154 <h2>My Amebo Wallet</h2> 155 <p id="user-email"></p> 156 <div style="margin: 15px 0;"> 157 <h3>Cash Balance: <span id="naira-balance">â¦0</span></h3> 158 <h3>Value Coins: <span id="coin-balance">0 ðª</span></h3> 159 </div> 160 161 <!-- Deposit Section --> 162 <h4>Choose Deposit Amount</h4> 163 <div id="deposit-options" class="amount-buttons"></div> 164 <input 165 id="custom-amount" 166 class="custom-input" 167 placeholder="Custom â¦" 168 type="number" 169 min="100" 170 /> 171 <button id="deposit-btn">Deposit</button> 172 173 <!-- 174 LEGACY WITHDRAWAL BUTTON â intentionally preserved but hidden. 175 Restore only if general wallet withdrawals are enabled again. 176 <button id="withdraw-btn">Withdraw â¦</button> 177 --> 178 179 <section class="creator-program-notice" aria-labelledby="creator-cashout-title"> 180 <span class="creator-program-badge">CREATOR PROGRAM</span> 181 <h3 id="creator-cashout-title">Value Coin cash-out is for approved creators</h3> 182 <p> 183 Value Coins are available to all users for gifting and other in-app activities, 184 but they cannot be converted to cash from this general wallet. 185 </p> 186 <p> 187 Cash-out is available only to creators who have been reviewed and approved for 188 the <strong>Amebo Social Creator Program</strong>. Eligible creator earnings begin 189 after approval and are managed through the creator dashboard in the app. 190 </p> 191 <ul> 192 <li>
192Creator Program access is by approval and is not automatic.</li> 193 <li>Only eligible earnings recorded under an approved creator account can be cashed out.</li> 194 <li>Cash-out remains subject to the creator's tier, minimum payout, verification, and program terms.</li> 195 </ul> 196 <p> 197 Interested in becoming a creator? Contact <strong><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1a73747c755a7b777f7875697579737b7634797577">[email protected]</a></strong> 198 or use the in-app Help Center to ask about Creator Program eligibility. 199 </p> 200 </section> 201 <br /> 202 <button id="logout-btn">Logout</button> 203 <!-- ð§¾ Wallet Information --> 204 <div id="wallet-info"> 205 <details open> 206 <summary>ð¡ How the Amebo Wallet Works</summary> 207 208 <h3>1. Adding Money (Deposits)</h3> 209 <p> 210 Fund your wallet using <strong>Paystack</strong>. Choose a quick preset (â¦500, â¦1000, â¦2000) or enter a custom amount. 211 Deposits are verified automatically, and your balance updates instantly. 212 For every â¦10 you deposit, you earn <strong>1 Value Coin (ðª)</strong>. 213 </p> 214 <p> 215 âï¸ <strong>Deposit Handling Fees:</strong> 216 Amebo Social charges a small <strong>5% handling fee (â¦100 minimum)</strong> plus Paystackâs payment fee 217 <strong>(1.5% + â¦100)</strong>. 218 This ensures your full wallet balance reflects accurately and transactions remain secure. 219</p> 220 221 222 <h3>2. Your Balance</h3> 223 <ul> 224 <li><strong>Cash Balance (â¦):</strong> Real naira amount youâve deposited or earned.</li> 225 <li><strong>Value Coins (ðª):</strong> Internal Amebo coins used for gifting and in-app rewards.</li> 226 </ul> 227 <p><em>Conversion rate:</em> â¦10 = 1 Coin.</p> 228 229 <!-- 230 LEGACY GENERAL-WALLET WITHDRAWAL EXPLANATION â preserved for possible future use. 231 <h3>3. Withdrawals</h3> 232 <p> 233 When you request a withdrawal, itâs marked as <strong>Pending</strong>. 234 The Amebo Wallet Team reviews and manually approves payouts within <strong>24â48 hours</strong>. 235 The minimum amount that can be withdrawn is 1000 VC <strong> â¦10,000 Naira</strong>. 236 </p> 237 <p> 238 Manual approval ensures each request is verified before funds are released â keeping your wallet secure. 239 </p> 240 <h3>âï¸ Withdrawal Fees</h3> 241<p> 242 Withdrawals attract a <strong>10% Amebo handling fee</strong> and a 243 <strong>â¦10 Paystack payout fee</strong>. 244 Example: If you withdraw â¦5,000, youâll receive â¦4,490 after fees. 245</p> 246<p> 247 Fees help maintain instant payouts, system security, and operational costs. 248</p> 249 --> 250 251 <h3>3. Creator Program Cash-Out</h3> 252 <p> 253 General wallet users cannot convert Value Coins to cash. Cash-out is reserved 254 for approved members of the <strong>Amebo Social Creator Program</strong> and is 255 managed through the creator dashboard in the app. 256 </p> 257 <p> 258 Only eligible creator earnings recorded after Creator Program approval qualify. 259 Payout availability depends on the creatorâs active status, tier, minimum payout, 260 account verification, and the current Creator Program terms. 261 </p> 262 263 264 <h3>4. Gifting & Coins</h3> 265 <p> 266 Inside the Amebo Social app, you can gift Value Coins to others. 267 Coins are deducted from your wallet and instantly credited to the recipientâs account. 268 </p> 269 270 <h3>5. Transaction Records</h3> 271 <p> 272 All transactions (deposits, withdrawals, gifts) are logged securely. 273 A full transaction history view will be available soon. 274 </p> 275 276 <h3>6. Security</h3> 277 <p> 278 The wallet is secured by <strong>Clerk Authentication</strong>, <strong>Supabase</strong> for storage, and <strong>Paystack</strong> for payments. 279 All user data and transactions are encrypted. 280 </p> 281 282 <h3>7. Coming Soon</h3> 283 <ul> 284 <!-- Legacy roadmap item: <li>Automated withdrawals via Paystack</li> --> 285 <li>More Creator Program earning insights</li> 286 <li>Full transaction history dashboard</li> 287 <li>Referral bonuses & coin analytics</li> 288 </ul> 289 290 <h3>8. Support</h3> 291 <p> 292 Need help? Contact <strong><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4f262129200f2e222a2d203c202c262e23612c2022">[email protected]</a></strong> or message us through the in-app Help Center. 293 </p> 294 </details> 295 </div> 296 </div>
vendor: 110 bytes, lines 296-298
296 297 298<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
298<script> 299 window.addEventListener("load", async function () { 300 const SUPABASE_URL = "https://rdprzxtffdzzunlxveag.supabase.co"; 301 const SUPABASE_ANON_KEY = 302 "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJkcHJ6eHRmZmR6enVubHh2ZWFnIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTc5NTcyMjEsImV4cCI6MjA3MzUzMzIyMX0.yS1Qqsp2C7V2lJKebN70IdmyoswyXpSikkjBICoXvN4"; 303 304 const VERIFY_FUNCTION_URL = 305 "https://rdprzxtffdzzunlxveag.supabase.co/functions/v1/verify-paystack"; 306 307 function calculateFees(amount) { 308 const paystackFee = Math.min(amount * 0.015 + 100, 2000); 309 const ameboFee = Math.max(amount * 0.05, 100); 310 const totalFee = paystackFee + ameboFee; 311 const totalToPay = amount + totalFee; 312 return { paystackFee, ameboFee, totalFee, totalToPay }; 313 } 314 315 try { 316 await Clerk.load(); 317 318 const app = document.getElementById("app"); 319 const walletContainer = document.getElementById("wallet-container"); 320 321 if (!app) { 322 throw new Error("Missing #app container"); 323 } 324 325 if (!walletContainer) { 326 throw new Error("Missing #wallet-container"); 327 } 328 329 if (!window.supabase) { 330 throw new Error("Supabase script did not load"); 331 } 332 333 if (typeof window.PaystackPop === "undefined") { 334 throw new Error("Paystack script did not load"); 335 } 336 337 if (!Clerk.isSignedIn) { 338 app.innerHTML = `<div id="sign-in"></div>`; 339 Clerk.mountSignIn(document.getElementById("sign-in")); 340 return; 341 } 342 343 app.innerHTML = ""; 344 walletContainer.classList.add("active"); 345 346 const token = await Clerk.session.getToken({ template: "supabase" }); 347 const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY, { 348 global: { headers: { Authorization: `Bearer ${token}` } }, 349 }); 350 351 const user = Clerk.user; 352 const clerkId = user.id.toLowerCase(); 353 const email = user.primaryEmailAddress.emailAddress; 354 355 document.getElementById("user-email").innerText = email; 356 357 const { data: wallet, error } = await supabase 358 .from("wallets") 359 .select("*") 360 .eq("clerk_user_id", clerkId) 361 .maybeSingle(); 362 363 if (error) throw error; 364 365 let userWallet = wallet; 366 367 if (!userWallet) { 368 const { data: newWallet, error: insertError } = await supabase 369 .from("wallets") 370 .insert([{ clerk_user_id: clerkId, email, balance: 0 }]) 371 .select() 372 .single(); 373 374 if (insertError) throw insertError; 375 userWallet = newWallet; 376 } 377 378 document.getElementById("naira-balance").innerText = `â¦${userWallet.balance || 0}`; 379 document.getElementById("coin-balance").innerText = `${userWallet.coins_balance || 0} ðª`; 380 381 const amounts = [1000, 5000, 10000]; 382 const optionsDiv = document.getElementById("deposit-options"); 383 optionsDiv.innerHTML = amounts 384 .map((a) => `<button type="button" data-amount="${a}">â¦${a}</button>`) 385 .join(""); 386 387 optionsDiv.querySelectorAll("button").forEach((btn) => { 388 btn.addEventListener("click", () => { 389 const amount = parseInt(btn.dataset.amount, 10); 390 startPaystack(amount); 391 }); 392 }); 393 394 document.getElementById("deposit-btn").onclick = function () { 395 const customAmount = parseInt(document.getElementById("custom-amount").value, 10); 396 if (!isNaN(customAmount) && customAmount > 0) { 397 startPaystack(customAmount); 398 } else { 399 alert("Enter a valid amount or select a preset."); 400 } 401 }; 402 403 function startPaystack(amount) { 404 const { paystackFee, ameboFee, totalToPay } = calculateFees(amount); 405 406 const confirmMsg = ` 407Youâre depositing â¦${amount}. 408Paystack fee: â¦${paystackFee.toFixed(0)} 409Amebo fee (5%): â¦${ameboFee.toFixed(0)} 410------------------------------ 411Total charged: â¦${totalToPay.toFixed(0)} 412 `; 413 414 if (!confirm(confirmMsg)) return; 415 416 const handler = PaystackPop.setup({ 417 key: "pk_live_3285337249c902b9727ffa42be50f06720e03048", 418 email, 419 amount: totalToPay * 100, 420 currency: "NGN", 421 metadata: { 422 custom_fields: [ 423 { display_name: "Amebo Fee", value: `â¦${ameboFee.toFixed(0)}` }, 424 { display_name: "Paystack Fee", value: `â¦${paystackFee.toFixed(0)}` }, 425 ], 426 }, 427 callback: function (response) { 428 if (!response || !response.reference) { 429 alert("No reference returned from Paystack!"); 430 return; 431 } 432 433 (async () => { 434 try { 435 const verifyRes = await fetch(VERIFY_FUNCTION_URL, { 436 method: "POST", 437 headers: { 438 "Content-Type": "application/json", 439 Authorization: "Bearer " + SUPABASE_ANON_KEY, 440 }, 441 body: JSON.stringify({ 442 reference: response.reference, 443 clerk_user_id: clerkId, 444 }), 445 }); 446 447 const result = await verifyRes.json(); 448 449 if (result.success) { 450 alert( 451 `â Deposit verified! â¦${amount} credited (â¦${ameboFee.toFixed(0)} Amebo fee + â¦${paystackFee.toFixed(0)} Paystack fee applied).` 452 ); 453 window.location.reload(); 454 } else { 455 alert("â Deposit verification failed: " + (result.error || "Unknown error")); 456 } 457 } catch (err) { 458 console.error("Error verifying payment:", err); 459 alert("Something went wrong verifying your payment."); 460 } 461 })(); 462 }, 463 onClose: function () { 464 alert("Transaction cancelled."); 465 }, 466 }); 467 468 handler.openIframe(); 469 } 470 471 document.getElementById("logout-btn").onclick = async () => { 472 await Clerk.signOut(); 473 window.location.reload(); 474 }; 475 476 /* 477 * LEGACY GENERAL-WALLET WITHDRAWAL HANDLER
478 * Intentionally preserved but disabled while cash-out is limited to 479 * approved Creator Program accounts. Restore together with #withdraw-btn 480 * only if general wallet withdrawals are enabled again. 481 * 482 document.getElementById("withdraw-btn").onclick = async () => { 483 const withdrawAmount = prompt("Enter amount to withdraw (â¦):"); 484 if (!withdrawAmount) return; 485 486 const amount = parseInt(withdrawAmount, 10); 487 if (isNaN(amount) || amount <= 0) { 488 alert("Please enter a valid amount."); 489 return; 490 } 491 492 const { data: latestWallet, error: fetchErr } = await supabase 493 .from("wallets") 494 .select("*") 495 .eq("clerk_user_id", clerkId) 496 .maybeSingle(); 497 498 if (fetchErr) { 499 alert("Error fetching wallet. Try again."); 500 console.error(fetchErr); 501 return; 502 } 503 504 if (!latestWallet || latestWallet.balance < amount) { 505 alert("â Insufficient balance."); 506 return; 507 } 508 509 const bankName = prompt("Enter your bank name:"); 510 const accountNumber = prompt("Enter your account number (10 digits):"); 511 const accountName = prompt("Enter account name:"); 512 513 if (!bankName || !accountNumber || !accountName) { 514 alert("Please fill all bank details."); 515 return; 516 } 517 518 try { 519 const WITHDRAW_FUNCTION_URL = 520 "https://rdprzxtffdzzunlxveag.supabase.co/functions/v1/withdraw-funds"; 521 522 const withdrawRes = await fetch(WITHDRAW_FUNCTION_URL, { 523 method: "POST", 524 headers: { 525 "Content-Type": "application/json", 526 Authorization: "Bearer " + SUPABASE_ANON_KEY, 527 }, 528 body: JSON.stringify({ 529 clerk_user_id: clerkId, 530 email, 531 amount, 532 bank_name: bankName, 533 account_number: accountNumber, 534 account_name: accountName, 535 }), 536 }); 537 538 const result = await withdrawRes.json(); 539 540 if (result.success) { 541 alert(`â Withdrawal of â¦${amount} initiated successfully!`); 542 window.location.reload(); 543 } else { 544 alert("â Withdrawal failed: " + (result.error || "Unknown error")); 545 } 546 } catch (err) { 547 console.error("â Withdrawal error:", err); 548 alert("Something went wrong processing withdrawal."); 549 } 550 }; 551 */ 552 } catch (err) { 553 console.error("â Error initializing wallet:", err); 554 alert("Could not load your wallet. Check console for details."); 555 } 556 }); 557</script>
557 558</body>
559<script>'undefined'=== typeof _trfq || (window._trfq = []);'undefined'=== typeof _trfd && (window._trfd=[]),_trfd.push({'tccl.baseHost':'secureserver.net'},{'ap':'cpsh-oh'},{'server':'p3plzcpnl509555'},{'dcenter':'p3'},{'cp_id':'10465300'},{'cp_cl':'8'}) // Monitoring performance to make your website faster. If you want to opt-out, please contact web hosting support.</script>
559<script src='https://img1.wsimg.com/traffic-assets/js/tccl.min.js'></script>
559</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.