tx · DEQbkGJAGJLkBj9sooumWCBCk9Warjo3EhEm7KiJTQa6 3P2YBCpek2KbwaxHBSRRa4DWcJUkPu2mCCj: -0.01000000 Waves 2024.04.09 01:00 [4120311] smart account 3P2YBCpek2KbwaxHBSRRa4DWcJUkPu2mCCj > SELF 0.00000000 Waves
{ "type": 13, "id": "DEQbkGJAGJLkBj9sooumWCBCk9Warjo3EhEm7KiJTQa6", "fee": 1000000, "feeAssetId": null, "timestamp": 1712613602050, "version": 2, "chainId": 87, "sender": "3P2YBCpek2KbwaxHBSRRa4DWcJUkPu2mCCj", "senderPublicKey": "3C2anUH59qjkVSB8AuFYGBNhSqcgvJhq1BBRodM74pEf", "proofs": [ "2i7NnwFxfiD5opXRsT4KMjTbf1A9TaYeJ8MQCznuzNHr6R4zenN8YK64jpDACrZoBwsSDdmAuRA9VBjKLALShcd3" ], "script": "base64:BgIGCAISABIAEwEJYXNBbnlMaXN0AQN2YWwEByRtYXRjaDAFA3ZhbAMJAAECBQckbWF0Y2gwAglMaXN0W0FueV0ECnZhbEFueUxpc3QFByRtYXRjaDAFCnZhbEFueUxpc3QJAAIBAhtmYWlsIHRvIGNhc3QgaW50byBMaXN0W0FueV0BCGFzU3RyaW5nAQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAUBcwkAAgECGGZhaWwgdG8gY2FzdCBpbnRvIFN0cmluZwEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFpBQckbWF0Y2gwBQFpCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AAtwdXp6bGVJZFN0cgIsSEVCOFFhdzl4cldwV3M4dEhzaUFUWUdCV0RCdFAyUzdrY1BBTHJNdTQzQVMACHB1enpsZUlkCQDZBAEFC3B1enpsZUlkU3RyAAh4dG5JZFN0cgIsREcyeEZrUGREd0tVb0JrekdBaFF0THBTR3pmWExpQ1lQRXplS0gyQWQyNHAABXh0bklkCQDZBAEFCHh0bklkU3RyAAhwekZvcmJlcwkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BRbnpwNVlvZ0J2Sm13UG52U1dvYXJnUE1jZDFSNEdMYTgADXB6QmFzaWNQdXp6bGUJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQUUFoUE01aUhReVlyQXFUVnRzNTNVZ2lMR3RWdVNaOHhEAAZ3eFJlc3QJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQOE1vUG5zYXVyb2ZrMVZ5aHNkQUZrZVE2aWpwSllYQ3BXAAZ3eFN3b3AJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQNjh6Tml1ZnN1MXZpWnB1MWFZM2NkYWhSUktjdlY1TjkzAA13eFB1enpsZVdhdmVzCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUFFhWW00cGJSVnJOVFRuTDhwREpaVHhoY21ENGpSc2tyegALd3hQdXp6bGVYdG4JARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQNjE1eVhlUTlRdTRxQk0xUUdpbUd6aXh5TVM1VzRLdHVnAAp3eFdhdmVzWHRuCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUFBaV2dGTlJLSEx2TTUxcHdTOTM0QzhWWjdkMkY0WjU4ZwANc3dvcFB1enpsZVh0bgkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BCSHlFd21FUlIxQ0VrclROYlBqMmJneWlzVGZQUnFmZWUADHN3b3BXYXZlc1h0bgkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BIYU5nb21Ca3J2RUwyUW51SmFyUVZKYTcxd2p3OXFpcUcBC3N3b3BCYWxhbmNlAgtwb29sQWRkcmVzcwRBb3JCCQERQGV4dHJOYXRpdmUoMTA1MCkCBQtwb29sQWRkcmVzcwkArAICBQRBb3JCAg5fYXNzZXRfYmFsYW5jZQENd3hQb29sQmFsYW5jZQILcG9vbEFkZHJlc3MKYXNzZXRJbmRleAQMd3hSZXN0UmVzdWx0CQC1CQIJAQhhc1N0cmluZwEJAPwHBAUGd3hSZXN0AhFwb29sU3RhdHNSRUFET05MWQkAzAgCCQClCAEFC3Bvb2xBZGRyZXNzBQNuaWwFA25pbAICX18JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQx3eFJlc3RSZXN1bHQFCmFzc2V0SW5kZXgBCXB6QmFsYW5jZQILcG9vbEFkZHJlc3MHYXNzZXRJZAkA8AcCBQtwb29sQWRkcmVzcwUHYXNzZXRJZAIBaQEOYnV5WHRuRm9yV2F2ZXMABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQId2F2ZXNBbXQIBQNwbXQGYW1vdW50BA93YXZlc1RvWHRuVmlhV3gJAQ13eFBvb2xCYWxhbmNlAgUKd3hXYXZlc1h0bgABBBF3YXZlc1RvWHRuVmlhU3dvcAkBC3N3b3BCYWxhbmNlAgUMc3dvcFdhdmVzWHRuAgFBBA93YXZlc1RvWHRuVG90YWwJAGQCBQ93YXZlc1RvWHRuVmlhV3gFEXdhdmVzVG9YdG5WaWFTd29wBBJ3YXZlc1RvWHRuVmlhV3hBbXQJAGsDBQh3YXZlc0FtdAUPd2F2ZXNUb1h0blZpYVd4BQ93YXZlc1RvWHRuVG90YWwEFHdhdmVzVG9YdG5WaWFTd29wQW10CQBrAwUId2F2ZXNBbXQFEXdhdmVzVG9YdG5WaWFTd29wBQ93YXZlc1RvWHRuVG90YWwEFXdhdmVzVG9YdG5WaWFXeFJlc3VsdAkA/AcEBQZ3eFN3b3ACBHN3YXAJAMwIAgABCQDMCAIFCHh0bklkU3RyCQDMCAIJAKUIAQUEdGhpcwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQR1bml0BRJ3YXZlc1RvWHRuVmlhV3hBbXQFA25pbAMJAAACBRV3YXZlc1RvWHRuVmlhV3hSZXN1bHQFFXdhdmVzVG9YdG5WaWFXeFJlc3VsdAQXd2F2ZXNUb1h0blZpYVN3b3BSZXN1bHQJAQlhc0FueUxpc3QBCQD8BwQFDHN3b3BXYXZlc1h0bgIIZXhjaGFuZ2UJAMwIAgABBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBHVuaXQFFHdhdmVzVG9YdG5WaWFTd29wQW10BQNuaWwDCQAAAgUXd2F2ZXNUb1h0blZpYVN3b3BSZXN1bHQFF3dhdmVzVG9YdG5WaWFTd29wUmVzdWx0BAZ4dG5BbXQJAPAHAgUEdGhpcwUFeHRuSWQJAJQKAgUDbmlsBQZ4dG5BbXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERYnV5UHV6emxlRm9yV2F2ZXMABA1wekZvcmJlc1ZhbHVlCQEJcHpCYWxhbmNlAgUIcHpGb3JiZXMFCHB1enpsZUlkBBJwekJhc2ljUHV6emxlVmFsdWUJAQlwekJhbGFuY2UCBQ1wekJhc2ljUHV6emxlBQhwdXp6bGVJZAQSd3hQdXp6bGVXYXZlc1ZhbHVlCQENd3hQb29sQmFsYW5jZQIFDXd4UHV6emxlV2F2ZXMAAQQSc3dvcFB1enpsZVh0blZhbHVlCQELc3dvcEJhbGFuY2UCBQ1zd29wUHV6emxlWHRuAgFBBAV0b3RhbAkAZAIJAGQCCQBkAgUNcHpGb3JiZXNWYWx1ZQUScHpCYXNpY1B1enpsZVZhbHVlBRJ3eFB1enpsZVdhdmVzVmFsdWUFEnN3b3BQdXp6bGVYdG5WYWx1ZQQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEBnBtdEFtdAgFA3BtdAZhbW91bnQEDHB6Rm9yYmVzUGFydAkAawMFDXB6Rm9yYmVzVmFsdWUFBnBtdEFtdAUFdG90YWwEEXB6QmFzaWNQdXp6bGVQYXJ0CQBrAwUScHpCYXNpY1B1enpsZVZhbHVlBQZwbXRBbXQFBXRvdGFsBBF3eFB1enpsZVdhdmVzUGFydAkAawMFEnd4UHV6emxlV2F2ZXNWYWx1ZQUGcG10QW10BQV0b3RhbAQRc3dvcFB1enpsZVh0blBhcnQJAGsDBRJzd29wUHV6emxlWHRuVmFsdWUFBnBtdEFtdAUFdG90YWwEBnh0bkFtdAkBBWFzSW50AQkA/AcEBQR0aGlzAg5idXlYdG5Gb3JXYXZlcwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQR1bml0BRFzd29wUHV6emxlWHRuUGFydAUDbmlsAwkAAAIFBnh0bkFtdAUGeHRuQW10BBx3YXZlc1RvUHV6emxlVmlhRm9yYmVzUmVzdWx0CQD8BwQFCHB6Rm9yYmVzAgRzd2FwCQDMCAIFC3B1enpsZUlkU3RyCQDMCAIAAQUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQR1bml0BQxwekZvcmJlc1BhcnQFA25pbAMJAAACBRx3YXZlc1RvUHV6emxlVmlhRm9yYmVzUmVzdWx0BRx3YXZlc1RvUHV6emxlVmlhRm9yYmVzUmVzdWx0BBt3YXZlc1RvUHV6emxlVmlhQmFzaWNSZXN1bHQJAPwHBAUNcHpCYXNpY1B1enpsZQIEc3dhcAkAzAgCBQtwdXp6bGVJZFN0cgkAzAgCAAEFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUEdW5pdAURcHpCYXNpY1B1enpsZVBhcnQFA25pbAMJAAACBRt3YXZlc1RvUHV6emxlVmlhQmFzaWNSZXN1bHQFG3dhdmVzVG9QdXp6bGVWaWFCYXNpY1Jlc3VsdAQYd2F2ZXNUb1B1enpsZVZpYVd4UmVzdWx0CQD8BwQFBnd4U3dvcAIEc3dhcAkAzAgCAAEJAMwIAgULcHV6emxlSWRTdHIJAMwIAgkApQgBBQR0aGlzBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBHVuaXQFEXd4UHV6emxlV2F2ZXNQYXJ0BQNuaWwDCQAAAgUYd2F2ZXNUb1B1enpsZVZpYVd4UmVzdWx0BRh3YXZlc1RvUHV6emxlVmlhV3hSZXN1bHQEGHh0blRvUHV6emxlVmlhU3dvcFJlc3VsdAkBCWFzQW55TGlzdAEJAPwHBAUNc3dvcFB1enpsZVh0bgIIZXhjaGFuZ2UJAMwIAgABBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBXh0bklkBQZ4dG5BbXQFA25pbAMJAAACBRh4dG5Ub1B1enpsZVZpYVN3b3BSZXN1bHQFGHh0blRvUHV6emxlVmlhU3dvcFJlc3VsdAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIICQDvBwEFBHRoaXMJYXZhaWxhYmxlBQR1bml0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AyIjPfw==", "height": 4120311, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 4qowiJio2r7jxg2TxbgU1RphfaqaE6jQB8iBa7oU7SpQ Next: 4CamTyyYwMtz1vuUyia97QYz7u8QGraBhYNqQ8AaVWz1 Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let ProtocolSEP = ":" | |
4 | + | func asAnyList (val) = match val { | |
5 | + | case valAnyList: List[Any] => | |
6 | + | valAnyList | |
7 | + | case _ => | |
8 | + | throw("fail to cast into List[Any]") | |
9 | + | } | |
5 | 10 | ||
6 | - | let SEP = "__" | |
7 | - | ||
8 | - | let percentPriceOffset = 95 | |
9 | 11 | ||
10 | 12 | func asString (v) = match v { | |
11 | 13 | case s: String => | |
15 | 17 | } | |
16 | 18 | ||
17 | 19 | ||
18 | - | func keyPrice (symbol) = ("%s%s__price__" + symbol) | |
20 | + | func asInt (v) = match v { | |
21 | + | case i: Int => | |
22 | + | i | |
23 | + | case _ => | |
24 | + | throw("fail to cast into Int") | |
25 | + | } | |
19 | 26 | ||
20 | 27 | ||
21 | - | func keyOracles () = "%s%s__config__oracles" | |
28 | + | let puzzleIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS" | |
29 | + | ||
30 | + | let puzzleId = fromBase58String(puzzleIdStr) | |
31 | + | ||
32 | + | let xtnIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
33 | + | ||
34 | + | let xtnId = fromBase58String(xtnIdStr) | |
35 | + | ||
36 | + | let pzForbes = addressFromStringValue("3PQnzp5YogBvJmwPnvSWoargPMcd1R4GLa8") | |
37 | + | ||
38 | + | let pzBasicPuzzle = addressFromStringValue("3PQAhPM5iHQyYrAqTVts53UgiLGtVuSZ8xD") | |
39 | + | ||
40 | + | let wxRest = addressFromStringValue("3P8MoPnsaurofk1VyhsdAFkeQ6ijpJYXCpW") | |
41 | + | ||
42 | + | let wxSwop = addressFromStringValue("3P68zNiufsu1viZpu1aY3cdahRRKcvV5N93") | |
43 | + | ||
44 | + | let wxPuzzleWaves = addressFromStringValue("3PQaYm4pbRVrNTTnL8pDJZTxhcmD4jRskrz") | |
45 | + | ||
46 | + | let wxPuzzleXtn = addressFromStringValue("3P615yXeQ9Qu4qBM1QGimGzixyMS5W4Ktug") | |
47 | + | ||
48 | + | let wxWavesXtn = addressFromStringValue("3PPZWgFNRKHLvM51pwS934C8VZ7d2F4Z58g") | |
49 | + | ||
50 | + | let swopPuzzleXtn = addressFromStringValue("3PBHyEwmERR1CEkrTNbPj2bgyisTfPRqfee") | |
51 | + | ||
52 | + | let swopWavesXtn = addressFromStringValue("3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG") | |
53 | + | ||
54 | + | func swopBalance (poolAddress,AorB) = getIntegerValue(poolAddress, (AorB + "_asset_balance")) | |
22 | 55 | ||
23 | 56 | ||
24 | - | func keyGroupData (groupNum) = ("%s%d__group__" + groupNum) | |
25 | - | ||
26 | - | ||
27 | - | func keyMinConsensus () = "%s%s__config__minConsensus" | |
28 | - | ||
29 | - | ||
30 | - | func keyPriceFailure (symbol) = makeString(["%s%s%d__finalizationFailure", symbol, toString(height)], SEP) | |
31 | - | ||
32 | - | ||
33 | - | func keyLastHeight (symbol) = ("%s%s__lastHeight__" + symbol) | |
34 | - | ||
35 | - | ||
36 | - | func keyPriceByHeight (symbol,h) = makeString(["%s%s%d__priceByHeight", symbol, toString(h)], SEP) | |
37 | - | ||
38 | - | ||
39 | - | func keyIdx (symbol) = ("%s%s__idxCurrent__" + symbol) | |
40 | - | ||
41 | - | ||
42 | - | func keyIdx2Height (symbol,idx) = makeString(["%s%s%d__idx2Height", symbol, toString(idx)], SEP) | |
43 | - | ||
44 | - | ||
45 | - | func keyHeight2Idx (symbol,h) = makeString(["%s%s%d__height2Idx", symbol, toString(h)], SEP) | |
46 | - | ||
47 | - | ||
48 | - | func keyGroupStatus (groupNum,finHeightStr) = makeString(["%s%d%d__groupStatus", groupNum, finHeightStr], SEP) | |
49 | - | ||
50 | - | ||
51 | - | func keyIsMarketOpened (symbol) = ("%s%s__isMarketOpened__" + symbol) | |
52 | - | ||
53 | - | ||
54 | - | func keyEmptyPriceMsg (position) = makeString(["%s%d%d__emptyPriceMsg", toString(height), toString(position)], SEP) | |
55 | - | ||
56 | - | ||
57 | - | func keyIsBlocked (symbol) = ("%s%s__isBlocked__" + symbol) | |
58 | - | ||
59 | - | ||
60 | - | func keyIsBlockedSender (symbol) = makeString(["%s%s%s__isBlocked", symbol, "sender"], SEP) | |
61 | - | ||
62 | - | ||
63 | - | func keyIsBlockedReason (symbol) = makeString(["%s%s%s__isBlocked", symbol, "reason"], SEP) | |
64 | - | ||
65 | - | ||
66 | - | func keyBlackSwarmPrice (h,symbol) = makeString(["%s%s%s%d__isBlocked", symbol, "blackSwarmPrice", toString(h)], SEP) | |
67 | - | ||
68 | - | ||
69 | - | let DAYMILLIS = 86400000 | |
70 | - | ||
71 | - | let H4MILLIS = 14400000 | |
72 | - | ||
73 | - | func toPeriod (timestamp,period) = ((timestamp / period) * period) | |
74 | - | ||
75 | - | ||
76 | - | func keyStats1stPeriod (symbol) = makeString(["%s%s", "stats1stPeriod", symbol], SEP) | |
77 | - | ||
78 | - | ||
79 | - | func keyStatsPriceSum (symbol) = makeString(["%s%s", "statsPriceSum", symbol], SEP) | |
80 | - | ||
81 | - | ||
82 | - | func keyStatsCountSum (symbol) = makeString(["%s%s", "statsCountSum", symbol], SEP) | |
83 | - | ||
84 | - | ||
85 | - | func keyStatsByPeriodPriceSum (symbol,period) = makeString(["%s%s%d", "statsPriceSum", symbol, period], SEP) | |
86 | - | ||
87 | - | ||
88 | - | func keyStatsByPeriodCountSum (symbol,period) = makeString(["%s%s%d", "statsCountSum", symbol, period], SEP) | |
89 | - | ||
90 | - | ||
91 | - | func keyStatsByPeriodMin (symbol,period) = makeString(["%s%s%d", "statsPriceMin", symbol, period], SEP) | |
92 | - | ||
93 | - | ||
94 | - | func keyStatsByPeriodMax (symbol,period) = makeString(["%s%s%d", "statsPriceMax", symbol, period], SEP) | |
95 | - | ||
96 | - | ||
97 | - | func StatsEntry (symbol,price) = { | |
98 | - | let period = toPeriod(lastBlock.timestamp, H4MILLIS) | |
99 | - | let periodStr = toString(period) | |
100 | - | let stats1stPeriodKEY = keyStats1stPeriod(symbol) | |
101 | - | let statsPriceSumKEY = keyStatsPriceSum(symbol) | |
102 | - | let statsCountSumKEY = keyStatsCountSum(symbol) | |
103 | - | let statsByPeriodPriceSumKEY = keyStatsByPeriodPriceSum(symbol, periodStr) | |
104 | - | let statsByPeriodCountSumKEY = keyStatsByPeriodCountSum(symbol, periodStr) | |
105 | - | let statsByPeriodMinKEY = keyStatsByPeriodMin(symbol, periodStr) | |
106 | - | let statsByPeriodMaxKEY = keyStatsByPeriodMax(symbol, periodStr) | |
107 | - | let statsPriceSum = parseBigIntValue(valueOrElse(getString(this, statsPriceSumKEY), "0")) | |
108 | - | let statsCountSum = valueOrElse(getInteger(this, statsCountSumKEY), 0) | |
109 | - | let statsByPeriodMin = valueOrElse(getInteger(this, statsByPeriodMinKEY), 9223372036854775) | |
110 | - | let statsByPeriodMax = valueOrElse(getInteger(this, statsByPeriodMaxKEY), 0) | |
111 | - | let newStatsPriceSum = (statsPriceSum + toBigInt(price)) | |
112 | - | let newStatsCountSum = (statsCountSum + 1) | |
113 | - | let newStatsByPeriodPriceSum = newStatsPriceSum | |
114 | - | let newStatsByPeriodCountSum = newStatsCountSum | |
115 | - | let newStatsByPeriodMin = min([statsByPeriodMin, price]) | |
116 | - | let newStatsByPeriodMax = max([statsByPeriodMax, price]) | |
117 | - | let stats1stPeriod = valueOrElse(getInteger(this, stats1stPeriodKEY), -1) | |
118 | - | ([StringEntry(statsPriceSumKEY, toString(newStatsPriceSum)), IntegerEntry(statsCountSumKEY, newStatsCountSum), StringEntry(statsByPeriodPriceSumKEY, toString(newStatsByPeriodPriceSum)), IntegerEntry(statsByPeriodCountSumKEY, newStatsByPeriodCountSum), IntegerEntry(statsByPeriodMinKEY, newStatsByPeriodMin), IntegerEntry(statsByPeriodMaxKEY, newStatsByPeriodMax)] ++ (if ((0 > stats1stPeriod)) | |
119 | - | then [IntegerEntry(stats1stPeriodKEY, period)] | |
120 | - | else nil)) | |
57 | + | func wxPoolBalance (poolAddress,assetIndex) = { | |
58 | + | let wxRestResult = split(asString(invoke(wxRest, "poolStatsREADONLY", [toString(poolAddress)], nil)), "__") | |
59 | + | parseIntValue(wxRestResult[assetIndex]) | |
121 | 60 | } | |
122 | 61 | ||
123 | 62 | ||
124 | - | func isGroupFinalaized (groupNum,finHeightStr) = isDefined(getBoolean(this, keyGroupStatus(groupNum, finHeightStr))) | |
125 | - | ||
126 | - | ||
127 | - | func readGroupDataOrFail (groupNum) = { | |
128 | - | let k = keyGroupData(groupNum) | |
129 | - | let groupDataOpt = getString(this, k) | |
130 | - | if (isDefined(groupDataOpt)) | |
131 | - | then value(groupDataOpt) | |
132 | - | else throw(("empty group data for key=" + k)) | |
133 | - | } | |
134 | - | ||
135 | - | ||
136 | - | let pubKeyOraclesList = split(getStringValue(this, keyOracles()), ",") | |
137 | - | ||
138 | - | let oracleCount = size(pubKeyOraclesList) | |
139 | - | ||
140 | - | let minConsensus = valueOrElse(getInteger(this, keyMinConsensus()), 3) | |
141 | - | ||
142 | - | func PriceFailedResult (symbol,msg) = [StringEntry(keyPriceFailure(symbol), msg)] | |
143 | - | ||
144 | - | ||
145 | - | func throwInvalidFinalizationHeight (finHeightStr) = throw(((("invalid finalization height: height=" + toString(height)) + " finalizationHeight=") + finHeightStr)) | |
146 | - | ||
147 | - | ||
148 | - | func throwGroupAlreadyFinalized (groupNum,finHeightStr) = throw((((("prices for groupNum=" + groupNum) + " at ") + finHeightStr) + " height have been already finalized")) | |
149 | - | ||
150 | - | ||
151 | - | func throwInvalidSignsParamLength (num,param) = throw(((((("invalid signs" + toString(num)) + " parameter: actual.size=") + toString(size(param))) + " base58Val=") + toBase58String(param))) | |
152 | - | ||
153 | - | ||
154 | - | func throwOutOfTurnFinalization () = throw(((("Out of turn finalization: " + toString(height)) + " block should be finalize by ") + pubKeyOraclesList[(height % oracleCount)])) | |
155 | - | ||
156 | - | ||
157 | - | func throwBlockedError () = throw("contract is blocked by EMERGENCY SHUTDOWN action") | |
158 | - | ||
159 | - | ||
160 | - | func PriceEntry (symbol,newPrice,isMarketOpened) = { | |
161 | - | let idx = valueOrElse(getInteger(this, keyIdx(symbol)), 0) | |
162 | - | let newIdx = (idx + 1) | |
163 | - | [IntegerEntry(keyPrice(symbol), newPrice), IntegerEntry(keyLastHeight(symbol), height), IntegerEntry(keyPriceByHeight(symbol, height), newPrice), IntegerEntry(keyIdx(symbol), newIdx), IntegerEntry(keyIdx2Height(symbol, newIdx), height), IntegerEntry(keyHeight2Idx(symbol, height), newIdx), BooleanEntry(keyIsMarketOpened(symbol), isMarketOpened)] | |
164 | - | } | |
165 | - | ||
166 | - | ||
167 | - | func finalizeUsdnUsdtOnchain () = { | |
168 | - | let symbol = "USDN-USDT" | |
169 | - | let usdnId = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
170 | - | let usdtId = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ" | |
171 | - | let usdnAmount = 1000000000 | |
172 | - | let wxPoolAddressStr = "3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz" | |
173 | - | let wxPoolAddress = addressFromStringValue(wxPoolAddressStr) | |
174 | - | let $t077107849 = { | |
175 | - | let @ = invoke(wxPoolAddress, "putOneTknV2WithBonusREADONLY", [usdnAmount, usdnId], nil) | |
176 | - | if ($isInstanceOf(@, "(Int, Int, Int)")) | |
177 | - | then @ | |
178 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)")) | |
179 | - | } | |
180 | - | let lpAmount = $t077107849._1 | |
181 | - | let feeAmount1 = $t077107849._2 | |
182 | - | let bonus = $t077107849._3 | |
183 | - | let $t078527970 = { | |
184 | - | let @ = invoke(wxPoolAddress, "getOneTknV2READONLY", [usdtId, lpAmount], nil) | |
185 | - | if ($isInstanceOf(@, "(Int, Int)")) | |
186 | - | then @ | |
187 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int)")) | |
188 | - | } | |
189 | - | let usdtAmount = $t078527970._1 | |
190 | - | let feeAmount2 = $t078527970._2 | |
191 | - | let newPrice = fraction(usdtAmount, 1000000, usdnAmount) | |
192 | - | (PriceEntry(symbol, newPrice, true) ++ StatsEntry(symbol, newPrice)) | |
193 | - | } | |
194 | - | ||
195 | - | ||
196 | - | func finalizePwrUsdtOnchainV2 () = { | |
197 | - | let symbol = "PWR-USDT" | |
198 | - | let wavesUsdPriceX6 = getIntegerValue(this, "%s%s__price__WAVES-USDT") | |
199 | - | let ethUsdtPriceX6 = getIntegerValue(this, "%s%s__price__ETH-USDT") | |
200 | - | let wx_restAddressStr = "3P8MoPnsaurofk1VyhsdAFkeQ6ijpJYXCpW" | |
201 | - | let wx_restDapp = addressFromStringValue(wx_restAddressStr) | |
202 | - | let wx_pwrWavesPoolStr = "3PDi7Qq8pLQYvtKyTfQuqqPUWyhoYbU957t" | |
203 | - | let wx_pwrWavesPoolAddress = addressFromStringValue(wx_pwrWavesPoolStr) | |
204 | - | let wx_PwrWaves_lp = "AKQsEQoeinKRFtdx6rhKWcpkAMu6cbDLdtSWnR8tpBCq" | |
205 | - | let wxRestResult = split(asString(invoke(wx_restDapp, "poolStatsREADONLY", [wx_PwrWaves_lp], nil)), "__") | |
206 | - | let wx_PwrWaves_WavesX8 = parseIntValue(wxRestResult[2]) | |
207 | - | let wx_PwrWaves_PwrX8 = parseIntValue(wxRestResult[1]) | |
208 | - | let wx_PwrWaves_WxUsdPriceX6 = fraction(wx_PwrWaves_WavesX8, wavesUsdPriceX6, wx_PwrWaves_PwrX8) | |
209 | - | let debug = ((((("wavesUsdPriceX6=" + toString(wavesUsdPriceX6)) + " wx_PwrWaves_WavesX8=") + toString(wx_PwrWaves_WavesX8)) + " wx_PwrWaves_PwrX8=") + toString(wx_PwrWaves_PwrX8)) | |
210 | - | $Tuple2(wx_PwrWaves_WxUsdPriceX6, debug) | |
211 | - | } | |
212 | - | ||
213 | - | ||
214 | - | func finalizeUsdnUsdtOnchainV2 () = { | |
215 | - | let wavesUsdtPriceX6 = getIntegerValue(this, "%s%s__price__WAVES-USDT") | |
216 | - | let ethUsdtPriceX6 = getIntegerValue(this, "%s%s__price__ETH-USDT") | |
217 | - | let symbol = "USDN-USDT" | |
218 | - | let xtnIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
219 | - | let xtnId = fromBase58String(xtnIdStr) | |
220 | - | let usdtIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ" | |
221 | - | let usdnAmount = 1000000000 | |
222 | - | let wxUsdtXtnPoolStr = "3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz" | |
223 | - | let wxUsdtXtnPoolAddress = addressFromStringValue(wxUsdtXtnPoolStr) | |
224 | - | let wxUsdtXtnW = 67 | |
225 | - | let $t097969944 = { | |
226 | - | let @ = invoke(wxUsdtXtnPoolAddress, "putOneTknV2WithBonusREADONLY", [usdnAmount, xtnIdStr], nil) | |
227 | - | if ($isInstanceOf(@, "(Int, Int, Int)")) | |
228 | - | then @ | |
229 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)")) | |
230 | - | } | |
231 | - | let lpAmount = $t097969944._1 | |
232 | - | let feeAmount1 = $t097969944._2 | |
233 | - | let bonus = $t097969944._3 | |
234 | - | let $t0994710075 = { | |
235 | - | let @ = invoke(wxUsdtXtnPoolAddress, "getOneTknV2READONLY", [usdtIdStr, lpAmount], nil) | |
236 | - | if ($isInstanceOf(@, "(Int, Int)")) | |
237 | - | then @ | |
238 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int)")) | |
239 | - | } | |
240 | - | let usdtAmount = $t0994710075._1 | |
241 | - | let feeAmount2 = $t0994710075._2 | |
242 | - | let wxUsdtXtnPrice = fraction(usdtAmount, 1000000, usdnAmount) | |
243 | - | let wxWavesXtnW = 550 | |
244 | - | let wxWavesXtnPoolStr = "3PPZWgFNRKHLvM51pwS934C8VZ7d2F4Z58g" | |
245 | - | let wxWavesXtnPoolAddress = addressFromStringValue(wxWavesXtnPoolStr) | |
246 | - | let wavesWavesXtnX8 = wavesBalance(wxWavesXtnPoolAddress).regular | |
247 | - | let xtnWavesXtnX6 = assetBalance(wxWavesXtnPoolAddress, xtnId) | |
248 | - | let wavesXtnPriceX6 = fraction(xtnWavesXtnX6, 100000000, wavesWavesXtnX8) | |
249 | - | let wxWavesUsdtXtnPrice = fraction(wavesUsdtPriceX6, 1000000, wavesXtnPriceX6) | |
250 | - | let wxEthXtnW = 5 | |
251 | - | let ethIdStr = "474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu" | |
252 | - | let ethId = fromBase58String(ethIdStr) | |
253 | - | let wxEthXtnPoolStr = "3PEMqetsaJDbYMw1XGovmE37FB8VUhGnX9A" | |
254 | - | let wxEthXtnPoolAddress = addressFromStringValue(wxEthXtnPoolStr) | |
255 | - | let ethEthXtnX8 = assetBalance(wxEthXtnPoolAddress, ethId) | |
256 | - | let xtnEthXtnX6 = assetBalance(wxEthXtnPoolAddress, xtnId) | |
257 | - | let ethXtnPriceX6 = fraction(xtnEthXtnX6, 100000000, ethEthXtnX8) | |
258 | - | let wxEthUsdtXtnPrice = fraction(ethUsdtPriceX6, 1000000, ethXtnPriceX6) | |
259 | - | let swopfiWavesXtnW = 1000 | |
260 | - | let swopfiRest = addressFromStringValue("3P56jNQzECXnrWpnbbSJKw7Eooo6fkUaMPp") | |
261 | - | let swopfiWavesXtnPriceX6 = { | |
262 | - | let @ = invoke(swopfiRest, "calcGetAmountCPMM", ["3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG", "3PQHCTqfzE8e1Jo8m1QVaCXATSKyMmkYasF", "WAVES", 100000000], nil) | |
263 | - | if ($isInstanceOf(@, "Int")) | |
264 | - | then @ | |
265 | - | else throw(($getType(@) + " couldn't be cast to Int")) | |
266 | - | } | |
267 | - | let swopfiWavesUsdtXtnPrice = fraction(wavesUsdtPriceX6, 1000000, swopfiWavesXtnPriceX6) | |
268 | - | let newPrice = fraction(swopfiWavesUsdtXtnPrice, swopfiWavesXtnW, 1000) | |
269 | - | (PriceEntry(symbol, newPrice, true) ++ StatsEntry(symbol, newPrice)) | |
270 | - | } | |
271 | - | ||
272 | - | ||
273 | - | func finalizePriceV2Common (position,groupNum,groupDataStr,msgArray,signs) = { | |
274 | - | let msgOffset = (position * 3) | |
275 | - | if ((msgOffset >= size(msgArray))) | |
276 | - | then [StringEntry(keyEmptyPriceMsg(position), "price data is empty")] | |
277 | - | else { | |
278 | - | let symbol = msgArray[(msgOffset + 0)] | |
279 | - | let newPriceStr = msgArray[(msgOffset + 1)] | |
280 | - | let isMarketOpenedStr = msgArray[(msgOffset + 2)] | |
281 | - | let newPriceOpt = parseInt(newPriceStr) | |
282 | - | let isMarketOpenedOpt = parseInt(isMarketOpenedStr) | |
283 | - | let sig0 = take(signs, 64) | |
284 | - | let sig1 = take(drop(signs, 64), 64) | |
285 | - | let sig2 = take(drop(signs, 128), 64) | |
286 | - | let sig3 = take(drop(signs, 192), 64) | |
287 | - | let sig4 = takeRight(signs, 64) | |
288 | - | let isBlocked = valueOrElse(getBoolean(this, keyIsBlocked(symbol)), false) | |
289 | - | if ((symbol == "")) | |
290 | - | then nil | |
291 | - | else if (isBlocked) | |
292 | - | then PriceFailedResult(symbol, (symbol + " is blocked")) | |
293 | - | else if (contains(groupDataStr, symbol)) | |
294 | - | then if (if (isDefined(newPriceOpt)) | |
295 | - | then isDefined(isMarketOpenedOpt) | |
296 | - | else false) | |
297 | - | then { | |
298 | - | let newPrice = value(newPriceOpt) | |
299 | - | let isMarketOpened = if ((value(isMarketOpenedOpt) == 1)) | |
300 | - | then true | |
301 | - | else false | |
302 | - | let priceMsgStr = makeString(["WAVES-DORA2", groupNum, toString(height), symbol, newPriceStr, isMarketOpenedStr], ProtocolSEP) | |
303 | - | let priceMsg = toBytes(priceMsgStr) | |
304 | - | let verificationsCount = (((((if (sigVerify_8Kb(priceMsg, sig0, fromBase58String(pubKeyOraclesList[0]))) | |
305 | - | then 1 | |
306 | - | else 0) + (if (sigVerify_8Kb(priceMsg, sig1, fromBase58String(pubKeyOraclesList[1]))) | |
307 | - | then 1 | |
308 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig2, fromBase58String(pubKeyOraclesList[2]))) | |
309 | - | then 1 | |
310 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig3, fromBase58String(pubKeyOraclesList[3]))) | |
311 | - | then 1 | |
312 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig4, fromBase58String(pubKeyOraclesList[4]))) | |
313 | - | then 1 | |
314 | - | else 0)) | |
315 | - | if ((verificationsCount >= minConsensus)) | |
316 | - | then { | |
317 | - | let price = valueOrElse(getInteger(this, keyPrice(symbol)), 0) | |
318 | - | if (if ((price != 0)) | |
319 | - | then if ((newPrice >= (price + ((price * percentPriceOffset) / 100)))) | |
320 | - | then true | |
321 | - | else ((price - ((price * percentPriceOffset) / 100)) >= newPrice) | |
322 | - | else false) | |
323 | - | then { | |
324 | - | let reason = "automatic emergency shutdown because of large price variability" | |
325 | - | [BooleanEntry(keyIsBlocked(symbol), true), StringEntry(keyIsBlockedSender(symbol), toString(this)), StringEntry(keyIsBlockedReason(symbol), reason), IntegerEntry(keyBlackSwarmPrice(height, symbol), newPrice)] | |
326 | - | } | |
327 | - | else (PriceEntry(symbol, newPrice, isMarketOpened) ++ StatsEntry(symbol, newPrice)) | |
328 | - | } | |
329 | - | else PriceFailedResult(symbol, ((((((((("verificationsCount = " + toString(verificationsCount)) + "signs0.length=") + toString(size(signs))) + " msg0 = ") + priceMsgStr) + " sig0 = ") + toBase58String(sig0)) + " key0 = ") + pubKeyOraclesList[0])) | |
330 | - | } | |
331 | - | else PriceFailedResult(symbol, ((("data parsing error: newPrice=" + newPriceStr) + " isMarketOpened=") + isMarketOpenedStr)) | |
332 | - | else PriceFailedResult(symbol, ((symbol + " doesn't exist in group: groupDataStr=") + groupDataStr)) | |
333 | - | } | |
334 | - | } | |
63 | + | func pzBalance (poolAddress,assetId) = assetBalance(poolAddress, assetId) | |
335 | 64 | ||
336 | 65 | ||
337 | 66 | @Callable(i) | |
338 | - | func finalizeDORA2 (header,msg,signs0,signs1,signs2,signs3) = { | |
339 | - | let headerArray = split(header, ProtocolSEP) | |
340 | - | let groupNum = headerArray[1] | |
341 | - | let finHeightStr = headerArray[2] | |
342 | - | let finHeight = parseIntValue(finHeightStr) | |
343 | - | let signsLength = (64 * oracleCount) | |
344 | - | if ((height != finHeight)) | |
345 | - | then throwInvalidFinalizationHeight(finHeightStr) | |
346 | - | else if (isGroupFinalaized(groupNum, finHeightStr)) | |
347 | - | then throwGroupAlreadyFinalized(groupNum, finHeightStr) | |
348 | - | else if ((pubKeyOraclesList[(height % oracleCount)] != toBase58String(i.callerPublicKey))) | |
349 | - | then throwOutOfTurnFinalization() | |
350 | - | else if ((size(signs0) != signsLength)) | |
351 | - | then throwInvalidSignsParamLength(0, signs0) | |
352 | - | else if ((size(signs1) != signsLength)) | |
353 | - | then throwInvalidSignsParamLength(1, signs1) | |
354 | - | else if ((size(signs2) != signsLength)) | |
355 | - | then throwInvalidSignsParamLength(2, signs2) | |
356 | - | else if ((size(signs3) != signsLength)) | |
357 | - | then throwInvalidSignsParamLength(3, signs3) | |
358 | - | else { | |
359 | - | let groupDataKey = keyGroupData(groupNum) | |
360 | - | let groupDataStr = valueOrErrorMessage(getString(this, groupDataKey), ("empty group data for key=" + groupDataKey)) | |
361 | - | let msgArray = split(msg, ProtocolSEP) | |
362 | - | if (((size(msgArray) % 3) != 0)) | |
363 | - | then throw(("msg parameters count must be multiple of 3: msgArray.size=" + toString(size(msg)))) | |
364 | - | else ((((finalizePriceV2Common(0, groupNum, groupDataStr, msgArray, signs0) ++ finalizePriceV2Common(1, groupNum, groupDataStr, msgArray, signs1)) ++ finalizePriceV2Common(2, groupNum, groupDataStr, msgArray, signs2)) ++ (if ((groupNum == "0")) | |
365 | - | then finalizeUsdnUsdtOnchainV2() | |
366 | - | else finalizePriceV2Common(3, groupNum, groupDataStr, msgArray, signs3))) :+ BooleanEntry(keyGroupStatus(groupNum, finHeightStr), true)) | |
367 | - | } | |
67 | + | func buyXtnForWaves () = { | |
68 | + | let pmt = value(i.payments[0]) | |
69 | + | let wavesAmt = pmt.amount | |
70 | + | let wavesToXtnViaWx = wxPoolBalance(wxWavesXtn, 1) | |
71 | + | let wavesToXtnViaSwop = swopBalance(swopWavesXtn, "A") | |
72 | + | let wavesToXtnTotal = (wavesToXtnViaWx + wavesToXtnViaSwop) | |
73 | + | let wavesToXtnViaWxAmt = fraction(wavesAmt, wavesToXtnViaWx, wavesToXtnTotal) | |
74 | + | let wavesToXtnViaSwopAmt = fraction(wavesAmt, wavesToXtnViaSwop, wavesToXtnTotal) | |
75 | + | let wavesToXtnViaWxResult = invoke(wxSwop, "swap", [1, xtnIdStr, toString(this)], [AttachedPayment(unit, wavesToXtnViaWxAmt)]) | |
76 | + | if ((wavesToXtnViaWxResult == wavesToXtnViaWxResult)) | |
77 | + | then { | |
78 | + | let wavesToXtnViaSwopResult = asAnyList(invoke(swopWavesXtn, "exchange", [1], [AttachedPayment(unit, wavesToXtnViaSwopAmt)])) | |
79 | + | if ((wavesToXtnViaSwopResult == wavesToXtnViaSwopResult)) | |
80 | + | then { | |
81 | + | let xtnAmt = assetBalance(this, xtnId) | |
82 | + | $Tuple2(nil, xtnAmt) | |
83 | + | } | |
84 | + | else throw("Strict value is not equal to itself.") | |
85 | + | } | |
86 | + | else throw("Strict value is not equal to itself.") | |
368 | 87 | } | |
369 | 88 | ||
370 | 89 | ||
371 | 90 | ||
372 | 91 | @Callable(i) | |
373 | - | func price (hours) = { | |
374 | - | let symbol = "USDN-USDT" | |
375 | - | let periodSTEP = H4MILLIS | |
376 | - | let maxHours = 80 | |
377 | - | let iters = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] | |
378 | - | if ((hours > maxHours)) | |
379 | - | then throw("hours is greater then max 80") | |
380 | - | else if ((4 > hours)) | |
381 | - | then throw("hours is less then min value 4") | |
382 | - | else { | |
383 | - | let currTime = lastBlock.timestamp | |
384 | - | let startTime = ((currTime - (hours * 3600000)) - H4MILLIS) | |
385 | - | let period = toPeriod(currTime, periodSTEP) | |
386 | - | let periodStr = toString(period) | |
387 | - | let smallestPeriod = getIntegerValue(this, keyStats1stPeriod(symbol)) | |
388 | - | let startPeriodTmp = toPeriod(startTime, periodSTEP) | |
389 | - | let isEnoughData = (startPeriodTmp >= smallestPeriod) | |
390 | - | let startPeriod = if (isEnoughData) | |
391 | - | then startPeriodTmp | |
392 | - | else smallestPeriod | |
393 | - | let startPeriodStr = toString(startPeriod) | |
394 | - | let startPriceSumX = parseBigIntValue(getStringValue(this, keyStatsByPeriodPriceSum(symbol, startPeriodStr))) | |
395 | - | let startCountSum = getIntegerValue(this, keyStatsByPeriodCountSum(symbol, startPeriodStr)) | |
396 | - | let endPriceSumX = if (isEnoughData) | |
397 | - | then parseBigIntValue(getStringValue(this, keyStatsByPeriodPriceSum(symbol, periodStr))) | |
398 | - | else toBigInt(0) | |
399 | - | let endCountSum = if (isEnoughData) | |
400 | - | then getIntegerValue(this, keyStatsByPeriodCountSum(symbol, periodStr)) | |
401 | - | else 0 | |
402 | - | let priceSum = toInt((endPriceSumX - startPriceSumX)) | |
403 | - | let priceCount = (endCountSum - startCountSum) | |
404 | - | let priceAvg = (priceSum / priceCount) | |
405 | - | if ((0 >= priceAvg)) | |
406 | - | then throw("calculation error") | |
407 | - | else { | |
408 | - | func findMinMax (minAndMax,nextIdx) = { | |
409 | - | let periodToCheck = (period - (nextIdx * periodSTEP)) | |
410 | - | if ((startPeriod > periodToCheck)) | |
411 | - | then minAndMax | |
412 | - | else { | |
413 | - | let periodToCheckStr = toString(periodToCheck) | |
414 | - | let minVal = minAndMax._1 | |
415 | - | let maxVal = minAndMax._2 | |
416 | - | let newMinVal = getIntegerValue(this, keyStatsByPeriodMin(symbol, periodToCheckStr)) | |
417 | - | let newMaxVal = getIntegerValue(this, keyStatsByPeriodMax(symbol, periodToCheckStr)) | |
418 | - | $Tuple2(min([minVal, newMinVal]), max([maxVal, newMaxVal])) | |
92 | + | func buyPuzzleForWaves () = { | |
93 | + | let pzForbesValue = pzBalance(pzForbes, puzzleId) | |
94 | + | let pzBasicPuzzleValue = pzBalance(pzBasicPuzzle, puzzleId) | |
95 | + | let wxPuzzleWavesValue = wxPoolBalance(wxPuzzleWaves, 1) | |
96 | + | let swopPuzzleXtnValue = swopBalance(swopPuzzleXtn, "A") | |
97 | + | let total = (((pzForbesValue + pzBasicPuzzleValue) + wxPuzzleWavesValue) + swopPuzzleXtnValue) | |
98 | + | let pmt = value(i.payments[0]) | |
99 | + | let pmtAmt = pmt.amount | |
100 | + | let pzForbesPart = fraction(pzForbesValue, pmtAmt, total) | |
101 | + | let pzBasicPuzzlePart = fraction(pzBasicPuzzleValue, pmtAmt, total) | |
102 | + | let wxPuzzleWavesPart = fraction(wxPuzzleWavesValue, pmtAmt, total) | |
103 | + | let swopPuzzleXtnPart = fraction(swopPuzzleXtnValue, pmtAmt, total) | |
104 | + | let xtnAmt = asInt(invoke(this, "buyXtnForWaves", nil, [AttachedPayment(unit, swopPuzzleXtnPart)])) | |
105 | + | if ((xtnAmt == xtnAmt)) | |
106 | + | then { | |
107 | + | let wavesToPuzzleViaForbesResult = invoke(pzForbes, "swap", [puzzleIdStr, 1], [AttachedPayment(unit, pzForbesPart)]) | |
108 | + | if ((wavesToPuzzleViaForbesResult == wavesToPuzzleViaForbesResult)) | |
109 | + | then { | |
110 | + | let wavesToPuzzleViaBasicResult = invoke(pzBasicPuzzle, "swap", [puzzleIdStr, 1], [AttachedPayment(unit, pzBasicPuzzlePart)]) | |
111 | + | if ((wavesToPuzzleViaBasicResult == wavesToPuzzleViaBasicResult)) | |
112 | + | then { | |
113 | + | let wavesToPuzzleViaWxResult = invoke(wxSwop, "swap", [1, puzzleIdStr, toString(this)], [AttachedPayment(unit, wxPuzzleWavesPart)]) | |
114 | + | if ((wavesToPuzzleViaWxResult == wavesToPuzzleViaWxResult)) | |
115 | + | then { | |
116 | + | let xtnToPuzzleViaSwopResult = asAnyList(invoke(swopPuzzleXtn, "exchange", [1], [AttachedPayment(xtnId, xtnAmt)])) | |
117 | + | if ((xtnToPuzzleViaSwopResult == xtnToPuzzleViaSwopResult)) | |
118 | + | then [ScriptTransfer(i.caller, wavesBalance(this).available, unit)] | |
119 | + | else throw("Strict value is not equal to itself.") | |
419 | 120 | } | |
121 | + | else throw("Strict value is not equal to itself.") | |
420 | 122 | } | |
421 | - | ||
422 | - | let price = getIntegerValue(this, keyPrice(symbol)) | |
423 | - | let minMaxSTRUCT = { | |
424 | - | let $l = iters | |
425 | - | let $s = size($l) | |
426 | - | let $acc0 = $Tuple2(9223372036854775, 0) | |
427 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
428 | - | then $a | |
429 | - | else findMinMax($a, $l[$i]) | |
430 | - | ||
431 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
432 | - | then $a | |
433 | - | else throw("List size exceeds 21") | |
434 | - | ||
435 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21) | |
436 | - | } | |
437 | - | $Tuple2(nil, $Tuple4(price, priceAvg, minMaxSTRUCT._1, minMaxSTRUCT._2)) | |
438 | - | } | |
439 | - | } | |
123 | + | else throw("Strict value is not equal to itself.") | |
124 | + | } | |
125 | + | else throw("Strict value is not equal to itself.") | |
126 | + | } | |
127 | + | else throw("Strict value is not equal to itself.") | |
440 | 128 | } | |
441 | 129 | ||
442 | 130 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let ProtocolSEP = ":" | |
4 | + | func asAnyList (val) = match val { | |
5 | + | case valAnyList: List[Any] => | |
6 | + | valAnyList | |
7 | + | case _ => | |
8 | + | throw("fail to cast into List[Any]") | |
9 | + | } | |
5 | 10 | ||
6 | - | let SEP = "__" | |
7 | - | ||
8 | - | let percentPriceOffset = 95 | |
9 | 11 | ||
10 | 12 | func asString (v) = match v { | |
11 | 13 | case s: String => | |
12 | 14 | s | |
13 | 15 | case _ => | |
14 | 16 | throw("fail to cast into String") | |
15 | 17 | } | |
16 | 18 | ||
17 | 19 | ||
18 | - | func keyPrice (symbol) = ("%s%s__price__" + symbol) | |
20 | + | func asInt (v) = match v { | |
21 | + | case i: Int => | |
22 | + | i | |
23 | + | case _ => | |
24 | + | throw("fail to cast into Int") | |
25 | + | } | |
19 | 26 | ||
20 | 27 | ||
21 | - | func keyOracles () = "%s%s__config__oracles" | |
28 | + | let puzzleIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS" | |
29 | + | ||
30 | + | let puzzleId = fromBase58String(puzzleIdStr) | |
31 | + | ||
32 | + | let xtnIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
33 | + | ||
34 | + | let xtnId = fromBase58String(xtnIdStr) | |
35 | + | ||
36 | + | let pzForbes = addressFromStringValue("3PQnzp5YogBvJmwPnvSWoargPMcd1R4GLa8") | |
37 | + | ||
38 | + | let pzBasicPuzzle = addressFromStringValue("3PQAhPM5iHQyYrAqTVts53UgiLGtVuSZ8xD") | |
39 | + | ||
40 | + | let wxRest = addressFromStringValue("3P8MoPnsaurofk1VyhsdAFkeQ6ijpJYXCpW") | |
41 | + | ||
42 | + | let wxSwop = addressFromStringValue("3P68zNiufsu1viZpu1aY3cdahRRKcvV5N93") | |
43 | + | ||
44 | + | let wxPuzzleWaves = addressFromStringValue("3PQaYm4pbRVrNTTnL8pDJZTxhcmD4jRskrz") | |
45 | + | ||
46 | + | let wxPuzzleXtn = addressFromStringValue("3P615yXeQ9Qu4qBM1QGimGzixyMS5W4Ktug") | |
47 | + | ||
48 | + | let wxWavesXtn = addressFromStringValue("3PPZWgFNRKHLvM51pwS934C8VZ7d2F4Z58g") | |
49 | + | ||
50 | + | let swopPuzzleXtn = addressFromStringValue("3PBHyEwmERR1CEkrTNbPj2bgyisTfPRqfee") | |
51 | + | ||
52 | + | let swopWavesXtn = addressFromStringValue("3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG") | |
53 | + | ||
54 | + | func swopBalance (poolAddress,AorB) = getIntegerValue(poolAddress, (AorB + "_asset_balance")) | |
22 | 55 | ||
23 | 56 | ||
24 | - | func keyGroupData (groupNum) = ("%s%d__group__" + groupNum) | |
25 | - | ||
26 | - | ||
27 | - | func keyMinConsensus () = "%s%s__config__minConsensus" | |
28 | - | ||
29 | - | ||
30 | - | func keyPriceFailure (symbol) = makeString(["%s%s%d__finalizationFailure", symbol, toString(height)], SEP) | |
31 | - | ||
32 | - | ||
33 | - | func keyLastHeight (symbol) = ("%s%s__lastHeight__" + symbol) | |
34 | - | ||
35 | - | ||
36 | - | func keyPriceByHeight (symbol,h) = makeString(["%s%s%d__priceByHeight", symbol, toString(h)], SEP) | |
37 | - | ||
38 | - | ||
39 | - | func keyIdx (symbol) = ("%s%s__idxCurrent__" + symbol) | |
40 | - | ||
41 | - | ||
42 | - | func keyIdx2Height (symbol,idx) = makeString(["%s%s%d__idx2Height", symbol, toString(idx)], SEP) | |
43 | - | ||
44 | - | ||
45 | - | func keyHeight2Idx (symbol,h) = makeString(["%s%s%d__height2Idx", symbol, toString(h)], SEP) | |
46 | - | ||
47 | - | ||
48 | - | func keyGroupStatus (groupNum,finHeightStr) = makeString(["%s%d%d__groupStatus", groupNum, finHeightStr], SEP) | |
49 | - | ||
50 | - | ||
51 | - | func keyIsMarketOpened (symbol) = ("%s%s__isMarketOpened__" + symbol) | |
52 | - | ||
53 | - | ||
54 | - | func keyEmptyPriceMsg (position) = makeString(["%s%d%d__emptyPriceMsg", toString(height), toString(position)], SEP) | |
55 | - | ||
56 | - | ||
57 | - | func keyIsBlocked (symbol) = ("%s%s__isBlocked__" + symbol) | |
58 | - | ||
59 | - | ||
60 | - | func keyIsBlockedSender (symbol) = makeString(["%s%s%s__isBlocked", symbol, "sender"], SEP) | |
61 | - | ||
62 | - | ||
63 | - | func keyIsBlockedReason (symbol) = makeString(["%s%s%s__isBlocked", symbol, "reason"], SEP) | |
64 | - | ||
65 | - | ||
66 | - | func keyBlackSwarmPrice (h,symbol) = makeString(["%s%s%s%d__isBlocked", symbol, "blackSwarmPrice", toString(h)], SEP) | |
67 | - | ||
68 | - | ||
69 | - | let DAYMILLIS = 86400000 | |
70 | - | ||
71 | - | let H4MILLIS = 14400000 | |
72 | - | ||
73 | - | func toPeriod (timestamp,period) = ((timestamp / period) * period) | |
74 | - | ||
75 | - | ||
76 | - | func keyStats1stPeriod (symbol) = makeString(["%s%s", "stats1stPeriod", symbol], SEP) | |
77 | - | ||
78 | - | ||
79 | - | func keyStatsPriceSum (symbol) = makeString(["%s%s", "statsPriceSum", symbol], SEP) | |
80 | - | ||
81 | - | ||
82 | - | func keyStatsCountSum (symbol) = makeString(["%s%s", "statsCountSum", symbol], SEP) | |
83 | - | ||
84 | - | ||
85 | - | func keyStatsByPeriodPriceSum (symbol,period) = makeString(["%s%s%d", "statsPriceSum", symbol, period], SEP) | |
86 | - | ||
87 | - | ||
88 | - | func keyStatsByPeriodCountSum (symbol,period) = makeString(["%s%s%d", "statsCountSum", symbol, period], SEP) | |
89 | - | ||
90 | - | ||
91 | - | func keyStatsByPeriodMin (symbol,period) = makeString(["%s%s%d", "statsPriceMin", symbol, period], SEP) | |
92 | - | ||
93 | - | ||
94 | - | func keyStatsByPeriodMax (symbol,period) = makeString(["%s%s%d", "statsPriceMax", symbol, period], SEP) | |
95 | - | ||
96 | - | ||
97 | - | func StatsEntry (symbol,price) = { | |
98 | - | let period = toPeriod(lastBlock.timestamp, H4MILLIS) | |
99 | - | let periodStr = toString(period) | |
100 | - | let stats1stPeriodKEY = keyStats1stPeriod(symbol) | |
101 | - | let statsPriceSumKEY = keyStatsPriceSum(symbol) | |
102 | - | let statsCountSumKEY = keyStatsCountSum(symbol) | |
103 | - | let statsByPeriodPriceSumKEY = keyStatsByPeriodPriceSum(symbol, periodStr) | |
104 | - | let statsByPeriodCountSumKEY = keyStatsByPeriodCountSum(symbol, periodStr) | |
105 | - | let statsByPeriodMinKEY = keyStatsByPeriodMin(symbol, periodStr) | |
106 | - | let statsByPeriodMaxKEY = keyStatsByPeriodMax(symbol, periodStr) | |
107 | - | let statsPriceSum = parseBigIntValue(valueOrElse(getString(this, statsPriceSumKEY), "0")) | |
108 | - | let statsCountSum = valueOrElse(getInteger(this, statsCountSumKEY), 0) | |
109 | - | let statsByPeriodMin = valueOrElse(getInteger(this, statsByPeriodMinKEY), 9223372036854775) | |
110 | - | let statsByPeriodMax = valueOrElse(getInteger(this, statsByPeriodMaxKEY), 0) | |
111 | - | let newStatsPriceSum = (statsPriceSum + toBigInt(price)) | |
112 | - | let newStatsCountSum = (statsCountSum + 1) | |
113 | - | let newStatsByPeriodPriceSum = newStatsPriceSum | |
114 | - | let newStatsByPeriodCountSum = newStatsCountSum | |
115 | - | let newStatsByPeriodMin = min([statsByPeriodMin, price]) | |
116 | - | let newStatsByPeriodMax = max([statsByPeriodMax, price]) | |
117 | - | let stats1stPeriod = valueOrElse(getInteger(this, stats1stPeriodKEY), -1) | |
118 | - | ([StringEntry(statsPriceSumKEY, toString(newStatsPriceSum)), IntegerEntry(statsCountSumKEY, newStatsCountSum), StringEntry(statsByPeriodPriceSumKEY, toString(newStatsByPeriodPriceSum)), IntegerEntry(statsByPeriodCountSumKEY, newStatsByPeriodCountSum), IntegerEntry(statsByPeriodMinKEY, newStatsByPeriodMin), IntegerEntry(statsByPeriodMaxKEY, newStatsByPeriodMax)] ++ (if ((0 > stats1stPeriod)) | |
119 | - | then [IntegerEntry(stats1stPeriodKEY, period)] | |
120 | - | else nil)) | |
57 | + | func wxPoolBalance (poolAddress,assetIndex) = { | |
58 | + | let wxRestResult = split(asString(invoke(wxRest, "poolStatsREADONLY", [toString(poolAddress)], nil)), "__") | |
59 | + | parseIntValue(wxRestResult[assetIndex]) | |
121 | 60 | } | |
122 | 61 | ||
123 | 62 | ||
124 | - | func isGroupFinalaized (groupNum,finHeightStr) = isDefined(getBoolean(this, keyGroupStatus(groupNum, finHeightStr))) | |
125 | - | ||
126 | - | ||
127 | - | func readGroupDataOrFail (groupNum) = { | |
128 | - | let k = keyGroupData(groupNum) | |
129 | - | let groupDataOpt = getString(this, k) | |
130 | - | if (isDefined(groupDataOpt)) | |
131 | - | then value(groupDataOpt) | |
132 | - | else throw(("empty group data for key=" + k)) | |
133 | - | } | |
134 | - | ||
135 | - | ||
136 | - | let pubKeyOraclesList = split(getStringValue(this, keyOracles()), ",") | |
137 | - | ||
138 | - | let oracleCount = size(pubKeyOraclesList) | |
139 | - | ||
140 | - | let minConsensus = valueOrElse(getInteger(this, keyMinConsensus()), 3) | |
141 | - | ||
142 | - | func PriceFailedResult (symbol,msg) = [StringEntry(keyPriceFailure(symbol), msg)] | |
143 | - | ||
144 | - | ||
145 | - | func throwInvalidFinalizationHeight (finHeightStr) = throw(((("invalid finalization height: height=" + toString(height)) + " finalizationHeight=") + finHeightStr)) | |
146 | - | ||
147 | - | ||
148 | - | func throwGroupAlreadyFinalized (groupNum,finHeightStr) = throw((((("prices for groupNum=" + groupNum) + " at ") + finHeightStr) + " height have been already finalized")) | |
149 | - | ||
150 | - | ||
151 | - | func throwInvalidSignsParamLength (num,param) = throw(((((("invalid signs" + toString(num)) + " parameter: actual.size=") + toString(size(param))) + " base58Val=") + toBase58String(param))) | |
152 | - | ||
153 | - | ||
154 | - | func throwOutOfTurnFinalization () = throw(((("Out of turn finalization: " + toString(height)) + " block should be finalize by ") + pubKeyOraclesList[(height % oracleCount)])) | |
155 | - | ||
156 | - | ||
157 | - | func throwBlockedError () = throw("contract is blocked by EMERGENCY SHUTDOWN action") | |
158 | - | ||
159 | - | ||
160 | - | func PriceEntry (symbol,newPrice,isMarketOpened) = { | |
161 | - | let idx = valueOrElse(getInteger(this, keyIdx(symbol)), 0) | |
162 | - | let newIdx = (idx + 1) | |
163 | - | [IntegerEntry(keyPrice(symbol), newPrice), IntegerEntry(keyLastHeight(symbol), height), IntegerEntry(keyPriceByHeight(symbol, height), newPrice), IntegerEntry(keyIdx(symbol), newIdx), IntegerEntry(keyIdx2Height(symbol, newIdx), height), IntegerEntry(keyHeight2Idx(symbol, height), newIdx), BooleanEntry(keyIsMarketOpened(symbol), isMarketOpened)] | |
164 | - | } | |
165 | - | ||
166 | - | ||
167 | - | func finalizeUsdnUsdtOnchain () = { | |
168 | - | let symbol = "USDN-USDT" | |
169 | - | let usdnId = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
170 | - | let usdtId = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ" | |
171 | - | let usdnAmount = 1000000000 | |
172 | - | let wxPoolAddressStr = "3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz" | |
173 | - | let wxPoolAddress = addressFromStringValue(wxPoolAddressStr) | |
174 | - | let $t077107849 = { | |
175 | - | let @ = invoke(wxPoolAddress, "putOneTknV2WithBonusREADONLY", [usdnAmount, usdnId], nil) | |
176 | - | if ($isInstanceOf(@, "(Int, Int, Int)")) | |
177 | - | then @ | |
178 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)")) | |
179 | - | } | |
180 | - | let lpAmount = $t077107849._1 | |
181 | - | let feeAmount1 = $t077107849._2 | |
182 | - | let bonus = $t077107849._3 | |
183 | - | let $t078527970 = { | |
184 | - | let @ = invoke(wxPoolAddress, "getOneTknV2READONLY", [usdtId, lpAmount], nil) | |
185 | - | if ($isInstanceOf(@, "(Int, Int)")) | |
186 | - | then @ | |
187 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int)")) | |
188 | - | } | |
189 | - | let usdtAmount = $t078527970._1 | |
190 | - | let feeAmount2 = $t078527970._2 | |
191 | - | let newPrice = fraction(usdtAmount, 1000000, usdnAmount) | |
192 | - | (PriceEntry(symbol, newPrice, true) ++ StatsEntry(symbol, newPrice)) | |
193 | - | } | |
194 | - | ||
195 | - | ||
196 | - | func finalizePwrUsdtOnchainV2 () = { | |
197 | - | let symbol = "PWR-USDT" | |
198 | - | let wavesUsdPriceX6 = getIntegerValue(this, "%s%s__price__WAVES-USDT") | |
199 | - | let ethUsdtPriceX6 = getIntegerValue(this, "%s%s__price__ETH-USDT") | |
200 | - | let wx_restAddressStr = "3P8MoPnsaurofk1VyhsdAFkeQ6ijpJYXCpW" | |
201 | - | let wx_restDapp = addressFromStringValue(wx_restAddressStr) | |
202 | - | let wx_pwrWavesPoolStr = "3PDi7Qq8pLQYvtKyTfQuqqPUWyhoYbU957t" | |
203 | - | let wx_pwrWavesPoolAddress = addressFromStringValue(wx_pwrWavesPoolStr) | |
204 | - | let wx_PwrWaves_lp = "AKQsEQoeinKRFtdx6rhKWcpkAMu6cbDLdtSWnR8tpBCq" | |
205 | - | let wxRestResult = split(asString(invoke(wx_restDapp, "poolStatsREADONLY", [wx_PwrWaves_lp], nil)), "__") | |
206 | - | let wx_PwrWaves_WavesX8 = parseIntValue(wxRestResult[2]) | |
207 | - | let wx_PwrWaves_PwrX8 = parseIntValue(wxRestResult[1]) | |
208 | - | let wx_PwrWaves_WxUsdPriceX6 = fraction(wx_PwrWaves_WavesX8, wavesUsdPriceX6, wx_PwrWaves_PwrX8) | |
209 | - | let debug = ((((("wavesUsdPriceX6=" + toString(wavesUsdPriceX6)) + " wx_PwrWaves_WavesX8=") + toString(wx_PwrWaves_WavesX8)) + " wx_PwrWaves_PwrX8=") + toString(wx_PwrWaves_PwrX8)) | |
210 | - | $Tuple2(wx_PwrWaves_WxUsdPriceX6, debug) | |
211 | - | } | |
212 | - | ||
213 | - | ||
214 | - | func finalizeUsdnUsdtOnchainV2 () = { | |
215 | - | let wavesUsdtPriceX6 = getIntegerValue(this, "%s%s__price__WAVES-USDT") | |
216 | - | let ethUsdtPriceX6 = getIntegerValue(this, "%s%s__price__ETH-USDT") | |
217 | - | let symbol = "USDN-USDT" | |
218 | - | let xtnIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p" | |
219 | - | let xtnId = fromBase58String(xtnIdStr) | |
220 | - | let usdtIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ" | |
221 | - | let usdnAmount = 1000000000 | |
222 | - | let wxUsdtXtnPoolStr = "3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz" | |
223 | - | let wxUsdtXtnPoolAddress = addressFromStringValue(wxUsdtXtnPoolStr) | |
224 | - | let wxUsdtXtnW = 67 | |
225 | - | let $t097969944 = { | |
226 | - | let @ = invoke(wxUsdtXtnPoolAddress, "putOneTknV2WithBonusREADONLY", [usdnAmount, xtnIdStr], nil) | |
227 | - | if ($isInstanceOf(@, "(Int, Int, Int)")) | |
228 | - | then @ | |
229 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)")) | |
230 | - | } | |
231 | - | let lpAmount = $t097969944._1 | |
232 | - | let feeAmount1 = $t097969944._2 | |
233 | - | let bonus = $t097969944._3 | |
234 | - | let $t0994710075 = { | |
235 | - | let @ = invoke(wxUsdtXtnPoolAddress, "getOneTknV2READONLY", [usdtIdStr, lpAmount], nil) | |
236 | - | if ($isInstanceOf(@, "(Int, Int)")) | |
237 | - | then @ | |
238 | - | else throw(($getType(@) + " couldn't be cast to (Int, Int)")) | |
239 | - | } | |
240 | - | let usdtAmount = $t0994710075._1 | |
241 | - | let feeAmount2 = $t0994710075._2 | |
242 | - | let wxUsdtXtnPrice = fraction(usdtAmount, 1000000, usdnAmount) | |
243 | - | let wxWavesXtnW = 550 | |
244 | - | let wxWavesXtnPoolStr = "3PPZWgFNRKHLvM51pwS934C8VZ7d2F4Z58g" | |
245 | - | let wxWavesXtnPoolAddress = addressFromStringValue(wxWavesXtnPoolStr) | |
246 | - | let wavesWavesXtnX8 = wavesBalance(wxWavesXtnPoolAddress).regular | |
247 | - | let xtnWavesXtnX6 = assetBalance(wxWavesXtnPoolAddress, xtnId) | |
248 | - | let wavesXtnPriceX6 = fraction(xtnWavesXtnX6, 100000000, wavesWavesXtnX8) | |
249 | - | let wxWavesUsdtXtnPrice = fraction(wavesUsdtPriceX6, 1000000, wavesXtnPriceX6) | |
250 | - | let wxEthXtnW = 5 | |
251 | - | let ethIdStr = "474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu" | |
252 | - | let ethId = fromBase58String(ethIdStr) | |
253 | - | let wxEthXtnPoolStr = "3PEMqetsaJDbYMw1XGovmE37FB8VUhGnX9A" | |
254 | - | let wxEthXtnPoolAddress = addressFromStringValue(wxEthXtnPoolStr) | |
255 | - | let ethEthXtnX8 = assetBalance(wxEthXtnPoolAddress, ethId) | |
256 | - | let xtnEthXtnX6 = assetBalance(wxEthXtnPoolAddress, xtnId) | |
257 | - | let ethXtnPriceX6 = fraction(xtnEthXtnX6, 100000000, ethEthXtnX8) | |
258 | - | let wxEthUsdtXtnPrice = fraction(ethUsdtPriceX6, 1000000, ethXtnPriceX6) | |
259 | - | let swopfiWavesXtnW = 1000 | |
260 | - | let swopfiRest = addressFromStringValue("3P56jNQzECXnrWpnbbSJKw7Eooo6fkUaMPp") | |
261 | - | let swopfiWavesXtnPriceX6 = { | |
262 | - | let @ = invoke(swopfiRest, "calcGetAmountCPMM", ["3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG", "3PQHCTqfzE8e1Jo8m1QVaCXATSKyMmkYasF", "WAVES", 100000000], nil) | |
263 | - | if ($isInstanceOf(@, "Int")) | |
264 | - | then @ | |
265 | - | else throw(($getType(@) + " couldn't be cast to Int")) | |
266 | - | } | |
267 | - | let swopfiWavesUsdtXtnPrice = fraction(wavesUsdtPriceX6, 1000000, swopfiWavesXtnPriceX6) | |
268 | - | let newPrice = fraction(swopfiWavesUsdtXtnPrice, swopfiWavesXtnW, 1000) | |
269 | - | (PriceEntry(symbol, newPrice, true) ++ StatsEntry(symbol, newPrice)) | |
270 | - | } | |
271 | - | ||
272 | - | ||
273 | - | func finalizePriceV2Common (position,groupNum,groupDataStr,msgArray,signs) = { | |
274 | - | let msgOffset = (position * 3) | |
275 | - | if ((msgOffset >= size(msgArray))) | |
276 | - | then [StringEntry(keyEmptyPriceMsg(position), "price data is empty")] | |
277 | - | else { | |
278 | - | let symbol = msgArray[(msgOffset + 0)] | |
279 | - | let newPriceStr = msgArray[(msgOffset + 1)] | |
280 | - | let isMarketOpenedStr = msgArray[(msgOffset + 2)] | |
281 | - | let newPriceOpt = parseInt(newPriceStr) | |
282 | - | let isMarketOpenedOpt = parseInt(isMarketOpenedStr) | |
283 | - | let sig0 = take(signs, 64) | |
284 | - | let sig1 = take(drop(signs, 64), 64) | |
285 | - | let sig2 = take(drop(signs, 128), 64) | |
286 | - | let sig3 = take(drop(signs, 192), 64) | |
287 | - | let sig4 = takeRight(signs, 64) | |
288 | - | let isBlocked = valueOrElse(getBoolean(this, keyIsBlocked(symbol)), false) | |
289 | - | if ((symbol == "")) | |
290 | - | then nil | |
291 | - | else if (isBlocked) | |
292 | - | then PriceFailedResult(symbol, (symbol + " is blocked")) | |
293 | - | else if (contains(groupDataStr, symbol)) | |
294 | - | then if (if (isDefined(newPriceOpt)) | |
295 | - | then isDefined(isMarketOpenedOpt) | |
296 | - | else false) | |
297 | - | then { | |
298 | - | let newPrice = value(newPriceOpt) | |
299 | - | let isMarketOpened = if ((value(isMarketOpenedOpt) == 1)) | |
300 | - | then true | |
301 | - | else false | |
302 | - | let priceMsgStr = makeString(["WAVES-DORA2", groupNum, toString(height), symbol, newPriceStr, isMarketOpenedStr], ProtocolSEP) | |
303 | - | let priceMsg = toBytes(priceMsgStr) | |
304 | - | let verificationsCount = (((((if (sigVerify_8Kb(priceMsg, sig0, fromBase58String(pubKeyOraclesList[0]))) | |
305 | - | then 1 | |
306 | - | else 0) + (if (sigVerify_8Kb(priceMsg, sig1, fromBase58String(pubKeyOraclesList[1]))) | |
307 | - | then 1 | |
308 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig2, fromBase58String(pubKeyOraclesList[2]))) | |
309 | - | then 1 | |
310 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig3, fromBase58String(pubKeyOraclesList[3]))) | |
311 | - | then 1 | |
312 | - | else 0)) + (if (sigVerify_8Kb(priceMsg, sig4, fromBase58String(pubKeyOraclesList[4]))) | |
313 | - | then 1 | |
314 | - | else 0)) | |
315 | - | if ((verificationsCount >= minConsensus)) | |
316 | - | then { | |
317 | - | let price = valueOrElse(getInteger(this, keyPrice(symbol)), 0) | |
318 | - | if (if ((price != 0)) | |
319 | - | then if ((newPrice >= (price + ((price * percentPriceOffset) / 100)))) | |
320 | - | then true | |
321 | - | else ((price - ((price * percentPriceOffset) / 100)) >= newPrice) | |
322 | - | else false) | |
323 | - | then { | |
324 | - | let reason = "automatic emergency shutdown because of large price variability" | |
325 | - | [BooleanEntry(keyIsBlocked(symbol), true), StringEntry(keyIsBlockedSender(symbol), toString(this)), StringEntry(keyIsBlockedReason(symbol), reason), IntegerEntry(keyBlackSwarmPrice(height, symbol), newPrice)] | |
326 | - | } | |
327 | - | else (PriceEntry(symbol, newPrice, isMarketOpened) ++ StatsEntry(symbol, newPrice)) | |
328 | - | } | |
329 | - | else PriceFailedResult(symbol, ((((((((("verificationsCount = " + toString(verificationsCount)) + "signs0.length=") + toString(size(signs))) + " msg0 = ") + priceMsgStr) + " sig0 = ") + toBase58String(sig0)) + " key0 = ") + pubKeyOraclesList[0])) | |
330 | - | } | |
331 | - | else PriceFailedResult(symbol, ((("data parsing error: newPrice=" + newPriceStr) + " isMarketOpened=") + isMarketOpenedStr)) | |
332 | - | else PriceFailedResult(symbol, ((symbol + " doesn't exist in group: groupDataStr=") + groupDataStr)) | |
333 | - | } | |
334 | - | } | |
63 | + | func pzBalance (poolAddress,assetId) = assetBalance(poolAddress, assetId) | |
335 | 64 | ||
336 | 65 | ||
337 | 66 | @Callable(i) | |
338 | - | func finalizeDORA2 (header,msg,signs0,signs1,signs2,signs3) = { | |
339 | - | let headerArray = split(header, ProtocolSEP) | |
340 | - | let groupNum = headerArray[1] | |
341 | - | let finHeightStr = headerArray[2] | |
342 | - | let finHeight = parseIntValue(finHeightStr) | |
343 | - | let signsLength = (64 * oracleCount) | |
344 | - | if ((height != finHeight)) | |
345 | - | then throwInvalidFinalizationHeight(finHeightStr) | |
346 | - | else if (isGroupFinalaized(groupNum, finHeightStr)) | |
347 | - | then throwGroupAlreadyFinalized(groupNum, finHeightStr) | |
348 | - | else if ((pubKeyOraclesList[(height % oracleCount)] != toBase58String(i.callerPublicKey))) | |
349 | - | then throwOutOfTurnFinalization() | |
350 | - | else if ((size(signs0) != signsLength)) | |
351 | - | then throwInvalidSignsParamLength(0, signs0) | |
352 | - | else if ((size(signs1) != signsLength)) | |
353 | - | then throwInvalidSignsParamLength(1, signs1) | |
354 | - | else if ((size(signs2) != signsLength)) | |
355 | - | then throwInvalidSignsParamLength(2, signs2) | |
356 | - | else if ((size(signs3) != signsLength)) | |
357 | - | then throwInvalidSignsParamLength(3, signs3) | |
358 | - | else { | |
359 | - | let groupDataKey = keyGroupData(groupNum) | |
360 | - | let groupDataStr = valueOrErrorMessage(getString(this, groupDataKey), ("empty group data for key=" + groupDataKey)) | |
361 | - | let msgArray = split(msg, ProtocolSEP) | |
362 | - | if (((size(msgArray) % 3) != 0)) | |
363 | - | then throw(("msg parameters count must be multiple of 3: msgArray.size=" + toString(size(msg)))) | |
364 | - | else ((((finalizePriceV2Common(0, groupNum, groupDataStr, msgArray, signs0) ++ finalizePriceV2Common(1, groupNum, groupDataStr, msgArray, signs1)) ++ finalizePriceV2Common(2, groupNum, groupDataStr, msgArray, signs2)) ++ (if ((groupNum == "0")) | |
365 | - | then finalizeUsdnUsdtOnchainV2() | |
366 | - | else finalizePriceV2Common(3, groupNum, groupDataStr, msgArray, signs3))) :+ BooleanEntry(keyGroupStatus(groupNum, finHeightStr), true)) | |
367 | - | } | |
67 | + | func buyXtnForWaves () = { | |
68 | + | let pmt = value(i.payments[0]) | |
69 | + | let wavesAmt = pmt.amount | |
70 | + | let wavesToXtnViaWx = wxPoolBalance(wxWavesXtn, 1) | |
71 | + | let wavesToXtnViaSwop = swopBalance(swopWavesXtn, "A") | |
72 | + | let wavesToXtnTotal = (wavesToXtnViaWx + wavesToXtnViaSwop) | |
73 | + | let wavesToXtnViaWxAmt = fraction(wavesAmt, wavesToXtnViaWx, wavesToXtnTotal) | |
74 | + | let wavesToXtnViaSwopAmt = fraction(wavesAmt, wavesToXtnViaSwop, wavesToXtnTotal) | |
75 | + | let wavesToXtnViaWxResult = invoke(wxSwop, "swap", [1, xtnIdStr, toString(this)], [AttachedPayment(unit, wavesToXtnViaWxAmt)]) | |
76 | + | if ((wavesToXtnViaWxResult == wavesToXtnViaWxResult)) | |
77 | + | then { | |
78 | + | let wavesToXtnViaSwopResult = asAnyList(invoke(swopWavesXtn, "exchange", [1], [AttachedPayment(unit, wavesToXtnViaSwopAmt)])) | |
79 | + | if ((wavesToXtnViaSwopResult == wavesToXtnViaSwopResult)) | |
80 | + | then { | |
81 | + | let xtnAmt = assetBalance(this, xtnId) | |
82 | + | $Tuple2(nil, xtnAmt) | |
83 | + | } | |
84 | + | else throw("Strict value is not equal to itself.") | |
85 | + | } | |
86 | + | else throw("Strict value is not equal to itself.") | |
368 | 87 | } | |
369 | 88 | ||
370 | 89 | ||
371 | 90 | ||
372 | 91 | @Callable(i) | |
373 | - | func price (hours) = { | |
374 | - | let symbol = "USDN-USDT" | |
375 | - | let periodSTEP = H4MILLIS | |
376 | - | let maxHours = 80 | |
377 | - | let iters = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] | |
378 | - | if ((hours > maxHours)) | |
379 | - | then throw("hours is greater then max 80") | |
380 | - | else if ((4 > hours)) | |
381 | - | then throw("hours is less then min value 4") | |
382 | - | else { | |
383 | - | let currTime = lastBlock.timestamp | |
384 | - | let startTime = ((currTime - (hours * 3600000)) - H4MILLIS) | |
385 | - | let period = toPeriod(currTime, periodSTEP) | |
386 | - | let periodStr = toString(period) | |
387 | - | let smallestPeriod = getIntegerValue(this, keyStats1stPeriod(symbol)) | |
388 | - | let startPeriodTmp = toPeriod(startTime, periodSTEP) | |
389 | - | let isEnoughData = (startPeriodTmp >= smallestPeriod) | |
390 | - | let startPeriod = if (isEnoughData) | |
391 | - | then startPeriodTmp | |
392 | - | else smallestPeriod | |
393 | - | let startPeriodStr = toString(startPeriod) | |
394 | - | let startPriceSumX = parseBigIntValue(getStringValue(this, keyStatsByPeriodPriceSum(symbol, startPeriodStr))) | |
395 | - | let startCountSum = getIntegerValue(this, keyStatsByPeriodCountSum(symbol, startPeriodStr)) | |
396 | - | let endPriceSumX = if (isEnoughData) | |
397 | - | then parseBigIntValue(getStringValue(this, keyStatsByPeriodPriceSum(symbol, periodStr))) | |
398 | - | else toBigInt(0) | |
399 | - | let endCountSum = if (isEnoughData) | |
400 | - | then getIntegerValue(this, keyStatsByPeriodCountSum(symbol, periodStr)) | |
401 | - | else 0 | |
402 | - | let priceSum = toInt((endPriceSumX - startPriceSumX)) | |
403 | - | let priceCount = (endCountSum - startCountSum) | |
404 | - | let priceAvg = (priceSum / priceCount) | |
405 | - | if ((0 >= priceAvg)) | |
406 | - | then throw("calculation error") | |
407 | - | else { | |
408 | - | func findMinMax (minAndMax,nextIdx) = { | |
409 | - | let periodToCheck = (period - (nextIdx * periodSTEP)) | |
410 | - | if ((startPeriod > periodToCheck)) | |
411 | - | then minAndMax | |
412 | - | else { | |
413 | - | let periodToCheckStr = toString(periodToCheck) | |
414 | - | let minVal = minAndMax._1 | |
415 | - | let maxVal = minAndMax._2 | |
416 | - | let newMinVal = getIntegerValue(this, keyStatsByPeriodMin(symbol, periodToCheckStr)) | |
417 | - | let newMaxVal = getIntegerValue(this, keyStatsByPeriodMax(symbol, periodToCheckStr)) | |
418 | - | $Tuple2(min([minVal, newMinVal]), max([maxVal, newMaxVal])) | |
92 | + | func buyPuzzleForWaves () = { | |
93 | + | let pzForbesValue = pzBalance(pzForbes, puzzleId) | |
94 | + | let pzBasicPuzzleValue = pzBalance(pzBasicPuzzle, puzzleId) | |
95 | + | let wxPuzzleWavesValue = wxPoolBalance(wxPuzzleWaves, 1) | |
96 | + | let swopPuzzleXtnValue = swopBalance(swopPuzzleXtn, "A") | |
97 | + | let total = (((pzForbesValue + pzBasicPuzzleValue) + wxPuzzleWavesValue) + swopPuzzleXtnValue) | |
98 | + | let pmt = value(i.payments[0]) | |
99 | + | let pmtAmt = pmt.amount | |
100 | + | let pzForbesPart = fraction(pzForbesValue, pmtAmt, total) | |
101 | + | let pzBasicPuzzlePart = fraction(pzBasicPuzzleValue, pmtAmt, total) | |
102 | + | let wxPuzzleWavesPart = fraction(wxPuzzleWavesValue, pmtAmt, total) | |
103 | + | let swopPuzzleXtnPart = fraction(swopPuzzleXtnValue, pmtAmt, total) | |
104 | + | let xtnAmt = asInt(invoke(this, "buyXtnForWaves", nil, [AttachedPayment(unit, swopPuzzleXtnPart)])) | |
105 | + | if ((xtnAmt == xtnAmt)) | |
106 | + | then { | |
107 | + | let wavesToPuzzleViaForbesResult = invoke(pzForbes, "swap", [puzzleIdStr, 1], [AttachedPayment(unit, pzForbesPart)]) | |
108 | + | if ((wavesToPuzzleViaForbesResult == wavesToPuzzleViaForbesResult)) | |
109 | + | then { | |
110 | + | let wavesToPuzzleViaBasicResult = invoke(pzBasicPuzzle, "swap", [puzzleIdStr, 1], [AttachedPayment(unit, pzBasicPuzzlePart)]) | |
111 | + | if ((wavesToPuzzleViaBasicResult == wavesToPuzzleViaBasicResult)) | |
112 | + | then { | |
113 | + | let wavesToPuzzleViaWxResult = invoke(wxSwop, "swap", [1, puzzleIdStr, toString(this)], [AttachedPayment(unit, wxPuzzleWavesPart)]) | |
114 | + | if ((wavesToPuzzleViaWxResult == wavesToPuzzleViaWxResult)) | |
115 | + | then { | |
116 | + | let xtnToPuzzleViaSwopResult = asAnyList(invoke(swopPuzzleXtn, "exchange", [1], [AttachedPayment(xtnId, xtnAmt)])) | |
117 | + | if ((xtnToPuzzleViaSwopResult == xtnToPuzzleViaSwopResult)) | |
118 | + | then [ScriptTransfer(i.caller, wavesBalance(this).available, unit)] | |
119 | + | else throw("Strict value is not equal to itself.") | |
419 | 120 | } | |
121 | + | else throw("Strict value is not equal to itself.") | |
420 | 122 | } | |
421 | - | ||
422 | - | let price = getIntegerValue(this, keyPrice(symbol)) | |
423 | - | let minMaxSTRUCT = { | |
424 | - | let $l = iters | |
425 | - | let $s = size($l) | |
426 | - | let $acc0 = $Tuple2(9223372036854775, 0) | |
427 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
428 | - | then $a | |
429 | - | else findMinMax($a, $l[$i]) | |
430 | - | ||
431 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
432 | - | then $a | |
433 | - | else throw("List size exceeds 21") | |
434 | - | ||
435 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21) | |
436 | - | } | |
437 | - | $Tuple2(nil, $Tuple4(price, priceAvg, minMaxSTRUCT._1, minMaxSTRUCT._2)) | |
438 | - | } | |
439 | - | } | |
123 | + | else throw("Strict value is not equal to itself.") | |
124 | + | } | |
125 | + | else throw("Strict value is not equal to itself.") | |
126 | + | } | |
127 | + | else throw("Strict value is not equal to itself.") | |
440 | 128 | } | |
441 | 129 | ||
442 | 130 |
github/deemru/w8io/3ef1775 47.74 ms ◑![]()