Gas Fee Delegation
Kaia Fee Delegation Program for Kaia Wave Builders
Introduction
The fee delegation of Kaia network is a feature that allows another account to pay for the transaction gas fee. This allows users to perform transactions without spending their own $KAIA for the gas fee of a transaction.
Apply Form >
Concept
Kaia fee delegation consists of three main components:
- Sender: The account submitting the transaction (from)
- Unifi Apps: The relayer that relays the user signed transaction to the fee payer server
- Fee payer server: Sign as fee payer and send the signed transaction to the network and return the receipt to the caller
The operations of Kaia fee delegation are as follows:
- The sender creates the transaction.
- The sender specifies the fee payer's address in the transaction.
- The sender signs the transaction.
- The sender sends the signed transaction to backend of Unifi Apps.
- The backend requests a transaction sign to the fee payer server.
- The fee payer server signs the transaction as a fee payer, sends it to the network, gets a receipt of the transaction and returns the transaction receipt.
Code Samples
Pre-requisite
- SDK
- ethers-ext is one of kaia-sdk should be installed.
- ethers-ext getting-started
- Wallet
- fee-delegation is only supported by
- kaia-wallet mobile/extension, Unifi-wallet liff/web
- Unifi Apps front-end should get a user signed transaction via the wallets
- fee-delegation is only supported by
Code snippet in web application
Frontend (React) - getting a user signed transaction
fee-delegated value transfer example
import { Web3Provider } from "@kaiachain/ethers-ext"; import { TxType, parseKaia } from "@kaiachain/js-ext-core"; import DappPortalSDK from "@linenext/dapp-portal-sdk"; import { useEffect, useState } from "react"; // testnet const feePayer = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; // mainnet const feePayer = "0x22a4ebd6c88882f7c5907ec5a2ee269fecb5ed7a"; const clientId = "30e…b89"; const chainId = "1001"; export default function home() { const [provider, setProvider] = useState<any>(null); const [accounts, setAccounts] = useState<string[]>([]); const initProvider = async () => { const sdk = await DappPortalSDK.init({ clientId, chainId, }); const provider = new Web3Provider(sdk.getWalletProvider()); const accounts = await provider.send("kaia_requestAccounts", []); setProvider(provider); setAccounts(accounts); }; const sign = async () => { const tx = { typeInt: TxType.FeeDelegatedValueTransfer, from: accounts[0], to: accounts[0], value: parseKaia("0.1").toHexString(), feePayer, }; const signedTx = await provider.send("kaia_signTransaction", [tx]); // send the signed tx to backend console.log(signedTx); }; useEffect(() => { initProvider(); }, []); return ( <div> <button onClick={sign}>Get user signed tx</button> </div> ); }
fee-delegated smart contract execution example
import { Web3Provider } from "@kaiachain/ethers-ext"; import { TxType, parseKaia } from "@kaiachain/js-ext-core"; import DappPortalSDK from "@linenext/dapp-portal-sdk"; import { useEffect, useState } from "react"; const feePayer = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; const clientId = "30e…b89"; const chainId = "1001"; const contractAddr = "0x95Be48607498109030592C08aDC9577c7C2dD505"; const abi = '[...]' //copy from https://docs.kaia.io/ko/references/sdk/ethers-ext/v6/smart-contract/write/ export default function home() { const [provider, setProvider] = useState<any>(null); const [accounts, setAccounts] = useState<string[]>([]); const initProvider = async () => { const sdk = await DappPortalSDK.init({ clientId, chainId, }); const provider = new Web3Provider(sdk.getWalletProvider()); const accounts = await provider.send("kaia_requestAccounts", []); setProvider(provider); setAccounts(accounts); }; const sign = async () => { const contract = new ethers.Contract(contractAddr, abi, provider); const contractCallData = await contract.increment.populateTransaction(); const tx = { typeInt: TxType.FeeDelegatedSmartContractExecution, // fee delegated smart contract execution from: accountAddress, to: contractCallData.to, input: contractCallData.data, value: "0x0", feePayer: feePayer, }; const signedTx = await provider.send("kaia_signTransaction", [tx]); // send the signed tx to backend console.log(signedTx); }; useEffect(() => { initProvider(); }, []); return ( <div> <button onClick={sign}>Get user signed tx</button> </div> ); }
backend - request 'sign' to feePayer server
-
input : userSignedTx - RLP encoded transaction
-
return : transaction receipt
-
feePayer server URL
const { Wallet } = require("@kaiachain/ethers-ext/v6");const ethers = require("ethers");//testnetconst feePayerServer = "https://fee-delegation-kairos.kaia.io";const provider = new ethers.JsonRpcProvider("https://public-en-kairos.node.kaia.io");async function main() {/* signed tx from user on frontend side */const signedTxRLPEncoded = {raw: RLP encoded signed TX hex string}const response = await fetch(`${feePayerServer}/api/signAsFeePayer`, {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify({ userSignedTx:signedTxRLPEncoded }),});const data = await response.json();console.log(data);}main();- https://fee-delegation.kaia.io (mainnet)
- Contract or sender should be registered
- https://fee-delegation-kairos.kaia.io (testnet)
- https://fee-delegation.kaia.io (mainnet)
-
balance check
const checkBalance = async () => {// It's an address of contracts or senders you registered for fee delegationconst address = "0x63d4f17d2a8a729fd050f7679d961b1dfbb1e3af";const result = await fetch(`${feePayerServer}/api/balance?address=${address}`);const isEnough = (await result.json()).data;console.log(isEnough ? "enough balance" : "not enough balance");};