Message Signing

In order to submit a transaction to the Kima blockchain, the user must sign a message containing the transaction details. This message is signed by the user's wallet and then included in data submitted to the Kima Transaction Backend submit endpoints (/submit/transfer or /submit/swap).

Message Structure

The message is a string that is signed by the user's wallet. It contains the following information:

  • Allowance amount: in whole tokens i.e. 10.23 not 10230000

  • Origin token symbol

  • Origin chain symbol: see the list of chain symbols in the Supported Assets section

  • Target address

  • Target chain symbol

Template:

I approve the transfer of {allowanceAmount} {originSymbol} from {originChain} to {targetAddress} on {targetChain}.

Example

Get the message to sign by calling the /submit/fees endpoint and selecting the appropriate version based on whether the user is paying fees from the origin or target chain.

To sign the message, the user's wallet must be connected and the message must be passed to the wallet client sign function. The following is an example of how to sign the message on EVM chains using Viemarrow-up-right.

import { Address } from "viem";
import { avalanche } from "viem/chains";

// however these are obtained in your app
import {  getUserWalletAddress, fetchFeeData, getUserFeeChoice } from "../utils";

const walletAddress = getUserWalletAddress()
const feeData = await fetchFeeData()
const isFeeFromOrigin = getUserFeeChoice() // boolean
const message = isFeeFromOrigin
  ? feeData.transactionValues.feeFromOrigin.message
  : feeData.transactionValues.feeFromTarget.message

const walletClient = createWalletClient({
    account: walletAddress as Address,
    chain: avalanche,
    transport: custom(window.ethereum),
})

 const signature = await walletClient.signMessage({
    account: walletAddress as Address,
    message
})

This signature will be passed to the options param of the submit endpoint.

Permit2 tokens

If the selected origin token has isPermit2=true in /chains, the standard approval message signature is still mandatory, and you must also include options.permit2 in submit payload:

  • r

  • s

  • v

  • deadline

Some supported tokens use a signature-based approval flow through Permit2 instead of a regular on-chain approval transaction.

Regular approval

With a regular ERC-20 approval flow, the user must first send an approve() transaction to grant spending permission to the spender contract. After that transaction is confirmed, the transfer transaction can be submitted.

This means the user usually pays gas twice:

  1. once for the approval transaction

  2. once for the transfer transaction

Permit2 approval

With Permit2, the user signs an off-chain permission message instead of sending a separate approve() transaction from their wallet. That signed permission is then used as part of the transfer flow.

This reduces friction because:

  • no separate approval transaction is required

  • the user avoids paying gas for a standalone approval

  • the approval and transfer flow becomes faster and simpler

Key difference

The main difference is where the approval happens:

  • Regular approval: permission is granted on-chain through an approve() transaction

  • Permit2: permission is granted by signing a message, which removes the need for a separate approval transaction

For supported Permit2 tokens, the wallet will ask the user to sign a permission message instead of confirming a standard approval transaction.

Why sign a message?

Signing a messge significantly improves security in the following ways:

  • The signature is cryptographically verifiable as coming from the user's wallet. This is proof that the user has authorized the transaction.

  • The transaction details cannot be modified without invalidating the signature. This prevents a "man in the middle" attack where the destination address is changed to the attacker's address.

Last updated