trade.gno
2.25 Kb · 86 lines
1package market
2
3import (
4 "chain"
5 "chain/banker"
6 "chain/runtime/unsafe"
7
8 "gno.land/p/nt/grc721/v0"
9)
10
11// List puts tid on sale for price ugnot. The token stays with the owner.
12// A dead listing (the recorded seller no longer owns it) is replaced.
13func List(cur realm, tid string, price int64) {
14 caller := requireUser(cur)
15 requireReady()
16 if price < 1 {
17 panic("market: price")
18 }
19 id := parseTid(tid)
20 if ownerOf(id) != caller {
21 panic("market: not owner")
22 }
23 listings.Set(string(id), listing{Seller: caller, Price: price})
24 chain.Emit("List", "tid", string(id), "seller", caller.String(), "price", i64(price))
25}
26
27// Cancel removes the caller's listing, or a listing whose seller no longer owns the token.
28func Cancel(cur realm, tid string) {
29 caller := requireUser(cur)
30 requireReady()
31 id := parseTid(tid)
32 lot := mustListing(id)
33 if caller != lot.Seller && caller != ownerOf(id) {
34 panic("market: cancel")
35 }
36 listings.Remove(string(id))
37 chain.Emit("Cancel", "tid", string(id), "caller", caller.String())
38}
39
40// Buy pays the listing price in ugnot and takes the token.
41// The attached send must be exactly the price, one ugnot coin.
42func Buy(cur realm, tid string) {
43 caller := requireUser(cur)
44 requireReady()
45 id := parseTid(tid)
46 lot := mustListing(id)
47 if caller == lot.Seller {
48 panic("market: self")
49 }
50 if ownerOf(id) != lot.Seller {
51 panic("market: stale")
52 }
53 paid := unsafe.OriginSend()
54 if len(paid) != 1 || paid[0].Denom != "ugnot" || paid[0].Amount != lot.Price {
55 panic("market: pay")
56 }
57 if err := ledger.TransferFrom(lot.Seller, lot.Seller, caller, id); err != nil {
58 panic("market: transfer")
59 }
60 coins := chain.NewCoins(chain.NewCoin("ugnot", lot.Price))
61 bank := banker.NewBanker(banker.BankerTypeOriginSend, cur)
62 bank.SendCoins(cur.Address(), lot.Seller, coins)
63 listings.Remove(string(id))
64 name, _ := metaNameImage(id)
65 pushSale(sale{Tid: string(id), Seller: lot.Seller, Buyer: caller, Price: lot.Price, Name: name})
66 chain.Emit(
67 "Buy",
68 "tid", string(id),
69 "seller", lot.Seller.String(),
70 "buyer", caller.String(),
71 "price", i64(lot.Price),
72 )
73}
74
75func mustListing(id grc721.TokenID) listing {
76 got := listings.Get(string(id))
77 if got == nil {
78 panic("market: no listing")
79 }
80 return got.(listing)
81}
82
83func pushSale(s sale) {
84 sales[saleN%saleCap] = s
85 saleN++
86}