Skip to content

Gasless intents

Most on-chain actions on Necter are gasless: you sign typed data in your wallet, and the Hub’s relayer sends the transaction and pays the gas. You never need Sepolia ETH to mine.

Action Endpoint Contract call relayed
Bond / top up collateral POST /v1/subscriptions (returns the payload), POST /v1/subscriptions/{id}/bond, …/bond-payload Staking.bondBySig with an EIP-2612 NECTA permit
Unbond POST /v1/subscriptions/{id}/unbond Staking.unbondBySig
Withdraw collateral POST /v1/subscriptions/{id}/withdraw Staking.withdrawBySig
Change payout address POST /v1/subscriptions/{id}/payout Staking.setPayoutBySig
Claim rewards POST /v1/me/withdrawals/claims ProjectVault.claimMany (anyone may claim; funds always go to the miner)
Faucet POST /v1/faucet/drip NectaFaucet.dripTo
Register a project POST /v1/developers/projects/{id}/register ProjectRegistry.registerBySig
Publish a consensus version POST /v1/developers/projects/{id}/versions/{v}/publish ProjectRegistry.publishVersionBySig

The one action that is not gasless is creating a project’s vault: the developer sends createVault from their own wallet, which needs a little Sepolia ETH. Vault

Endpoints that change on-chain state work in two steps:

  1. Ask for the payload. Call the endpoint with no body (or {}, or the parameters it needs such as {"payout_address": "0x…"}). The Hub answers with a GaslessPayload:

    {
    "action": "unbond",
    "typed_data": { "types": { … }, "domain": { … }, "primaryType": "…", "message": { … } },
    "permit": null,
    "direct_tx": { "chain_id": 11155111, "to": "0x…", "data": "0x…" },
    "expires_at": 1791478000
    }
  2. Sign and post it back. Sign typed_data with eth_signTypedData_v4 (and permit too when present), then post {"typed_data": …, "signature": "0x…", "permit": …, "permit_signature": "0x…"} to the same endpoint. The Hub checks the signer, relays the transaction and answers 202 with {"status": "queued" | "sent" | "confirmed" | "reverted" | "failed", "tx_hash": …}.

direct_tx is the equivalent ordinary transaction, for wallets that prefer to pay gas themselves.

Check what your wallet shows before you sign: the domain names the contract (verifyingContract, chain id 11155111) and the message names the subscription, amount, payout address or project. The miner apps validate every field (type strings, chain id, contract addresses from GET /, owner, deadline, amount) before asking you to sign, and never sign anything silently except a Sign-In with Ethereum message that passes every check.