Sign a message

When a web application is connected to Jelli, it can also request that the user signs a given message. Applications are free to write their own messages which will be displayed to users from within Jelli's signature prompt. Message signatures do not involve network fees and are a convenient way for apps to verify ownership of an address.

πŸ” Message Signing Methods

Jelli supports two message signing methods, both 100% compatible with Phantom wallet:

Method 1: Direct signMessage()

Signature: signMessage(message: Uint8Array, encoding?: string): Promise<SignedMessage>

const provider = getProvider();
await provider.connect(); // Must connect first

const message = "To avoid digital dognappers, sign below to authenticate with CryptoCorgis";
const encodedMessage = new TextEncoder().encode(message);

try {
    const result = await provider.signMessage(encodedMessage, "utf8");
    
    console.log('βœ… Message signed successfully!');
    console.log('Signature:', result.signature);     // Uint8Array (64 bytes)
    console.log('Public Key:', result.publicKey);    // PublicKey object
    console.log('Address:', result.publicKey.toString()); // Base58 address
} catch (error) {
    console.error('❌ Signing failed:', error.message);
}

Method 2: JSON RPC request()

Signature: request(params: { method: string, params: object }): Promise<SignedMessage>

const provider = getProvider();
await provider.connect(); // Must connect first

const message = "To avoid digital dognappers, sign below to authenticate with CryptoCorgis";
const encodedMessage = new TextEncoder().encode(message);

try {
    const result = await provider.request({
        method: "signMessage",
        params: {
            message: encodedMessage,
            display: "hex", // or "utf8"
        },
    });
    
    console.log('βœ… Message signed successfully!');
    console.log('Signature:', result.signature);     // Uint8Array (64 bytes)
    console.log('Public Key:', result.publicKey);    // PublicKey object
} catch (error) {
    console.error('❌ Signing failed:', error.message);
}

Input Requirements

  • Message Format: Hex or UTF-8 encoded string as Uint8Array

  • Connection: Wallet must be connected before signing

  • Encoding: Supports both "utf8" and "hex" display formats

Return Value Structure

Both methods return the same structure:

interface SignedMessage {
    signature: Uint8Array;  // 64-byte Ed25519 signature
    publicKey: PublicKey;   // Solana PublicKey object
}

βœ… Signature Verification

Jelli uses Ed25519 signatures compatible with the tweetnacl library (same as Phantom):

import nacl from 'tweetnacl';

// After signing a message
const message = new TextEncoder().encode("Your message here");
const signedMessage = await provider.signMessage(message, "utf8");

// Verify the signature
const publicKeyBytes = signedMessage.publicKey.toBytes(); // Convert to Uint8Array
const isValid = nacl.sign.detached.verify(
    message,                    // Original message
    signedMessage.signature,    // Signature from Jelli
    publicKeyBytes             // Public key as Uint8Array
);

console.log('Signature valid:', isValid); // true/false

Verification Example with Manual Public Key

// If you have the public key as a string
const publicKeyString = "YourBase58PublicKeyHere";
const publicKeyBytes = bs58.decode(publicKeyString); // Requires bs58 library

const isValid = nacl.sign.detached.verify(message, signature, publicKeyBytes);

Sign-In with Solana (SIWS)

Coming soon πŸ”œ

Last updated