Skip to main content

Snaps entry points

Snaps can expose the following entry points.

onCronjob

To run cron jobs for the user, a Snap must expose the onCronjob entry point. MetaMask calls the onCronjob handler method at the specified schedule with the requests defined in the endowment:cronjob permission.

note

For MetaMask to call the Snap's onCronjob method, you must request the endowment:cronjob permission.

Parameters

An object containing an RPC request specified in the endowment:cronjob permission.

Example

index.ts
import type { OnCronjobHandler } from "@metamask/snaps-sdk";

export const onCronjob: OnCronjobHandler = async ({ request }) => {
switch (request.method) {
case "exampleMethodOne":
return snap.request({
method: "snap_notify",
params: {
type: "inApp",
message: "Hello, world!",
},
});

default:
throw new Error("Method not found.");
}
};

onHomePage

To build an embedded UI in MetaMask that any user can access through the Snaps menu, a Snap must expose the onHomePage entry point. MetaMask calls the onHomePage handler method when the user selects the Snap name in the Snaps menu.

note

For MetaMask to call the Snap's onHomePage method, you must request the endowment:page-home permission.

Parameters

None.

Returns

One of the following:

Example

index.ts
import type { OnHomePageHandler } from "@metamask/snaps-sdk";
import { panel, text, heading } from "@metamask/snaps-sdk";

export const onHomePage: OnHomePageHandler = async () => {
return {
content: panel([
heading("Hello world!"),
text("Welcome to my Snap home page!"),
]),
};
};

onInstall

To implement a lifecycle hook that runs an action upon installation, a Snap must expose the onInstall entry point. MetaMask calls the onInstall handler method after the Snap is installed successfully.

note

For MetaMask to call the Snap's onInstall method, you must request the endowment:lifecycle-hooks permission.

Parameters

None.

Example

index.ts
import type { OnInstallHandler } from "@metamask/snaps-sdk";
import { heading, panel, text } from "@metamask/snaps-sdk";

export const onInstall: OnInstallHandler = async () => {
await snap.request({
method: "snap_dialog",
params: {
type: "alert",
content: panel([
heading("Thank you for installing my Snap"),
text(
"To use this Snap, visit the companion dapp at [metamask.io](https://metamask.io).",
),
]),
},
});
};

onKeyringRequest

To implement the Account Management API to integrate custom EVM accounts, an account management Snap must expose the onKeyringRequest entry point. Whenever the Snap receives an Account Management API request, MetaMask calls the onKeyringRequest handler method.

note

For MetaMask to call the Snap's onKeyringRequest method, you must request the endowment:keyring permission.

Parameters

An object containing:

  • origin - The origin as a string.
  • request - The JSON-RPC request.

Returns

A promise containing the return of the implemented method.

Example

index.ts
export const onKeyringRequest: OnKeyringRequestHandler = async ({
origin,
request,
}) => {
// Any custom logic or extra security checks here.
return handleKeyringRequest(keyring, request);
};

onNameLookup

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

To provide custom name resolution, a Snap must export onNameLookup. Whenever a user types in the send field, MetaMask calls this method. MetaMask passes the user input to the onNameLookup handler method.

note

For MetaMask to call the Snap's onNameLookup method, you must request the endowment:name-lookup permission.

Parameters

An object containing:

  • chainId - The CAIP-2 chain ID.
  • address or domain - One of these parameters is defined, and the other is undefined.

Example

index.ts
import type { OnNameLookupHandler } from "@metamask/snaps-sdk";

export const onNameLookup: OnNameLookupHandler = async (request) => {
const { chainId, address, domain } = request;

if (address) {
const shortAddress = address.substring(2, 5);
const chainIdDecimal = parseInt(chainId.split(":")[1], 10);
const resolvedDomain = `${shortAddress}.${chainIdDecimal}.test.domain`;
return { resolvedDomains: [{ resolvedDomain, protocol: "test protocol" }] };
}

if (domain) {
const resolvedAddress = "0xc0ffee254729296a45a3885639AC7E10F9d54979";
return {
resolvedAddresses: [{ resolvedAddress, protocol: "test protocol" }],
};
}

return null;
};

onRpcRequest

To implement a custom JSON-RPC API to communicate with dapps and other Snaps, a Snap must expose the onRpcRequest entry point. Whenever the Snap receives a JSON-RPC request, MetaMask calls the onRpcRequest handler method.

note

For MetaMask to call the Snap's onRpcRequest method, you must request the endowment:rpc permission.

Parameters

An object containing:

  • origin - The origin as a string.
  • request - The JSON-RPC request.

Returns

A promise containing the return of the implemented method.

Example

index.ts
import type { OnRpcRequestHandler } from "@metamask/snaps-sdk";

export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
switch (request.method) {
case "hello":
return "world!";

default:
throw new Error("Method not found.");
}
};

onSignature

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

To provide signature insights before a user signs a message, a Snap must expose the onSignature entry point. Whenever a signing method is called, such as personal_sign or eth_signTypedData_v4, MetaMask passes the raw unsigned signature payload to the onSignature handler method.

note

For MetaMask to call the Snap's onSignature method, you must request the endowment:signature-insight permission.

Parameters

An object containing:

  • signature - The raw signature payload.
  • signatureOrigin - The signature origin if allowSignatureOrigin is set to true.

Returns

  • An optional severity property that, if present, must be set to SeverityLevel.Critical.
  • A content object displayed using custom UI after the user selects the Sign button. Due to current limitations of MetaMask's signature confirmation UI, the content will only be displayed if the severity property is present and set to SeverityLevel.Critical.

Example

index.ts
import type { OnSignatureHandler, SeverityLevel } from "@metamask/snaps-sdk";
import { panel, heading, text } from "@metamask/snaps-sdk";

export const onSignature: OnSignatureHandler = async ({
signature,
signatureOrigin,
}) => {
const insights = /* Get insights */;
return {
content: panel([
heading("My Signature Insights"),
text("Here are the insights:"),
...(insights.map((insight) => text(insight.value))),
]),
severity: SeverityLevel.Critical,
};
};

onTransaction

To provide transaction insights before a user signs a transaction, a Snap must expose the onTransaction entry point. Whenever there's a contract interaction, and a transaction is submitted using the MetaMask extension, MetaMask calls the onTransaction handler method. MetaMask passes the raw unsigned transaction payload to onTransaction.

note

For MetaMask to call the Snap's onTransaction method, you must request the endowment:transaction-insight permission.

Parameters

An object containing:

  • transaction - The raw transaction payload.
  • chainId - The CAIP-2 chain ID.
  • transactionOrigin - The transaction origin if allowTransactionOrigin is set to true.

Returns

One of the following:

Example

index.ts
import type { OnTransactionHandler } from "@metamask/snaps-sdk";
import { panel, heading, text } from "@metamask/snaps-sdk";

export const onTransaction: OnTransactionHandler = async ({
transaction,
chainId,
transactionOrigin,
}) => {
const insights = /* Get insights */;
return {
content: panel([
heading("My Transaction Insights"),
text("Here are the insights:"),
...(insights.map((insight) => text(insight.value))),
]),
};
};

Transaction severity level

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

This feature enables transaction insight Snaps to return an optional severity level of critical. MetaMask shows a modal with the warning before the user can confirm the transaction. Using the previous example for onTransaction, the following code adds a single line to return an insight with the severity level critical:

index.ts
import type { OnTransactionHandler } from "@metamask/snaps-sdk";
import { panel, heading, text } from "@metamask/snaps-sdk";

export const onTransaction: OnTransactionHandler = async ({
transaction,
chainId,
transactionOrigin,
}) => {
const insights = /* Get insights */;
return {
content: panel([
heading("My Transaction Insights"),
text("Here are the insights:"),
...(insights.map((insight) => text(insight.value))),
]),
severity: "critical",
};
};

onUpdate

To implement a lifecycle hook that runs an action upon update, a Snap must expose the onUpdate entry point. MetaMask calls the onUpdate handler method after the Snap is updated successfully.

note

For MetaMask to call the Snap's onUpdate method, you must request the endowment:lifecycle-hooks permission.

Parameters

None.

Example

index.ts
import type { OnUpdateHandler } from "@metamask/snaps-sdk";
import { heading, panel, text } from "@metamask/snaps-sdk";

export const onUpdate: OnUpdateHandler = async () => {
await snap.request({
method: "snap_dialog",
params: {
type: "alert",
content: panel([
heading("Thank you for updating my Snap"),
text(
"New features added in this version:",
),
text(
"Added a dialog that appears when updating."
),
]),
},
});
};

onUserInput

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

To respond to interactive UI events, a Snap must export onUserInput.

Parameters

  • id - The ID of the interface being acted on.
  • event - An event object containing:
    • type - The type of the event. Possible values are ButtonClickEvent, FormSubmitEvent, or InputChangeEvent. These enums are exported from the @metamask/snaps-sdk module.
    • name - The name of the component that fired the event. Optional when the event type is ButtonClickEvent.
    • value - When the event type is FormSubmitEvent, the values in the form as an object.

Example

index.ts
import type { OnUserInputHandler } from "@metamask/snaps-sdk";
import { UserInputEventType } from "@metamask/snaps-sdk";

export const onUserInput: OnUserInputHandler = async ({ id, event }) => {
if (event.type === UserInputEventType.FormSubmitEvent) {
console.log("The submitted form values are", event.value);
}
};