import { useState } from "react";
import bs58 from "bs58";
import nacl from "tweetnacl";
import { Buffer } from "buffer";
function App() {
const [token, setToken] = useState("");
const [status, setStatus] = useState("");
const [address, setAddress] = useState("");
const [loading, setLoading] = useState(false);
const authMessage = "I accept Loop Crypto Inc's Terms of Service";
async function generateAuthToken() {
try {
setLoading(true);
if (!window.solana || !window.solana.isPhantom) {
throw new Error("Phantom wallet is not installed");
}
const resp = await window.solana.connect();
const walletAddress = resp.publicKey.toString();
setAddress(walletAddress);
const encodedMessage = new TextEncoder().encode(authMessage);
const { signature: signatureBytes } = await window.solana.request({
method: "signMessage",
params: {
message: encodedMessage,
display: "utf8",
},
});
const signature = Buffer.from(signatureBytes).toString("base64");
setToken(signature);
setStatus("Signature generated successfully!");
console.log("Wallet Address:", walletAddress);
console.log("Signature:", signature);
// Verify the signature
const verified = nacl.sign.detached.verify(
encodedMessage,
Buffer.from(signature, "base64"),
resp.publicKey.toBytes()
);
console.log("Signature Verified:", verified);
} catch (error) {
console.error(error);
setStatus(`Error: ${error.message}`);
} finally {
setLoading(false);
}
}
const styles = {
container: {
maxWidth: "800px",
margin: "40px auto",
padding: "0 20px",
fontFamily: "Arial, sans-serif",
},
button: {
padding: "10px 20px",
margin: "20px 0",
cursor: "pointer",
backgroundColor: "#0066cc",
color: "white",
border: "none",
borderRadius: "4px",
},
pre: {
backgroundColor: "#f5f5f5",
padding: "15px",
borderRadius: "4px",
overflowX: "auto",
wordWrap: "break-word",
whiteSpace: "pre-wrap",
},
section: {
marginTop: "20px",
},
};
return (
<div style={styles.container}>
<h1>API Authentication Token Generator</h1>
<p>
Generate a token to authenticate with the API using your wallet.
</p>
<button
onClick={generateAuthToken}
disabled={loading}
style={styles.button}
>
{loading ? "Connecting..." : "Connect Wallet & Generate Token"}
</button>
{address && (
<div style={styles.section}>
<h3>Connected Address</h3>
<pre style={styles.pre}>{address}</pre>
</div>
)}
{status && (
<div style={styles.section}>
<h3>Status</h3>
<div
style={{
color: status.includes("Error")
? "#dc3545"
: "#198754",
}}
>
{status}
</div>
</div>
)}
{token && (
<div style={styles.section}>
<h3>Generated Token</h3>
<pre style={styles.pre}>{token}</pre>
</div>
)}
</div>
);
}
export default App;