Swagger

Allowances

Check and grant the ERC-20 allowances required by the executor rail.

How an allowance is granted

The executor rail needs sufficient ERC-20 allowance for each token it spends. Set it up per account, token, spender and network. Existing allowance can be reused while it remains sufficient; a revoked or reduced allowance can require setup again.

A prepare that needs one is refused with 400 and code=EXECUTOR_ALLOWANCE_MISSING. POST /transaction/allowance-setup then answers what this token needs: kind "permit" returns EIP-712 typed data to relay through POST /transaction/setup-permit, and kind "approve" means the token has no EIP-2612 support, so the account signs an ordinary approve and UGTP broadcasts it through POST /transaction/setup-approval, which is bounded per account and per project. Neither call accepts a spender or an amount — both are decided server-side.

Worked example

Granting an allowance, end to end

On the executor rail, check allowance before preparing or handle EXECUTOR_ALLOWANCE_MISSING. Reuse an existing allowance while it remains sufficient.

  1. 01

    Ask what this token needs

    POST /transaction/allowance-setup

    Call it after a prepare is refused with EXECUTOR_ALLOWANCE_MISSING. The answer is kind "permit" when the token implements EIP-2612, and kind "approve" when it does not — you never choose the spender or the amount.

    Input — the request

    curl -X POST "https://api.ugtp.io/v1/transaction/allowance-setup" \
      -H "X-API-Key: $UGTP_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "networkId": "43114",
      "ownerAddress": "0x0a1758ad202a2059e8c2970b562597ca45d863c4",
      "tokenAddress": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"
    }'

    Output — 200 response

    {
      "kind": "permit",
      "primaryType": "Permit",
      "domain": {},
      "types": {},
      "message": {},
      "deadline": 1780000000
    }

    Every status this call can answer with
    StatusWhen
    200What the account must sign
    400Invalid request body or query parameters
    401Missing or invalid credentials
    429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
    500Internal server error
  2. 02

    Relay a permit

    POST /transaction/setup-permit

    The path for a token that supports EIP-2612, and the one to prefer: the account signs typed data and needs no native coin at all. A permit that already exists comes back as a 409, inspect PERMIT_ALREADY_GRANTED to confirm that the allowance is already in place.

    Input — the request

    curl -X POST "https://api.ugtp.io/v1/transaction/setup-permit" \
      -H "X-API-Key: $UGTP_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "networkId": "43114",
      "ownerAddress": "0x0a1758ad202a2059e8c2970b562597ca45d863c4",
      "tokenAddress": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
      "deadline": 1780000000,
      "signature": "0x..."
    }'

    Output — 200 response

    {
      "transactionHash": "0x...the approve transaction UGTP broadcast",
      "status": "confirmed",
      "allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
    }

    Every status this call can answer with
    StatusWhen
    200Permit relayed
    400Invalid request body or query parameters
    401Missing or invalid credentials
    409code=PERMIT_ALREADY_GRANTED — this account already permitted the executor.
  3. 03

    Or broadcast a plain approve

    POST /transaction/setup-approval

    For a token with no permit. The account signs an ordinary approve and UGTP broadcasts it; the sender, token, spender and amount are all read from the signed bytes. One-time and tightly bounded per account and per project.

    Input — the request

    curl -X POST "https://api.ugtp.io/v1/transaction/setup-approval" \
      -H "X-API-Key: $UGTP_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
      "networkId": "43114",
      "rawTransaction": "0x02f8..."
    }'

    Output — 200 response

    {
      "fundingTransactionHash": "0xaaa...",
      "approvalTransactionHash": "0xbbb...",
      "approvalStatus": "confirmed",
      "allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
    }

    Every status this call can answer with
    StatusWhen
    200Gas funded and the approval broadcast
    400Invalid approval transaction, unsupported token or spender, incorrect amount, or a failed simulation. Inspect the returned approval error code.
    401Missing or invalid credentials
    403code=APPROVAL_SENDER_BLOCKED — this account previously spent funded gas on a different transaction and is permanently ineligible for funded approvals.
    409APPROVAL_ALREADY_GRANTED, APPROVAL_TX_NONCE_STALE, APPROVAL_TX_NONCE_IN_FLIGHT or APPROVAL_FUNDING_IN_PROGRESS. Check allowance and pending transactions before retrying.
    429Approval funding limit reached. A lifetime allowance does not reset after backoff; inspect the reported limit before retrying.
    502APPROVAL_FUNDING_FAILED: retry. APPROVAL_FUNDED_BUT_NOT_BROADCAST: gas was funded; broadcast the same signed approval through the account wallet or RPC. APPROVAL_MINED_WITHOUT_ALLOWANCE: inspect the receipt and allowance.
    503Approval setup is temporarily unavailable or a required chain read failed. Retry with bounded backoff and the same signed approval.
    504code=APPROVAL_FUNDING_NOT_CONFIRMED — the funding transfer has not confirmed yet; a retry resumes it without funding again.