book.gno
3.84 Kb · 165 lines
1package bazaargens3
2
3import (
4 "chain"
5 "chain/banker"
6 "strconv"
7
8 "gno.land/p/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/fee/v1"
9 factory "gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/bazaar/bazaarv4"
10)
11
12func List(cur realm, id int, priceUgnot int64) {
13 caller := requireUser(cur)
14 if priceUgnot <= 0 {
15 panic("col: price")
16 }
17 it := mustItem(id)
18 if it.listed {
19 panic("col: listed")
20 }
21 if it.owner != caller {
22 panic("col: not owner")
23 }
24 grcTransfer(caller, caller, self, id)
25 it.listed = true
26 it.seller = caller
27 it.price = priceUgnot
28 it.owner = self
29 items.Set(itemKey(id), it)
30 chain.Emit("List", "id", strconv.Itoa(id), "seller", caller.String(), "price", strconv.FormatInt(priceUgnot, 10))
31}
32
33func UpdatePrice(cur realm, id int, priceUgnot int64) {
34 caller := requireUser(cur)
35 if priceUgnot <= 0 {
36 panic("col: price")
37 }
38 it := mustItem(id)
39 if !it.listed {
40 panic("col: not listed")
41 }
42 if it.seller != caller {
43 panic("col: not seller")
44 }
45 it.price = priceUgnot
46 items.Set(itemKey(id), it)
47 chain.Emit("List", "id", strconv.Itoa(id), "seller", caller.String(), "price", strconv.FormatInt(priceUgnot, 10))
48}
49
50func Cancel(cur realm, id int) {
51 caller := requireUser(cur)
52 it := mustItem(id)
53 if !it.listed {
54 panic("col: not listed")
55 }
56 if caller != it.seller {
57 panic("col: not seller")
58 }
59 grcTransfer(self, self, it.seller, id)
60 it.listed = false
61 it.owner = it.seller
62 it.seller = address("")
63 it.price = 0
64 items.Set(itemKey(id), it)
65 chain.Emit("Cancel", "id", strconv.Itoa(id))
66}
67
68func Buy(cur realm, id int) {
69 caller := requireUser(cur)
70 it := mustItem(id)
71 if !it.listed {
72 panic("col: not listed")
73 }
74 if caller == it.seller {
75 panic("col: self buy")
76 }
77 takeExact(it.price)
78 price := it.price
79 proto := fee.ProtocolFee(price, tradeProtocolBps(it.seller, caller))
80 royal := int64(0)
81 if royaltyBps > 0 {
82 royal = fee.ProtocolFee(price, int64(royaltyBps))
83 }
84 if proto+royal > price {
85 panic("col: fee")
86 }
87 sellerAmt := price - proto - royal
88 share := int64(0)
89 if proto > 0 {
90 share = fee.ProtocolFee(proto, factory.GenesisShareBps())
91 }
92 sinkAmt := proto - share
93 sink := factory.ProtocolSink()
94 if proto > 0 && !sink.IsValid() {
95 panic("col: sink")
96 }
97 bk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
98 if sellerAmt > 0 {
99 bk.SendCoins(self, it.seller, chain.Coins{{Denom: nativeDenom, Amount: sellerAmt}})
100 }
101 if royal > 0 {
102 bk.SendCoins(self, creator, chain.Coins{{Denom: nativeDenom, Amount: royal}})
103 }
104 if sinkAmt > 0 {
105 bk.SendCoins(self, sink, chain.Coins{{Denom: nativeDenom, Amount: sinkAmt}})
106 }
107 if share > 0 {
108 gaddr := factory.GenesisSink()
109 if !gaddr.IsValid() {
110 panic("col: genesis")
111 }
112 bk.SendCoins(self, gaddr, chain.Coins{{Denom: nativeDenom, Amount: share}})
113 }
114 grcTransfer(self, self, caller, id)
115 it.listed = false
116 it.owner = caller
117 it.seller = address("")
118 it.price = 0
119 items.Set(itemKey(id), it)
120 chain.Emit("Buy", "id", strconv.Itoa(id), "buyer", caller.String(), "fee", strconv.FormatInt(proto, 10))
121}
122
123func Transfer(cur realm, to address, id int) {
124 caller := requireUser(cur)
125 if !to.IsValid() {
126 panic("col: invalid address")
127 }
128 if to == caller || to == self {
129 panic("col: invalid address")
130 }
131 it := mustItem(id)
132 if it.listed {
133 panic("col: listed")
134 }
135 if it.owner != caller {
136 panic("col: not owner")
137 }
138 grcTransfer(caller, caller, to, id)
139 it.owner = to
140 items.Set(itemKey(id), it)
141 chain.Emit("Transfer", "id", strconv.Itoa(id), "to", to.String())
142}
143
144func ProtocolBps() int64 {
145 return factory.ProtocolBps()
146}
147
148func tradeProtocolBps(seller, buyer address) int64 {
149 bps := ProtocolBps()
150 d := factory.HolderDiscount(seller.String())
151 if bd := factory.HolderDiscount(buyer.String()); bd > d {
152 d = bd
153 }
154 if d > bps {
155 return 0
156 }
157 return bps - d
158}
159
160func grcTransfer(spender, from, to address, id int) {
161 err := ledger.TransferFrom(spender, from, to, itemTid(id))
162 if err != nil {
163 panic("col: transfer")
164 }
165}