import { describe, it, expect } from "vitest"; import { base58 } from "@scure/base"; import nacl from "tweetnacl"; import { ProofStatus, ProofTypes, SignatureProof, } from "@notabene/javascript-sdk"; import { verifySolanaSignature, verifySolanaSIWS } from "../solana"; describe("verifySolanaSignature", () => { const keypair = nacl.sign.keyPair(); const address = base58.encode(keypair.publicKey); it("verifies valid Solana signature", async () => { // Generate a test keypair const message = "Test message"; const messageBytes = new TextEncoder().encode(message); const signature = nacl.sign.detached(messageBytes, keypair.secretKey); const proof: SignatureProof = { type: ProofTypes.ED25519, status: ProofStatus.PENDING, did: `did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`, address: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`, attestation: message, proof: Buffer.from(signature).toString("base64"), wallet_provider: "Phantom", }; const result = await verifySolanaSignature(proof); expect(result.status).toBe(ProofStatus.VERIFIED); }); it("fails for invalid signature", async () => { const proof: SignatureProof = { type: ProofTypes.ED25519, status: ProofStatus.PENDING, did: `did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`, address: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${address}`, attestation: "Test message", proof: "invalid_signature", wallet_provider: "Phantom", }; const result = await verifySolanaSignature(proof); expect(result.status).toBe(ProofStatus.FAILED); }); it("fails for non-Solana address", async () => { const proof: SignatureProof = { type: ProofTypes.ED25519, status: ProofStatus.PENDING, did: "did:pkh:eth:0x1234567890123456789012345678901234567890", address: "eth:1:0x1234567890123456789012345678901234567890", attestation: "Test message", proof: "some_signature", wallet_provider: "MetaMask", }; const result = await verifySolanaSignature(proof); expect(result.status).toBe(ProofStatus.FAILED); }); }); describe("verifySolanaSIWS", () => { it("verifies valid Solana SIWS signature", async () => { // Generate a test keypair for SIWS const keypair = nacl.sign.keyPair(); const publicKeyBase58 = base58.encode(keypair.publicKey); // Create SIWS message with current timestamp const now = new Date(); const issuedAt = now.toISOString(); const expirationTime = new Date(now.getTime() + 24 * 60 * 60 * 1000).toISOString(); // 24h from now const siwsMessage = { domain: "localhost:8000", address: publicKeyBase58, statement: "Please sign this message to confirm your identity", version: "1", nonce: "9lduy1osnx", chainId: "mainnet", issuedAt, expirationTime, resources: ["https://notabene.id"] }; // Create the message string according to SIWS format const messageString = `${siwsMessage.domain} wants you to sign in with your Solana account: ${siwsMessage.address} ${siwsMessage.statement} Version: ${siwsMessage.version} Chain ID: ${siwsMessage.chainId} Nonce: ${siwsMessage.nonce} Issued At: ${siwsMessage.issuedAt} Expiration Time: ${siwsMessage.expirationTime} Resources: - ${siwsMessage.resources[0]}`; // Sign the message const messageBytes = new TextEncoder().encode(messageString); const signature = nacl.sign.detached(messageBytes, keypair.secretKey); const proof: SignatureProof = { address: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${publicKeyBase58}`, type: ProofTypes.SOL_SIWX, proof: Buffer.from(signature).toString("base64"), attestation: "Please sign this message to confirm your identity", wallet_provider: "SIWX - Phantom", did: `did:pkh:solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:${publicKeyBase58}`, status: ProofStatus.PENDING, chainSpecificData: { account: { publicKey: keypair.publicKey, address: publicKeyBase58, }, signedMessage: messageBytes, signature: signature, message: siwsMessage, }, }; const result = await verifySolanaSIWS(proof); expect(result.status).toBe(ProofStatus.VERIFIED); }); });