Transaction Payment


This example demonstrates a common and powerful use case for DID Connect: requesting a user to sign and submit an on-chain transaction for payment. This pattern is ideal for e-commerce checkouts, service subscriptions, content purchases, or any scenario that requires a transfer of tokens or assets.

We will use the signature claim to ask the user to sign a pre-constructed token transfer transaction.

How It Works#

The process involves the application creating a transaction and then asking the user's wallet to sign it. This ensures that the user maintains full control over their assets, and the application never handles the user's private key.

Here is the typical flow:

  1. Transaction Creation: The application's backend determines the details of the payment (e.g., amount, token type, recipient address) and uses a library like @ocap/client to construct a raw transaction.
  2. Claim Request: The application initiates a DID Connect session and requests a signature claim from the user. The raw transaction data is embedded within this claim request.
  3. User Approval: The user's DID Wallet receives the request, decodes the transaction, and displays a human-readable summary (e.g., "Pay 100 ABC Tokens to 'My App'"). The user can then choose to approve and sign the transaction with their private key.
  4. Response Handling: Upon approval, the wallet sends the signed transaction back to the application. The application can then verify the signature and broadcast the transaction to the blockchain to complete the payment.

This entire process is secure and non-custodial, providing a seamless Web3 payment experience.

Code Example#

Let's build an example where our application requests a payment of 100 native tokens from the user.

1. Configure WalletAuthenticator#

First, set up the WalletAuthenticator with your application's details and the chain information.

Transaction Payment Authenticator Setup

import { WalletAuthenticator } from '@did-connect/lib';
import { fromRandom } from '@ocap/wallet';

// Your application's wallet
const appWallet = fromRandom();

const auth = new WalletAuthenticator({
  wallet: appWallet,
  baseUrl: 'https://yourapp.com',
  appInfo: {
    name: 'My Awesome App',
    description: 'An app that requires payment.',
    icon: 'https://yourapp.com/logo.png',
    link: 'https://yourapp.com',
  },
  chainInfo: {
    host: 'https://beta.abtnetwork.io/api',
    id: 'beta',
  },
});

2. Define the Signature Claim#

Next, define the claims to be requested. We'll use a single signature claim. Inside the claim function, we'll construct the transaction.

This requires @ocap/client to encode the transaction and @ocap/util to convert the resulting buffer to a Base58 string, which is the format the wallet expects.

Create Transaction Signature Claim

import Client from '@ocap/client';
import { fromPublicKey } from '@ocap/wallet';
import { toBase58 } from '@ocap/util';

const client = new Client('https://beta.abtnetwork.io/api');
const NATIVE_TOKEN_ADDRESS = 'z35nB2SA6xxBuoaiuUXUw6Gah2SNU3UzqdgEt'; // Native token on ArcBlock chains

// Define the claims for an Express.js handler
const claims = {
  signature: async ({ userDid, userPk }) => {
    // 1. Construct the transaction object
    const txPayload = {
      tx: {
        from: userDid,
        pk: userPk,
        itx: {
          to: appWallet.address, // Send payment to the app's address
          tokens: [
            {
              address: NATIVE_TOKEN_ADDRESS,
              value: '100000000000000000000', // 100 tokens (with 18 decimals)
            },
          ],
        },
      },

See all 26 lines

In this example:

  • userDid and userPk are provided by the DID Connect session context after the user has connected their wallet.
  • We use client.encodeTransferV2Tx to create a standard token transfer transaction.
  • The to address is our application's wallet address, where the funds will be sent.
  • The requirement object is crucial for a good user experience. It allows the wallet to parse the transaction and show the user exactly what they are being asked to pay, preventing them from signing a malicious or incorrect transaction.

3. Handling the Wallet's Response#

After the user signs the transaction in their wallet, your application's callback endpoint will receive the signed transaction data. You can then use a library like @ocap/client again to broadcast it to the blockchain.

For a complete guide on setting up handlers to process wallet responses, see the Handling Wallet Responses guide.


This example covers a fundamental Web3 interaction. By leveraging the signature claim, you can securely request payments and other on-chain actions without ever taking custody of user keys.

To see another practical application of claims, check out the NFT Gated Access example.