Skip to content

Instantly share code, notes, and snippets.

@danfinlay
Created March 18, 2025 20:38
Show Gist options
  • Save danfinlay/5e2d916c0de79a1073889960d3cade35 to your computer and use it in GitHub Desktop.
Save danfinlay/5e2d916c0de79a1073889960d3cade35 to your computer and use it in GitHub Desktop.
MetaMask Snaps Internal UI Generating API Documentation

MetaMask Snaps JSON-RPC UI API Documentation

This documentation covers the JSON-RPC methods provided by the SnapInterfaceController for generating user interfaces in MetaMask Snaps.

Overview

The MetaMask Snaps platform provides a JSON-RPC API for Snaps (third-party extensions) to create and interact with user interfaces within the MetaMask environment. These interfaces allow Snaps to display information, collect user input, and provide interactive experiences without requiring direct DOM access.

Available Methods

snap_dialog

Displays a dialog to the user with customizable content and interface elements.

Parameters

interface DialogParams {
  type: DialogType;
  content: DialogContent;
}

type DialogType = 'alert' | 'confirmation' | 'prompt';

type DialogContent = {
  prompt?: string;
  description?: string;
  placeholder?: string;
  textAreaContent?: string | null;
};

Dialog Types

  1. Alert: Displays a message to the user with an acknowledgment button.
  2. Confirmation: Asks the user to confirm or reject an action.
  3. Prompt: Requests text input from the user.

Returns

  • For alert: Returns null when the user acknowledges the alert.
  • For confirmation: Returns true if the user confirms, false if they reject.
  • For prompt: Returns the user-entered string if confirmed, or null if canceled.

Example Usage

// Display an alert
await ethereum.request({
  method: 'snap_dialog',
  params: {
    type: 'alert',
    content: {
      prompt: 'Operation Successful',
      description: 'Your transaction has been submitted to the network.'
    }
  }
});

// Request confirmation
const confirmed = await ethereum.request({
  method: 'snap_dialog',
  params: {
    type: 'confirmation',
    content: {
      prompt: 'Confirm Transaction',
      description: 'Do you want to send 0.1 ETH to 0x1234...?'
    }
  }
});

// Request user input
const userInput = await ethereum.request({
  method: 'snap_dialog',
  params: {
    type: 'prompt',
    content: {
      prompt: 'Enter password',
      description: 'Please provide your password to continue',
      placeholder: 'Password'
    }
  }
});

snap_manageState

Allows a Snap to manage its persistent state.

Parameters

interface ManageStateParams {
  operation: ManageStateOperation;
  newState?: Record<string, unknown>;
}

type ManageStateOperation = 'clear' | 'get' | 'update';

Operations

  1. get: Retrieves the current state.
  2. update: Updates the state with new values.
  3. clear: Clears all stored state.

Returns

  • For get: Returns the current state object.
  • For update: Returns null after updating.
  • For clear: Returns null after clearing.

Example Usage

// Get current state
const state = await ethereum.request({
  method: 'snap_manageState',
  params: { operation: 'get' }
});

// Update state
await ethereum.request({
  method: 'snap_manageState',
  params: {
    operation: 'update',
    newState: { userPreference: 'dark-mode' }
  }
});

// Clear state
await ethereum.request({
  method: 'snap_manageState',
  params: { operation: 'clear' }
});

snap_notify

Displays a notification to the user.

Parameters

interface NotifyParams {
  type: NotificationType;
  message: string;
}

type NotificationType = 'native' | 'inApp';

Notification Types

  1. native: Sends a native system notification.
  2. inApp: Displays a notification within the MetaMask interface.

Returns

Returns null after showing the notification.

Example Usage

// Display an in-app notification
await ethereum.request({
  method: 'snap_notify',
  params: {
    type: 'inApp',
    message: 'Transaction confirmed!'
  }
});

// Send a native system notification
await ethereum.request({
  method: 'snap_notify',
  params: {
    type: 'native',
    message: 'Your funds have arrived'
  }
});

snap_createInterface

Creates a custom interface element that can be displayed to the user.

Parameters

interface CreateInterfaceParams {
  ui: InterfaceDefinition;
}

type InterfaceDefinition = {
  type: string;
  // Additional properties depend on the interface type
};

Returns

Returns an interface handle that can be used with other interface methods.

Example Usage

// Create a custom form interface
const interfaceHandle = await ethereum.request({
  method: 'snap_createInterface',
  params: {
    ui: {
      type: 'form',
      fields: [
        {
          type: 'text',
          label: 'Username',
          name: 'username',
          required: true
        },
        {
          type: 'password',
          label: 'Password',
          name: 'password',
          required: true
        }
      ],
      submitButton: 'Login'
    }
  }
});

snap_showInterface

Displays a previously created interface to the user.

Parameters

interface ShowInterfaceParams {
  interfaceId: string;
}

Returns

Returns data based on user interaction with the interface.

Example Usage

// Show a previously created interface
const userResponse = await ethereum.request({
  method: 'snap_showInterface',
  params: {
    interfaceId: interfaceHandle
  }
});

snap_getInterfaceState

Retrieves the current state of a created interface.

Parameters

interface GetInterfaceStateParams {
  interfaceId: string;
}

Returns

Returns the current state of the specified interface.

Example Usage

// Get the current state of an interface
const interfaceState = await ethereum.request({
  method: 'snap_getInterfaceState',
  params: {
    interfaceId: interfaceHandle
  }
});

snap_updateInterface

Updates an existing interface with new properties or content.

Parameters

interface UpdateInterfaceParams {
  interfaceId: string;
  updates: Partial<InterfaceDefinition>;
}

Returns

Returns null after updating the interface.

Example Usage

// Update an existing interface
await ethereum.request({
  method: 'snap_updateInterface',
  params: {
    interfaceId: interfaceHandle,
    updates: {
      fields: [
        // Updated field definitions
      ]
    }
  }
});

snap_dismissInterface

Dismisses a currently displayed interface.

Parameters

interface DismissInterfaceParams {
  interfaceId: string;
}

Returns

Returns null after dismissing the interface.

Example Usage

// Dismiss an interface
await ethereum.request({
  method: 'snap_dismissInterface',
  params: {
    interfaceId: interfaceHandle
  }
});

Error Handling

All methods may throw errors with the following structure:

interface SnapRpcError {
  code: number;
  message: string;
  data?: unknown;
}

Common error codes:

  • -32603: Internal error
  • -32602: Invalid parameters
  • -32001: User rejected request
  • -32000: Method not supported

Security Considerations

  • All UI interactions require user approval and are subject to the permissions granted to the Snap.
  • Snaps should handle user rejection gracefully, as users may dismiss dialogs or reject confirmations.
  • State management should implement proper validation to prevent injection attacks.

Best Practices

  1. Keep dialog messages clear and concise.
  2. Provide adequate context for confirmation requests.
  3. Use appropriate dialog types for the required interaction.
  4. Implement proper error handling for rejected requests.
  5. Minimize the frequency of notifications to avoid overwhelming users.
  6. Follow MetaMask's design guidelines when creating custom interfaces.
  7. Always validate and sanitize user input received through prompts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment