---
updatedAt: 2025-06-09T22:51:38.000Z
agentTools:
  projectIndex: https://docs.metakeep.xyz/llms.txt
---

# Invoke Solana Lambda method as an end-user (Zero-Friction and Gasless)

In the previous part, we tried the powerful MetaKeep Lambda APIs to invoke a Lambda method as you (the developer). However, the Lamba Invocation for end-users works differently and leverages the MetaKeep SDK to support gasless transactions for non-custodial end-user wallets. In this tutorial, we will look into how to integrate the MetaKeep SDK for any custom Solana application and enable scalable and gasless transactions for the end users.

> 🚧 User Wallets are non-custodial
>
> Only the wallet owner can perform operations on the wallet. MetaKeep and developers can't touch user wallets.

In this tutorial, like earlier we will start with the built-in Memo Program of Solana.

You can find an end-to-end working demo [here](https://github.com/PassbirdCo/MetaKeepCodeSamples/tree/main/solana/lambda/).

## Generate Consent Token

> ❗️ Consent Token Generation Happens in the backend
>
> Consent token generation requires your API key. Never expose your secrets/keys to the public.

When a lambda invocation is requested on behalf of a user, you get back a `Consent Token`- looks like a base64 string. This needs to be signed by the user before the invocation can happen. The token also gives MetaKeep the approval to pay for the transaction gas fees and bill you(the developer) later.

> 👍 Users don't pay gas fee.
>
> MetaKeep provides zero-friction gasless lambda invocations.

Behind the scenes, Consent Token is a cryptographic challenge generated directly by MetaKeep's hardware root of trust, based on non-custodial Private Key Management (ncPKM) infra, which can be satisfied exclusively by the cryptographic proof of identity of the end-user.

### Step 1: Create the transaction object with the memo log instructions

You can use `@solana/web3.js` to create the transaction object.

### Step 2: Make A POST request to the API.

To invoke without any external signers, you need to provide the following fields in the request body:

```json Invoke Without External Signers
{
  "serializedTransactionMessage": "0x1234....",
  "reason": "Reason for Invocation",
  "as": {
    "email": "<Email of User who will be invoking the lambda method.>"
  }
}
```

If there are external signers, you also need to provide the signers with their signatures in the request body. The request body will look like this:

```json Invoke With External Signers
{
  "serializedTransactionMessage": "0x1234....",
  "reason": "Reason for Invocation",
  "signatures": [
    {
      "publicKey": "2k1ZTti7uQ1BZyMTscVLbzm3H74ncv2JdtLTio3FQxpb",
      "signature": "0x1234...."
    },
    {
      "publicKey": "HLETGSnF62q7ANP8SoWe7sxq7qrG3CEH6rJJhjaPadn8",
      "signature": "0x1234...."
    }
  ],
  "as": {
    "email": "<Email of User who will be invoking the lambda method.>"
  }
}
```

### Get the User's Approval

On making the API call, you will a `consentToken` back in the response.

```json Consent Token
{
  "status": "USER_CONSENT_NEEDED",
  "consentToken": "CrgBAQIDAHjkSP_5liFU1kRiwcsjaYhL70lMH28zlSAGMUGu-qcyhwFlzokiZCBBJXIGos8D3l02AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMFqkScqTlO68uvf6-AgEQgDvbTbd4sVsiGC9kpvrQcvRdl0LMFiVmg0K0eHZnlYm1M1mMyOV4X99ONhwBF3DHbtEcHs_Hfpg9AtHdExK1AgoM6uVs1U4BA3NKsVb5EqQCOPEYB6rgp_v5U-K71Rm7g1bbPhLKchRonB2teGsr7mi3tsENX0pm4fRn8al8EbeHmiSQCtvK-qAFr6SMYHW9wkc3_HBmrYYz6NbZpmie8xn3UllEy7YyWHEh7nRCajXKF79j3k-DOsdoWUe58ML_blzpicwcsNB358A7pIe6-hBn4XNL5wll_UXJEQBmDAPLp650CXmINwJWawWnQo3Jj4neTtNzXepLIWmJXRX1oW-hMyYq6Ng5oWxdkuCTqRnhRTxD5esADlbzArq8RZkM4lcPX2uNhcxAvMVS9sEhTVeFHTsuXKS-b1y-e7g5FKfe-5_lDdN-tX76LttLBWAbp05HFv5cXsAMDvI4y7_zVDQ0zDmKu4InZ_zgfJuwTh5faX98Sg=="
}
```

Once you have the \`consent token\`\`, use the SDK to get the user's approval for Lambda invocation.

```javascript Get User Consent
const consent = await sdk.getConsent(consentToken);
```

## Running the Demo Application.

You can find the end-to-end working demo [here](https://github.com/PassbirdCo/MetaKeepCodeSamples/tree/main/solana/lambda/). Follow these steps to run the demo:

### Step 1: Update backend  .env file.

Update the [.env](https://github.com/PassbirdCo/MetaKeepCodeSamples/blob/main/solana/lambda/backend/.env) file with the MetaKeep Solana API key. You can get the API key from the MetaKeep dashboard.

### Step 2: Start backend.

Navigate to `solana/lambda/backend` directory. Then, start the server.

```shell
npm install
npm run start
```

This will start the server at port number 3001. This server will allow your end-users to invoke the memo program using the consent token flow without paying any gas fees and having to create a new account.

### Step 3: Update frontend .env file.

Update the [.env](https://github.com/PassbirdCo/MetaKeepCodeSamples/blob/main/solana/lambda/frontend/.env) file with the App ID of your MetaKeep Solana App.

### Step 4: Start frontend

Open a new terminal window, navigate to `solana/lambda/frontend` directory, and run the following command.

```shell
npm install
npm run start
```

This will open the demo application in your browser.

### Step 5: Invoke the Memo Program with and without external signers.

Fill in the user's email and the memo log message. Then, click on the `Invoke Log Memo` button. Make sure that the `Include external signers` checkbox is not selected.

<Image align="center" className="border" border={true} src="https://files.readme.io/3981002-Screenshot_from_2023-11-16_13-16-56.png" />

To invoke with external signers, select the `Include external signers` checkbox. It will log the memo message using the end-user's wallet and an external signer.

<Image align="center" className="border" border={true} src="https://files.readme.io/099a65f-Screenshot_from_2023-11-16_14-15-28.png" />

### Step 6: Click the `Invoke Log Memo` Button.

The backend will generate a `Consent Token` and the frontend will ask for the user's approval using the MetaKeep SDK.

<Image align="center" className="border" border={true} src="https://files.readme.io/2ac9352-Screenshot_from_2023-11-16_13-17-19.png" />

### Step 8: Approve the invocation.

For verification, MetaKeep will send an OTP to the user's email. Copy the OTP and paste it into the approval UI.

<Image align="center" className="border" border={true} src="https://files.readme.io/9517e58-Screenshot_from_2023-11-16_13-17-26.png" />

Once the verification succeeds, MetaKeep will queue a new transaction.

<Image align="center" className="border" border={true} src="https://files.readme.io/2fa7985-Screenshot_from_2023-08-05_13-12-45.png" />

After you close the window, you can view the transaction details below.

<Image align="center" className="border" border={true} src="https://files.readme.io/1e1f49e-Screenshot_from_2023-11-16_13-46-08.png" />

MetaKeep, behind the scenes, employs several strategies to ensure transaction succeeds and at the lowest cost. To get your transaction's status, you can also use the [Transaction Status API](https://docs.metakeep.xyz/reference/v2apptransactionstatus).

### Next Steps

Congratulations🎉🎉🎉🎉!!!! You have now enabled zero-friction and gasless Solana transactions for your end users.