Skip to main content

EIP-191 (personal_sign)

<script lang="ts">
  import { SunbreakProvider } from '@tdfc/sunbreak-svelte';
  import type { Proof } from '@tdfc/sunbreak-svelte';
  import { PUBLIC_SUNBREAK_CLIENT_ID, PUBLIC_SUNBREAK_BASE } from '$env/static/public';

  let address = $state('');
  let proof = $state<Proof | null>(null);

  async function connect() {
    const eth = (window as any).ethereum;
    if (!eth) { alert('No injected EVM wallet found'); return; }
    const accounts: string[] = await eth.request({ method: 'eth_requestAccounts' });
    address = (accounts[0] ?? '').toLowerCase();
  }

  function disconnect() {
    address = '';
    proof = null;
  }

  async function sign() {
    if (!address) return;
    const msg = `Sign in to Sunbreak @ ${window.location.host}`;
    const sig: string = await (window as any).ethereum.request({
      method: 'personal_sign',
      params: [msg, address],
    });
    proof = { method: 'eip191', message: msg, signature: sig };
  }
</script>

<SunbreakProvider
  baseUrl={PUBLIC_SUNBREAK_BASE}
  clientId={PUBLIC_SUNBREAK_CLIENT_ID}
  wallet={address || undefined}
  {proof}
>
  <button onclick={connect}>Connect</button>
  <button onclick={sign} disabled={!address}>Sign</button>
  <button onclick={disconnect}>Disconnect</button>
</SunbreakProvider>

SIWE (EIP-4361)

For a full SIWE message, build the message string per the EIP-4361 spec and use method: 'siwe':
proof = { method: 'siwe', message: siweMessage, signature: sig };
The signing call is the same (personal_sign), but the message follows the structured SIWE format with domain, nonce, chain ID, and expiry.