I’ve created a simple grin testnet exchange example so that we can play with it, analyze the flow and try to improve its UX and security. I would call it some kind of a beta version since it probably has some bugs and security issues, so sorry in advance for that, will try to fix them asap (i know i still need to check some stuff but i’ve decided to let you play with it to not delay this any longer). I might reset the database when doing upgrades if I won’t feel like bothering with the updates so you might lose your coins on the exchange because of it. But you should not be keeping the coins on this test exchange anyway.
Current grin-wallet rust implementation has some wallet-api bugs, so i’ve forked it and the testnet exchange is currently using this branch - i could create a PR but since i’m not that familiar with rust and grin-wallet i’m not sure if my fixes are appropriate and don’t break some other stuff.
Implementation
For those who like to dive into the code, here it is. The most important files are backend.api.views.py
and backend.api.tasks.py
. Thanks to @bladedoyle and @xiaojay for their python wallet and node api implementation (i’ve partially done it myself, then blade showed me their implementation so i’ve reused the rest). Also thanks to @david for helping me understand some grin-wallet basics which helped me fix the grin-wallet api issues that were needed for this exchange to work.
Deposit and Withdrawal
I used django and vue (both are very readable and i know them, so yeah good reasons :D).
Deposits are done through invoice flow (RSR), Withdrawals are done through payment flow (SRS). This seems the best to me because it makes the flow practically the same for the user to do both and at the same time exchange is the one responsible for finalizing stuff (well i would hope they know more about how to do that than the users). In withdrawal we require a payment proof, in deposits we don’t since payment proofs for invoice flows are not yet implemented. In both cases the user gets an encrypted slatepack for his wallet and after he performs “pay” (deposit) or “receive” (withdrawal) the generated slatepack is also encrypted for the exchange’s wallet.
Confirmations update
I wasn’t sure how to check for confirmations so what i do is i store the kernel of deposit/withdrawal and then each minute i have a task which gets the current height and checks the height of all “active” deposits/withdrawals and updates number of confirmations. Until there are 10 confirmations the funds are locked, after that they’re unlocked (in the case of deposit that means they become useful, in the case of withdrawal they disappear). User can only have 1 active deposit (eg. waiting for user’s signature), if he creates another one, the old one gets canceled (tx is also canceled, but as we know grin-wallet currently doesn’t have a proper cancel implemented yet so that might not be the best).
Automatic transaction rebroadcast
I’ve wanted to do that through the “repost”, but wallet-api doesn’t have it implemented yet and i wasn’t sure if i can just pass everything to the owner api or not, so i didn’t implement that. The idea was to automatically try to rebroadcast the transaction if it didn’t land on chain for 30 minutes or so (should reduce the number of tickets an exchange gets).
For more detailed explanation on how to deposit and withdraw you can click on Instructions at the top-left corner on the website.
Important
This is a testnet exchange example, security is probably not the best, so no, it was not built to be anything more than a testnet exchange and there is no plan for it to be anything more than that.
Getting testnet coins
One way to get testnet coins is through faucet. The faucet communication works through TOR so you need to have it installed on your system and then run grin-wallet --testnet listen
to listen for TOR communication (when you run this command it will output that you don’t have TOR if you don’t have it installed). Then run curl -d '{"address": "<your wallet address>"}' http://faucet.testnet.grin.lesceller.com
- that’s basically “please send me 1 grin”. You get 1 grin for each call, can do this up to 5 times i think - probably per day or smth - thanks to @quentinlesceller for the faucet
Website
https://exchange.learngrin.com/
Bug reporting
Either write it here or open an issue on github repo