GOAT Name Service (.goat)
The gns plugin provides a complete ENS-style .goat namespace stack:
- Read paths: check availability, get name details, list names owned by an address, estimate registration price.
- Two-phase ENS-style registration:
commit→waitForCommitment(min/max commitment age verified on-chain) →register(with permit or pre-approve) →renew. - Profile management:
setAddress,setProfileRecords(text + addr multicall),setPrimaryName(reverse record). - x402-paid registration: pay for a
.goatregistration in USDC/USDT on Ethereum, Optimism, BSC, GOAT Mainnet, Base, or Arbitrum. The GNS backend completes registration on GOAT mainnet after the x402 payment is detected.
End users register names via the agentkit-gns CLI; programmatic consumers use the plugin's 15 actions directly.
Quick Start (CLI)
Actions
Read
| Action | Name | Risk | Description |
|---|---|---|---|
checkAvailabilityAction | goat.gns.checkAvailability | read | Is the .goat name available? |
getNameDetailsAction | goat.gns.getNameDetails | read | Full record: owner, expiry, resolver, primary, profile records |
getMyNamesAction | goat.gns.getMyNames | read | All .goat names owned by a given address |
estimatePriceAction | goat.gns.estimatePrice | read | Quote registration price for a name + duration + payment token |
Two-phase registration
| Action | Name | Risk | Description |
|---|---|---|---|
commitAction | goat.gns.commit | medium | Generate a 32-byte secret, compute commit hash, broadcast on-chain commit |
waitForCommitmentAction | goat.gns.waitForCommitment | read | Poll on-chain commit storage until block.timestamp ≥ revealAt (or detect expiry) |
registerAction | goat.gns.register | high | Reveal-phase register; re-derives the commit hash on-chain and rejects parameter drift |
renewAction | goat.gns.renew | high | Extend an existing registration |
commit returns the 32-byte secret as a top-level sensitiveOutputFields value — redacted by default in hook events; the CLI exposes it under --reveal-secrets only.
Profile
| Action | Name | Risk | Description |
|---|---|---|---|
setAddressAction | goat.gns.setAddress | medium | Set / update the address that a name resolves to |
setProfileRecordsAction | goat.gns.setProfileRecords | medium | Batch set text + addr records via PublicResolver multicall |
setPrimaryNameAction | goat.gns.setPrimaryName | medium | Set the reverse (primary) record for the caller |
x402-paid registration
| Action | Name | Risk | Description |
|---|---|---|---|
x402CreateOrderAction | goat.gns.x402.createOrder | medium | Create an x402-paid registration order via the GNS backend |
x402SubmitSignatureAction | goat.gns.x402.submitSignature | high | EIP-712 sign the calldata authorization (GOAT-adapter chain) |
x402PayOrderAction | goat.gns.x402.payOrder | high | Broadcast the payment-chain ERC-20 transfer that fulfills the order |
x402GetOrderStatusAction | goat.gns.x402.getOrderStatus | read | Poll lifecycle: CHECKOUT_VERIFIED → PAYMENT_CONFIRMED → INVOICED |
x402 Registration — Orchestration
The CLI (agentkit-gns x402-register) and the examples/gns-x402-register demo both run this 8-step sequence:
Lifecycle states
The GNS backend's OrderStatus enum (no PAYMENT_PENDING):
| State | Meaning |
|---|---|
CHECKOUT_VERIFIED | Order created and signature authorized; ready for payment-chain payment |
PAYMENT_CONFIRMED | Upstream watcher detected the payment-chain ERC-20 transfer |
INVOICED | True success — the adaptor callback executed on GOAT and the .goat name is registered |
FAILED / EXPIRED / CANCELLED | Terminal failure |
For DELEGATE / callback orders (the GNS flow), PAYMENT_CONFIRMED is an intermediate state — clients must keep polling until INVOICED to confirm the name was actually registered. The CLI does this automatically.
Commit-hash binding invariant
The on-chain commit's payment tuple must match what the GNS backend re-derives in createOrder, or registration is rejected with Commitment does not match registration payload. AgentKit binds:
paymentToken = GOAT-side stablecoin addressresolved by canonical symbol via the SDK'sGNS_PAYMENT_TOKENStable (mirrors the backend'spaymentTokenAddressFromSymbol).maxPaymentAmount = totalWeifrom/names/quote, forwarded tocreateOrderascommitMaxAmountWei.
The register action additionally re-derives the commitment hash on-chain and rejects any drift of (secret / token / amount / years / owner / resolver / data / reverseRecord / referrer) vs the original commit.
payOrder Security Model
x402.payOrder is a money path. Beyond the lifecycle gate (require CHECKOUT_VERIFIED, refuse to double-pay or pay a dead order), it cross-checks every caller-supplied routing field against three trust anchors:
- Status endpoint
OrderProof—chainId,amountWei,fromAddress(strict type + value). calldataSignRequest.message(backend-signed, verified on-chain by the adaptor):message.owner≡input.payToAddress— caller cannot redirect the merchant's payment-receive address (mandatory; fail-closed if absent).message.payer≡ wallet address — bind the signed payer authorization to the broadcasting wallet.
x402Configtoken allowlist —input.tokenContractmust appear inchains[payChainId].tokens[].contract. Unknown tokens or unsupported chains are refused.
A 3-way payer binding (wallet.getAddress() ≡ payer.getAddress() ≡ message.payer) catches mis-wired payer adapters where wallet and payer wrap different signers.
A module-scope inflight Map dedupes concurrent payOrder calls for the same orderId (double-pay TOCTOU defense).
Network Addresses (Predeployed)
The SDK's getGnsContracts(network) returns the full registry. GOAT mainnet ships with these addresses pre-wired:
| Contract | goat-mainnet (chain 2345) |
|---|---|
| Controller | 0x271AfB3d228BB3169F5d10b8F34e227EEF43a5d9 |
| PublicResolver | 0xC624A087E2fEC3bcB63fdA984829Eb18E56be210 |
| EnsRegistry | 0xEce959d7669a81964b86c3704335fD0332087BAe |
| ReverseRegistrar | 0xC7e6944fb92bc810C2784b6595ff8753A5364Ae4 |
| BaseRegistrar | 0x8aB04C7c002C4B2c655aFec245296d8ef874933F |
| x402Adaptor | 0x03Ae465d2ccd719416f9BC52783F268DC2f277e6 |
| PriceBook | 0xa651803328a0236cEFf271e136131Ad8071365B9 |
| GoatNameWrapper | 0x15F5875c7CDA8C0576e649677eBA938cC9082dFC |
| StaticMetadataService | 0xC2c18F8afeBc5EDE41c801016023B38Fad15DEC2 |
GOAT-side payment tokens
| Symbol | Address | Decimals |
|---|---|---|
| USDC | 0x3022b87ac063DE95b1570F46f5e470F8B53112D8 | 6 |
| USDT | 0xE1AD845D93853fff44990aE0DcecD8575293681e | 6 |
Programmatic Usage
Environment Variables
| Variable | Required | Description |
|---|---|---|
GOAT_PRIVATE_KEY | Always | Wallet key for the GOAT-side wallet (owner of the registered name) |
PAYMENT_CHAIN_RPC_URL | x402-register only | RPC URL of the payment chain you're paying from (e.g. BSC). When the payment chain is GOAT Mainnet, you can use the GOAT RPC/default configuration. |
PAYMENT_CHAIN_PRIVATE_KEY | Optional | Payment-chain signer key for x402-register; falls back to GOAT_PRIVATE_KEY (same wallet on both chains) |
GNS_API_BASE_URL | Optional | Override default https://gns-api.goat.network/api |
GOAT_MAINNET_RPC_URL | Optional | Override the default GOAT mainnet RPC endpoint |
Run agentkit-gns doctor for a full env diagnostic.
Examples
examples/gns-x402-register— full x402 register demobin/_lib/cli-gns.ts— the reference implementation of theagentkit-gnsCLI
Related
- CLIs —
agentkit-gnsflags and env vars - Plugins Reference — full inventory of all 15 plugins
- x402 Payments — the underlying agent payment protocol
Plugins Reference
Complete reference for all 15 AgentKit plugins and 118 on-chain actions — wallet, DEX, bridge, payments, identity, cross-chain, .goat naming, x402 giftcard purchase, and more.
x402 Giftcard Purchase
Turn-key cross-chain consumer flow — agents pay USDC/USDT on Polygon, Base, Arbitrum, Optimism, BSC, or Metis, and the recipient gets a giftcard delivered off-chain.