@gasfree-kit/react
v1.1.0
Published
React hooks for gasless USDT transfers — powered by gasfree-kit
Maintainers
Readme
@gasfree-kit/react
⚠️ Deprecation notice (v2.0.0) —
useBalance,useIntent,useGaslessTransfer,useTonTransfer, andusePaymentLinkare deprecated in favour ofuseReadBalance,useSendIntent,usePlanIntent,useExecuteIntent,useGaslessSend, anduseTonSend(react-query convention).They will be removed three weeks after the v2.0.0 publish date in the next major release. Migrate using the Hooks table below; the legacy hooks still work in v2 and emit
@deprecatedJSDoc in your IDE.
React hooks for gasless USDT transfers across EVM and TON networks.
Wrap your app in a provider, call a hook, and get multi-chain balance discovery, gasless transfers, cross-chain bridging, and payment links — all with zero gas costs for your users.
How It Works
┌──────────────────────────────────────────────────────────┐
│ Your React App │
│ │
│ <GasfreeProvider config={...}> │
│ <App /> │
│ </GasfreeProvider> │
└────────────────────────────┬─────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
v v v
┌──────────────┐ ┌─────────────────┐ ┌────────────────┐
│ useBalance() │ │ useIntent() │ │useTonTransfer()│
│ │ │ useGasless │ │ │
│ EVM + TON │ │ Transfer() │ │ TON gasless │
│ combined │ │ usePayment │ │ relay │
│ balances │ │ Link() │ │ │
└──────┬───────┘ └────────┬────────┘ └───────┬────────┘
│ │ │
v v v
┌──────────────┐ ┌────────────────┐ ┌────────────────┐
│ @gasfree-kit │ │ @gasfree-kit/ │ │ @gasfree-kit/ │
│ /intent │ │ intent │ │ ton-gasless │
│ (discovery) │ │ (plan+execute) │ │ (relay) │
└──────────────┘ └────────────────┘ └────────────────┘Prerequisites
This package depends on:
@gasfree-kit/corefor chain metadata, types, and errors@gasfree-kit/intentfor EVM balance discovery, route planning, and execution@gasfree-kit/ton-gaslessfor TON gasless transfers
All are installed automatically as dependencies.
Installation
npm install @gasfree-kit/reactRequired peer dependencies:
npm install react @tanstack/react-queryThe SDK is connector-agnostic — pass the connected EVM address to
<GasfreeProvider> from whichever library you use (RainbowKit, ConnectKit,
Privy, Dynamic, wagmi, raw viem, …). No specific connector is required or
endorsed.
Quick Start
EVM — gasless transfer in 10 lines
import { GasfreeProvider, Signer, useGaslessSend } from '@gasfree-kit/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function PayButton() {
const { mutateAsync, isPending, data } = useGaslessSend();
return (
<button
disabled={isPending}
onClick={() => mutateAsync({ to: '0xRecipient...', amount: '50.00' })}
>
{isPending ? 'Sending...' : 'Pay 50 USDT'}
</button>
);
}
function App() {
return (
<QueryClientProvider client={queryClient}>
<GasfreeProvider
address="0xSender..."
config={{
evm: {
chains: ['base', 'arbitrum', 'optimism'],
signer: Signer.seedPhrase('your seed phrase ...'),
bundlerUrl: 'https://your-bundler.example.com',
paymasterUrl: 'https://your-paymaster.example.com',
isSponsored: true,
sponsorshipPolicyId: 'your-policy-id',
},
}}
>
<PayButton />
</GasfreeProvider>
</QueryClientProvider>
);
}TON — gasless transfer
import { GasfreeProvider, useTonSend } from '@gasfree-kit/react';
function TonPayButton() {
const { mutateAsync, isPending, data } = useTonSend();
return (
<button
disabled={isPending}
onClick={() => mutateAsync({ to: 'UQRecipient...', amount: '25.00' })}
>
{isPending ? 'Sending...' : 'Pay 25 USDT (TON)'}
</button>
);
}
// In your provider setup. URLs default to public endpoints — pass API keys
// for production-grade rate limits.
<GasfreeProvider
config={{
ton: {
clientConfig: {
tonCenterApiKey: 'your-key',
tonApiSecretKey: 'your-secret',
},
seedPhrase: 'your ton seed phrase ...',
},
}}
>
<TonPayButton />
</GasfreeProvider>;Multi-network — EVM + TON together
<GasfreeProvider
address="0xEvmAddress..."
config={{
evm: {
chains: ['base', 'arbitrum'],
signer: { type: 'passkey', credential },
bundlerUrl: '...',
paymasterUrl: '...',
isSponsored: true,
sponsorshipPolicyId: '...',
},
ton: {
clientConfig: { tonCenterUrl, tonCenterApiKey, tonApiUrl, tonApiSecretKey },
seedPhrase: '...',
},
}}
>
<App />
</GasfreeProvider>Hooks
All current hooks follow the standard react-query shape — queries return
{ data, isPending, isError, error, refetch } and mutations return
{ data, isPending, isError, error, mutate, mutateAsync, reset }.
| Hook | Kind | Replaces (legacy) |
| ------------------ | -------- | --------------------------- |
| useReadBalance | query | useBalance |
| useSendIntent | mutation | useIntent().sendIntent |
| usePlanIntent | mutation | useIntent().planIntent |
| useExecuteIntent | mutation | useIntent().executeIntent |
| useGaslessSend | mutation | useGaslessTransfer |
| useTonSend | mutation | useTonTransfer().transfer |
The legacy hooks remain available and continue to work — they are marked
@deprecated in JSDoc so editors surface the replacement automatically.
useReadBalance
Discover USDT balances across all configured networks (EVM + TON). Read-only: no signer required.
const { data, isPending, error, refetch } = useReadBalance();
if (data) {
console.log(data.total); // "130.00" — grand total across all networks
console.log(data.evm?.total); // "100.00"
console.log(data.evm?.chains); // [{ chain: 'base', balance: '75.00', ... }, ...]
console.log(data.ton?.balance); // "30.00"
}Pass { address: '0xOther...' } to query a different address, or
{ enabled: false } to defer the initial fetch.
useSendIntent
One-shot intent send — discover balances, plan optimal route, execute.
const { mutateAsync, data, isPending, error } = useSendIntent();
const receipt = await mutateAsync({
request: { to: '0xRecipient...', amount: '50.00' },
overrides: { bundlerUrl: 'https://custom-bundler.example' }, // optional
});The from address is auto-filled from the provider. Pass per-call
overrides to swap the bundler, paymaster, timeouts, or signer for a
single call without rebuilding the instance.
usePlanIntent + useExecuteIntent
Two-step UX — preview the plan, confirm, then execute.
const plan = usePlanIntent();
const execute = useExecuteIntent();
const previewPlan = await plan.mutateAsync({
request: { to: '0xRecipient...', amount: '50.00' },
});
console.log(previewPlan.route); // "direct" | "bridge" | "aggregate"
console.log(previewPlan.estimatedFee);
// After user confirms:
const receipt = await execute.mutateAsync({ plan: previewPlan });useGaslessSend
Convenience mutation hook with flat variables — equivalent to useSendIntent
but you pass { to, amount } directly.
const { mutateAsync, isPending } = useGaslessSend();
await mutateAsync({ to: '0xRecipient...', amount: '25.00' });useTonSend
Gasless USDT transfer on TON.
const { mutateAsync, data, isPending } = useTonSend();
await mutateAsync({ to: 'UQRecipient...', amount: '10.00' });Legacy hooks (deprecated)
The hooks below predate the react-query alignment and remain available for backwards compatibility. New code should use the equivalents above.
useBalance
Discover USDT balances across all configured networks. Works in read-only mode — no signer required for EVM balance discovery.
const { balances, isLoading, error, refetch } = useBalance();
if (balances) {
console.log(balances.total); // "130.00" (grand total across all networks)
console.log(balances.evm?.total); // "100.00" (EVM total)
console.log(balances.evm?.chains); // [{ chain: 'base', balance: '75.00', ... }, ...]
console.log(balances.ton?.balance); // "30.00"
}Accepts an optional address override: useBalance('0xOtherAddress...').
Automatically refetches based on balanceCacheTTL (default 15 seconds).
useIntent
Full EVM intent lifecycle — plan, execute, or one-shot send. Requires a signer in the provider config.
const {
planIntent,
executeIntent,
sendIntent,
plan,
receipt,
events,
isPlanning,
isExecuting,
error,
reset,
} = useIntent();
// Two-step: plan then confirm
const plan = await planIntent({ to: '0x...', amount: '50.00' });
console.log(plan.route); // "direct" | "bridge" | "aggregate"
console.log(plan.estimatedFee); // "0" (sponsored)
const receipt = await executeIntent(plan);
console.log(receipt.status); // "completed"
// Or one-shot
const receipt = await sendIntent({ to: '0x...', amount: '50.00' });The from address is auto-filled from the provider context.
Track execution progress via the events array — events are appended in real-time as steps start, complete, or fail.
useGaslessTransfer
Simplified wrapper around useIntent().sendIntent(). The happy-path hook for one-shot EVM transfers.
const { transfer, receipt, isLoading, error, events, reset } = useGaslessTransfer();
const receipt = await transfer({ to: '0x...', amount: '25.00' });
if (receipt.status === 'completed') {
alert('Payment sent!');
}useTonTransfer
Gasless USDT transfers on the TON network. Requires TON configuration in the provider.
const { transfer, estimateFee, checkBalance, result, isLoading, error, reset } = useTonTransfer();
// Estimate fee first
const fee = await estimateFee({ to: 'UQ...', amount: '10.00' });
console.log(`Fee: ${fee} USDT`);
// Check balance
const { balance } = await checkBalance();
console.log(`Balance: ${balance} USDT`);
// Execute transfer
const result = await transfer({ to: 'UQ...', amount: '10.00' });
if (result.success) {
console.log(`TX: ${result.transactionHash}`);
}usePaymentLink
Generate, parse, and execute payment links. Supports both EVM and TON networks.
Pass your app's payment page URL as the base URL — the hook appends query params to it.
const { generateLink, parseLink, pay, receipt, isLoading, error } =
usePaymentLink('https://myapp.com/pay');
// Merchant side — generate a link
const url = generateLink({
to: '0xMerchant...',
amount: '50.00',
metadata: { orderId: 'order-123' },
});
// https://myapp.com/pay?to=0xMerchant...&amount=50.00&meta=eyJvcmRlcklkIjoib3JkZXItMTIzIn0=
// TON payment link
const tonUrl = generateLink({
to: 'UQRecipient...',
amount: '25.00',
network: 'ton',
});
// Payer side — parse and pay
const params = parseLink(window.location.href);
if (params) {
const receipt = await pay(params);
}useGasfree
Access the raw provider context. Useful for building custom hooks or checking capabilities.
const { intent, config, address, canExecuteEvm, tonConfig, canExecuteTon } = useGasfree();Provider Configuration
<GasfreeProvider
address="0x..." // EVM wallet address (required for EVM hooks)
config={{
evm: { ... }, // EVM config (optional — omit to disable EVM)
ton: { ... }, // TON config (optional — omit to disable TON)
balanceCacheTTL: 15000, // balance cache TTL in ms (default: 15s)
}}
>EVM Config
| Parameter | Type | Default | Description |
| --------------------- | -------------------------------------- | -------- | ---------------------------------------------- |
| chains | EvmChain[] | Required | EVM chains to operate on |
| signer | IntentSigner | - | Omit for read-only mode (balance queries only) |
| bundlerUrl | string | Required | ERC-4337 bundler endpoint |
| paymasterUrl | string | Required | Paymaster endpoint |
| isSponsored | boolean | Required | Whether gas is sponsored |
| sponsorshipPolicyId | string | - | Required when isSponsored is true |
| paymasterAddress | string | - | Paymaster contract (non-sponsored mode) |
| chainOverrides | Partial<Record<EvmChain, overrides>> | - | Per-chain RPC, bundler, paymaster overrides |
| bridgeConfig | { enabled: boolean, ... } | disabled | Must be { enabled: true } for bridge routes |
TON Config
| Parameter | Type | Default | Description |
| ---------------- | ------------------------ | ---------- | -------------------------------- |
| clientConfig | TonGaslessClientConfig | Required | TON network client configuration |
| seedPhrase | string | Required | Seed phrase for the TON wallet |
| derivationPath | string | "0'/0/0" | Custom derivation path |
Signer Types
The EVM hooks support two signer types:
| Signer type | type value | Frontend-friendly? | Supports bridge? |
| ----------- | -------------- | ------------------ | ---------------- |
| Passkey | 'passkey' | Yes (biometric) | No |
| Seed phrase | 'seedPhrase' | Custodial only | Yes |
For frontend apps, prefer passkey signing (WebAuthn / biometric). Seed phrase signers should only be used in custodial backends or server-side rendering.
Main Exports
| Export | What it does |
| -------------------- | ----------------------------------------------------------------------------------------------------------- |
| GasfreeProvider | React context provider for SDK configuration |
| useGasfree | Access raw provider context (intent instance, config, status) |
| useBalance | Combined EVM + TON balance discovery via react-query |
| useIntent | Full EVM intent lifecycle (plan, execute, send) |
| useGaslessTransfer | Simplified one-shot EVM transfer |
| useTonTransfer | TON gasless transfer, fee estimation, balance check |
| usePaymentLink | Payment link generation, parsing, and execution |
| Types | GasfreeProviderConfig, EvmConfig, TonConfig, CombinedBalances, PaymentLinkParams, etc. |
| Re-exported types | IntentRequest, ExecutionPlan, IntentReceipt, BalanceMap, EvmChain, TonGaslessClientConfig, etc. |
License
MIT
