POST /v1/sponsor endpoint is DarkPool’s gas onramp. It uses Sui’s native sponsored-transaction protocol with no Enoki Portal allowlist, no third-party dependency, and the ability to sponsor any package. Both zkLogin and wallet users sign trades without holding any SUI.
Why we shipped it
The user had configuredAllowed Addresses in the Enoki Portal with the package IDs (wrong field; that section gates sender addresses, not Move targets), so every sponsorship attempt 403’d. Asking the user to redo the Portal config was both fragile and a third-party dependency. Self-sponsorship sidesteps it entirely.
Enoki sponsorship stays as Strategy 1 for zk users. The user paid for the credits and we shouldn’t waste them when the Portal is correctly configured.
Wire protocol
sender == user (their signature is mandatory). Gas comes from the sponsor.
Abuse bounds
Three caps prevent a hostile PTB:| Env var | Default | Bound |
|---|---|---|
SPONSOR_MAX_GAS_BUDGET_SUI | 0.03 | Per-tx hard ceiling on gas budget |
SPONSOR_PER_USER_DAILY_CAP_SUI | 0.5 | Per-sender daily cap (Redis-tracked) |
SPONSOR_DAILY_CAP_SUI | 5 | Global daily cap |
sponsor:user:<addr>:<yyyy-mm-dd> and sponsor:global:<yyyy-mm-dd> use INCRBYFLOAT with EXPIRE-to-end-of-day.
Worst case: one bad actor at the per-user cap drains 0.5 SUI/day, the global cap drains 5 SUI/day total. Both fit a hackathon budget.
PTB-command inspection (reject
tx.gas references in TransferObjects and SplitCoins) is a v0.4 hardening follow-up.Frontend integration
packages/frontend/src/lib/wallet.ts is the three-strategy signer:
- Self-sponsor first. Works for both wallet and zk users. Sponsors any package.
- Enoki sponsorship. Zk users only, on
SponsorUnavailableError. - Direct execution. User pays gas (last resort).
useTxSigner() which encapsulates the cascade.