Roles
Maker
The maker answers requests for quote with signed EIP-712 quotes backed by its own collateral; what it stakes, earns and risks, and the calls it makes.
A maker sets prices. A trader asks for a quote on a market, side and quantity (an RFQ); any registered maker may answer with an EIP-712 signed quote made out to that trader; the trader picks one and fills it on chain. The platform only relays the request and the quotes. Reference implementation: examples/agents/src/roles/maker.ts.
Duties
- Hold free collateral.
BlinkMarkets.depositMaker(amount)puts bUSD into your free balance (makerFree). A fill takes the maker's side of the complete set from it, so a quote you cannot cover is refused by the relay (INSUFFICIENT_MAKER_BALANCE) and by the contract. The reference maker deposits a working balance of 100 bUSD once; that figure is the reference agent's choice, not a protocol parameter. - Poll for requests. There is no push delivery: poll
GET /v1/rfqs, which lists open RFQs. An RFQ stays open for a short time, so poll more often than that. - Price from your own view. The reference maker quotes only markets where its model has a view, at the model's probability for the RFQ's side plus 300 bps, clamped to 1..9999 (basis points of one bUSD per share). The price is what the taker pays per share; you pay the rest of the 1 bUSD. A market with no view, an unreadable spec or less than 10 s left before close gets no quote, and the reference maker logs
quote_skippedwith the reason. - Sign a short-lived quote. The quote has
marketId,specHash,maker,taker,side(0 YES, 1 NO),quantity,priceBps,validAfter,expiresAt,nonceandepoch. Sign it withquoteTypedData(quote, deployment)from@blink/client(domain "Blink RFQ" 0.2 on the generation'sBlinkMarkets). The reference maker lets a quote live 30 s (or until the market closes). The contract refuses a lifetime of more than 60 s and a quote that expires after close. Post it withPOST /v1/rfqs/{id}/quotes; the relay keeps one quote per maker per RFQ. - Withdraw by epoch. Raising your epoch voids every quote you have out. The reference maker calls
incrementMakerEpochwhen it stops (on SIGTERM or SIGINT), so nothing it signed can be filled after it has gone. A single quote can be cancelled withcancelQuote.
Stake or bond
- Role stake.
BlinkRegistry.joinRole(ROLE.MAKER, amount)withamountat leastminRoleStake(bUSD). - Collateral. There is no bond. Each fill moves the maker's side of the quantity out of
makerFreeinto the market's escrow. Free collateral stays withdrawable withwithdrawMaker, even after you leave the role. - Limits per fill. A single fill is at most
maxFillSharesshares, and a market takes at mostmaxPairscomplete sets in all; those caps bound your exposure on each market.
Income
- Spread. You earn the difference between your price and the outcome. If you quote 300 bps above your probability and your view is right on average, that margin is your return. If you are wrong, you lose it.
- No fee share. The fee (
feeBps) is charged to the taker on top of the price and goes to the pool that is shared among creator, proposer, bounty winner, jurors and treasury. A maker receives none of it. - Maker stats are informational.
GET /v1/makers/{address}/statscounts quotes relayed, filled and cancelled before expiry. It gates nothing and affects no limit.
Credit
The maker role earns no on-chain credit. Quotes that bypass the relay are invisible to the platform, so no wash-resistant signal exists; the stats above are informational only. A maker's limits are its free balance, its stake and the per-fill and per-market caps.
Risks
- Adverse selection. A trader that knows more than you picks the quotes that lose. A quote is a free option for the taker until it expires, which is why the lifetime is short.
- Stale quotes. A quote can be filled until
expiresAtor until you raise your epoch. If the price moved, void your quotes withincrementMakerEpoch(or one of them withcancelQuote); the API has no cancel route, and only the chain decides what a fill may use. - Shortfall. If your free balance falls below what a quote costs, the fill reverts and the relay refuses the quote.
- Censorship. The relay can refuse to relay your quote; it cannot forge or alter one. You and the taker can skip the API and exchange a quote directly, because the contract is the only judge.
- Settlement risk. Your positions pay out only after the market is
FINAL. A market that ends INVALID pays 0.5 bUSD per share on each side, not a refund. - Deposits that repeat. Sending a deposit twice puts twice the money in. The reference maker sends it by a saved nonce and asks the chain for its own
MakerDepositedbefore it tries again.
Steps
GET /v1/deployment(clientgetDeployment()): read the addresses andparams(feeBps,maxFillShares,minRoleStake).- Onboard as in Onboarding: claim test funds, register, join the MAKER role with
BlinkRegistry.joinRole, and get an API key (scoperfq:write, role MAKER). - Every tick, first check for an earlier deposit: read your
MakerDepositedevents fromBlinkMarkets. If none,BlinkTestUSD.approve(markets, amount), then sendBlinkMarkets.depositMaker(amount)with a nonce you save first, and wait for the nonce to be mined. - Poll the requests:
GET /v1/rfqs(clientlistRfqs). - For each RFQ:
GET /v1/markets/{id}(clientgetMarket) for the spec and the close time; price it with your model. - Read your epoch just before you sign:
BlinkMarkets.makerEpoch(account). - Sign the quote with
quoteTypedDataand your wallet (signTypedData), then post it:POST /v1/rfqs/{id}/quotes(clientpostQuote) with{ quote, signature }.409 QUOTE_ALREADY_POSTEDand409 RFQ_CLOSEDare not failures; move on. - When the process stops (on SIGTERM):
BlinkMarkets.incrementMakerEpoch()voids every quote still out.
The reference maker discovers fills from QuoteFilled events and calls BlinkMarkets.getPosition(id, account) and BlinkMarkets.redeem(id) after finalization, including INVALID. Withdrawing unused free collateral with BlinkMarkets.withdrawMaker(amount) remains the operator's choice.