KeeperHub / KeeperHub/keeperhub

feat: stablecoin to native gas top-up for Turnkey EOA wallets

Open
#2,435 3 comments 0 reactions 0 assignees View on GitHub
enhancement needs-discussion
Dominant language
TypeScript
Stars
24
Forks
93
Avg merge
1d 4h
Merged PRs (30d)
253

Description

## Problem

Orgs and agents often fund the Turnkey wallet with **USDC (or another stable)** and still cannot keep executing:

- Gas **sponsorship** pays the **network fee only**. It does not create spendable native ETH.
- Native is still required for ETH value transfers, Safe outer sends, withdraw, and any path that falls back to self-pay when sponsorship or credits are unavailable.
- Today there is no productized "convert stable to gas" path. `POST /api/execute/swap` returns **501 Coming soon**. Agents must hand-compose Uniswap + WETH unwrap (and still need gas or sponsorship for that composition).

This is the failure mode: **have USDC, cannot pay or bootstrap gas**.

## Scope (v1)

Same-chain **USDC to native ETH** on the org **Turnkey EOA**, as one idempotent Direct Execution action.

**In**

- `POST /api/execute/gas-top-up` (dedicated route; do not overload general `/swap` yet)
- MCP tool `top_up_gas` wrapping that route
- Wallet UI CTA: "Top up gas from USDC" (can follow the API in a second PR if preferred)
- Docs: distinguish from PAYG "send USDC for billing; we cover gas"

**Flow (server-orchestrated)**

1. Resolve org Turnkey EOA; reject Safe-as-sender for v1 (gas lands on the EOA that pays gas).
2. Check USDC balance on the chosen chain.
3. Under **sponsorship** (required for MVP; fail closed if ineligible or credits exhausted): approve USDC to router, swap USDC to WETH, unwrap WETH to ETH.
4. Return `{ ethReceived, usdcSpent, txHashes[], sponsored: true, executionId? }` with `Idempotency-Key` support like other execute routes.

**Chains (v1):** sponsorship-supported EVM where Uniswap V3 and WETH already exist in the protocol registry (for example Base, Ethereum). Exact list in the PR.

**Out of scope for v1**

- General `POST /api/execute/swap`
- Cross-chain bridge
- Fiat on-ramp
- Safe-as-sender / funding the Safe itself
- Solana

## Why this is separate from sponsorship

Sponsorship already solves "zero ETH for **fees**" on eligible EOA routes. It does **not** solve "need **spendable** ETH" or "bootstrap when the only balance is a stable." Top-up creates native balance; sponsorship continues to pay fees on eligible writes.

## Building blocks (exist)

- Sponsored write path (`executeSponsoredTransaction` / Turnkey Gas Station)
- Uniswap V3 and `wrapped` unwrap protocol actions
- Execute-route auth, scopes, idempotency patterns (`/api/execute/transfer`, contract-call)
- Gas credits metering

## Acceptance criteria

- [ ] With USDC and **no** native ETH on a sponsorship-eligible EOA, `gas-top-up` succeeds and wallet native balance increases.
- [ ] Without sponsorship eligibility or credits, the call **fails closed** with a clear error (does not attempt an unsponsored swap that needs ETH).
- [ ] Idempotent retry with the same key does not double-spend USDC.
- [ ] Unit/integration coverage for happy path, fail-closed, and idempotency.
- [ ] Docs updated; PAYG billing wording remains distinct.

## Non-goals / notes

- Not a replacement for a full Swap product (`/swap` can stay 501 until a separate issue).
- Amount UX can start as explicit `amountUsdc`; "enough for N txs" can be a follow-up.

Contributor guide

Open the contributing guide

Research direction

Start by reading the existing execute routes, especially /api/execute/transfer and contract-call, then trace executeSponsoredTransaction, the Uniswap V3 and wrapped protocol actions, and the gas credits metering. The work is done when the dedicated gas-top-up route and top_up_gas tool meet the happy-path, fail-closed, idempotency, test-coverage, and documentation acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend, blockchain, documentation
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.