Blinks

The Actions Spec v1 does not concern itself with visualization or layout, such as image, title, button or input positioning.

This is the responsibility of Blinks. In this section, we describe how blinks are constructed from actions, aspects of Blinks that are affected by the Actions specification, and other matters of design.

Detecting Actions via URL Schemes

Blinks may be linked to Actions in at least 3 ways:

  1. Sharing an explicit Action URL: solana-action://https://actions.alice.com/donate. In this case, only supported clients may render the Blink. There will be no fallback link preview, or site that may be visited outside of the unsupporting client.

  2. Sharing a link to a website that is linked to an actions API via an actions.json file on the website root domain.

    E.g. https://alice.com/actions.json maps https://alice.com/donate, a website URL at which users can donate to Alice, to API URL e.g. https://actions.alice.com/donate, at which Actions for donating to Alice are hosted.

  3. Embedding an Action URL in an “interstitial” site or mobile app deep link URL that understands how to parse actions.

    E.g. https://dial.to/?action=solana-action:https://actions.alice.com/donate or https://dial.to/?action=solana-action:https://dial.to/api/donate

If you want to test if your Action URL does indeed unfurl on a Blink, you can paste it into dial.to and it will render the Blink modal.

We've included an Action validation tool in there which will parse your API and check if the GET, POST and OPTIONS requests work as required. (It even checks for CORS errors)

Clients that support Blinks should take any of the 3 above formats and correctly unfurl the action directly in the client.

For clients that do not support Blinks, there should be an underlying website. In other words, the browser is the universal fallback.

If a user taps anywhere on a client that is not an action button or text input field, they should be taken to the underlying site.

  • Option 1 above is the most basic form, but also the most limiting in that unsupported clients have no way to handle the link.

  • Option 2 is the most advanced, in that the developer has done work to map some site to some action.

  • Option 3 on the other hand, is the purest manifestation of the actions technology: it fully decouples the action to be taken (the inner URL) from the client in which it’s taken (the outer URL).

We cover Option 3 in greater detail in the next section.

Layout

This section describes how Blinks choose to layout actions based on the types and number of actions returned from an Action API.

It will be filled in soon.

Multi-action

Blinks should support some combination of the above—multiple actions & at most one user input text field—where there may be multiple actions, & user input.

Text fields have a single button associated with them, that requires an input from the user to be clicked. Text fields may not be linked to multiple buttons. (E.g. memo on your vote is not supported by the MVP.)

Render lifecycle

Users should not have to tap anything to render the current state of an action, including any dynamic content or validation state that may be needed. That state is determined when the action is first rendered on the screen.

Chrome extensions may be used to add Blink support to clients that would not normally support Blinks. E.g. Twitter web may be made to support Blinks if chrome extensions such as Backpack, Sofllare or Phantom integrate Blinks capabilities.

In this section we cover Option 3 above in more detail, as it is the pure URL-encoding of the full experience: specifying both an action and the client in which it is to be executed.

<interstitial-site-or-deeplink-url>/?action=solana:<action-url>

Interstitials—

Interstitial URLs are website or mobile app deep link URLs specifying a client in which to sign for an action. Examples include wallets or other wallet-related applications that are typically responsible for storing keypairs, and that are capable of giving user signing experiences.

Any signing client can implement an interstitial site for execution, and developers and users can compose interstitials and actions as they see fit. We describe some examples in the next section.

User journeys—

Alice is using Jupiter to swap tokens. She chooses the paying & receiving tokens, say SOL & WIF. Near the Swap button is another button she may press, that allows for sharing the action with others.

When she presses it, she is presented with a sheet in which she can choose the signing client. It’s a CTA like “Sign with…” and then a grid of well-known wallets or key holding apps like Phantom, Backpack, Solflare, Tiplink, etc.

Once she chooses one, say Backpack, it copies to her clipboard a URL of the format https://backpack.app/?action=solana:<swap-url>

Determining interstitials—

Note that in the above example, jup.ag’s interface gives Alice choice for the interstitial, not the blink itself. When Bob taps Alice’s choice for backpack, he is taken to Backpack.

💡 If for example Dialect chose to implement an interstitial-choosing step at https://dialect.to/?action=… —where a user chooses which signing client to use—Backpack, Phantom, etc.—then this is an entirely different abstraction than an interstitial URL, and not a part of the official Blink implementation.

Execution & lifecycle

When one action is being taken from a set of available actions, all other actions become un-executable until such time as the current executing action succeeds or fails (incl. timeout).

In future versions, this may no longer be true, and more flexible experiences may be created.

Blinks do not need to persist their lifecycle beyond the in-the-moment, single user session. If a user refreshes the client, or leaves and comes back at a later time, past or current interactions with the Blink are no longer reflected by the client. This includes not just succeeded actions, but also actions in the middle of execution.

In future versions, Action and Blink outcomes may persist beyond single-session use.

Last updated