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). - Cross-chain x402 registration: pay for a
.goatregistration in USDC/USDT on Polygon, Base, Arbitrum, Optimism, BSC, or Metis. The GNS backend settles on goat-mainnet after the source-chain transfer 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 |
Cross-chain x402-paid registration
| Action | Name | Risk | Description |
|---|---|---|---|
x402CreateOrderAction | goat.gns.x402.createOrder | medium | Create a cross-chain x402 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 source-chain ERC-20 transfer that fulfills the order |
x402GetOrderStatusAction | goat.gns.x402.getOrderStatus | read | Poll lifecycle: CHECKOUT_VERIFIED → PAYMENT_CONFIRMED → INVOICED |
Cross-Chain 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 source-chain payment |
PAYMENT_CONFIRMED | Upstream watcher detected the source-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 | 0xdD3912A19eB9Aab0Cd88DdA107ec4fc2dA51D5e9 |
| PublicResolver | 0xD56644B440B6d0326dc777a92FB2A0d9FdB4e59D |
| EnsRegistry | 0x4d652092fB4a08D186C2797e96623deaEE46aa91 |
| ReverseRegistrar | 0x49275954460f2f6d3F8ba537E95Db8293C7c4058 |
| BaseRegistrar | 0xB3Bd3075A9C12eFF3b23FAEF165D12B5C20966E0 |
| x402Adaptor | 0xC0cEB3b632B0264b739BE115604D1911917d5471 |
| PriceBook | 0x81B36cf45Ac52F868D8948c033b9572C674ec3A4 |
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 source chain you're paying from (e.g. BSC) |
PAYMENT_CHAIN_PRIVATE_KEY | Optional | Source-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 cross-chain 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.