Market board
The market board is a public list of open swap offers. A taker finds an offer and a price without already knowing the maker. The board never holds coins or keys: it stores offer links, checks them against the chain, and passes acceptances back to the maker, who still signs last. Design, rules and research: Market board.
For a swap at once, without waiting for a maker, use a dealer pool. The board
runs behind the gateway at /market/v1 and needs no account. In the wallets it is the Market
tab of the Swap screen; the explorer shows a read-only copy.
Read the board
import { createClient, listMarketPairs, listMarketOffers, listMarketTrades } from 'arrekta-sdk'
const gw = createClient({ url: 'http://127.0.0.1:3000' })
const pairs = await listMarketPairs(gw) // [{ pair: 'GOLD/ARRK', best_bid, best_ask, last_price, … }]
const { base, quote } = pairs[0]
const book = await listMarketOffers(gw, { base: base.asset, quote: quote.asset }) // best price first
const trades = await listMarketTrades(gw, { base: base.asset, quote: quote.asset, limit: 20 })from arrekta_sdk import Client
gw = Client("http://127.0.0.1:3000")
pairs = gw.list_market_pairs()
base, quote = pairs[0]["base"]["asset"], pairs[0]["quote"]["asset"]
book = gw.list_market_offers(base=base, quote=quote)
trades = gw.list_market_trades(base=base, quote=quote, limit=20)ARRK is always the quote asset. side: "sell" means the maker gives the base asset, and price is
quote per base in display units. Amounts are base-unit strings.
List an offer
Any valid arrektaswap: offer can be listed if its transaction is version 2 with valid_until set,
it expires within 30 days, and its coins are unspent and not behind another listing. Posting the
same offer twice returns the existing listing.
import { postMarketOffer, marketOfferId } from 'arrekta-sdk'
const listed = await postMarketOffer(gw, { offer: link }) // { id, state: 'open', … }
listed.id === marketOfferId(offer.pst) // the id is derived from the offer itselffrom arrekta_sdk import market_offer_id
listed = gw.post_market_offer(link)
assert listed["id"] == market_offer_id(offer.pst)Take an offer
Build and sign your half exactly as for a shared link (Take it, then complete it), then hand the acceptance to the board. The board checks it and the maker collects it.
import { postMarketAcceptance } from 'arrekta-sdk'
await postMarketAcceptance(gw, { id: offer.id, acceptance }) // { txid, offer_id, state: 'pending' }gw.post_market_acceptance(offer["id"], acceptance)The maker reads waiting acceptances with listMarketAcceptances / list_market_acceptances,
checks each one with swapAcceptanceMatches, signs and broadcasts. The board marks the offer
filling, then filled once the transaction is in a block, and records the trade.
Withdraw an offer
Withdrawing needs no transaction. Sign a message with the key of any of the offer's coins. The offer was never signed, so nobody can fill it from a saved copy.
import { cancelMarketOffer, signMarketCancel } from 'arrekta-sdk'
await cancelMarketOffer(gw, { id, ...signMarketCancel(inputKey, id, 'regtest') })from arrekta_sdk import sign_market_cancel
gw.cancel_market_offer(id, **sign_market_cancel(input_key, id, "regtest"))In a wallet
@arrekta/wallet-core wraps all of this, and the board URL is the wallet's gateway setting:
// maker: list it and let the wallet complete fills while it is unlocked
const offer = await maker.createSwapOffer({ give: { asset: 'GOLD', amount: '10' }, want: { asset: 'ARRK', amount: '5' }, post: true, autoComplete: true })
// taker: browse, then take (the acceptance goes to the maker through the board)
const [pair] = await taker.marketPairs()
const [best] = await taker.marketBook({ base: pair.base.asset, quote: pair.quote.asset })
const take = await taker.prepareMarketTake(best.id) // preview first
await taker.confirmSwapTake(take.id)
// maker: picks it up (watch() also does this every 20 s)
await maker.syncBoard() // { completed: [txid] }cancelSwap(id) releases the coins and withdraws the listing. Errors from the board come back as
market-unavailable when the gateway cannot be reached, otherwise with the board's own code
(coin-spent, input-in-offer, too-many-offers, offer-closed, …).