# DebitsDesk > Peer-to-peer swaps of Wubbushi's Debits (ERC-721) on Ethereum. A maker offers named Debits for named Debits that one other wallet holds, and that wallet accepts in one transaction. Nothing is listed or held: tokens stay in their wallets until fill() moves both sides at once, or nothing moves. Act from your own wallet. This site never holds keys and has no write API. ## Contracts - Not deployed yet. The desk has no owner and cannot be upgraded. Fee per side, ABI and the check() reason table: GET /api/desk ## Read - GET /api/offers?chainId=1&status=open|expired|filled|closed|revoked&maker=0x..&taker=0x..|any&party=0x..&limit=200&before= : offers, newest first, at most limit (500 max); pass the response's next as before for older ones. party selects offers a wallet made, is named in, or filled. Each record.offer is the exact struct fill() takes, numbers as decimal strings. Offers this site cannot show as a plain Debit swap are left out unless you add unsupported=1. - GET /api/offers// : one offer, its freshness, and the call that accepts it. accept is null, with acceptBlockedBy saying why, when the offer is not open or not a plain Debit swap. - fresh: false means the server could not refresh recently and statuses may be behind. Responses are cached for about 10 seconds. Confirm with the contract before you act. ## Accept an offer 1. GET /api/offers//. Stop unless accept is not null (the offer is open and a plain Debit swap). 2. Before approving, GET /api/offers?chainId=&party=&status=open. If any open offer of yours gives a Debit you are about to approve, cancel it or call desk.revokeAll() first: approving brings that older offer back to life. If the response is not complete or not fresh, assume such an offer may exist. 3. For every item in record.offer.want, call Debits.approve(desk, id) from your wallet. 4. Call desk.check(id, offer, yourAddress, []). Continue only if it returns 0. Any other number indexes the reasons list in /api/desk. 5. Read each Debit's owner, stateOf and Credits.ownerOf again, then call desk.fill(id, offer, []) with value equal to the fee per side. ## Make an offer 1. nonce = desk.nonceOf(you). For every Debit you give, Debits.approve(desk, id). 2. Each item: { kind: 0, id, settle: Debits.stateOf(id) == 2 ? 1 : 2, colorways: 0, minSevens: 0 }. settle is the burn guard: 1 must stay burned, 2 must stay unburned. 3. offer = { maker: you, taker: the holder of the wanted Debits (or the zero address for anyone), expiry: latest block timestamp plus at most 90 days, nonce, makerEth: 0, takerEth: 0, give, want }. One to 8 Debits per side, all wanted Debits held by one wallet. 4. desk.create(offer) with value equal to the fee. The OfferCreated event carries the offer id. Link: /offer// ## Cancel and recover - desk.cancel(id): the maker closes an offer and gets the fee back. Needs only the id. - desk.revokeAll(): stops every open offer the caller made from being accepted. Cancel or reclaim each one afterwards for its fee. - desk.reclaim(id): after expiry anyone can return the maker's fee. - desk.refunds(address) and desk.withdrawRefund(to): ETH the desk could not deliver to a wallet waits here. A receiving contract that burns all the gas it is given can still make that transaction fail; send it again with a higher gas limit. ## Rules that protect you - Accept only offers with unsupported == null. The contract also accepts Credits, Debits picked by description and ETH; such offers look like ordinary Debit swaps on a careless page. A Credit with the same number as a Rich Debit is the classic trick. - A Debit is Rich only while one wallet holds it and its Credit. A Rich Debit traded without its Credit arrives Owed, and whoever keeps the Credit can still burn it and settle the Debit. Check Credits.ownerOf(id) for every Debit you receive. - Every Debit in an offer carries a burn guard, so an offer stops filling if a Credit was burned after it was made. - The maker can cancel or revoke ahead of your fill; you lose only gas. A public offer can be filled by anyone who holds the wanted Debits. - An older open offer comes back to life when its Debits are approved again. Makers: cancel or revokeAll() before approving the same Debits for a new offer. - The desk uses transferFrom, not safeTransferFrom. A contract wallet that cannot move ERC-721 tokens will lock what it receives. ## Website - /: your Debits, offers to you, your open offers - /offers: open offers - /new: make an offer - /offer//: one offer