| <!DOCTYPE html> |
| <html lang="vi"> |
| <head> |
| <meta charset="UTF-8" /> |
| <title>Solana IDM Demo – Fixed Buffer</title> |
| <style> |
| body { font-family: sans-serif; padding: 20px; max-width: 500px; margin: auto; } |
| input, textarea, button { width: 100%; margin-top: 10px; padding: 10px; font-size: 16px; } |
| button { background: #4CAF50; color: white; border: none; cursor: pointer; } |
| button:hover { background: #45a049; } |
| </style> |
| </head> |
| <body> |
| <h2>📨 Gửi Tin nhắn (IDM) qua Solana</h2> |
| <button onclick="connectWallet()">🔌 Kết nối ví Phantom</button> |
| <div id="wallet-address" style="margin-top:10px; font-weight: bold;"></div> |
|
|
| <input type="text" id="recipient" placeholder="🎯 Nhập địa chỉ ví người nhận (ví dụ: của bạn)"> |
| <textarea id="message" rows="4" placeholder="💬 Nhập nội dung IDM (Memo)"></textarea> |
| <button onclick="sendMemo()">📤 Gửi IDM</button> |
|
|
| <div id="result" style="margin-top: 15px;"></div> |
|
|
| |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/buffer/6.0.3/buffer.min.js"></script> |
| <script> |
| window.global = window; |
| window.Buffer = buffer.Buffer; |
| </script> |
|
|
| |
| <script src="https://cdn.jsdelivr.net/npm/@solana/web3.js@1.77.2/lib/index.iife.min.js"></script> |
|
|
| <script> |
| let provider = null; |
| |
| async function connectWallet() { |
| if ('solana' in window) { |
| provider = window.solana; |
| if (provider.isPhantom) { |
| try { |
| const resp = await provider.connect(); |
| document.getElementById("wallet-address").innerText = "🪪 Đã kết nối: " + resp.publicKey.toString(); |
| } catch (err) { |
| alert("Kết nối bị từ chối!"); |
| } |
| } else { |
| alert("Cài ví Phantom trước nhé!"); |
| } |
| } else { |
| alert("Trình duyệt không tìm thấy ví Solana."); |
| } |
| } |
| |
| async function sendMemo() { |
| const connection = new solanaWeb3.Connection(solanaWeb3.clusterApiUrl('devnet')); |
| const recipient = document.getElementById("recipient").value.trim(); |
| const message = document.getElementById("message").value.trim(); |
| |
| if (!provider || !provider.publicKey) { |
| alert("Bạn chưa kết nối ví Phantom!"); |
| return; |
| } |
| if (!recipient || !message) { |
| alert("Vui lòng nhập đầy đủ địa chỉ và nội dung."); |
| return; |
| } |
| |
| try { |
| const transaction = new solanaWeb3.Transaction(); |
| |
| transaction.add(solanaWeb3.SystemProgram.transfer({ |
| fromPubkey: provider.publicKey, |
| toPubkey: new solanaWeb3.PublicKey(recipient), |
| lamports: 0 |
| })); |
| |
| transaction.add(new solanaWeb3.TransactionInstruction({ |
| keys: [], |
| programId: new solanaWeb3.PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"), |
| data: new TextEncoder().encode(message) |
| })); |
| |
| transaction.feePayer = provider.publicKey; |
| const blockhashObj = await connection.getLatestBlockhash(); |
| transaction.recentBlockhash = blockhashObj.blockhash; |
| |
| const signed = await provider.signTransaction(transaction); |
| const txid = await connection.sendRawTransaction(signed.serialize()); |
| |
| await connection.confirmTransaction(txid); |
| document.getElementById("result").innerHTML = |
| `✅ Đã gửi! <br>🧾 TxID: <a href="https://explorer.solana.com/tx/${txid}?cluster=devnet" target="_blank">${txid}</a>`; |
| |
| } catch (err) { |
| console.error("Lỗi khi gửi giao dịch:", err); |
| document.getElementById("result").innerText = "❌ Gửi thất bại: " + err.message; |
| } |
| } |
| </script> |
| </body> |
| </html> |
|
|