Skip to main content

Services on subtun0

These SUBFROST services are reached by a .peer name on subtun0. Connect through the entry relay wss://wss-1.subdns.to/ws, with its identity fr1rx2zvtw676fm3x5krvt893ktu5cdycu9ft4jmcfxlleeuvmp587su6wsmp.peer as the first hop, and open a stream to the service's name: see Connecting over subtun0. Each name is derived from the service's own key, so nobody else can answer under it.

Service.peer nameSpeaks
Peg-in service (pegd)fr173rdd4ld26sequ3ps6jrwaemxxzrsrnaaua9z6vh58y04guckmtqd23s4r.peerHTTP, port 80
DIESEL fee brokerfr12quta238kx3l4mfd2jnqv6sgsfa87gskm7avzegg66kdcwjqsh5scqqm58.peerHTTP, port 80
Fractal gateway servicefr1kq3hutys4xp0gvukkpr68nyzrjt2tnrwlafnqxuuv8agh2l720tqlxjywg.peerits own framing (FBG1)
SIGIL DAOfr1rvrz4mzz0m0sw0uvm2py5mn2grlrjk8mhu995w2revrh4cdkxgesj7vye2.peerHTTP, port 80

Paths below are relative to http://<name>.peer, over that stream.

Peg-in service (pegd)​

fr173rdd4ld26sequ3ps6jrwaemxxzrsrnaaua9z6vh58y04guckmtqd23s4r.peer

pegd turns a signed deposit intent into a watched deposit. It derives the Ethereum deposit address for the intent independently, compares it with the one you derived, stores the intent, watches for the funds and follows them through settlement into the frUSD vault. It is the service behind frUSD deposits from other chains; the encodings it accepts are in Encoding Pegs and Swaps.

RequestDoes
POST /v1/multichainRegister an intent funded from BNB Chain, Polygon or Base. Body: the intent, its preimage, your own derivation, and a source block naming the source chain, forwarder, lane and signatures
POST /v1/gatewaysRegister an intent for a deposit address on Ethereum itself (a plain ERC-20 transfer to the address)
POST /v1/permitRegister a gasless intent for funds already on Ethereum. Not usable yet: the Ethereum Permit2Gateway it needs is not deployed
GET /v1/gatewaysList registrations. Query status, kind (deposit_address, multichain, permit), chainId, limit (max 1000), offset
GET /v1/gateways/:idOne registration, by deposit address or by intent hash, with its recent events
GET /v1/gateways/:id/eventsIts full event log (limit max 5000, offset)
POST /v1/gasdropsRegister a recipient-signed gas drop for a peg-out (see Optional gas drop)
GET /v1/gasdropsThe gas-drop registry for one chain. Query chain_id (required), as_of, order=last_requested_desc, limit (1–1000, default 200), offset
GET /v1/healthService status, and the derivation constants it checks against
  • No API key is needed. A registration is accepted only if pegd reproduces its derivation (and, for a gas drop, the recipient's signature verifies), so a bad request can't register anything useful.
  • Every registration is public once made. GET /v1/gateways lists the intents, the source-chain owner address, and the transactions. Don't put anything in an intent that you would not publish.
  • A registration is a record, not a promise of custody. pegd never holds funds. The deposit address is fixed by the intent hash on the GatewayFactory, and anyone can call register and settle there.

Derivation check​

pegd refuses to register an address it can't reproduce. Send your own derivation in expected (at least depositAddress). If pegd's derivation differs, it answers 409 with the first field that disagrees (factory_mismatch, type_hash_mismatch, struct_hash_mismatch, domain_separator_mismatch, intent_hash_mismatch, deposit_address_mismatch, …) and its own values in details.nodeDerivation. Stop there: one of you has the intent or the constants wrong.

GET /v1/health publishes the constants it uses, so you can compare before you sign:

{
"status": "ok",
"service": "subfrost-pegd",
"chainId": 1,
"derivation": {
"factory": "0xaf4c39a0da304ef39d56783d785ea52bb8431362",
"initCodeHash": "0xae78bd81aa686ad972e9cf69b3b526123eae9615a544c18a6b64819d63072968",
"domainName": "SUBFROST frUSD Gateway",
"domainVersion": "1",
"typeHash": "0xd0ba66893952bd61d59c1120e0819129666508130451c7f40bba1c37f5d730c5",
"requireClientDerivation": true
},
"gateways": { "Watching": 0, "Seen": 0, "Confirming": 1, "Swept": 0, "Relayed": 0, "Complete": 0, "Expired": 0, "Refunded": 0, "Failed": 0 }
}

Status​

A registration moves through Watching → Seen → Confirming → Swept → Relayed → Complete. It can also end in Expired, Refunded or Failed. Its event log records created, deposit_seen, confirmed, swept, relayed, minted, refunded, expired, balance_decrease and error.

Errors share one shape: {"error": {"code": "...", "message": "...", "details": {...}}}.

DIESEL fee broker​

fr12quta238kx3l4mfd2jnqv6sgsfa87gskm7avzegg66kdcwjqsh5scqqm58.peer

The broker is the front door to the relayers that let a wallet pay its Bitcoin network fee in DIESEL. It tracks the relayer fleet, picks one that can cover a fee, and passes quotes and funding requests to it.

RequestDoes
GET /v1/tokensThe tokens fees can be paid in, with terms: margin, the largest fee one quote can cover, the minimum fee rate, the treasury that is repaid, and an indicative price. Also a summary of the healthy relayers and their capacity
POST /v1/quote {"fee_target_sats": n}A signed quote (a ticket) from a relayer that can cover n sats of fee. 503 when none can
POST /v1/fund {"signed_ticket": {...}, "tx_hex": "..."}Hand the relayer your transaction, built with the ticket's funding input, to sign and fund
POST /v1/abandonRelease a ticket you will not use
GET /healthzLiveness, and how many relayers are known and healthy

An answer from GET /v1/tokens, abbreviated:

{
"tokens": [{
"id": {"block": "2", "tx": "0"},
"symbol": "DIESEL",
"decimals": 8,
"treasury": {"block": "2", "tx": "96782"},
"margin_bps": 200,
"max_fee_sats": 20000,
"min_fee_rate_sat_vb": 1,
"indicative_price": {"sats_num": "44114", "sats_den": "100000000", "struck_at_height": 970368, "source": "pool:2:77087:med12g12@970368"}
}],
"fleet": {"relayers_healthy": 3, "capacity_sats": 600000, "relayers": ["…"]},
"tip_height": 970374
}

Every u128 on this wire, alkane id parts and price numerators included, is a decimal string. The indicative price is DIESEL's price in sats, taken from the DIESEL/frBTC pool 2:77087; the price you actually pay is fixed in the signed ticket.

Check a ticket's signature against the broker's directory, not against the key that came with it. The ticket carries the relayer's public key for convenience, but anything that could swap the signature could swap that key too. Compare it with the ticket_pubkey that GET /v1/tokens publishes for that relayer.

Fractal gateway service​

fr1kq3hutys4xp0gvukkpr68nyzrjt2tnrwlafnqxuuv8agh2l720tqlxjywg.peer

The Fractal gateway service derives and registers gateway addresses for FB deposits, and sweeps them into the fb-vault. Its requests are POST /v1/gateway, GET /v1/gateway/:address, GET /v1/vault and GET /healthz; the Fractal Developer Guide documents them.

It is not an HTTP server. It speaks its own request framing (FBG1) directly to its .peer name, so curl over a subtun0 stream doesn't reach it. The service registers on wss://wss-1.subdns.to/ws. Use its own client, fb-gatewayd client, and point it there with --relays wss://wss-1.subdns.to/ws.

SIGIL DAO​

fr1rvrz4mzz0m0sw0uvm2py5mn2grlrjk8mhu995w2revrh4cdkxgesj7vye2.peer

The SIGIL DAO peer serves the DAO's data and app over subtun0: the app itself at /, plus /dao, /proposals, /identities, /profiles and /health. The SIGIL web app joins subtun0 through wss://wss-1.subdns.to/ws and talks to this peer.

Where to go next​