Blinks
Last updated
Last updated
The v1 of the Actions spec does not concern itself with visualization or layout, including images, titles, buttons, or input positioning.
All of this is handled on the Blinks side. In this section, we describe how Blinks are constructed from actions, various aspects of Blinks that are affected by the Actions specification, and other matters of design.
Blinks may be linked to Actions in at least three ways:
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 unsupported client.
Sharing a link to a website that is linked to an Actions API via an actions.json
file on the website root domain.
For example, https://alice.com/actions.json maps https://alice.com/donate--a website URL at which users can donate to Alice--to an API URL like https://actions.alice.com/donate, which hosts Actions for donating to Alice.
Embedding an Action URL in an “interstitial” site or mobile app deep link URL that understands how to parse actions.
For example,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.
At this location we've included an Action validation tool 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 three 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 one above is the most basic form, but it's also the most limiting in that unsupported clients have no way to handle the link.
Option two is the most advanced, in that the developer has done work to map some site to some action.
Option three, 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 three in greater detail in the next section.
This section describes how Blinks choose to layout actions based on the types and number of actions returned from an Action API.
Check back here for updates!
Blinks should support some combination of the above—multiple actions and at most one user input text field—where there may be multiple actions and user input.
Text fields have a single associated button 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.)
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 three above in more detail, as it is the pure URL encoding of the full experience, i.e., specifying both an Action and the client in which it is to be executed.
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
Let's imagine that Alice is using Jupiter to swap tokens. She chooses the paying and receiving tokens; for this example, we'll assume it's SOL and 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, it's not the not the Blink that gives Alice a choice for the interstitial, it's jup.ag interface. When Bob taps Alice’s choice for backpack, he is taken to Backpack.
💡 If, for example, Dialect chooses to implement an interstitial-choosing step at https://dialect.to/?action=… where a user chooses which signing client to use—Backpack, Phantom, etc.— this is an entirely different abstraction than an interstitial URL and not a part of the official Blink implementation.
When one action is being taken from a set of available actions, all other actions become un-executable until such time as the currently executing action succeeds or fails, which can include a timeout.
This may or may not be true in future versions, and more flexible experiences might be possible.
Blinks do not need to persist their lifecycle beyond the present single-user session. If a user refreshes the client or leaves and returns later, past or current interactions with the Blink will no longer reflected by the client. This includes both successful actions and actions in the middle of executing.
In future versions, Action and Blink outcomes may persist beyond single-session use.