Gas Fee Delegation
Kaia Wave 빌더를 위한 Kaia Fee Delegation 프로그램
소개
Kaia 네트워크의 fee delegation은 다른 계정이 트랜잭션 gas fee를 대신 지불할 수 있게 해주는 기능입니다. 이를 통해 사용자는 트랜잭션의 gas fee로 자신의 $KAIA를 소비하지 않고도 트랜잭션을 수행할 수 있습니다.
신청서 작성 >
개념
Kaia fee delegation은 세 가지 주요 구성 요소로 이루어집니다:
- Sender: 트랜잭션을 제출하는 계정 (from)
- Unifi Apps: 사용자가 서명한 트랜잭션을 fee payer 서버로 전달하는 relayer
- Fee payer server: fee payer로서 서명하고 서명된 트랜잭션을 네트워크로 전송한 뒤 호출자에게 receipt를 반환
Kaia fee delegation의 동작 과정은 다음과 같습니다:
- sender가 트랜잭션을 생성합니다.
- sender가 트랜잭션에 fee payer의 주소를 지정합니다.
- sender가 트랜잭션에 서명합니다.
- sender가 서명된 트랜잭션을 Unifi Apps의 backend로 전송합니다.
- backend가 fee payer 서버에 트랜잭션 서명을 요청합니다.
- fee payer 서버가 fee payer로서 트랜잭션에 서명하고, 네트워크로 전송하여 트랜잭션 receipt를 받아 반환합니다.
코드 샘플
사전 준비
- SDK
- kaia-sdk 중 하나인 ethers-ext를 설치해야 합니다.
- ethers-ext getting-started
- Wallet
- fee-delegation은 다음에서만 지원됩니다
- kaia-wallet mobile/extension, Unifi-wallet liff/web
- Unifi Apps front-end는 wallet을 통해 사용자가 서명한 트랜잭션을 받아야 합니다
- fee-delegation은 다음에서만 지원됩니다
웹 애플리케이션 코드 스니펫
Frontend (React) - 사용자가 서명한 트랜잭션 받기
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: "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: accounts[0], 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 - feePayer 서버에 'sign' 요청
-
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 또는 sender가 등록되어 있어야 합니다
- 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");};