| |
|
|
| export type Hex = `0x${string}` |
|
|
| export type Address = Hex |
|
|
| export type EIP1193EventMap = { |
| accountsChanged(accounts: Address[]): void |
| chainChanged(chainId: string): void |
| connect(connectInfo: { chainId: string }): void |
| disconnect(error: { code: number; message: string }): void |
| message(message: { type: string; data: unknown }): void |
| } |
|
|
| export type EIP1193Events = { |
| on<event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]): void |
| removeListener<event extends keyof EIP1193EventMap>( |
| event: event, |
| listener: EIP1193EventMap[event] |
| ): void |
| } |
|
|
| export type EIP1193RequestFn = (args: { method: string; params?: unknown }) => Promise<unknown> |
|
|
| export type EIP1193Provider = EIP1193Events & { |
| address: string |
| request: EIP1193RequestFn |
| } |
|
|
| export type EthereumWallet = EIP1193Provider |
|
|
| |
| |
| |
| export type SiweMessage = { |
| |
| |
| |
| address: Address |
| |
| |
| |
| chainId: number |
| |
| |
| |
| domain: string |
| |
| |
| |
| expirationTime?: Date | undefined |
| |
| |
| |
| issuedAt?: Date | undefined |
| |
| |
| |
| nonce?: string |
| |
| |
| |
| notBefore?: Date | undefined |
| |
| |
| |
| requestId?: string | undefined |
| |
| |
| |
| resources?: string[] | undefined |
| |
| |
| |
| scheme?: string | undefined |
| |
| |
| |
| statement?: string | undefined |
| |
| |
| |
| uri: string |
| |
| |
| |
| version: '1' |
| } |
|
|
| export type EthereumSignInInput = SiweMessage |
|
|
| export function getAddress(address: string): Address { |
| if (!/^0x[a-fA-F0-9]{40}$/.test(address)) { |
| throw new Error(`@supabase/auth-js: Address "${address}" is invalid.`) |
| } |
| return address.toLowerCase() as Address |
| } |
|
|
| export function fromHex(hex: Hex): number { |
| return parseInt(hex, 16) |
| } |
|
|
| export function toHex(value: string): Hex { |
| const bytes = new TextEncoder().encode(value) |
| const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('') |
| return ('0x' + hex) as Hex |
| } |
|
|
| |
| |
| |
| export function createSiweMessage(parameters: SiweMessage): string { |
| const { |
| chainId, |
| domain, |
| expirationTime, |
| issuedAt = new Date(), |
| nonce, |
| notBefore, |
| requestId, |
| resources, |
| scheme, |
| uri, |
| version, |
| } = parameters |
|
|
| |
| { |
| if (!Number.isInteger(chainId)) |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "chainId". Chain ID must be a EIP-155 chain ID. Provided value: ${chainId}` |
| ) |
|
|
| if (!domain) |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "domain". Domain must be provided.` |
| ) |
|
|
| if (nonce && nonce.length < 8) |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "nonce". Nonce must be at least 8 characters. Provided value: ${nonce}` |
| ) |
|
|
| if (!uri) |
| throw new Error(`@supabase/auth-js: Invalid SIWE message field "uri". URI must be provided.`) |
|
|
| if (version !== '1') |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "version". Version must be '1'. Provided value: ${version}` |
| ) |
|
|
| if (parameters.statement?.includes('\n')) |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "statement". Statement must not include '\\n'. Provided value: ${parameters.statement}` |
| ) |
| } |
|
|
| |
| const address = getAddress(parameters.address) |
| const origin = scheme ? `${scheme}://${domain}` : domain |
| const statement = parameters.statement ? `${parameters.statement}\n` : '' |
| const prefix = `${origin} wants you to sign in with your Ethereum account:\n${address}\n\n${statement}` |
|
|
| let suffix = `URI: ${uri}\nVersion: ${version}\nChain ID: ${chainId}${ |
| nonce ? `\nNonce: ${nonce}` : '' |
| }\nIssued At: ${issuedAt.toISOString()}` |
|
|
| if (expirationTime) suffix += `\nExpiration Time: ${expirationTime.toISOString()}` |
| if (notBefore) suffix += `\nNot Before: ${notBefore.toISOString()}` |
| if (requestId) suffix += `\nRequest ID: ${requestId}` |
| if (resources) { |
| let content = '\nResources:' |
| for (const resource of resources) { |
| if (!resource || typeof resource !== 'string') |
| throw new Error( |
| `@supabase/auth-js: Invalid SIWE message field "resources". Every resource must be a valid string. Provided value: ${resource}` |
| ) |
| content += `\n- ${resource}` |
| } |
| suffix += content |
| } |
|
|
| return `${prefix}\n${suffix}` |
| } |
|
|