The Kima Transaction Back End
This is a web server that works as middleware between the Kima Transaction Widget and Kima Chain. Once it receives a transaction request from the widget, it will submit a transaction to Kima Chain signed by a local wallet.
The server is an Express application and requires minimal setup. Here are the instructions:
Create a wallet for development purposes
We recommend Keplr, which is a widely used wallet for blockchains within the Cosmos ecosystem.
Install it from here and make sure you back it up by saving the seed phrase.
You will need to record the mnemonic seed phrase rather than the private key, as the seed phrase is used as an environment variable.
⚠️ In order to connect to the Kima chain (both Mainnet and Sardis Testnet), you will need to get your Kima address whitelisted. Please contact us at [email protected] with your public address- it will start with
kima1. This is a temporary measure to combat spammers.
You can find your Kima address in the Keplr wallet by
Clicking the "Copy Address" button
Find "Kima" in the list of chains
Click the "Copy Address" button
If you have not yet added the Kima Network to Keplr, you can enter "Kima" in the "Search for a chain" field when copying the address.

Get some KIMA tokens to use for transaction fees
If you are developing on the KIMA testnet, you can acquire test KIMA tokens from our faucet site. For mainnet, there is a list of exchanges where you can buy KIMA tokens here.
Follow the instructions here if you have not used a faucet before.
Clone the repo at:
https://github.com/kima-finance/kima-transaction-backend
Set your environment variables
For local development, create a .env file in the project root and copy the relevant values from .env.sample.
This repository does not currently include docker-compose.yml, docker-compose-prod.yml, or separate /env/*.env files. If you containerize the backend in your own environment, pass the same variables from .env.sample through your deployment platform or container runtime.
The .env file will be ignored by git, but .env.sample is not, so do NOT accidentally fill real secrets into the sample file.
A few notes about these environment variables:
KIMA_BACKEND_MNEMONIC is the seed phrase from the wallet you installed. Never share this with anyone. Never commit this to a code repository. Use a secret manager service like Google Secret Manager or AWS Secrets Manager to store your seed phrase instead of putting it in the .env file.
KIMA_ENVIRONMENT is separate from the NODE_ENV variable and determines whether information endpoints like /chains will return testnet or mainnet values.
DOMAIN is a comma separated list of urls that the server will accept requests from. All other domains will be blocked (except in the dev environment). Put the url of your frontend here.
COMPLIANCE_URL (OPTIONAL) If your app needs to block non-compliant addresses contact us for more information and the url to use here.
/chains/env returns the environment metadata expected by the widget. A typical response looks like this:
Field meanings:
env: active Kima environment used by the widget to configure network behaviorkimaExplorer: explorer base URL used for status and transaction linkstransferLimitMaxUSDT: optional transfer cap used by light mode and validation logicpaymentPartnerId: FIAT widget partner identifier used by widget-managed payment flows
Mainnet
Here are the mainnet specific environment variables. See the .env.sample for the most up to date list of ENV variables and default values. The other vars you will need to fill in with your specific values.
Testnet
Install and start
You can run:
npm install
then
npm run dev
If you deploy the backend in a container or cloud runtime, provide the same environment variables shown above through that platform's configuration.
Test the installation
In your terminal, run the following command:
The server should respond with a 200 and a JSON body similar to:
Available routes
See OpenAPI documentation at /docs for more details (only available when NODE_ENV is development). The following is an overview of how the routes are used together.
Get various info for the frontend from
/chains/*like supported chains, tokens, pool addresses, etc.Token entries in
/chainsincludeisPermit2metadata. Use this to decide whether submitoptionsmust include a Permit2 payload.
GET /submit/fees: get the service fees and token authorization amountsThe response includes
feeTotalFiatandfeeTotalBigIntfor the total fee value.Returns a ready-to-use
transactionValues.*.allowanceAmountobject withvalueanddecimals, representing the origin token authorization amount. For regular ERC-20 tokens, pass thevalueusing the accompanyingdecimalscontext toapprove(). For Permit2 tokens, use the same amount data when building the Permit2 authorization flow. Bigints are used to avoid floating point errors.The required authorization step must be completed before submitting the transaction or the transfer will fail.
Use the
submitAmountwhen calling/submit/transferor/submit/swap; it is already properly adjusted based on whether fees are deducted from origin or target.Use the
decimalsproperty to convert to a number if needed elsewhere.
POST /submit/transfer: initiates a transfer transaction and returns data containing the Kima transaction idPOST /submit/swap: initiates a swap transaction and returns data containing the Kima transaction idGET /tx/{txId}/status: use the transaction id returned from submit to get the transaction statusBTC route group (
/btc/*) for BTC-origin flows:GET /btc/balance?address={address}: fetch BTC balance (sats) for an addressPOST /btc/htlc/lock-intent: create HTLC lock intent and return lock metadataPOST /btc/htlc/record: record a broadcast BTC lock transaction and return submit-ready HTLC fieldsGET /btc/height: get current BTC chain height from configured mempool backendGET /btc/tip: get current BTC tip height and timestampGET /btc/outspend?txid={txid}&vout={index}: fetch spend status for a specific transaction outputGET /btc/transaction?hash={txid}: fetch BTC transaction detailsGET /btc/utxo/{address}: fetch UTXO set for an address
Permit2 Tokens
For origin tokens where /chains reports isPermit2: true:
submit payload
options.signatureis still requiredsubmit payload
optionsmust includepermit2permit2requiresr,s,v,deadlinemode=lightis not supported for Permit2 tokens
What is an HTLC lock?
In BTC-origin flows, funds are first sent to an HTLC address. This creates an on-chain lock with a timeout.
Before timeout: funds are handled according to the HTLC conditions.
After timeout: the lock can be reclaimed according to HTLC rules.
In Kima, that BTC lock transaction is recorded via /btc/htlc/record, and the returned HTLC metadata is attached to /submit/transfer or /submit/swap.
Expected timing model for BTC-origin flow
Timing is confirmation-based and variable.
BTC confirmation threshold is chain-parameter driven (default BTC confirmation blocks:
6).Observer validation waits until the required number of confirmations is reached.
Observer hash collection and processing run on a periodic cadence (about every
5seconds).
Because mempool, block production, and validator consensus timings vary, this flow should be treated as variable-time (no fixed minute SLA).
Optional Features
Custom Transaction Validation
In /src/custom-transaction-validation.ts you can add your own custom validation logic. Kima does not know the requirements of your app, so it is up to you to make sure the transaction makes sense. This is a convenience function, feel free to modify the middleware if you need lower level access.
The customTransValidation function
Will be called in middleware after basic param validation and before the
/submit/transferor/submit/swaproute handler is calledShould return a
stringwith the error message or the empty string if the transaction is valid.
The following are some example of things you may want to check:
When accepting cross chain payment for goods and services
Ensure the
targetAddressis your app's payment addressCheck the chains are supported by your app
Chain Filtering
Chain filtering is an optional feature that can be enabled by setting the KIMA_CHAIN_FILTER environment variable. This will:
Filter the chains returned by the
/chainsendpoint and therefore the options listed in the React componentRestricts the allowed chains for
/submit/transferand/submit/swap, causing a400error if the chain is not allowed
It supports two modes:
whitelist: Only chains in the whitelist will be returned.blacklist: Only chains not in the blacklist will be returned.
This is a JSON object with the following structure:
origin: Filter for the origin chainmode: The mode to use. Can bewhitelistorblacklistchains: An array of chain short names to filter
target: Filter for the target chainmode: The mode to use. Can bewhitelistorblacklistchains: An array of chain short names to filter
FIAT rails note:
Request-level origin chain values can be
CCandBANK.Backend normalizes
CCandBANKtoFIATbefore submitting to Kima Chain viakima-transaction-api.If you want to block FIAT-origin flows robustly, include
CCandBANKin your origin filter.
Example: only ARB and OPT chains are allowed for the origin and all chains except TRX are allowed for the target:
Example filtering out FIAT-origin rails (CC / BANK / normalized FIAT):
The stringified version:
Compliance
If enabled by supplying the COMPLIANCE_URL environment variable, use GET /compliant/enabled to check whether compliance is active, and GET /compliant to check whether an address meets compliance requirements.
Use this in the frontend to check if an address is not compliant BEFORE the authorization step. When compliance is enabled, /submit/transfer and /submit/swap return status 403 (Forbidden) for non-compliant addresses.
If you are interested in using compliance, contact us at [email protected] for more information and the URL to use here.
KYC
If using the KYC in the widget:
GET /uuidwill return the external identifier you needPOST /kycreturns the KYC status for a specificuuidverification session
Again, please contact us for more information on how to implement this feature.
Last updated