4 | | - | let adminAddress = base58'3MtpNV4Fin2hjw5pmA5ZJHLSPVAkVLiN3Bi' |
---|
5 | | - | |
---|
6 | | - | let IdxPrice = 0 |
---|
7 | | - | |
---|
8 | | - | let IdxAmount = 1 |
---|
9 | | - | |
---|
10 | | - | let IdxTradePair = 2 |
---|
11 | | - | |
---|
12 | | - | let IdxOrderType = 3 |
---|
13 | | - | |
---|
14 | | - | let IdxSender = 4 |
---|
15 | | - | |
---|
16 | | - | let IdxAssetId = 5 |
---|
17 | | - | |
---|
18 | | - | let BUY = "BUY" |
---|
19 | | - | |
---|
20 | | - | let SELL = "SELL" |
---|
21 | | - | |
---|
22 | | - | func retainMatcherFee (amount) = fraction(amount, 999, 1000) |
---|
23 | | - | |
---|
24 | | - | |
---|
25 | | - | func matcherFee (amount) = (amount - fraction(amount, 999, 1000)) |
---|
26 | | - | |
---|
27 | | - | |
---|
28 | | - | func RemoveUnderscoreIfPresent (remaining) = if ((size(remaining) > 0)) |
---|
29 | | - | then drop(remaining, 1) |
---|
30 | | - | else remaining |
---|
31 | | - | |
---|
32 | | - | |
---|
33 | | - | func FormatDataParam (p) = { |
---|
34 | | - | let s = size(p) |
---|
35 | | - | if ((s == 0)) |
---|
36 | | - | then throw("Parameter size must be greater then 0") |
---|
37 | | - | else if ((s > 99)) |
---|
38 | | - | then throw("Parameter size must be less then 100") |
---|
39 | | - | else if ((10 > s)) |
---|
40 | | - | then (("0" + toString(s)) + p) |
---|
41 | | - | else (toString(s) + p) |
---|
42 | | - | } |
---|
43 | | - | |
---|
44 | | - | |
---|
45 | | - | func ParseNextAttribute (remaining) = { |
---|
46 | | - | let s = size(remaining) |
---|
47 | | - | if ((s > 0)) |
---|
48 | | - | then { |
---|
49 | | - | let nn = parseIntValue(take(remaining, 2)) |
---|
50 | | - | let v = take(drop(remaining, 2), nn) |
---|
51 | | - | let tmpRemaining = drop(remaining, (nn + 2)) |
---|
52 | | - | let remainingState = RemoveUnderscoreIfPresent(tmpRemaining) |
---|
53 | | - | [v, remainingState] |
---|
54 | | - | } |
---|
55 | | - | else throw("Empty string was passed into parseNextAttribute func") |
---|
56 | | - | } |
---|
57 | | - | |
---|
58 | | - | |
---|
59 | | - | func FormatOrderDataStr (traidPair,sender,orderType,price,amount,assetId) = { |
---|
60 | | - | let fullStateStr = ((((((((((FormatDataParam(traidPair) + "_") + FormatDataParam(sender)) + "_") + FormatDataParam(orderType)) + "_") + FormatDataParam(toString(price))) + "_") + FormatDataParam(toString(amount))) + "_") + FormatDataParam(assetId)) |
---|
61 | | - | fullStateStr |
---|
62 | | - | } |
---|
63 | | - | |
---|
64 | | - | |
---|
65 | | - | func ParseOrderRawDataStr (rawStateStr) = { |
---|
66 | | - | let tradePair = ParseNextAttribute(rawStateStr) |
---|
67 | | - | let sender = ParseNextAttribute(tradePair[1]) |
---|
68 | | - | let orderType = ParseNextAttribute(sender[1]) |
---|
69 | | - | let price = ParseNextAttribute(orderType[1]) |
---|
70 | | - | let amount = ParseNextAttribute(price[1]) |
---|
71 | | - | let assetId = ParseNextAttribute(amount[1]) |
---|
72 | | - | [price[0], amount[0], tradePair[0], orderType[0], sender[0], assetId[0]] |
---|
73 | | - | } |
---|
74 | | - | |
---|
75 | | - | |
---|
76 | | - | func pow10 (exp) = if ((exp == 0)) |
---|
77 | | - | then 1 |
---|
78 | | - | else if ((exp == 1)) |
---|
79 | | - | then 10 |
---|
80 | | - | else if ((exp == 2)) |
---|
81 | | - | then 100 |
---|
82 | | - | else if ((exp == 3)) |
---|
83 | | - | then 1000 |
---|
84 | | - | else if ((exp == 4)) |
---|
85 | | - | then 10000 |
---|
86 | | - | else if ((exp == 5)) |
---|
87 | | - | then 100000 |
---|
88 | | - | else if ((exp == 6)) |
---|
89 | | - | then 1000000 |
---|
90 | | - | else if ((exp == 7)) |
---|
91 | | - | then 10000000 |
---|
92 | | - | else if ((exp == 8)) |
---|
93 | | - | then 100000000 |
---|
94 | | - | else if ((exp == 9)) |
---|
95 | | - | then 1000000000 |
---|
96 | | - | else if ((exp == 10)) |
---|
97 | | - | then 10000000000 |
---|
98 | | - | else if ((exp == 11)) |
---|
99 | | - | then 100000000000 |
---|
100 | | - | else if ((exp == 12)) |
---|
101 | | - | then 1000000000000 |
---|
102 | | - | else throw("Pow10 more then 12 is not supported") |
---|
103 | | - | |
---|
104 | | - | |
---|
105 | | - | func assetIdFromString (assetId) = if (if ((assetId == "WAVES")) |
---|
106 | | - | then true |
---|
107 | | - | else (assetId == "")) |
---|
108 | | - | then unit |
---|
109 | | - | else fromBase58String(assetId) |
---|
115 | | - | let pmtAssetIdStr = if (isDefined(pmt.assetId)) |
---|
116 | | - | then toBase58String(value(pmt.assetId)) |
---|
117 | | - | else "WAVES" |
---|
118 | | - | let possibleTraidPair1 = getString(this, ((assetId + "/") + pmtAssetIdStr)) |
---|
119 | | - | let possibleTraidPair2 = getString(this, ((pmtAssetIdStr + "/") + assetId)) |
---|
120 | | - | let traidPair = if (isDefined(possibleTraidPair1)) |
---|
121 | | - | then value(possibleTraidPair1) |
---|
122 | | - | else if (isDefined(possibleTraidPair2)) |
---|
123 | | - | then value(possibleTraidPair2) |
---|
124 | | - | else throw("Traiding for that assets is not supported") |
---|
125 | | - | let orderType = if (isDefined(possibleTraidPair1)) |
---|
126 | | - | then BUY |
---|
127 | | - | else SELL |
---|
128 | | - | let orderStr = FormatOrderDataStr(traidPair, toBase58String(i.caller.bytes), orderType, price, pmt.amount, pmtAssetIdStr) |
---|
129 | | - | WriteSet([DataEntry(toBase58String(i.transactionId), orderStr)]) |
---|
130 | | - | } |
---|
131 | | - | |
---|
132 | | - | |
---|
133 | | - | |
---|
134 | | - | @Callable(i) |
---|
135 | | - | func matchOrders (order1Id,order2Id) = { |
---|
136 | | - | let order1 = ParseOrderRawDataStr(getStringValue(this, order1Id)) |
---|
137 | | - | let order2 = ParseOrderRawDataStr(getStringValue(this, order2Id)) |
---|
138 | | - | if ((order1[IdxTradePair] != order2[IdxTradePair])) |
---|
139 | | - | then throw("Trying to match orders from different trading pairs") |
---|
140 | | - | else if ((order1[IdxOrderType] == order2[IdxOrderType])) |
---|
141 | | - | then throw("Trying to match orders of the same type") |
---|
142 | | - | else { |
---|
143 | | - | let order1isSell = (order1[IdxOrderType] == SELL) |
---|
144 | | - | let sellOrder = if (order1isSell) |
---|
145 | | - | then order1 |
---|
146 | | - | else order2 |
---|
147 | | - | let buyOrder = if (!(order1isSell)) |
---|
148 | | - | then order1 |
---|
149 | | - | else order2 |
---|
150 | | - | let sellPrice = parseIntValue(sellOrder[IdxPrice]) |
---|
151 | | - | let buyPrice = parseIntValue(buyOrder[IdxPrice]) |
---|
152 | | - | let sellOrderAmount = parseIntValue(sellOrder[IdxAmount]) |
---|
153 | | - | let buyOrderAmount = parseIntValue(buyOrder[IdxAmount]) |
---|
154 | | - | if ((sellPrice > buyPrice)) |
---|
155 | | - | then throw("Orders are not match by price") |
---|
156 | | - | else { |
---|
157 | | - | let exchangePrice = sellPrice |
---|
158 | | - | let amountAssetDecimals = if ((sellOrder[IdxAssetId] == "WAVES")) |
---|
159 | | - | then 8 |
---|
160 | | - | else value(assetInfo(value(assetIdFromString(sellOrder[IdxAssetId])))).decimals |
---|
161 | | - | let priceAssetDecimals = if ((buyOrder[IdxAssetId] == "WAVES")) |
---|
162 | | - | then 8 |
---|
163 | | - | else value(assetInfo(value(assetIdFromString(buyOrder[IdxAssetId])))).decimals |
---|
164 | | - | let buyAmount = ((buyOrderAmount * pow10(amountAssetDecimals)) / exchangePrice) |
---|
165 | | - | let sellAmount = sellOrderAmount |
---|
166 | | - | let amountAssetAmount = if ((buyAmount >= sellAmount)) |
---|
167 | | - | then sellAmount |
---|
168 | | - | else buyAmount |
---|
169 | | - | let priceAssetAmount = ((amountAssetAmount * exchangePrice) / pow10(amountAssetDecimals)) |
---|
170 | | - | let updatedBuyStr = FormatOrderDataStr(buyOrder[IdxTradePair], buyOrder[IdxSender], buyOrder[IdxOrderType], buyPrice, (buyOrderAmount - priceAssetAmount), sellOrder[IdxAssetId]) |
---|
171 | | - | let updatedSellStr = FormatOrderDataStr(sellOrder[IdxTradePair], sellOrder[IdxSender], sellOrder[IdxOrderType], sellPrice, (sellOrderAmount - amountAssetAmount), buyOrder[IdxAssetId]) |
---|
172 | | - | ScriptResult(WriteSet([DataEntry(if (!(order1isSell)) |
---|
173 | | - | then order1Id |
---|
174 | | - | else order2Id, updatedBuyStr), DataEntry(if (order1isSell) |
---|
175 | | - | then order1Id |
---|
176 | | - | else order2Id, updatedSellStr)]), TransferSet([ScriptTransfer(addressFromStringValue(buyOrder[IdxSender]), retainMatcherFee(amountAssetAmount), assetIdFromString(sellOrder[IdxAssetId])), ScriptTransfer(addressFromStringValue(sellOrder[IdxSender]), retainMatcherFee(priceAssetAmount), assetIdFromString(buyOrder[IdxAssetId])), ScriptTransfer(i.caller, matcherFee(amountAssetAmount), assetIdFromString(sellOrder[IdxAssetId])), ScriptTransfer(i.caller, matcherFee(priceAssetAmount), assetIdFromString(buyOrder[IdxAssetId]))])) |
---|
177 | | - | } |
---|
178 | | - | } |
---|
179 | | - | } |
---|
180 | | - | |
---|
181 | | - | |
---|
182 | | - | |
---|
183 | | - | @Callable(i) |
---|
184 | | - | func cancelOrder (orderId) = { |
---|
185 | | - | let order = ParseOrderRawDataStr(getStringValue(this, orderId)) |
---|
186 | | - | if ((addressFromStringValue(order[IdxSender]) != i.caller)) |
---|
187 | | - | then throw("Only order owner can cancel it") |
---|
| 9 | + | if (isDefined(pmt.assetId)) |
---|
| 10 | + | then throw("can hodl waves only at the moment") |
---|
197 | | - | func registerTraidPair (asset1,priceAsset,traidPair) = if ((i.caller == addressFromStringValue(toBase58String(adminAddress)))) |
---|
198 | | - | then WriteSet([DataEntry(((asset1 + "/") + priceAsset), traidPair)]) |
---|
199 | | - | else throw("Only administrator can register traiding pair") |
---|
| 27 | + | func withdraw (amount) = { |
---|
| 28 | + | let currentKey = toBase58String(i.caller.bytes) |
---|
| 29 | + | let currentAmount = match getInteger(this, currentKey) { |
---|
| 30 | + | case a: Int => |
---|
| 31 | + | a |
---|
| 32 | + | case _ => |
---|
| 33 | + | 0 |
---|
| 34 | + | } |
---|
| 35 | + | let newAmount = (currentAmount - amount) |
---|
| 36 | + | if ((0 > amount)) |
---|
| 37 | + | then throw("Can't withdraw negative amount") |
---|
| 38 | + | else if ((0 > newAmount)) |
---|
| 39 | + | then throw("Not enough balance") |
---|
| 40 | + | else ScriptResult(WriteSet([DataEntry(currentKey, newAmount)]), TransferSet([ScriptTransfer(i.caller, amount, unit)])) |
---|
| 41 | + | } |
---|